[vlc-devel] [PATCH 08/17] es_out: use the input_clock as a master source of vlc_clock

Thomas Guillem thomas at gllm.fr
Mon Feb 15 10:15:03 UTC 2021


There is now always a master clock, the input one or the audio one.

input_clock.c is now feeding PCR points to the vlc_clock (used by
output). This restore the same behavior as VLC 3.O when the input clock
is the main source (--clock-master=1).

When the master ES (only audio for now) is starting, it will synchronize
from the input source and override it. When this source is flushed or
stopped, the input source will take precedence again.

This will allow to simplify pts_delay handling in vlc_clock (cf. next
commits). Indeed, the pts_delay, used by the master ES, and sent via
vlc_clock_main_SetInputDejitter() was calculated only once (from the
first input update). The master ES will now use the last pts_delay
updated when the input buffering ends.

The handling of input discontinuities when an ES is used as a master is
still not handled correctly (this is the topic of an other future patch
set).
---
 src/clock/input_clock.c | 31 ++++++++++++++++++++++++++++++-
 src/clock/input_clock.h |  6 +++++-
 src/input/es_out.c      | 33 +++++++++++++++++++--------------
 3 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/src/clock/input_clock.c b/src/clock/input_clock.c
index f09e0bbb8f2..101039b3f79 100644
--- a/src/clock/input_clock.c
+++ b/src/clock/input_clock.c
@@ -104,6 +104,8 @@
 /* */
 struct input_clock_t
 {
+    vlc_clock_t *clock_listener;
+
     /* Last point
      * It is used to detect unexpected stream discontinuities */
     clock_point_t last;
@@ -142,14 +144,30 @@ static vlc_tick_t ClockSystemToStream( input_clock_t *, vlc_tick_t i_system );
 
 static vlc_tick_t ClockGetTsOffset( input_clock_t * );
 
+static void UpdateListener( input_clock_t *cl )
+{
+    const vlc_tick_t system_expected =
+        ClockStreamToSystem( cl, cl->last.stream + AvgGet( &cl->drift ) ) +
+        cl->i_pts_delay + ClockGetTsOffset( cl );
+
+    vlc_clock_Update( cl->clock_listener, system_expected, cl->last.stream, cl->rate );
+}
+
 /*****************************************************************************
  * input_clock_New: create a new clock
  *****************************************************************************/
-input_clock_t *input_clock_New( float rate )
+input_clock_t *input_clock_New( vlc_clock_t *clock_listener, float rate )
 {
+    assert( clock_listener != NULL );
+
     input_clock_t *cl = malloc( sizeof(*cl) );
     if( !cl )
+    {
+        vlc_clock_Delete( cl->clock_listener );
         return NULL;
+    }
+
+    cl->clock_listener = clock_listener;
 
     cl->b_has_reference = false;
     cl->ref = clock_point_Create( VLC_TICK_INVALID, VLC_TICK_INVALID );
@@ -180,6 +198,7 @@ input_clock_t *input_clock_New( float rate )
 void input_clock_Delete( input_clock_t *cl )
 {
     AvgClean( &cl->drift );
+    vlc_clock_Delete( cl->clock_listener );
     free( cl );
 }
 
@@ -271,6 +290,8 @@ vlc_tick_t input_clock_Update( input_clock_t *cl, vlc_object_t *p_log,
         cl->late.i_index = ( cl->late.i_index + 1 ) % INPUT_CLOCK_LATE_COUNT;
     }
 
+    UpdateListener( cl );
+
     return i_late;
 }
 
@@ -282,6 +303,8 @@ void input_clock_Reset( input_clock_t *cl )
     cl->b_has_reference = false;
     cl->ref = clock_point_Create( VLC_TICK_INVALID, VLC_TICK_INVALID );
     cl->b_has_external_clock = false;
+
+    vlc_clock_Reset( cl->clock_listener );
 }
 
 /*****************************************************************************
@@ -296,6 +319,8 @@ void input_clock_ChangeRate( input_clock_t *cl, float rate )
         cl->ref.system = cl->last.system - (vlc_tick_t) ((cl->last.system - cl->ref.system) / rate * cl->rate);
     }
     cl->rate = rate;
+
+    UpdateListener( cl );
 }
 
 /*****************************************************************************
@@ -313,6 +338,8 @@ void input_clock_ChangePause( input_clock_t *cl, bool b_paused, vlc_tick_t i_dat
         {
             cl->ref.system += i_duration;
             cl->last.system += i_duration;
+
+            UpdateListener( cl );
         }
     }
     cl->i_pause_date = i_date;
@@ -377,6 +404,8 @@ void input_clock_ChangeSystemOrigin( input_clock_t *cl, bool b_absolute, vlc_tic
 
     cl->ref.system += i_offset;
     cl->last.system += i_offset;
+
+    UpdateListener( cl );
 }
 
 void input_clock_GetSystemOrigin( input_clock_t *cl, vlc_tick_t *pi_system, vlc_tick_t *pi_delay )
diff --git a/src/clock/input_clock.h b/src/clock/input_clock.h
index f9a74f08096..094e8b4f54e 100644
--- a/src/clock/input_clock.h
+++ b/src/clock/input_clock.h
@@ -26,6 +26,7 @@
 
 #include <vlc_common.h>
 #include <vlc_input.h> /* FIXME Needed for input_clock_t */
+#include "clock.h"
 
 /** @struct input_clock_t
  * This structure is used to manage clock drift and reception jitters
@@ -36,9 +37,12 @@ typedef struct input_clock_t input_clock_t;
 
 /**
  * This function creates a new input_clock_t.
+ *
+ * \param clock_listener clock created with vlc_clock_main_CreateInput(), the
+ * input_clock_t will take ownership of this clock.
  * You must use input_clock_Delete to delete it once unused.
  */
-input_clock_t *input_clock_New( float rate );
+input_clock_t *input_clock_New( vlc_clock_t *clock_listener, float rate );
 
 /**
  * This function destroys a input_clock_t created by input_clock_New.
diff --git a/src/input/es_out.c b/src/input/es_out.c
index b3b35621052..0d95e0f8c8a 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -918,7 +918,6 @@ static void EsOutChangePosition( es_out_t *out, bool b_flush )
     vlc_list_foreach(pgrm, &p_sys->programs, node)
     {
         input_clock_Reset(pgrm->p_input_clock);
-        vlc_clock_main_Reset(pgrm->p_main_clock);
         pgrm->i_last_pcr = VLC_TICK_INVALID;
     }
 
@@ -1017,11 +1016,6 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
 
     const vlc_tick_t update = i_current_date + i_wakeup_delay - i_buffering_duration;
 
-    /* Send the first PCR to the output clock. This will be used as a reference
-     * point for the sync point. */
-    vlc_clock_main_SetFirstPcr(p_sys->p_pgrm->p_main_clock, update,
-                               i_stream_start);
-
     input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_input_clock, true, update );
 
     foreach_es_then_es_slaves(p_es)
@@ -1382,21 +1376,35 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, input_source_t *source, in
     p_pgrm->p_meta = NULL;
 
     p_pgrm->p_master_clock = NULL;
-    p_pgrm->p_input_clock = input_clock_New( p_sys->rate );
     p_pgrm->p_main_clock = vlc_clock_main_New();
-    if( !p_pgrm->p_input_clock || !p_pgrm->p_main_clock )
+    if( p_pgrm->p_main_clock == NULL )
+    {
+        free( p_pgrm );
+        return NULL;
+    }
+
+    vlc_clock_t *clock_listener =
+        vlc_clock_main_CreateInput( p_pgrm->p_main_clock, NULL, NULL );
+    if( clock_listener == NULL )
+    {
+        vlc_clock_main_Delete( p_pgrm->p_main_clock );
+        free( p_pgrm );
+        return NULL;
+    }
+
+    p_pgrm->p_input_clock = input_clock_New( clock_listener, p_sys->rate );
+    if( p_pgrm->p_input_clock == NULL )
     {
-        if( p_pgrm->p_input_clock )
-            input_clock_Delete( p_pgrm->p_input_clock );
+        vlc_clock_main_Delete( p_pgrm->p_main_clock );
         free( p_pgrm );
         return NULL;
     }
+
     if( p_sys->b_paused )
         input_clock_ChangePause( p_pgrm->p_input_clock, p_sys->b_paused, p_sys->i_pause_date );
     const vlc_tick_t pts_delay = p_sys->i_pts_delay + p_sys->i_pts_jitter
                                + p_sys->i_tracks_pts_delay;
     input_clock_SetJitter( p_pgrm->p_input_clock, pts_delay, p_sys->i_cr_average );
-    vlc_clock_main_SetInputDejitter( p_pgrm->p_main_clock, pts_delay );
 
     /* In case of low delay: don't use any output dejitter. This may result on
      * some audio/video glitches when starting, but low-delay is more important
@@ -3742,11 +3750,8 @@ static int EsOutVaPrivControlLocked( es_out_t *out, int query, va_list args )
             i_pts_delay += i_pts_jitter + i_tracks_pts_delay;
 
             vlc_list_foreach(pgrm, &p_sys->programs, node)
-            {
                 input_clock_SetJitter(pgrm->p_input_clock, i_pts_delay,
                                       i_cr_average);
-                vlc_clock_main_SetInputDejitter(pgrm->p_main_clock, i_pts_delay);
-            }
         }
         return VLC_SUCCESS;
     }
-- 
2.30.0



More information about the vlc-devel mailing list