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

Thomas Guillem thomas at gllm.fr
Thu Jun 6 08:28:05 CEST 2019


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);
 }
 
-- 
2.20.1



More information about the vlc-devel mailing list