[vlc-devel] [PATCH 14/18] core: switch to the new output clock

Thomas Guillem thomas at gllm.fr
Thu Mar 7 15:25:36 CET 2019


Co-authored-by: Denis Charmet <typx at videolan.org>
Co-authored-by: RĂ©mi Denis-Courmont <remi at remlab.net>
---
 src/input/decoder.c | 219 ++++++++++++++++++--------------------------
 src/input/decoder.h |   2 +-
 src/input/es_out.c  |  69 +++++++++++---
 3 files changed, 146 insertions(+), 144 deletions(-)

diff --git a/src/input/decoder.c b/src/input/decoder.c
index a3b55d85fe..cf7fd43995 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * decoder.c: Functions for the management of decoders
  *****************************************************************************
- * Copyright (C) 1999-2004 VLC authors and VideoLAN
+ * Copyright (C) 1999-2019 VLC authors, VideoLAN and Videolabs SAS
  *
  * Authors: Christophe Massiot <massiot at via.ecp.fr>
  *          Gildas Bazin <gbazin at videolan.org>
@@ -45,7 +45,7 @@
 #include "audio_output/aout_internal.h"
 #include "stream_output/stream_output.h"
 #include "input_internal.h"
-#include "../clock/input_clock.h"
+#include "../clock/clock.h"
 #include "decoder.h"
 #include "event.h"
 #include "resource.h"
@@ -67,8 +67,7 @@ struct decoder_owner
     decoder_t        dec;
     input_thread_t  *p_input;
     input_resource_t*p_resource;
-    input_clock_t   *p_clock;
-    float            last_rate;
+    vlc_clock_t     *p_clock;
 
     int              i_spu_channel;
     int64_t          i_spu_order;
@@ -100,7 +99,6 @@ struct decoder_owner
     vlc_cond_t  wait_request;
     vlc_cond_t  wait_acknowledge;
     vlc_cond_t  wait_fifo; /* TODO: merge with wait_acknowledge */
-    vlc_cond_t  wait_timed;
 
     /* -- These variables need locking on write(only) -- */
     audio_output_t *p_aout;
@@ -113,7 +111,8 @@ struct decoder_owner
     /* Pause & Rate */
     bool reset_out_state;
     vlc_tick_t pause_date;
-    float rate;
+    vlc_tick_t delay;
+    float request_rate, output_rate;
     unsigned frames_countdown;
     bool paused;
 
@@ -141,9 +140,6 @@ struct decoder_owner
         sout_packetizer_input_t *p_sout_input;
     } cc;
 
-    /* Delay */
-    vlc_tick_t i_ts_delay;
-
     /* Mouse event */
     vlc_mutex_t     mouse_lock;
     vlc_mouse_event mouse_event;
@@ -345,7 +341,7 @@ static int aout_update_format( decoder_t *p_dec )
             if( p_dec->fmt_out.i_codec == VLC_CODEC_DTS )
                 var_SetBool( p_aout, "dtshd", p_dec->fmt_out.i_profile > 0 );
 
-            if( aout_DecNew( p_aout, &format, NULL,
+            if( aout_DecNew( p_aout, &format, p_owner->p_clock,
                              &p_dec->fmt_out.audio_replay_gain ) )
             {
                 input_resource_PutAout( p_owner->p_resource, p_aout );
@@ -540,7 +536,7 @@ static int vout_update_format( decoder_t *p_dec )
         }
         p_vout = input_resource_GetVout( p_owner->p_resource,
             &(vout_configuration_t) {
-                .vout = p_vout, .fmt = &fmt,
+                .vout = p_vout, .clock = p_owner->p_clock, .fmt = &fmt,
                 .dpb_size = dpb_size + p_dec->i_extra_picture_buffers + 1,
                 .mouse_event = MouseEvent, .mouse_opaque = p_dec
             } );
@@ -607,6 +603,7 @@ 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_Release(p_owner->p_vout);
             p_owner->p_vout = NULL;
             vlc_mutex_unlock( &p_owner->lock );
@@ -621,9 +618,14 @@ 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_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
         vout_Release(p_vout);
@@ -656,24 +658,21 @@ static int DecoderGetInputAttachments( decoder_t *p_dec,
     return VLC_SUCCESS;
 }
 
-static vlc_tick_t DecoderGetDisplayDate( decoder_t *p_dec, vlc_tick_t i_ts )
+static vlc_tick_t DecoderGetDisplayDate( decoder_t *p_dec, vlc_tick_t system_now,
+                                      vlc_tick_t i_ts )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
 
     vlc_mutex_lock( &p_owner->lock );
     if( p_owner->b_waiting || p_owner->paused )
         i_ts = VLC_TICK_INVALID;
+    float rate = p_owner->output_rate;
     vlc_mutex_unlock( &p_owner->lock );
 
     if( !p_owner->p_clock || i_ts == VLC_TICK_INVALID )
         return i_ts;
 
-    if( input_clock_ConvertTS( VLC_OBJECT(p_dec), p_owner->p_clock, NULL, &i_ts, NULL, INT64_MAX ) ) {
-        msg_Err(p_dec, "Could not get display date for timestamp %"PRId64"", i_ts);
-        return VLC_TICK_INVALID;
-    }
-
-    return i_ts;
+    return vlc_clock_ConvertToSystem( p_owner->p_clock, system_now, i_ts, rate );
 }
 
 static float DecoderGetDisplayRate( decoder_t *p_dec )
@@ -682,7 +681,10 @@ static float DecoderGetDisplayRate( decoder_t *p_dec )
 
     if( !p_owner->p_clock )
         return 1.f;
-    return input_clock_GetRate( p_owner->p_clock );
+    vlc_mutex_lock( &p_owner->lock );
+    float rate = p_owner->output_rate;
+    vlc_mutex_unlock( &p_owner->lock );
+    return rate;
 }
 
 /*****************************************************************************
@@ -736,24 +738,6 @@ static void DecoderWaitUnblock( decoder_t *p_dec )
     }
 }
 
-/* DecoderTimedWait: Interruptible wait
- * Returns VLC_SUCCESS if wait was not interrupted, and VLC_EGENERIC otherwise */
-static int DecoderTimedWait( decoder_t *p_dec, vlc_tick_t deadline )
-{
-    struct decoder_owner *p_owner = dec_get_owner( p_dec );
-
-    if (deadline <= vlc_tick_now())
-        return VLC_SUCCESS;
-
-    vlc_fifo_Lock( p_owner->p_fifo );
-    while( !p_owner->flushing
-        && vlc_fifo_TimedWaitCond( p_owner->p_fifo, &p_owner->wait_timed,
-                                   deadline ) == 0 );
-    int ret = p_owner->flushing ? VLC_EGENERIC : VLC_SUCCESS;
-    vlc_fifo_Unlock( p_owner->p_fifo );
-    return ret;
-}
-
 static inline void DecoderUpdatePreroll( vlc_tick_t *pi_preroll, const block_t *p )
 {
     if( p->i_flags & BLOCK_FLAG_PREROLL )
@@ -768,55 +752,6 @@ static inline void DecoderUpdatePreroll( vlc_tick_t *pi_preroll, const block_t *
         *pi_preroll = __MIN( *pi_preroll, p->i_pts );
 }
 
-static void DecoderFixTs( decoder_t *p_dec, vlc_tick_t *pi_ts0, vlc_tick_t *pi_ts1,
-                          vlc_tick_t *pi_duration, float *p_rate, vlc_tick_t i_ts_bound )
-{
-    struct decoder_owner *p_owner = dec_get_owner( p_dec );
-    input_clock_t   *p_clock = p_owner->p_clock;
-
-    vlc_mutex_assert( &p_owner->lock );
-
-    const vlc_tick_t i_es_delay = p_owner->i_ts_delay;
-
-    if( !p_clock )
-        return;
-
-    const bool b_ephemere = pi_ts1 && *pi_ts0 == *pi_ts1;
-    float rate = 1.f;
-
-    if( *pi_ts0 != VLC_TICK_INVALID )
-    {
-        *pi_ts0 += i_es_delay;
-        if( pi_ts1 && *pi_ts1 != VLC_TICK_INVALID )
-            *pi_ts1 += i_es_delay;
-        if( i_ts_bound != INT64_MAX )
-            i_ts_bound += i_es_delay;
-        if( input_clock_ConvertTS( VLC_OBJECT(p_dec), p_clock, &rate, pi_ts0, pi_ts1, i_ts_bound ) ) {
-            const char *psz_name = module_get_name( p_dec->p_module, false );
-            if( pi_ts1 != NULL )
-                msg_Err(p_dec, "Could not convert timestamps %"PRId64
-                        ", %"PRId64" for %s", *pi_ts0, *pi_ts1, psz_name );
-            else
-                msg_Err(p_dec, "Could not convert timestamp %"PRId64" for %s", *pi_ts0, psz_name );
-            *pi_ts0 = VLC_TICK_INVALID;
-        }
-    }
-    else
-    {
-        rate = input_clock_GetRate( p_clock );
-    }
-
-    /* Do not create ephemere data because of rounding errors */
-    if( !b_ephemere && pi_ts1 && *pi_ts1 != VLC_TICK_INVALID && *pi_ts0 == *pi_ts1 )
-        *pi_ts1 += 1;
-
-    if( pi_duration )
-        *pi_duration = ( *pi_duration / rate ) + 0.999f;
-
-    if( p_rate )
-        *p_rate = rate;
-}
-
 #ifdef ENABLE_SOUT
 static int DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
 {
@@ -834,8 +769,6 @@ static int DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
     }
 
     DecoderWaitUnblock( p_dec );
-    DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts,
-                  &p_sout_block->i_length, NULL, INT64_MAX );
 
     vlc_mutex_unlock( &p_owner->lock );
 
@@ -1068,9 +1001,6 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
     }
 
     const bool b_dated = p_picture->date != VLC_TICK_INVALID;
-    float rate = 1.f;
-    DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
-                  &rate, DECODER_BOGUS_VIDEO_DELAY );
 
     vlc_mutex_unlock( &p_owner->lock );
 
@@ -1088,13 +1018,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
     if( p_picture->b_force || p_picture->date != VLC_TICK_INVALID )
         /* FIXME: VLC_TICK_INVALID -- verify video_output */
     {
-        if( rate != p_owner->last_rate || b_first_after_wait )
-        {
-            /* Be sure to not display old picture after our own */
-            vout_Flush( p_vout, p_picture->date );
-            p_owner->last_rate = rate;
-        }
-        else if( p_picture->b_still )
+        if( p_picture->b_still )
         {
             /* Ensure no earlier higher pts breaks still state */
             vout_Flush( p_vout, p_picture->date );
@@ -1235,19 +1159,12 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
     }
 
     /* */
-    float rate = 1.f;
-
     DecoderWaitUnblock( p_dec );
-    DecoderFixTs( p_dec, &p_audio->i_pts, NULL, &p_audio->i_length,
-                  &rate, AOUT_MAX_ADVANCE_TIME );
     vlc_mutex_unlock( &p_owner->lock );
 
     audio_output_t *p_aout = p_owner->p_aout;
 
-    if( p_aout != NULL && p_audio->i_pts != VLC_TICK_INVALID
-     && rate >= 1 / (float) AOUT_MAX_INPUT_RATE
-     && rate <= AOUT_MAX_INPUT_RATE
-     && !DecoderTimedWait( p_dec, p_audio->i_pts - AOUT_MAX_PREPARE_TIME ) )
+    if( p_aout != NULL && p_audio->i_pts != VLC_TICK_INVALID )
     {
         int status = aout_DecPlay( p_aout, p_audio );
         if( status == AOUT_DEC_CHANGED )
@@ -1336,12 +1253,9 @@ static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic )
     }
 
     DecoderWaitUnblock( p_dec );
-    DecoderFixTs( p_dec, &p_subpic->i_start, &p_subpic->i_stop, NULL,
-                  NULL, INT64_MAX );
     vlc_mutex_unlock( &p_owner->lock );
 
-    if( p_subpic->i_start == VLC_TICK_INVALID
-     || DecoderTimedWait( p_dec, p_subpic->i_start - SPU_MAX_PREPARE_TIME ) )
+    if( p_subpic->i_start == VLC_TICK_INVALID )
     {
         subpicture_Delete( p_subpic );
         return;
@@ -1598,12 +1512,42 @@ static void OutputChangeRate( decoder_t *p_dec, float rate )
     switch( p_dec->fmt_out.i_cat )
     {
         case VIDEO_ES:
+            if( p_owner->p_vout != NULL )
+                vout_ChangeRate( p_owner->p_vout, rate );
             break;
         case AUDIO_ES:
             if( p_owner->p_aout != NULL )
                 aout_DecChangeRate( p_owner->p_aout, rate );
             break;
         case SPU_ES:
+            if( p_owner->p_vout != NULL )
+                vout_ChangeSpuRate( p_owner->p_vout, rate );
+            break;
+        default:
+            vlc_assert_unreachable();
+    }
+    p_owner->output_rate = rate;
+}
+
+static void OutputChangeDelay( decoder_t *p_dec, vlc_tick_t delay )
+{
+    struct decoder_owner *p_owner = dec_get_owner( p_dec );
+
+    msg_Dbg( p_dec, "changing delay: %"PRId64, delay );
+
+    switch( p_dec->fmt_out.i_cat )
+    {
+        case VIDEO_ES:
+            if( p_owner->p_vout != NULL )
+                vout_ChangeDelay( p_owner->p_vout, delay );
+            break;
+        case AUDIO_ES:
+            if( p_owner->p_aout != NULL )
+                aout_DecChangeDelay( p_owner->p_aout, delay );
+            break;
+        case SPU_ES:
+            if( p_owner->p_vout != NULL )
+                vout_ChangeSpuDelay( p_owner->p_vout, delay );
             break;
         default:
             vlc_assert_unreachable();
@@ -1620,6 +1564,7 @@ static void *DecoderThread( void *p_data )
     decoder_t *p_dec = (decoder_t *)p_data;
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
     float rate = 1.f;
+    vlc_tick_t delay = 0;
     bool paused = false;
 
     /* The decoder's main loop */
@@ -1656,6 +1601,7 @@ static void *DecoderThread( void *p_data )
         {
             rate = 1.f;
             paused = false;
+            delay = 0;
             p_owner->reset_out_state = false;
         }
 
@@ -1676,11 +1622,11 @@ static void *DecoderThread( void *p_data )
             continue;
         }
 
-        if( rate != p_owner->rate )
+        if( rate != p_owner->request_rate )
         {
             int canc = vlc_savecancel();
 
-            rate = p_owner->rate;
+            rate = p_owner->request_rate;
             vlc_fifo_Unlock( p_owner->p_fifo );
 
             vlc_mutex_lock( &p_owner->lock );
@@ -1691,6 +1637,21 @@ static void *DecoderThread( void *p_data )
             vlc_fifo_Lock( p_owner->p_fifo );
         }
 
+        if( delay != p_owner->delay )
+        {
+            int canc = vlc_savecancel();
+
+            delay = p_owner->delay;
+            vlc_fifo_Unlock( p_owner->p_fifo );
+
+            vlc_mutex_lock( &p_owner->lock );
+            OutputChangeDelay( p_dec, delay );
+            vlc_mutex_unlock( &p_owner->lock );
+
+            vlc_restorecancel( canc );
+            vlc_fifo_Lock( p_owner->p_fifo );
+        }
+
         if( p_owner->paused && p_owner->frames_countdown == 0 )
         {   /* Wait for resumption from pause */
             p_owner->b_idle = true;
@@ -1794,7 +1755,7 @@ static const struct decoder_owner_callbacks dec_spu_cbs =
  */
 static decoder_t * CreateDecoder( vlc_object_t *p_parent,
                                   input_thread_t *p_input,
-                                  const es_format_t *fmt,
+                                  const es_format_t *fmt, vlc_clock_t *p_clock,
                                   input_resource_t *p_resource,
                                   sout_instance_t *p_sout )
 {
@@ -1806,8 +1767,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
         return NULL;
     p_dec = &p_owner->dec;
 
+    p_owner->p_clock = p_clock;
     p_owner->i_preroll_end = (vlc_tick_t)INT64_MIN;
-    p_owner->last_rate = 1.f;
     p_owner->p_input = p_input;
     p_owner->p_resource = p_resource;
     p_owner->p_aout = NULL;
@@ -1822,7 +1783,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     p_owner->p_description = NULL;
 
     p_owner->reset_out_state = false;
-    p_owner->rate = 1.f;
+    p_owner->delay = 0;
+    p_owner->output_rate = p_owner->request_rate = 1.f;
     p_owner->paused = false;
     p_owner->pause_date = VLC_TICK_INVALID;
     p_owner->frames_countdown = 0;
@@ -1857,7 +1819,6 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     vlc_cond_init( &p_owner->wait_request );
     vlc_cond_init( &p_owner->wait_acknowledge );
     vlc_cond_init( &p_owner->wait_fifo );
-    vlc_cond_init( &p_owner->wait_timed );
 
     /* Load a packetizer module if the input is not already packetized */
     if( p_sout == NULL && !fmt->b_packetized )
@@ -1934,7 +1895,6 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
         p_owner->cc.pp_decoder[i] = NULL;
     p_owner->cc.p_sout_input = NULL;
     p_owner->cc.b_sout_created = false;
-    p_owner->i_ts_delay = 0;
     return p_dec;
 }
 
@@ -1994,6 +1954,7 @@ 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_Release(p_owner->p_vout);
             }
             break;
@@ -2012,7 +1973,6 @@ static void DeleteDecoder( decoder_t * p_dec )
 
     decoder_Destroy( p_owner->p_packetizer );
 
-    vlc_cond_destroy( &p_owner->wait_timed );
     vlc_cond_destroy( &p_owner->wait_fifo );
     vlc_cond_destroy( &p_owner->wait_acknowledge );
     vlc_cond_destroy( &p_owner->wait_request );
@@ -2042,7 +2002,7 @@ static void DecoderUnsupportedCodec( decoder_t *p_dec, const es_format_t *fmt, b
 
 /* TODO: pass p_sout through p_resource? -- Courmisch */
 static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
-                               const es_format_t *fmt, input_clock_t *p_clock,
+                               const es_format_t *fmt, vlc_clock_t *p_clock,
                                input_resource_t *p_resource,
                                sout_instance_t *p_sout  )
 {
@@ -2051,7 +2011,7 @@ static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
     int i_priority;
 
     /* Create the decoder configuration structure */
-    p_dec = CreateDecoder( p_parent, p_input, fmt, p_resource, p_sout );
+    p_dec = CreateDecoder( p_parent, p_input, fmt, p_clock, p_resource, p_sout );
     if( p_dec == NULL )
     {
         msg_Err( p_parent, "could not create %s", psz_type );
@@ -2069,7 +2029,6 @@ static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
     }
 
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
-    p_owner->p_clock = p_clock;
     assert( p_dec->fmt_in.i_cat != UNKNOWN_ES );
 
     if( p_dec->fmt_in.i_cat == AUDIO_ES )
@@ -2112,7 +2071,7 @@ static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
  * \return the spawned decoder object
  */
 decoder_t *input_DecoderNew( input_thread_t *p_input,
-                             es_format_t *fmt, input_clock_t *p_clock,
+                             es_format_t *fmt, vlc_clock_t *p_clock,
                              sout_instance_t *p_sout  )
 {
     return decoder_New( VLC_OBJECT(p_input), p_input, fmt, p_clock,
@@ -2143,9 +2102,7 @@ void input_DecoderDelete( decoder_t *p_dec )
     vlc_cancel( p_owner->thread );
 
     vlc_fifo_Lock( p_owner->p_fifo );
-    /* Signal DecoderTimedWait */
     p_owner->flushing = true;
-    vlc_cond_signal( &p_owner->wait_timed );
     vlc_fifo_Unlock( p_owner->p_fifo );
 
     /* Make sure we aren't waiting/decoding anymore */
@@ -2293,7 +2250,6 @@ void input_DecoderFlush( decoder_t *p_dec )
         p_owner->frames_countdown++;
 
     vlc_fifo_Signal( p_owner->p_fifo );
-    vlc_cond_signal( &p_owner->wait_timed );
 
     vlc_fifo_Unlock( p_owner->p_fifo );
 }
@@ -2420,18 +2376,17 @@ void input_DecoderChangeRate( decoder_t *dec, float rate )
     struct decoder_owner *owner = dec_get_owner( dec );
 
     vlc_fifo_Lock( owner->p_fifo );
-    owner->rate = rate;
-    vlc_fifo_Signal( owner->p_fifo );
+    owner->request_rate = rate;
     vlc_fifo_Unlock( owner->p_fifo );
 }
 
-void input_DecoderChangeDelay( decoder_t *p_dec, vlc_tick_t i_delay )
+void input_DecoderChangeDelay( decoder_t *dec, vlc_tick_t delay )
 {
-    struct decoder_owner *p_owner = dec_get_owner( p_dec );
+    struct decoder_owner *owner = dec_get_owner( dec );
 
-    vlc_mutex_lock( &p_owner->lock );
-    p_owner->i_ts_delay = i_delay;
-    vlc_mutex_unlock( &p_owner->lock );
+    vlc_fifo_Lock( owner->p_fifo );
+    owner->delay = delay;
+    vlc_fifo_Unlock( owner->p_fifo );
 }
 
 void input_DecoderStartWait( decoder_t *p_dec )
diff --git a/src/input/decoder.h b/src/input/decoder.h
index db491ac44e..651bd13d69 100644
--- a/src/input/decoder.h
+++ b/src/input/decoder.h
@@ -28,7 +28,7 @@
 #include <vlc_codec.h>
 #include <vlc_mouse.h>
 
-decoder_t *input_DecoderNew( input_thread_t *, es_format_t *, input_clock_t *,
+decoder_t *input_DecoderNew( input_thread_t *, es_format_t *, vlc_clock_t *,
                              sout_instance_t * ) VLC_USED;
 
 /**
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 511b19a8d4..da5925933b 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * es_out.c: Es Out handler for input.
  *****************************************************************************
- * Copyright (C) 2003-2004 VLC authors and VideoLAN
+ * Copyright (C) 2003-2019 VLC authors, VideoLAN and Videolabs SAS
  *
  * Authors: Laurent Aimar <fenrir at via.ecp.fr>
  *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
@@ -42,6 +42,7 @@
 
 #include "input_internal.h"
 #include "../clock/input_clock.h"
+#include "../clock/clock.h"
 #include "decoder.h"
 #include "es_out.h"
 #include "event.h"
@@ -69,7 +70,9 @@ typedef struct
     bool b_scrambled;
 
     /* Clock for this program */
-    input_clock_t *p_input_clock;
+    input_clock_t    *p_input_clock;
+    vlc_clock_main_t *p_main_clock;
+    vlc_clock_t      *p_master_clock;
 
     vlc_meta_t *p_meta;
     struct vlc_list node;
@@ -113,6 +116,7 @@ struct es_out_id_t
 
     decoder_t   *p_dec;
     decoder_t   *p_dec_record;
+    vlc_clock_t *p_clock;
 
     /* Fields for Video with CC */
     struct
@@ -453,6 +457,7 @@ static void EsOutTerminate( es_out_t *out )
     vlc_list_foreach(p_pgrm, &p_sys->programs, node)
     {
         input_clock_Delete( p_pgrm->p_input_clock );
+        vlc_clock_main_Delete( p_pgrm->p_main_clock );
         if( p_pgrm->p_meta )
             vlc_meta_Delete( p_pgrm->p_meta );
 
@@ -612,7 +617,7 @@ static int EsOutSetRecord(  es_out_t *out, bool b_record )
             if( !p_es->p_dec )
                 continue;
 
-            p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_input_clock, p_sys->p_sout_record );
+            p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, NULL, p_sys->p_sout_record );
             if( p_es->p_dec_record && p_sys->b_buffering )
                 input_DecoderStartWait( p_es->p_dec_record );
         }
@@ -710,7 +715,10 @@ static void EsOutChangePosition( es_out_t *out )
 
     es_out_pgrm_t *pgrm;
     vlc_list_foreach(pgrm, &p_sys->programs, node)
+    {
         input_clock_Reset(pgrm->p_input_clock);
+        vlc_clock_main_Reset(pgrm->p_main_clock);
+    }
 
     p_sys->b_buffering = true;
     p_sys->i_buffering_extra_initial = 0;
@@ -792,12 +800,19 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
     /* Here is a good place to destroy unused vout with every demuxer */
     input_resource_TerminateVout( input_priv(p_sys->p_input)->p_resource );
 
+
     /* */
     const vlc_tick_t i_wakeup_delay = VLC_TICK_FROM_MS(10); /* FIXME CLEANUP thread wake up time*/
     const vlc_tick_t i_current_date = p_sys->b_paused ? p_sys->i_pause_date : vlc_tick_now();
 
-    input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_input_clock, true,
-                                    i_current_date + i_wakeup_delay - i_buffering_duration );
+    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)
     {
@@ -854,7 +869,10 @@ static void EsOutProgramChangePause( es_out_t *out, bool b_paused, vlc_tick_t i_
     es_out_pgrm_t *pgrm;
 
     vlc_list_foreach(pgrm, &p_sys->programs, node)
+    {
         input_clock_ChangePause(pgrm->p_input_clock, b_paused, i_date);
+        vlc_clock_main_ChangePause(pgrm->p_main_clock, i_date, b_paused);
+    }
 }
 
 static void EsOutDecoderChangeDelay( es_out_t *out, es_out_id_t *p_es )
@@ -1111,15 +1129,21 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
     p_pgrm->b_selected = false;
     p_pgrm->b_scrambled = false;
     p_pgrm->p_meta = NULL;
+
+    p_pgrm->p_master_clock = NULL;
     p_pgrm->p_input_clock = input_clock_New( p_sys->rate );
-    if( !p_pgrm->p_input_clock )
+    p_pgrm->p_main_clock = vlc_clock_main_New();
+    if( !p_pgrm->p_input_clock || !p_pgrm->p_main_clock )
     {
+        if( p_pgrm->p_input_clock )
+            input_clock_Delete( p_pgrm->p_input_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 );
     input_clock_SetJitter( p_pgrm->p_input_clock, p_sys->i_pts_delay, p_sys->i_cr_average );
+    vlc_clock_main_SetInputDejitter( p_pgrm->p_main_clock, p_sys->i_pts_delay );
 
     /* Append it */
     vlc_list_append(&p_pgrm->node, &p_sys->programs);
@@ -1167,6 +1191,7 @@ static int EsOutProgramDel( es_out_t *out, int i_group )
         p_sys->p_pgrm = NULL;
 
     input_clock_Delete( p_pgrm->p_input_clock );
+    vlc_clock_main_Delete( p_pgrm->p_main_clock );
 
     if( p_pgrm->p_meta )
         vlc_meta_Delete( p_pgrm->p_meta );
@@ -1711,6 +1736,7 @@ static es_out_id_t *EsOutAddSlaveLocked( es_out_t *out, const es_format_t *fmt,
     es->psz_title = EsGetTitle(es);
     es->p_dec = NULL;
     es->p_dec_record = NULL;
+    es->p_clock = NULL;
     es->cc.type = 0;
     es->cc.i_bitmap = 0;
     es->p_master = p_master;
@@ -1769,18 +1795,26 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es )
     input_thread_t *p_input = p_sys->p_input;
     decoder_t *dec;
 
-    dec = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_input_clock,
+    if( p_es->fmt.i_cat == AUDIO_ES && p_es->p_pgrm->p_master_clock == NULL )
+        p_es->p_pgrm->p_master_clock = p_es->p_clock =
+            vlc_clock_main_CreateMaster( p_es->p_pgrm->p_main_clock );
+    else
+        p_es->p_clock = vlc_clock_main_CreateSlave( p_es->p_pgrm->p_main_clock );
+    if( !p_es->p_clock )
+        return;
+
+    dec = input_DecoderNew( p_input, &p_es->fmt, p_es->p_clock,
                             input_priv(p_input)->p_sout );
     if( dec != NULL )
     {
-        input_DecoderChangeRate( dec, 1 / p_sys->rate );
+        input_DecoderChangeRate( dec, p_sys->rate );
 
         if( p_sys->b_buffering )
             input_DecoderStartWait( dec );
 
         if( !p_es->p_master && p_sys->p_sout_record )
         {
-            p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_input_clock, p_sys->p_sout_record );
+            p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, NULL, p_sys->p_sout_record );
             if( p_es->p_dec_record && p_sys->b_buffering )
                 input_DecoderStartWait( p_es->p_dec_record );
         }
@@ -1802,6 +1836,10 @@ static void EsOutDestroyDecoder( es_out_t *out, es_out_id_t *p_es )
 
     input_DecoderDelete( 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;
 
     if( p_es->p_dec_record )
     {
@@ -2698,7 +2736,10 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
 
                     /* reset clock */
                     vlc_list_foreach(pgrm, &p_sys->programs, node)
+                    {
                         input_clock_Reset(pgrm->p_input_clock);
+                        vlc_clock_main_Reset(p_pgrm->p_main_clock);
+                    }
                 }
                 else
                 {
@@ -3009,9 +3050,15 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
         p_sys->i_cr_average = i_cr_average;
 
         if (b_change_clock)
+        {
             vlc_list_foreach(pgrm, &p_sys->programs, node)
-                 input_clock_SetJitter(pgrm->p_input_clock, i_pts_delay
-                                       + i_pts_jitter, i_cr_average);
+            {
+                input_clock_SetJitter(pgrm->p_input_clock, i_pts_delay
+                                      + i_pts_jitter, i_cr_average);
+                vlc_clock_main_SetInputDejitter(pgrm->p_main_clock,
+                                                i_pts_delay + i_pts_jitter);
+            }
+        }
         return VLC_SUCCESS;
     }
 
-- 
2.20.1



More information about the vlc-devel mailing list