[vlc-devel] [PATCH 4/5] vout: spu: move clock into channels

Roland Bewick roland.bewick at gmail.com
Thu Jun 6 09:15:19 CEST 2019


Minor: I don't like the name RegisterSubpictureChannelAndClock. If you 
have to do something else too would it be 
RegisterSubpictureChannelAndClockAndSomethingElse()?

Maybe the old name was fine? you're just setting up a subpicture channel.

Roland

On 6/06/2019 1:28 PM, Thomas Guillem wrote:
> This pave the way to multiple subtitles: each registered spu channel has now
> its own clock.
>
> And fixes OSD subpictures date being messed up by the decoder clock.
>
> Fixes #22273
> ---
>   include/vlc_spu.h                    |  2 +-
>   modules/stream_out/transcode/video.c |  2 +-
>   src/input/decoder.c                  | 29 ++++++------
>   src/video_output/video_output.c      | 47 +++++++++---------
>   src/video_output/vout_internal.h     | 14 +++---
>   src/video_output/vout_subpictures.c  | 71 +++++++++++++++++-----------
>   6 files changed, 88 insertions(+), 77 deletions(-)
>
> diff --git a/include/vlc_spu.h b/include/vlc_spu.h
> index 00ef08c71d..e4fb9a7ec1 100644
> --- a/include/vlc_spu.h
> +++ b/include/vlc_spu.h
> @@ -74,7 +74,7 @@ VLC_API void spu_PutSubpicture( spu_t *, subpicture_t * );
>    */
>   VLC_API subpicture_t * spu_Render( spu_t *, const vlc_fourcc_t *p_chroma_list,
>                                      const video_format_t *p_fmt_dst, const video_format_t *p_fmt_src,
> -                                   vlc_tick_t system_now, vlc_tick_t pts, float rate,
> +                                   vlc_tick_t system_now, vlc_tick_t pts,
>                                      bool ignore_osd, bool external_scale );
>   
>   /**
> diff --git a/modules/stream_out/transcode/video.c b/modules/stream_out/transcode/video.c
> index ef64cf7539..9f1f72b8cf 100644
> --- a/modules/stream_out/transcode/video.c
> +++ b/modules/stream_out/transcode/video.c
> @@ -378,7 +378,7 @@ static picture_t * RenderSubpictures( sout_stream_t *p_stream, sout_stream_id_sy
>       }
>   
>       subpicture_t *p_subpic = spu_Render( id->p_spu, NULL, &fmt,
> -                                         &outfmt, vlc_tick_now(), p_pic->date, 1.f,
> +                                         &outfmt, vlc_tick_now(), p_pic->date,
>                                            false, false );
>   
>       /* Overlay subpicture */
> diff --git a/src/input/decoder.c b/src/input/decoder.c
> index fde43681e4..580724944c 100644
> --- a/src/input/decoder.c
> +++ b/src/input/decoder.c
> @@ -617,7 +617,6 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
>                                                    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);
> @@ -630,25 +629,20 @@ 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_channel =
> +            vout_RegisterSubpictureChannelAndClock(p_vout, p_owner->p_clock);
>           p_owner->i_spu_order = 0;
>   
>           if (p_owner->i_spu_channel != -1)
>           {
> -            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);
> -            }
> +            if (p_owner->p_vout && 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);
>           }
>       }
>       else
> @@ -1548,7 +1542,11 @@ static void OutputChangeRate( decoder_t *p_dec, float rate )
>               break;
>           case SPU_ES:
>               if( p_owner->p_vout != NULL )
> -                vout_ChangeSpuRate( p_owner->p_vout, rate );
> +            {
> +                assert(p_owner->i_spu_channel != -1);
> +                vout_ChangeSpuRate(p_owner->p_vout, p_owner->i_spu_channel,
> +                                   rate );
> +            }
>               break;
>           default:
>               vlc_assert_unreachable();
> @@ -1574,7 +1572,11 @@ static void OutputChangeDelay( decoder_t *p_dec, vlc_tick_t delay )
>               break;
>           case SPU_ES:
>               if( p_owner->p_vout != NULL )
> -                vout_ChangeSpuDelay( p_owner->p_vout, delay );
> +            {
> +                assert(p_owner->i_spu_channel != -1);
> +                vout_ChangeSpuDelay(p_owner->p_vout, p_owner->i_spu_channel,
> +                                    delay);
> +            }
>               break;
>           default:
>               vlc_assert_unreachable();
> @@ -1991,7 +1993,6 @@ static void DeleteDecoder( decoder_t * p_dec )
>                   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);
>               }
>               break;
> diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
> index 1f0a2391dd..ae8dc8e515 100644
> --- a/src/video_output/video_output.c
> +++ b/src/video_output/video_output.c
> @@ -280,20 +280,24 @@ ssize_t vout_RegisterSubpictureChannel( vout_thread_t *vout )
>       return channel;
>   }
>   
> -void vout_UnregisterSubpictureChannel( vout_thread_t *vout, size_t channel )
> +ssize_t vout_RegisterSubpictureChannelAndClock(vout_thread_t *vout,
> +                                               vlc_clock_t *clock)
>   {
>       assert(!vout->p->dummy);
> +    ssize_t channel = VOUT_SPU_CHANNEL_INVALID;
>   
>       if (vout->p->spu)
> -        spu_UnregisterChannel(vout->p->spu, channel);
> +        channel = spu_RegisterChannelAndClock(vout->p->spu, clock);
> +
> +    return channel;
>   }
>   
> -void vout_SetSubpictureClock( vout_thread_t *vout, vlc_clock_t *clock )
> +void vout_UnregisterSubpictureChannel( vout_thread_t *vout, size_t channel )
>   {
>       assert(!vout->p->dummy);
> +    assert(vout->p->spu);
>       vlc_mutex_lock(&vout->p->spu_lock);
> -    if (vout->p->spu)
> -        spu_clock_Set(vout->p->spu, clock);
> +    spu_UnregisterChannel(vout->p->spu, channel);
>       vlc_mutex_unlock(&vout->p->spu_lock);
>   }
>   
> @@ -301,10 +305,10 @@ void vout_FlushSubpictureChannel( vout_thread_t *vout, size_t channel )
>   {
>       vout_thread_sys_t *sys = vout->p;
>       assert(!sys->dummy);
> +    assert(sys->spu);
>   
>       vlc_mutex_lock(&sys->spu_lock);
> -    if (sys->spu != NULL)
> -        spu_ClearChannel(vout->p->spu, channel);
> +    spu_ClearChannel(vout->p->spu, channel);
>       vlc_mutex_unlock(&sys->spu_lock);
>   }
>   
> @@ -1081,7 +1085,7 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
>       subpicture_t *subpic = spu_Render(sys->spu,
>                                         subpicture_chromas, &fmt_spu_rot,
>                                         &vd->source, system_now,
> -                                      render_subtitle_date, sys->spu_rate,
> +                                      render_subtitle_date,
>                                         do_snapshot, vd->info.can_scale_spu);
>       /*
>        * Perform rendering
> @@ -1313,14 +1317,6 @@ static void vout_FlushUnlocked(vout_thread_t *vout, bool below,
>   
>       vlc_clock_Reset(vout->p->clock);
>       vlc_clock_SetDelay(vout->p->clock, vout->p->delay);
> -
> -    vlc_mutex_lock(&vout->p->spu_lock);
> -    if (vout->p->spu)
> -    {
> -        spu_clock_Reset(vout->p->spu);
> -        spu_clock_SetDelay(vout->p->spu, vout->p->spu_delay);
> -    }
> -    vlc_mutex_unlock(&vout->p->spu_lock);
>   }
>   
>   void vout_Flush(vout_thread_t *vout, vlc_tick_t date)
> @@ -1378,21 +1374,22 @@ void vout_ChangeRate(vout_thread_t *vout, float rate)
>       vout_control_Release(&sys->control);
>   }
>   
> -void vout_ChangeSpuDelay(vout_thread_t *vout, vlc_tick_t delay)
> +void vout_ChangeSpuDelay(vout_thread_t *vout, size_t channel_id,
> +                         vlc_tick_t delay)
>   {
>       assert(!vout->p->dummy);
> +    assert(vout->p->spu);
>       vlc_mutex_lock(&vout->p->spu_lock);
> -    if (vout->p->spu)
> -        spu_clock_SetDelay(vout->p->spu, delay);
> -    vout->p->spu_delay = delay;
> +    spu_SetClockDelay(vout->p->spu, channel_id, delay);
>       vlc_mutex_unlock(&vout->p->spu_lock);
>   }
>   
> -void vout_ChangeSpuRate(vout_thread_t *vout, float rate)
> +void vout_ChangeSpuRate(vout_thread_t *vout, size_t channel_id, float rate)
>   {
>       assert(!vout->p->dummy);
> +    assert(vout->p->spu);
>       vlc_mutex_lock(&vout->p->spu_lock);
> -    vout->p->spu_rate = rate;
> +    spu_SetClockRate(vout->p->spu, channel_id, rate);
>       vlc_mutex_unlock(&vout->p->spu_lock);
>   }
>   
> @@ -1946,10 +1943,10 @@ int vout_Request(const vout_configuration_t *cfg, input_thread_t *input)
>       } else
>           vout_UpdateWindowSizeLocked(vout);
>   
> -    sys->delay = sys->spu_delay = 0;
> -    sys->rate = sys->spu_rate = 1.f;
> +    sys->delay = 0;
> +    sys->rate = 1.f;
>       sys->clock = cfg->clock;
> -    sys->delay = sys->spu_delay = 0;
> +    sys->delay = 0;
>   
>       vlc_mutex_unlock(&sys->window_lock);
>   
> diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h
> index 56b4876f8b..d2cd60b4b7 100644
> --- a/src/video_output/vout_internal.h
> +++ b/src/video_output/vout_internal.h
> @@ -72,9 +72,7 @@ struct vout_thread_sys_t
>   
>       vlc_clock_t     *clock;
>       float           rate;
> -    float           spu_rate;
>       vlc_tick_t      delay;
> -    vlc_tick_t      spu_delay;
>   
>       /* */
>       video_format_t  original;   /* Original format ie coming from the decoder */
> @@ -262,12 +260,12 @@ int vout_OpenWrapper(vout_thread_t *, const char *,
>   void vout_CloseWrapper(vout_thread_t *);
>   
>   /* */
> -void vout_SetSubpictureClock(vout_thread_t *vout, vlc_clock_t *clock);
> +ssize_t vout_RegisterSubpictureChannelAndClock( vout_thread_t *, vlc_clock_t *clock );
> +ssize_t spu_RegisterChannelAndClock( spu_t *, vlc_clock_t * );
>   void spu_Attach( spu_t *, input_thread_t *input );
>   void spu_Detach( spu_t * );
> -void spu_clock_Set(spu_t *, vlc_clock_t *);
> -void spu_clock_Reset(spu_t *);
> -void spu_clock_SetDelay(spu_t *spu, vlc_tick_t delay);
> +void spu_SetClockDelay(spu_t *spu, size_t channel_id, vlc_tick_t delay);
> +void spu_SetClockRate(spu_t *spu, size_t channel_id, float rate);
>   void spu_ChangeMargin(spu_t *, int);
>   void spu_SetHighlight(spu_t *, const vlc_spu_highlight_t*);
>   
> @@ -293,12 +291,12 @@ void vout_ChangeDelay( vout_thread_t *, vlc_tick_t delay );
>    * This function will change the rate of the spu channel
>    * It is thread safe
>    */
> -void vout_ChangeSpuRate( vout_thread_t *, float rate );
> +void vout_ChangeSpuRate( vout_thread_t *, size_t channel_id, float rate );
>   /**
>    * This function will change the delay of the spu channel
>    * It is thread safe
>    */
> -void vout_ChangeSpuDelay( vout_thread_t *, vlc_tick_t delay );
> +void vout_ChangeSpuDelay( vout_thread_t *, size_t channel_id, vlc_tick_t delay );
>   
>   
>   /**
> diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c
> index 17cc6a7b77..16902835dc 100644
> --- a/src/video_output/vout_subpictures.c
> +++ b/src/video_output/vout_subpictures.c
> @@ -62,6 +62,9 @@ typedef struct {
>   struct spu_channel {
>       subpicture_t *entries[VOUT_MAX_SUBPICTURES];
>       size_t id;
> +    vlc_clock_t *clock;
> +    vlc_tick_t delay;
> +    float rate;
>   };
>   
>   typedef struct VLC_VECTOR(struct spu_channel) spu_channel_vector;
> @@ -71,7 +74,6 @@ struct spu_private_t {
>       input_thread_t *input;
>   
>       spu_channel_vector channels;
> -    vlc_clock_t *clock;
>   
>       int channel;             /**< number of subpicture channels registered */
>       filter_t *text;                              /**< text renderer module */
> @@ -102,9 +104,11 @@ struct spu_private_t {
>       vout_thread_t       *vout;
>   };
>   
> -static void spu_channel_Init(struct spu_channel *channel, size_t id)
> +static void spu_channel_Init(struct spu_channel *channel, size_t id,
> +                             vlc_clock_t *clock)
>   {
>       channel->id = id;
> +    channel->clock = clock;
>   
>       for (size_t i = 0; i < VOUT_MAX_SUBPICTURES; i++)
>           channel->entries[i] = NULL;
> @@ -563,10 +567,8 @@ static int SpuRenderCmp(const void *s0, const void *s1)
>   }
>   
>   static int spu_channel_ConvertDates(struct spu_channel *channel,
> -                                    vlc_clock_t *clock,
>                                       vlc_tick_t system_now,
> -                                    spu_render_entry_t *render_entries,
> -                                    float rate)
> +                                    spu_render_entry_t *render_entries)
>   {
>       /* Put every spu start and stop ts into the same array to convert them in
>        * one shot */
> @@ -587,9 +589,9 @@ static int spu_channel_ConvertDates(struct spu_channel *channel,
>           return 0;
>   
>       /* Convert all spu ts */
> -    if (clock)
> -        vlc_clock_ConvertArrayToSystem(clock, system_now, date_array,
> -                                       entry_count * 2, rate);
> +    if (channel->clock)
> +        vlc_clock_ConvertArrayToSystem(channel->clock, system_now, date_array,
> +                                       entry_count * 2, channel->rate);
>   
>       /* Put back the converted ts into the output spu_render_entry_t struct */
>       entry_count = 0;
> @@ -623,7 +625,7 @@ static int spu_channel_ConvertDates(struct spu_channel *channel,
>    *****************************************************************************/
>   static spu_render_entry_t *
>   spu_SelectSubpictures(spu_t *spu, vlc_tick_t system_now,
> -                      vlc_tick_t render_subtitle_date, float rate,
> +                      vlc_tick_t render_subtitle_date,
>                         bool ignore_osd, size_t *subpicture_count)
>   {
>       spu_private_t *sys = spu->p;
> @@ -653,8 +655,7 @@ spu_SelectSubpictures(spu_t *spu, vlc_tick_t system_now,
>           int64_t      ephemer_subtitle_order = INT64_MIN;
>           int64_t      ephemer_system_order = INT64_MIN;
>   
> -        if (spu_channel_ConvertDates(channel, sys->clock, system_now, render_entries,
> -                                     rate) == 0)
> +        if (spu_channel_ConvertDates(channel, system_now, render_entries) == 0)
>               continue;
>   
>           /* Select available pictures */
> @@ -1405,15 +1406,13 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
>       for (size_t i = 0; i < VOUT_SPU_CHANNEL_OSD_COUNT; ++i)
>       {
>           struct spu_channel channel;
> -        spu_channel_Init(&channel, i);
> +        spu_channel_Init(&channel, i, NULL);
>           vlc_vector_push(&sys->channels, channel);
>       }
>   
>       /* Initialize private fields */
>       vlc_mutex_init(&sys->lock);
>   
> -    sys->clock = NULL;
> -
>       atomic_init(&sys->margin, var_InheritInteger(spu, "sub-margin"));
>   
>       sys->source_chain_update = NULL;
> @@ -1522,21 +1521,27 @@ void spu_Detach(spu_t *spu)
>       vlc_mutex_unlock(&spu->p->lock);
>   }
>   
> -void spu_clock_Set(spu_t *spu, vlc_clock_t *clock)
> +void spu_SetClockDelay(spu_t *spu, size_t channel_id, vlc_tick_t delay)
>   {
> -    spu->p->clock = clock;
> -}
> +    spu_private_t *sys = spu->p;
>   
> -void spu_clock_Reset(spu_t *spu)
> -{
> -    if (spu->p->clock)
> -        vlc_clock_Reset(spu->p->clock);
> +    vlc_mutex_lock(&sys->lock);
> +    struct spu_channel *channel = spu_GetChannel(spu, channel_id);
> +    assert(channel->clock);
> +    vlc_clock_SetDelay(channel->clock, delay);
> +    channel->delay = delay;
> +    vlc_mutex_unlock(&sys->lock);
>   }
>   
> -void spu_clock_SetDelay(spu_t *spu, vlc_tick_t delay)
> +void spu_SetClockRate(spu_t *spu, size_t channel_id, float rate)
>   {
> -    if (spu->p->clock)
> -        vlc_clock_SetDelay(spu->p->clock, delay);
> +    spu_private_t *sys = spu->p;
> +
> +    vlc_mutex_lock(&sys->lock);
> +    struct spu_channel *channel = spu_GetChannel(spu, channel_id);
> +    assert(channel->clock);
> +    channel->rate = rate;
> +    vlc_mutex_unlock(&sys->lock);
>   }
>   
>   /**
> @@ -1639,7 +1644,7 @@ subpicture_t *spu_Render(spu_t *spu,
>                            const video_format_t *fmt_dst,
>                            const video_format_t *fmt_src,
>                            vlc_tick_t system_now,
> -                         vlc_tick_t render_subtitle_date, float rate,
> +                         vlc_tick_t render_subtitle_date,
>                            bool ignore_osd,
>                            bool external_scale)
>   {
> @@ -1697,7 +1702,7 @@ subpicture_t *spu_Render(spu_t *spu,
>   
>       /* Get an array of subpictures to render */
>       spu_render_entry_t *subpicture_array =
> -        spu_SelectSubpictures(spu, system_now, render_subtitle_date, rate,
> +        spu_SelectSubpictures(spu, system_now, render_subtitle_date,
>                                ignore_osd, &subpicture_count);
>       if (!subpicture_array)
>       {
> @@ -1747,7 +1752,7 @@ subpicture_t *spu_Render(spu_t *spu,
>       return render;
>   }
>   
> -ssize_t spu_RegisterChannel(spu_t *spu)
> +ssize_t spu_RegisterChannelAndClock(spu_t *spu, vlc_clock_t *clock)
>   {
>       spu_private_t *sys = spu->p;
>   
> @@ -1758,7 +1763,7 @@ ssize_t spu_RegisterChannel(spu_t *spu)
>       if (channel_id != VOUT_SPU_CHANNEL_INVALID)
>       {
>           struct spu_channel channel;
> -        spu_channel_Init(&channel, channel_id);
> +        spu_channel_Init(&channel, channel_id, clock);
>           if (vlc_vector_push(&sys->channels, channel))
>           {
>               vlc_mutex_unlock(&sys->lock);
> @@ -1771,6 +1776,11 @@ ssize_t spu_RegisterChannel(spu_t *spu)
>       return VOUT_SPU_CHANNEL_INVALID;
>   }
>   
> +ssize_t spu_RegisterChannel(spu_t *spu)
> +{
> +    return spu_RegisterChannelAndClock(spu, NULL);
> +}
> +
>   static void spu_channel_Clear(struct spu_channel *channel)
>   {
>       for (size_t i = 0; i < VOUT_MAX_SUBPICTURES; i++)
> @@ -1783,6 +1793,11 @@ void spu_ClearChannel(spu_t *spu, size_t channel_id)
>       vlc_mutex_lock(&sys->lock);
>       struct spu_channel *channel = spu_GetChannel(spu, channel_id);
>       spu_channel_Clear(channel);
> +    if (channel->clock)
> +    {
> +        vlc_clock_Reset(channel->clock);
> +        vlc_clock_SetDelay(channel->clock, channel->delay);
> +    }
>       vlc_mutex_unlock(&sys->lock);
>   }
>   


More information about the vlc-devel mailing list