[vlc-devel] [PATCH 1/5] vout: spu: rework channel registration

Roland Bewick roland.bewick at gmail.com
Thu Jun 6 09:07:04 CEST 2019


Nice.

It looks like VOUT_MAX_SUBPICTURES is being used for the number of 
channels too. I don't think they should share the same definition.

I think VOUT_MAX_SUBPICTURES controls how many subpictures are stored in 
memory ahead of the current time? (to check whether the subtitle should 
be displayed or not and how many can be displayed simultaneously)

If this is the case, that might be the (existing) problem that causes 
subtitles not to be displayed when a large delay is given (e.g. 1 minute).

Roland


On 6/06/2019 1:28 PM, Thomas Guillem wrote:
> Every registered channels need to be unregistered. The first 3 OSD channels
> don't need to be unregistered since they are automatically registered.
>
> sput_t now use a vector of struct spu_channel to keep its channels. This struct
> will contain parameters specific to a channel like the clock/delay/rate.
>
> The channel_id is now a ssize_t, -1 being invalid, 0, 1, 2 being the OSD
> channels, and [3; SSIZE_MAX] being registered spu channels.
>
> ES_OUT_VOUT_FLUSH_OVERLAY is renamed to ES_OUT_VOUT_DEL_OVERLAY since this
> control is only used to delete an overlay.
>
> Refs #22273
> ---
>   include/vlc_es_out.h                |   7 +-
>   include/vlc_spu.h                   |   7 +-
>   include/vlc_subpicture.h            |   2 +-
>   include/vlc_vout.h                  |  13 +--
>   modules/access/bluray.c             |   2 +-
>   modules/lua/libs/osd.c              |   6 +-
>   src/input/decoder.c                 |  60 ++++++++----
>   src/input/decoder.h                 |   4 +-
>   src/input/es_out.c                  |   8 +-
>   src/input/es_out_timeshift.c        |   8 +-
>   src/libvlccore.sym                  |   2 +
>   src/video_output/video_output.c     |  14 ++-
>   src/video_output/vout_subpictures.c | 137 +++++++++++++++++++++++-----
>   13 files changed, 197 insertions(+), 73 deletions(-)
>
> diff --git a/include/vlc_es_out.h b/include/vlc_es_out.h
> index b690d570e9..06b6a8f338 100644
> --- a/include/vlc_es_out.h
> +++ b/include/vlc_es_out.h
> @@ -104,10 +104,9 @@ enum es_out_query_e
>   
>       ES_OUT_VOUT_ADD_OVERLAY, /* arg1= es_out_id_t* (video es),
>                                 * arg2= subpicture_t *,
> -                              * arg3= int * (channel id), res= can fail */
> -
> -    ES_OUT_VOUT_FLUSH_OVERLAY, /* arg1= es_out_id_t* (video es),
> -                                * arg2= int (channel id), res= can fail */
> +                              * arg3= size_t * (channel id), res= can fail */
> +    ES_OUT_VOUT_DEL_OVERLAY, /* arg1= es_out_id_t* (video es),
> +                              * arg2= size_t (channel id), res= can fail */
>   
>       ES_OUT_SPU_SET_HIGHLIGHT, /* arg1= es_out_id_t* (spu es),
>                                    arg2= const vlc_spu_highlight_t *, res=can fail  */
> diff --git a/include/vlc_spu.h b/include/vlc_spu.h
> index ee6c68f784..00ef08c71d 100644
> --- a/include/vlc_spu.h
> +++ b/include/vlc_spu.h
> @@ -50,7 +50,7 @@ struct spu_t
>       spu_private_t *p;
>   };
>   
> -    VLC_API spu_t * spu_Create( vlc_object_t *, vout_thread_t * );
> +VLC_API spu_t * spu_Create( vlc_object_t *, vout_thread_t * );
>   #define spu_Create(a,b) spu_Create(VLC_OBJECT(a),b)
>   VLC_API void spu_Destroy( spu_t * );
>   
> @@ -80,12 +80,13 @@ VLC_API subpicture_t * spu_Render( spu_t *, const vlc_fourcc_t *p_chroma_list,
>   /**
>    * It registers a new SPU channel.
>    */
> -VLC_API int spu_RegisterChannel( spu_t * );
> +VLC_API ssize_t spu_RegisterChannel( spu_t * );
> +VLC_API void spu_UnregisterChannel( spu_t *, size_t );
>   
>   /**
>    * It clears all subpictures associated to a SPU channel.
>    */
> -VLC_API void spu_ClearChannel( spu_t *, int );
> +VLC_API void spu_ClearChannel( spu_t *, size_t );
>   
>   /**
>    * It changes the sub sources list
> diff --git a/include/vlc_subpicture.h b/include/vlc_subpicture.h
> index ea618e8aa1..606eb451e1 100644
> --- a/include/vlc_subpicture.h
> +++ b/include/vlc_subpicture.h
> @@ -165,7 +165,7 @@ struct subpicture_t
>   {
>       /** \name Channel ID */
>       /**@{*/
> -    int             i_channel;                    /**< subpicture channel ID */
> +    ssize_t         i_channel;                    /**< subpicture channel ID */
>       /**@}*/
>   
>       /** \name Type and flags
> diff --git a/include/vlc_vout.h b/include/vlc_vout.h
> index 88f825d3fa..da1a3a836c 100644
> --- a/include/vlc_vout.h
> +++ b/include/vlc_vout.h
> @@ -110,15 +110,16 @@ VLC_API void vout_PutPicture( vout_thread_t *, picture_t * );
>   
>   /* Subpictures channels ID */
>   #define VOUT_SPU_CHANNEL_INVALID      (-1) /* Always fails in comparison */
> -#define VOUT_SPU_CHANNEL_OSD            1 /* OSD channel is automatically cleared */
> -#define VOUT_SPU_CHANNEL_OSD_HSLIDER    2
> -#define VOUT_SPU_CHANNEL_OSD_VSLIDER    3
> -#define VOUT_SPU_CHANNEL_AVAIL_FIRST    8 /* Registerable channels from this offset */
> +#define VOUT_SPU_CHANNEL_OSD            0 /* OSD channel is automatically cleared */
> +#define VOUT_SPU_CHANNEL_OSD_HSLIDER    1
> +#define VOUT_SPU_CHANNEL_OSD_VSLIDER    2
> +#define VOUT_SPU_CHANNEL_OSD_COUNT      3
>   
>   /* */
>   VLC_API void vout_PutSubpicture( vout_thread_t *, subpicture_t * );
> -VLC_API int vout_RegisterSubpictureChannel( vout_thread_t * );
> -VLC_API void vout_FlushSubpictureChannel( vout_thread_t *, int );
> +VLC_API ssize_t vout_RegisterSubpictureChannel( vout_thread_t * );
> +VLC_API void vout_UnregisterSubpictureChannel( vout_thread_t *, size_t );
> +VLC_API void vout_FlushSubpictureChannel( vout_thread_t *, size_t );
>   /**
>    * This function will ensure that all ready/displayed pictures have at most
>    * the provided date.
> diff --git a/modules/access/bluray.c b/modules/access/bluray.c
> index c452327aeb..4e21ddbed1 100644
> --- a/modules/access/bluray.c
> +++ b/modules/access/bluray.c
> @@ -1531,7 +1531,7 @@ static int bluray_esOutControl(es_out_t *p_out, int i_query, va_list args)
>                  i_plane < MAX_OVERLAY &&
>                  esout_priv->overlay.channels[i_plane] != VOUT_SPU_CHANNEL_INVALID)
>               {
> -                i_ret = es_out_Control(esout_priv->p_dst_out, ES_OUT_VOUT_FLUSH_OVERLAY,
> +                i_ret = es_out_Control(esout_priv->p_dst_out, ES_OUT_VOUT_DEL_OVERLAY,
>                                          esout_priv->overlay.p_video_es,
>                                          esout_priv->overlay.channels[i_plane]);
>                   esout_priv->overlay.channels[i_plane] = VOUT_SPU_CHANNEL_INVALID;
> diff --git a/modules/lua/libs/osd.c b/modules/lua/libs/osd.c
> index 0131c8edf6..6aa3257e98 100644
> --- a/modules/lua/libs/osd.c
> +++ b/modules/lua/libs/osd.c
> @@ -166,7 +166,7 @@ static int vlclua_spu_channel_register( lua_State *L )
>       if( !p_vout )
>           return luaL_error( L, "Unable to find vout." );
>   
> -    int i_chan = vout_RegisterSubpictureChannel( p_vout );
> +    ssize_t i_chan = vout_RegisterSubpictureChannel( p_vout );
>       vout_Release( p_vout );
>       lua_pushinteger( L, i_chan );
>       return 1;
> @@ -174,12 +174,12 @@ static int vlclua_spu_channel_register( lua_State *L )
>   
>   static int vlclua_spu_channel_clear( lua_State *L )
>   {
> -    int i_chan = luaL_checkinteger( L, 1 );
> +    ssize_t i_chan = luaL_checkinteger( L, 1 );
>       vout_thread_t *p_vout = vlclua_get_vout_internal(L);
>       if( !p_vout )
>           return luaL_error( L, "Unable to find vout." );
>   
> -    vout_FlushSubpictureChannel( p_vout, i_chan );
> +    vout_UnregisterSubpictureChannel( p_vout, i_chan );
>       vout_Release(p_vout);
>       return 0;
>   }
> diff --git a/src/input/decoder.c b/src/input/decoder.c
> index 45cf9844b1..fde43681e4 100644
> --- a/src/input/decoder.c
> +++ b/src/input/decoder.c
> @@ -71,7 +71,7 @@ struct decoder_owner
>       input_resource_t*p_resource;
>       vlc_clock_t     *p_clock;
>   
> -    int              i_spu_channel;
> +    ssize_t          i_spu_channel;
>       int64_t          i_spu_order;
>   
>       sout_instance_t         *p_sout;
> @@ -611,8 +611,15 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
>           msg_Warn( p_dec, "no vout found, dropping subpicture" );
>           if( p_owner->p_vout )
>           {
> -            vlc_mutex_lock( &p_owner->lock );
> +            if (p_owner->i_spu_channel != -1)
> +            {
> +                vout_UnregisterSubpictureChannel(p_owner->p_vout,
> +                                                 p_owner->i_spu_channel);
> +                p_owner->i_spu_channel = -1;
> +            }
>               vout_SetSubpictureClock(p_owner->p_vout, NULL);
> +
> +            vlc_mutex_lock( &p_owner->lock );
>               vout_Release(p_owner->p_vout);
>               p_owner->p_vout = NULL;
>               vlc_mutex_unlock( &p_owner->lock );
> @@ -622,19 +629,27 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
>   
>       if( p_owner->p_vout != p_vout )
>       {
> +        ssize_t old_spu_channel = p_owner->i_spu_channel;
>           p_owner->i_spu_channel = vout_RegisterSubpictureChannel( p_vout );
>           p_owner->i_spu_order = 0;
>   
> -        vlc_mutex_lock( &p_owner->lock );
> -        if( p_owner->p_vout )
> +        if (p_owner->i_spu_channel != -1)
>           {
> -            vout_SetSubpictureClock(p_owner->p_vout, NULL);
> -            vout_Release(p_owner->p_vout);
> -        }
> -        p_owner->p_vout = p_vout;
> -        vlc_mutex_unlock( &p_owner->lock );
> +            if (p_owner->p_vout)
> +            {
> +                vout_SetSubpictureClock(p_owner->p_vout, NULL);
> +                if (old_spu_channel != -1)
> +                    vout_UnregisterSubpictureChannel(p_owner->p_vout,
> +                                                     old_spu_channel);
> +            }
> +            vlc_mutex_lock(&p_owner->lock);
> +            if (p_owner->p_vout)
> +                vout_Release(p_owner->p_vout);
> +            p_owner->p_vout = p_vout;
> +            vlc_mutex_unlock(&p_owner->lock);
>   
> -        vout_SetSubpictureClock( p_vout, p_owner->p_clock );
> +            vout_SetSubpictureClock(p_vout, p_owner->p_clock);
> +        }
>       }
>       else
>           vout_Release(p_vout);
> @@ -1484,7 +1499,10 @@ static void DecoderProcessFlush( decoder_t *p_dec )
>       else if( p_dec->fmt_out.i_cat == SPU_ES )
>       {
>           if( p_owner->p_vout )
> +        {
> +            assert( p_owner->i_spu_channel >= 0 );
>               vout_FlushSubpictureChannel( p_owner->p_vout, p_owner->i_spu_channel );
> +        }
>       }
>   
>       p_owner->i_preroll_end = (vlc_tick_t)INT64_MIN;
> @@ -1783,7 +1801,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
>       p_owner->p_resource = p_resource;
>       p_owner->p_aout = NULL;
>       p_owner->p_vout = NULL;
> -    p_owner->i_spu_channel = 0;
> +    p_owner->i_spu_channel = -1;
>       p_owner->i_spu_order = 0;
>       p_owner->p_sout = p_sout;
>       p_owner->p_sout_input = NULL;
> @@ -1970,8 +1988,9 @@ static void DeleteDecoder( decoder_t * p_dec )
>           {
>               if( p_owner->p_vout )
>               {
> -                vout_FlushSubpictureChannel( p_owner->p_vout,
> -                                             p_owner->i_spu_channel );
> +                assert( p_owner->i_spu_channel > 0 );
> +                vout_UnregisterSubpictureChannel( p_owner->p_vout,
> +                                                  p_owner->i_spu_channel );
>                   vout_SetSubpictureClock(p_owner->p_vout, NULL);
>                   vout_Release(p_owner->p_vout);
>               }
> @@ -2529,7 +2548,7 @@ void input_DecoderSetVoutMouseEvent( decoder_t *dec, vlc_mouse_event mouse_event
>   }
>   
>   int input_DecoderAddVoutOverlay( decoder_t *dec, subpicture_t *sub,
> -                                 int *channel )
> +                                 size_t *channel )
>   {
>       struct decoder_owner *owner = dec_get_owner( dec );
>       assert( dec->fmt_in.i_cat == VIDEO_ES );
> @@ -2542,8 +2561,15 @@ int input_DecoderAddVoutOverlay( decoder_t *dec, subpicture_t *sub,
>           vlc_mutex_unlock( &owner->lock );
>           return VLC_EGENERIC;
>       }
> +    ssize_t channel_id =
> +        vout_RegisterSubpictureChannel( owner->p_vout );
> +    if (channel_id == -1)
> +    {
> +        vlc_mutex_unlock( &owner->lock );
> +        return VLC_EGENERIC;
> +    }
>       sub->i_start = sub->i_stop = vlc_tick_now();
> -    sub->i_channel = *channel = vout_RegisterSubpictureChannel( owner->p_vout );
> +    sub->i_channel = *channel = channel_id;
>       sub->i_order = 0;
>       sub->b_ephemer = true;
>       vout_PutSubpicture( owner->p_vout, sub );
> @@ -2552,7 +2578,7 @@ int input_DecoderAddVoutOverlay( decoder_t *dec, subpicture_t *sub,
>       return VLC_SUCCESS;
>   }
>   
> -int input_DecoderFlushVoutOverlay( decoder_t *dec, int channel )
> +int input_DecoderDelVoutOverlay( decoder_t *dec, size_t channel )
>   {
>       struct decoder_owner *owner = dec_get_owner( dec );
>       assert( dec->fmt_in.i_cat == VIDEO_ES );
> @@ -2564,7 +2590,7 @@ int input_DecoderFlushVoutOverlay( decoder_t *dec, int channel )
>           vlc_mutex_unlock( &owner->lock );
>           return VLC_EGENERIC;
>       }
> -    vout_FlushSubpictureChannel( owner->p_vout, channel );
> +    vout_UnregisterSubpictureChannel( owner->p_vout, channel );
>   
>       vlc_mutex_unlock( &owner->lock );
>       return VLC_SUCCESS;
> diff --git a/src/input/decoder.h b/src/input/decoder.h
> index 0ac021e9b2..fbb266e139 100644
> --- a/src/input/decoder.h
> +++ b/src/input/decoder.h
> @@ -110,7 +110,7 @@ bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_me
>   size_t input_DecoderGetFifoSize( decoder_t *p_dec );
>   
>   void input_DecoderSetVoutMouseEvent( decoder_t *, vlc_mouse_event, void * );
> -int  input_DecoderAddVoutOverlay( decoder_t *, subpicture_t *, int * );
> -int  input_DecoderFlushVoutOverlay( decoder_t *, int );
> +int  input_DecoderAddVoutOverlay( decoder_t *, subpicture_t *, size_t * );
> +int  input_DecoderDelVoutOverlay( decoder_t *, size_t );
>   
>   #endif
> diff --git a/src/input/es_out.c b/src/input/es_out.c
> index 868ecbe9a1..7e8ad40a5f 100644
> --- a/src/input/es_out.c
> +++ b/src/input/es_out.c
> @@ -3130,17 +3130,17 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
>       {
>           es_out_id_t *p_es = va_arg( args, es_out_id_t * );
>           subpicture_t *sub = va_arg( args, subpicture_t * );
> -        int *channel = va_arg( args, int * );
> +        size_t *channel = va_arg( args, size_t * );
>           if( p_es && p_es->fmt.i_cat == VIDEO_ES && p_es->p_dec )
>               return input_DecoderAddVoutOverlay( p_es->p_dec, sub, channel );
>           return VLC_EGENERIC;
>       }
> -    case ES_OUT_VOUT_FLUSH_OVERLAY:
> +    case ES_OUT_VOUT_DEL_OVERLAY:
>       {
>           es_out_id_t *p_es = va_arg( args, es_out_id_t * );
> -        int channel = va_arg( args, int );
> +        size_t channel = va_arg( args, size_t );
>           if( p_es && p_es->fmt.i_cat == VIDEO_ES && p_es->p_dec )
> -            return input_DecoderFlushVoutOverlay( p_es->p_dec, channel );
> +            return input_DecoderDelVoutOverlay( p_es->p_dec, channel );
>           return VLC_EGENERIC;
>       }
>       case ES_OUT_SPU_SET_HIGHLIGHT:
> diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c
> index 5adbbc23e4..09482a2a10 100644
> --- a/src/input/es_out_timeshift.c
> +++ b/src/input/es_out_timeshift.c
> @@ -662,15 +662,15 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
>       {
>           es_out_id_t *p_es = va_arg( args, es_out_id_t * );
>           subpicture_t *sub = va_arg( args, subpicture_t * );
> -        int *channel = va_arg( args, int * );
> +        size_t *channel = va_arg( args, size_t * );
>           return es_out_Control( p_sys->p_out, ES_OUT_VOUT_ADD_OVERLAY,
>                                  p_es->p_es, sub, channel );
>       }
> -    case ES_OUT_VOUT_FLUSH_OVERLAY:
> +    case ES_OUT_VOUT_DEL_OVERLAY:
>       {
>           es_out_id_t *p_es = va_arg( args, es_out_id_t * );
> -        int channel = va_arg( args, int );
> -        return es_out_Control( p_sys->p_out, ES_OUT_VOUT_FLUSH_OVERLAY,
> +        size_t channel = va_arg( args, size_t );
> +        return es_out_Control( p_sys->p_out, ES_OUT_VOUT_DEL_OVERLAY,
>                                  p_es->p_es, channel );
>       }
>       case ES_OUT_SPU_SET_HIGHLIGHT:
> diff --git a/src/libvlccore.sym b/src/libvlccore.sym
> index f8252a8c61..c9bbd91ab7 100644
> --- a/src/libvlccore.sym
> +++ b/src/libvlccore.sym
> @@ -349,6 +349,7 @@ spu_ChangeSources
>   spu_ChangeFilters
>   spu_Render
>   spu_RegisterChannel
> +spu_UnregisterChannel
>   spu_ClearChannel
>   vlc_stream_directory_Attach
>   vlc_stream_extractor_Attach
> @@ -697,6 +698,7 @@ vout_GetPicture
>   vout_PutPicture
>   vout_PutSubpicture
>   vout_RegisterSubpictureChannel
> +vout_UnregisterSubpictureChannel
>   vout_FlushSubpictureChannel
>   vout_Flush
>   vout_GetSnapshot
> diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
> index 524135f013..1f0a2391dd 100644
> --- a/src/video_output/video_output.c
> +++ b/src/video_output/video_output.c
> @@ -267,10 +267,10 @@ void vout_PutSubpicture( vout_thread_t *vout, subpicture_t *subpic )
>       vlc_mutex_unlock(&sys->spu_lock);
>   }
>   
> -int vout_RegisterSubpictureChannel( vout_thread_t *vout )
> +ssize_t vout_RegisterSubpictureChannel( vout_thread_t *vout )
>   {
>       assert(!vout->p->dummy);
> -    int channel = VOUT_SPU_CHANNEL_AVAIL_FIRST;
> +    ssize_t channel = VOUT_SPU_CHANNEL_INVALID;
>   
>       vlc_mutex_lock(&vout->p->spu_lock);
>       if (vout->p->spu)
> @@ -280,6 +280,14 @@ int vout_RegisterSubpictureChannel( vout_thread_t *vout )
>       return channel;
>   }
>   
> +void vout_UnregisterSubpictureChannel( vout_thread_t *vout, size_t channel )
> +{
> +    assert(!vout->p->dummy);
> +
> +    if (vout->p->spu)
> +        spu_UnregisterChannel(vout->p->spu, channel);
> +}
> +
>   void vout_SetSubpictureClock( vout_thread_t *vout, vlc_clock_t *clock )
>   {
>       assert(!vout->p->dummy);
> @@ -289,7 +297,7 @@ void vout_SetSubpictureClock( vout_thread_t *vout, vlc_clock_t *clock )
>       vlc_mutex_unlock(&vout->p->spu_lock);
>   }
>   
> -void vout_FlushSubpictureChannel( vout_thread_t *vout, int channel )
> +void vout_FlushSubpictureChannel( vout_thread_t *vout, size_t channel )
>   {
>       vout_thread_sys_t *sys = vout->p;
>       assert(!sys->dummy);
> diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c
> index 247321f29c..108e0a46c6 100644
> --- a/src/video_output/vout_subpictures.c
> +++ b/src/video_output/vout_subpictures.c
> @@ -38,6 +38,7 @@
>   #include <vlc_vout.h>
>   #include <vlc_filter.h>
>   #include <vlc_spu.h>
> +#include <vlc_vector.h>
>   
>   #include "../libvlc.h"
>   #include "vout_internal.h"
> @@ -62,10 +63,17 @@ typedef struct {
>       subpicture_t *entries[VOUT_MAX_SUBPICTURES];
>   } spu_heap_t;
>   
> +struct spu_channel {
> +    size_t id;
> +};
> +
> +typedef struct VLC_VECTOR(struct spu_channel) spu_channel_vector;
> +
>   struct spu_private_t {
>       vlc_mutex_t  lock;            /* lock to protect all followings fields */
>       input_thread_t *input;
>   
> +    spu_channel_vector channels;
>       vlc_clock_t *clock;
>   
>       spu_heap_t   heap;
> @@ -152,6 +160,42 @@ static void SpuHeapClean(spu_heap_t *heap)
>       }
>   }
>   
> +static struct spu_channel *spu_GetChannel(spu_t *spu, size_t channel_id)
> +{
> +    spu_private_t *sys = spu->p;
> +
> +    for (size_t i = 0; i < sys->channels.size; ++i)
> +        if (sys->channels.data[i].id == channel_id)
> +            return &sys->channels.data[i];
> +
> +    vlc_assert_unreachable();
> +}
> +
> +static ssize_t spu_GetFreeChannelId(spu_t *spu)
> +{
> +    spu_private_t *sys = spu->p;
> +
> +    if (unlikely(sys->channels.size) > SSIZE_MAX)
> +        return VOUT_SPU_CHANNEL_INVALID;
> +
> +    size_t id;
> +    for (id = VOUT_SPU_CHANNEL_OSD_COUNT; id < sys->channels.size + 1; ++id)
> +    {
> +        bool used = false;
> +        for (size_t i = VOUT_SPU_CHANNEL_OSD_COUNT; i < sys->channels.size; ++i)
> +        {
> +            if (sys->channels.data[i].id == id)
> +            {
> +                used = true;
> +                break;
> +            }
> +        }
> +        if (!used)
> +            return id;
> +    }
> +    return VOUT_SPU_CHANNEL_INVALID;
> +}
> +
>   static void FilterRelease(filter_t *filter)
>   {
>       if (filter->p_module)
> @@ -491,6 +535,11 @@ static int IntegerCmp(int64_t i0, int64_t i1)
>   {
>       return i0 < i1 ? -1 : i0 > i1 ? 1 : 0;
>   }
> +
> +static int SSizeCmp(ssize_t i0, ssize_t i1)
> +{
> +    return i0 < i1 ? -1 : i0 > i1 ? 1 : 0;
> +}
>   /**
>    * This function compares 2 subpictures using the following properties
>    * (ordered by priority)
> @@ -514,7 +563,7 @@ static int SpuRenderCmp(const void *s0, const void *s1)
>       if (!r)
>           r = IntegerCmp(render_entry0->start, render_entry1->start);
>       if (!r)
> -        r = IntegerCmp(subpic0->i_channel, subpic1->i_channel);
> +        r = SSizeCmp(subpic0->i_channel, subpic1->i_channel);
>       if (!r)
>           r = IntegerCmp(subpic0->i_order, subpic1->i_order);
>       return r;
> @@ -595,14 +644,14 @@ static void SpuSelectSubpictures(spu_t *spu,
>           return;
>   
>       /* Create a list of channels */
> -    int channel[VOUT_MAX_SUBPICTURES];
> -    int channel_count = 0;
> +    ssize_t channel[VOUT_MAX_SUBPICTURES];
> +    size_t channel_count = 0;
>   
>       for (int index = 0; index < VOUT_MAX_SUBPICTURES; index++) {
>           if (!sys->heap.entries[index])
>               continue;
>           const int i_channel = sys->heap.entries[index]->i_channel;
> -        int i;
> +        size_t i;
>           for (i = 0; i < channel_count; i++) {
>               if (channel[i] == i_channel)
>                   break;
> @@ -612,7 +661,7 @@ static void SpuSelectSubpictures(spu_t *spu,
>       }
>   
>       /* Fill up the subpicture_array arrays with relevant pictures */
> -    for (int i = 0; i < channel_count; i++) {
> +    for (size_t i = 0; i < channel_count; i++) {
>           spu_render_entry_t available_entries[VOUT_MAX_SUBPICTURES];
>           bool         is_available_late[VOUT_MAX_SUBPICTURES];
>           size_t       available_count = 0;
> @@ -1257,7 +1306,7 @@ static void UpdateSPU(spu_t *spu, const vlc_spu_highlight_t *hl)
>   
>   static subpicture_t *sub_new_buffer(filter_t *filter)
>   {
> -    int channel = *(int *)filter->owner.sys;
> +    ssize_t channel = *(ssize_t *)filter->owner.sys;
>   
>       subpicture_t *subpicture = subpicture_New(NULL);
>       if (subpicture)
> @@ -1272,7 +1321,7 @@ static const struct filter_subpicture_callbacks sub_cbs = {
>   static int SubSourceInit(filter_t *filter, void *data)
>   {
>       spu_t *spu = data;
> -    int *channel = malloc(sizeof (int));
> +    ssize_t *channel = malloc(sizeof (ssize_t));
>       if (unlikely(channel == NULL))
>           return VLC_ENOMEM;
>   
> @@ -1285,7 +1334,7 @@ static int SubSourceInit(filter_t *filter, void *data)
>   static int SubSourceClean(filter_t *filter, void *data)
>   {
>       spu_t *spu = data;
> -    int *channel = filter->owner.sys;
> +    ssize_t *channel = filter->owner.sys;
>   
>       spu_ClearChannel(spu, *channel);
>       free(channel);
> @@ -1361,6 +1410,21 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
>       /* Initialize spu fields */
>       spu_private_t *sys = spu->p = (spu_private_t*)&spu[1];
>   
> +    vlc_vector_init(&sys->channels);
> +    if (!vlc_vector_reserve(&sys->channels, VOUT_SPU_CHANNEL_OSD_COUNT))
> +    {
> +        vlc_object_delete(spu);
> +        return NULL;
> +    }
> +    for (size_t i = 0; i < VOUT_SPU_CHANNEL_OSD_COUNT; ++i)
> +    {
> +        struct spu_channel channel = {
> +            .id = i,
> +        };
> +        bool success = vlc_vector_push(&sys->channels, channel);
> +        assert(success); /* already reserved */
> +    }
> +
>       /* Initialize private fields */
>       vlc_mutex_init(&sys->lock);
>   
> @@ -1370,9 +1434,6 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
>   
>       atomic_init(&sys->margin, var_InheritInteger(spu, "sub-margin"));
>   
> -    /* Register the default subpicture channel */
> -    sys->channel = VOUT_SPU_CHANNEL_AVAIL_FIRST;
> -
>       sys->source_chain_update = NULL;
>       sys->filter_chain_update = NULL;
>       vlc_mutex_init(&sys->filter_chain_lock);
> @@ -1443,6 +1504,8 @@ void spu_Destroy(spu_t *spu)
>       /* Destroy all remaining subpictures */
>       SpuHeapClean(&sys->heap);
>   
> +    vlc_vector_destroy(&sys->channels);
> +
>       vlc_mutex_destroy(&sys->lock);
>   
>       vlc_object_delete(spu);
> @@ -1712,36 +1775,60 @@ void spu_OffsetSubtitleDate(spu_t *spu, vlc_tick_t duration)
>       vlc_mutex_unlock(&sys->lock);
>   }
>   
> -int spu_RegisterChannel(spu_t *spu)
> +ssize_t spu_RegisterChannel(spu_t *spu)
>   {
>       spu_private_t *sys = spu->p;
>   
>       vlc_mutex_lock(&sys->lock);
> -    int channel = sys->channel++;
> +
> +    ssize_t channel_id = spu_GetFreeChannelId(spu);
> +
> +    if (channel_id != VOUT_SPU_CHANNEL_INVALID)
> +    {
> +        struct spu_channel channel = {
> +            .id = channel_id,
> +        };
> +        if (vlc_vector_push(&sys->channels, channel))
> +        {
> +            vlc_mutex_unlock(&sys->lock);
> +            return channel_id;
> +        }
> +    }
> +
>       vlc_mutex_unlock(&sys->lock);
>   
> -    return channel;
> +    return VOUT_SPU_CHANNEL_INVALID;
>   }
>   
> -void spu_ClearChannel(spu_t *spu, int channel)
> +static void spu_ClearChannelLocked(spu_t *spu, size_t channel_id)
>   {
>       spu_private_t *sys = spu->p;
>   
> -    vlc_mutex_lock(&sys->lock);
> -
> -    for (int i = 0; i < VOUT_MAX_SUBPICTURES; i++)
> +    for (size_t i = 0; i < VOUT_MAX_SUBPICTURES; i++)
>       {
>           subpicture_t *subpic = sys->heap.entries[i];
>   
> -        if (!subpic)
> -            continue;
> -        if (subpic->i_channel != channel &&
> -            (channel != VOUT_SPU_CHANNEL_INVALID || subpic->i_channel == VOUT_SPU_CHANNEL_OSD))
> -            continue;
> -
> -        SpuHeapDeleteAt(&sys->heap, i);
> +        if (subpic && subpic->i_channel >= 0
> +         && (size_t) subpic->i_channel == channel_id)
> +            SpuHeapDeleteAt(&sys->heap, i);
>       }
> +}
> +
> +void spu_ClearChannel(spu_t *spu, size_t channel_id)
> +{
> +    spu_private_t *sys = spu->p;
> +    vlc_mutex_lock(&sys->lock);
> +    spu_ClearChannelLocked(spu, channel_id);
> +    vlc_mutex_unlock(&sys->lock);
> +}
>   
> +void spu_UnregisterChannel(spu_t *spu, size_t channel_id)
> +{
> +    spu_private_t *sys = spu->p;
> +
> +    vlc_mutex_lock(&sys->lock);
> +    spu_ClearChannelLocked(spu, channel_id);
> +    vlc_vector_remove(&sys->channels, channel_id);
>       vlc_mutex_unlock(&sys->lock);
>   }
>   


More information about the vlc-devel mailing list