[vlc-commits] [Git][videolan/vlc][master] 5 commits: clock: add vlc_clock_main_CreateInputMaster()

Thomas Guillem gitlab at videolan.org
Tue May 4 08:27:37 UTC 2021



Thomas Guillem pushed to branch master at VideoLAN / VLC


Commits:
910e98c2 by Thomas Guillem at 2021-05-04T07:39:35+00:00
clock: add vlc_clock_main_CreateInputMaster()

The input master clock has a higher priority than the ES master clock.
There can be one input master and one es master at a given time. In that
case, the ES master will behave as a slave clock.

This will allow to be more flexible from the es_out.c when creating
input and ES clocks.

- - - - -
537c5039 by Thomas Guillem at 2021-05-04T07:39:35+00:00
es_out: use vlc_clock_main_CreateInputMaster

No functional changes for now since only one master is created from
es_out.c (for now).

- - - - -
dfd4929f by Thomas Guillem at 2021-05-04T07:39:35+00:00
input_clock: change clock listener attachment

Allow to attach the clock listener after the input clock is created.

- - - - -
04685396 by Thomas Guillem at 2021-05-04T07:39:35+00:00
es_out: move input clock attachment in a new function

No functional changes.

- - - - -
800482fb by Thomas Guillem at 2021-05-04T07:39:35+00:00
es_out: fix VLC_CLOCK_MASTER_AUTO detection

The clock source selection depends on priv->b_can_pace_control but this
variable is only initialized from the input_thread_t after the demux is
opened. Programs and ES tracks can be created from the demux open
callback or midstream (from the demux callback). Therefore, we can't
handle the clock source selection after the program is created since
priv->b_can_pace_control might not be initialized. To fix this issue,
handle clock source selection when the first PCR is sent (from
ES_OUT_SET_PCR).

- - - - -


5 changed files:

- src/clock/clock.c
- src/clock/clock.h
- src/clock/input_clock.c
- src/clock/input_clock.h
- src/input/es_out.c


Changes:

=====================================
src/clock/clock.c
=====================================
@@ -34,6 +34,7 @@ struct vlc_clock_main_t
     vlc_cond_t cond;
 
     vlc_clock_t *master;
+    vlc_clock_t *input_master;
 
     unsigned rc;
 
@@ -367,7 +368,7 @@ vlc_clock_main_t *vlc_clock_main_New(void)
 
     vlc_mutex_init(&main_clock->lock);
     vlc_cond_init(&main_clock->cond);
-    main_clock->master = NULL;
+    main_clock->input_master = main_clock->master = NULL;
     main_clock->rc = 1;
 
     main_clock->coeff = 1.0f;
@@ -567,7 +568,11 @@ vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
     vlc_mutex_lock(&main_clock->lock);
     assert(main_clock->master == NULL);
 
-    vlc_clock_set_master_callbacks(clock);
+    if (main_clock->input_master == NULL)
+        vlc_clock_set_master_callbacks(clock);
+    else
+        vlc_clock_set_slave_callbacks(clock);
+
     main_clock->master = clock;
     main_clock->rc++;
     vlc_mutex_unlock(&main_clock->lock);
@@ -575,6 +580,32 @@ vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
     return clock;
 }
 
+vlc_clock_t *vlc_clock_main_CreateInputMaster(vlc_clock_main_t *main_clock)
+{
+    /* The master has always the 0 priority */
+    vlc_clock_t *clock = vlc_clock_main_Create(main_clock, 0, NULL, NULL);
+    if (!clock)
+        return NULL;
+
+    vlc_mutex_lock(&main_clock->lock);
+    assert(main_clock->input_master == NULL);
+
+    /* Even if the master ES clock has already been created, it should not
+     * have updated any points */
+    assert(main_clock->offset == VLC_TICK_INVALID);
+
+    /* Override the master ES clock if it exists */
+    if (main_clock->master != NULL)
+        vlc_clock_set_slave_callbacks(main_clock->master);
+
+    vlc_clock_set_master_callbacks(clock);
+    main_clock->input_master = clock;
+    main_clock->rc++;
+    vlc_mutex_unlock(&main_clock->lock);
+
+    return clock;
+}
+
 vlc_clock_t *vlc_clock_main_CreateSlave(vlc_clock_main_t *main_clock,
                                         enum es_format_category_e cat,
                                         const struct vlc_clock_cbs *cbs,
@@ -620,9 +651,17 @@ void vlc_clock_Delete(vlc_clock_t *clock)
 {
     vlc_clock_main_t *main_clock = clock->owner;
     vlc_mutex_lock(&main_clock->lock);
-    if (clock == main_clock->master)
+    if (clock == main_clock->input_master)
+    {
+        /* The input master must be the last clock to be deleted */
+        assert(main_clock->rc == 2);
+    }
+    else if (clock == main_clock->master)
     {
-        vlc_clock_main_reset(main_clock);
+        /* Don't reset the main clock if the master has been overridden by the
+         * input master */
+        if (main_clock->input_master != NULL)
+            vlc_clock_main_reset(main_clock);
         main_clock->master = NULL;
     }
     main_clock->rc--;


=====================================
src/clock/clock.h
=====================================
@@ -105,6 +105,18 @@ vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
                                          const struct vlc_clock_cbs *cbs,
                                          void *cbs_data);
 
+/**
+ * This function creates a new input master vlc_clock_t interface
+ *
+ * Once the input master is created, the current or future master clock created
+ * from vlc_clock_main_CreateMaster() will be demoted as slave.
+ *
+ * @warning There can be only one input master at a given time.
+ *
+ * You must use vlc_clock_Delete to free it.
+ */
+vlc_clock_t *vlc_clock_main_CreateInputMaster(vlc_clock_main_t *main_clock);
+
 /**
  * This function creates a new slave vlc_clock_t interface
  *


=====================================
src/clock/input_clock.c
=====================================
@@ -159,17 +159,12 @@ static void UpdateListener( input_clock_t *cl )
 /*****************************************************************************
  * input_clock_New: create a new clock
  *****************************************************************************/
-input_clock_t *input_clock_New( vlc_clock_t *clock_listener, float rate )
+input_clock_t *input_clock_New( float rate )
 {
     input_clock_t *cl = malloc( sizeof(*cl) );
     if( !cl )
-    {
-        if( cl->clock_listener )
-            vlc_clock_Delete( cl->clock_listener );
         return NULL;
-    }
-
-    cl->clock_listener = clock_listener;
+    cl->clock_listener = NULL;
 
     cl->b_has_reference = false;
     cl->ref = clock_point_Create( VLC_TICK_INVALID, VLC_TICK_INVALID );
@@ -205,6 +200,14 @@ void input_clock_Delete( input_clock_t *cl )
     free( cl );
 }
 
+void input_clock_AttachListener( input_clock_t *cl, vlc_clock_t *clock_listener )
+{
+    assert( clock_listener && cl->clock_listener == NULL );
+    assert( !cl->b_has_reference );
+
+    cl->clock_listener = clock_listener;
+}
+
 /*****************************************************************************
  * input_clock_Update: manages a clock reference
  *


=====================================
src/clock/input_clock.h
=====================================
@@ -38,12 +38,21 @@ 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_CreateMaster(). If
- * valid, the input_clock_t will take ownership of this clock and drive the
- * main clock.
  * You must use input_clock_Delete to delete it once unused.
  */
-input_clock_t *input_clock_New( vlc_clock_t *clock_listener, float rate );
+input_clock_t *input_clock_New( float rate );
+
+/**
+ * This function attach a clock listener to the input clock
+ *
+ * It can be called only one time, with a valid clock, before the first update
+ * (input_clock_Update()).
+ *
+ * \param clock_listener clock created with vlc_clock_main_CreateInputMaster().
+ * The input_clock_t will take ownership of this clock and drive the main
+ * clock.
+ */
+void input_clock_AttachListener( input_clock_t *, vlc_clock_t *clock_listener );
 
 /**
  * This function destroys a input_clock_t created by input_clock_New.


=====================================
src/input/es_out.c
=====================================
@@ -77,7 +77,7 @@ typedef struct
     /* Clock for this program */
     input_clock_t    *p_input_clock;
     vlc_clock_main_t *p_main_clock;
-    const vlc_clock_t *p_master_clock;
+    enum vlc_clock_master_source active_clock_source;
 
     vlc_tick_t i_last_pcr;
 
@@ -1274,6 +1274,49 @@ static void EsOutSendEsEvent(es_out_t *out, es_out_id_t *es, int action,
     });
 }
 
+static void EsOutProgramHandleClockSource( es_out_t *out, es_out_pgrm_t *p_pgrm )
+{
+    es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
+    input_thread_t *p_input = p_sys->p_input;
+    input_thread_private_t *priv = input_priv(p_input);
+
+    /* XXX: The clock source selection depends on priv->b_can_pace_control but
+     * this variable is only initialized from the input_thread_t after the
+     * demux is opened. Programs and ES tracks can be created from the demux
+     * open callback or midstream (from the demux callback). Therefore, we
+     * can't handle the clock source selection after the program is created
+     * since priv->b_can_pace_control might not be initialized. To fix this
+     * issue, handle clock source selection when the first PCR is sent (from
+     * ES_OUT_SET_PCR). */
+    assert( p_sys->b_active );
+
+    switch( p_sys->clock_source )
+    {
+        case VLC_CLOCK_MASTER_AUTO:
+            if (priv->b_can_pace_control)
+            {
+                p_pgrm->active_clock_source = VLC_CLOCK_MASTER_AUDIO;
+                break;
+            }
+            msg_Dbg( p_input, "The input can't pace, selecting the input (PCR) as the "
+                     "clock source" );
+            /* Fall-through */
+        case VLC_CLOCK_MASTER_INPUT:
+        {
+            vlc_clock_t *p_master_clock =
+                vlc_clock_main_CreateInputMaster( p_pgrm->p_main_clock );
+
+            if( p_master_clock != NULL )
+                input_clock_AttachListener( p_pgrm->p_input_clock, p_master_clock );
+            p_pgrm->active_clock_source = VLC_CLOCK_MASTER_INPUT;
+            break;
+        }
+        default:
+            p_pgrm->active_clock_source = p_sys->clock_source;
+            break;
+    }
+}
+
 /* EsOutIsGroupSticky
  *
  * A sticky group can be attached to any other programs. This is the case for
@@ -1393,7 +1436,6 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, input_source_t *source, in
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     input_thread_t    *p_input = p_sys->p_input;
-    input_thread_private_t *priv = input_priv(p_input);
 
     /* Sticky groups will be attached to any existing programs, no need to
      * create one. */
@@ -1412,8 +1454,7 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, input_source_t *source, in
     p_pgrm->b_scrambled = false;
     p_pgrm->i_last_pcr = VLC_TICK_INVALID;
     p_pgrm->p_meta = NULL;
-
-    p_pgrm->p_master_clock = NULL;
+    p_pgrm->active_clock_source = VLC_CLOCK_MASTER_AUTO;
 
     p_pgrm->p_main_clock = vlc_clock_main_New();
     if( !p_pgrm->p_main_clock )
@@ -1422,24 +1463,7 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, input_source_t *source, in
         return NULL;
     }
 
-    vlc_clock_t *p_master_clock = NULL;
-    switch( p_sys->clock_source )
-    {
-        case VLC_CLOCK_MASTER_AUTO:
-            if (priv->b_can_pace_control)
-                break;
-            msg_Dbg( p_input, "The input can't pace, selecting the input (PCR) as the "
-                     "clock source" );
-            /* Fall-through */
-        case VLC_CLOCK_MASTER_INPUT:
-            p_pgrm->p_master_clock = p_master_clock =
-                vlc_clock_main_CreateMaster( p_pgrm->p_main_clock, NULL, NULL );
-            break;
-        default:
-            break;
-    }
-
-    p_pgrm->p_input_clock = input_clock_New( p_master_clock, p_sys->rate );
+    p_pgrm->p_input_clock = input_clock_New( p_sys->rate );
     if( !p_pgrm->p_input_clock )
     {
         vlc_clock_main_Delete( p_pgrm->p_main_clock );
@@ -2236,11 +2260,10 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es )
     }
 
     if( p_es->fmt.i_cat != UNKNOWN_ES
-     && p_es->fmt.i_cat == clock_source_cat
-     && p_es->p_pgrm->p_master_clock == NULL )
+     && p_es->fmt.i_cat == clock_source_cat )
     {
         p_es->master = true;
-        p_es->p_pgrm->p_master_clock = p_es->p_clock =
+        p_es->p_clock =
             vlc_clock_main_CreateMaster( p_es->p_pgrm->p_main_clock,
                                          &clock_cbs, p_es );
     }
@@ -2303,8 +2326,6 @@ static void EsOutDestroyDecoder( es_out_t *out, es_out_id_t *p_es )
 
     vlc_input_decoder_Delete( p_es->p_dec );
     p_es->p_dec = NULL;
-    if( p_es->p_pgrm->p_master_clock == p_es->p_clock )
-        p_es->p_pgrm->p_master_clock = NULL;
     vlc_clock_Delete( p_es->p_clock );
     p_es->p_clock = NULL;
 
@@ -3257,6 +3278,12 @@ static int EsOutVaControlLocked( es_out_t *out, input_source_t *source,
         if( !p_pgrm )
             return VLC_EGENERIC;
 
+        if( p_pgrm->active_clock_source == VLC_CLOCK_MASTER_AUTO )
+        {
+            EsOutProgramHandleClockSource( out, p_pgrm );
+            assert( p_pgrm->active_clock_source != VLC_CLOCK_MASTER_AUTO );
+        }
+
         i_pcr = va_arg( args, vlc_tick_t );
         if( i_pcr == VLC_TICK_INVALID )
         {



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/68b27c23fd6f87577d2f1c49821008fc5b86f75d...800482fbd2a1d3169a920f7b883590a6ff23949a

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/68b27c23fd6f87577d2f1c49821008fc5b86f75d...800482fbd2a1d3169a920f7b883590a6ff23949a
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list