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

Thomas Guillem thomas at gllm.fr
Thu Jun 6 09:13:48 CEST 2019


On Thu, Jun 6, 2019, at 09:07, Roland Bewick wrote:
> 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.

There is an "infinite" (more SSIZE_MAX) maximum number of channels now.

> 
> 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).

Agreed, I can easily remove the VOUT_MAX_SUBPICTURES limit now, by using a vlc_vector.

> 
> 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);
> >   }
> >   
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list