[vlc-devel] [PATCH 04/10] Add additional SPU clock to synchronize secondary subtitles

Roland Bewick roland.bewick at gmail.com
Sun May 5 12:01:44 CEST 2019


---
 src/input/decoder.c                 | 15 ++++++---
 src/video_output/video_output.c     | 17 ++++++----
 src/video_output/vout_internal.h    | 14 ++++----
 src/video_output/vout_subpictures.c | 50 +++++++++++++++++------------
 4 files changed, 59 insertions(+), 37 deletions(-)

diff --git a/src/input/decoder.c b/src/input/decoder.c
index b5fe1c2ca3..b699e52a67 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -612,7 +612,8 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
         if( p_owner->p_vout )
         {
             vlc_mutex_lock( &p_owner->lock );
-            vout_SetSubpictureClock(p_owner->p_vout, NULL);
+            vout_SetSubpictureClock(p_owner->p_vout, NULL,
+                                    p_owner->b_secondary);
             vout_Release(p_owner->p_vout);
             p_owner->p_vout = NULL;
             vlc_mutex_unlock( &p_owner->lock );
@@ -628,13 +629,15 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
         vlc_mutex_lock( &p_owner->lock );
         if( p_owner->p_vout )
         {
-            vout_SetSubpictureClock(p_owner->p_vout, NULL);
+            vout_SetSubpictureClock(p_owner->p_vout, NULL,
+                                    p_owner->b_secondary);
             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,
+                                 p_owner->b_secondary);
     }
     else
         vout_Release(p_vout);
@@ -1556,7 +1559,8 @@ 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 );
+                vout_ChangeSpuDelay( p_owner->p_vout, delay,
+                                     p_owner->b_secondary );
             break;
         default:
             vlc_assert_unreachable();
@@ -1973,7 +1977,8 @@ static void DeleteDecoder( decoder_t * p_dec )
             {
                 vout_FlushSubpictureChannel( p_owner->p_vout,
                                              p_owner->i_spu_channel );
-                vout_SetSubpictureClock(p_owner->p_vout, NULL);
+                vout_SetSubpictureClock(p_owner->p_vout, NULL,
+                                        p_owner->b_secondary);
                 vout_Release(p_owner->p_vout);
             }
             break;
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index b64c35bdec..23ab21b536 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -272,11 +272,12 @@ int vout_RegisterSubpictureChannel( vout_thread_t *vout )
     return channel;
 }
 
-void vout_SetSubpictureClock( vout_thread_t *vout, vlc_clock_t *clock )
+void vout_SetSubpictureClock( vout_thread_t *vout, vlc_clock_t *clock,
+                              bool b_secondary )
 {
     vlc_mutex_lock(&vout->p->spu_lock);
     if (vout->p->spu)
-        spu_clock_Set(vout->p->spu, clock);
+        spu_clock_Set(vout->p->spu, clock, b_secondary);
     vlc_mutex_unlock(&vout->p->spu_lock);
 }
 
@@ -1278,8 +1279,11 @@ static void vout_FlushUnlocked(vout_thread_t *vout, bool below,
     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);
+        for (int i = 0; i < 2; i++)
+        {
+            spu_clock_Reset(vout->p->spu, i);
+            spu_clock_SetDelay(vout->p->spu, vout->p->spu_delay, i);
+        }
     }
     vlc_mutex_unlock(&vout->p->spu_lock);
 }
@@ -1335,11 +1339,12 @@ 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, vlc_tick_t delay,
+                         bool b_secondary)
 {
     vlc_mutex_lock(&vout->p->spu_lock);
     if (vout->p->spu)
-        spu_clock_SetDelay(vout->p->spu, delay);
+        spu_clock_SetDelay(vout->p->spu, delay, b_secondary);
     vout->p->spu_delay = delay;
     vlc_mutex_unlock(&vout->p->spu_lock);
 }
diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h
index 295c35d61c..43ad5e83b2 100644
--- a/src/video_output/vout_internal.h
+++ b/src/video_output/vout_internal.h
@@ -252,13 +252,14 @@ 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);
+void vout_SetSubpictureClock(vout_thread_t *vout, vlc_clock_t *clock,
+                             bool b_secondary);
 int spu_ProcessMouse(spu_t *, const vlc_mouse_t *, const video_format_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_clock_Set(spu_t *, vlc_clock_t *, bool b_secondary);
+void spu_clock_Reset(spu_t *, bool b_secondary);
+void spu_clock_SetDelay(spu_t *spu, vlc_tick_t delay, bool b_secondary);
 void spu_ChangeMargin(spu_t *, int);
 void spu_SetHighlight(spu_t *, const vlc_spu_highlight_t*);
 
@@ -286,10 +287,11 @@ void vout_ChangeDelay( vout_thread_t *, vlc_tick_t delay );
  */
 void vout_ChangeSpuRate( vout_thread_t *, float rate );
 /**
- * This function will change the delay of the spu channel
+ * This function will change the delay of the primary or secondary spu channel
  * It is thread safe
  */
-void vout_ChangeSpuDelay( vout_thread_t *, vlc_tick_t delay );
+void vout_ChangeSpuDelay( vout_thread_t *, vlc_tick_t delay,
+                          bool b_secondary );
 
 
 /**
diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c
index 742a93cf14..86f7496442 100644
--- a/src/video_output/vout_subpictures.c
+++ b/src/video_output/vout_subpictures.c
@@ -72,7 +72,7 @@ struct spu_private_t {
     vlc_mutex_t  lock;            /* lock to protect all followings fields */
     input_thread_t *input;
 
-    vlc_clock_t *clock;
+    vlc_clock_t *clocks[2];  /* clocks for primary and secondary subtitles */
 
     spu_heap_t   heap;
 
@@ -541,10 +541,14 @@ static int SpuConvertDates(spu_t *spu, vlc_tick_t system_now,
 {
     spu_private_t *sys = spu->p;
 
-    /* Put every spu start and stop ts into the same array to convert them in
-     * one shot */
-    vlc_tick_t date_array[VOUT_MAX_SUBPICTURES *2];
+    /* Put every spu start and stop ts into an array based on which 
+     * clock the spu entry belongs to.
+     * All start and stop times can then be converted together
+     * with a maximum of two calls. */
+    vlc_tick_t date_array[2][VOUT_MAX_SUBPICTURES *2];
     size_t entry_count = 0;
+    bool hasEntry[2] = {false, false};
+
     for (size_t index = 0; index < VOUT_MAX_SUBPICTURES; index++)
     {
         spu_heap_entry_t *entry = &sys->heap.entry[index];
@@ -553,17 +557,21 @@ static int SpuConvertDates(spu_t *spu, vlc_tick_t system_now,
         if (!current)
             continue;
 
-        date_array[entry_count * 2] = current->i_start;
-        date_array[entry_count * 2 + 1] = current->i_stop;
+        hasEntry[current->b_secondary] = true;
+        date_array[current->b_secondary][entry_count * 2] = current->i_start;
+        date_array[current->b_secondary][entry_count * 2 + 1] = current->i_stop;
         entry_count++;
     }
     if (entry_count == 0)
         return 0;
 
     /* Convert all spu ts */
-    if (sys->clock)
-        vlc_clock_ConvertArrayToSystem(sys->clock, system_now, date_array,
-                                       entry_count * 2, rate);
+    for (int i = 0; i < 2; i++)
+    {
+        if (hasEntry[i] && sys->clocks[i])
+            vlc_clock_ConvertArrayToSystem(sys->clocks[i], system_now, date_array[i],
+                                        entry_count * 2, rate);
+    }
 
     /* Put back the converted ts into the output spu_render_entry_t struct */
     entry_count = 0;
@@ -578,8 +586,10 @@ static int SpuConvertDates(spu_t *spu, vlc_tick_t system_now,
         else
         {
             render_entry->subpicture = current;
-            render_entry->start = date_array[entry_count * 2];
-            render_entry->stop = date_array[entry_count * 2 + 1];
+            render_entry->start =
+                date_array[current->b_secondary][entry_count * 2];
+            render_entry->stop =
+                date_array[current->b_secondary][entry_count * 2 + 1];
             entry_count++;
         }
     }
@@ -1397,7 +1407,7 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
 
     SpuHeapInit(&sys->heap);
 
-    sys->clock = NULL;
+    sys->clocks[0] = sys->clocks[1] = NULL;
     sys->text = NULL;
     sys->scale = NULL;
     sys->scale_yuvp = NULL;
@@ -1507,21 +1517,21 @@ 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_clock_Set(spu_t *spu, vlc_clock_t *clock, bool b_secondary)
 {
-    spu->p->clock = clock;
+    spu->p->clocks[b_secondary] = clock;
 }
 
-void spu_clock_Reset(spu_t *spu)
+void spu_clock_Reset(spu_t *spu, bool b_secondary)
 {
-    if (spu->p->clock)
-        vlc_clock_Reset(spu->p->clock);
+    if (spu->p->clocks[b_secondary])
+        vlc_clock_Reset(spu->p->clocks[b_secondary]);
 }
 
-void spu_clock_SetDelay(spu_t *spu, vlc_tick_t delay)
+void spu_clock_SetDelay(spu_t *spu, vlc_tick_t delay, bool b_secondary)
 {
-    if (spu->p->clock)
-        vlc_clock_SetDelay(spu->p->clock, delay);
+    if (spu->p->clocks[b_secondary])
+        vlc_clock_SetDelay(spu->p->clocks[b_secondary], delay);
 }
 
 /**
-- 
2.17.1



More information about the vlc-devel mailing list