Made input_clock_t in charge of pts_delay.
authorLaurent Aimar <fenrir@videolan.org>
Sun, 18 Jan 2009 16:44:56 +0000 (17:44 +0100)
committerLaurent Aimar <fenrir@videolan.org>
Sun, 18 Jan 2009 16:55:03 +0000 (17:55 +0100)
It fixes a lot of unlocked access.
It will allows a better clock algo.

src/input/clock.c
src/input/clock.h
src/input/decoder.c
src/input/es_out.c
src/input/es_out.h
src/input/es_out_timeshift.c
src/input/input.c
src/input/input_internal.h
src/input/var.c

index 7ef5dba..62b3062 100644 (file)
@@ -107,6 +107,7 @@ static void    AvgClean( average_t * );
 static void    AvgReset( average_t * );
 static void    AvgUpdate( average_t *, mtime_t i_value );
 static mtime_t AvgGet( average_t * );
+static void    AvgRescale( average_t *, int i_divider );
 
 /* */
 typedef struct
@@ -144,6 +145,7 @@ struct input_clock_t
 
     /* Current modifiers */
     int     i_rate;
+    mtime_t i_pts_delay;
     bool    b_paused;
     mtime_t i_pause_date;
 };
@@ -154,7 +156,7 @@ static mtime_t ClockSystemToStream( input_clock_t *, mtime_t i_system );
 /*****************************************************************************
  * input_clock_New: create a new clock
  *****************************************************************************/
-input_clock_t *input_clock_New( int i_cr_average, int i_rate )
+input_clock_t *input_clock_New( int i_rate )
 {
     input_clock_t *cl = malloc( sizeof(*cl) );
     if( !cl )
@@ -169,9 +171,10 @@ input_clock_t *input_clock_New( int i_cr_average, int i_rate )
     cl->i_ts_max = 0;
 
     cl->i_next_drift_update = 0;
-    AvgInit( &cl->drift, i_cr_average );
+    AvgInit( &cl->drift, 10 );
 
     cl->i_rate = i_rate;
+    cl->i_pts_delay = 0;
     cl->b_paused = false;
     cl->i_pause_date = 0;
 
@@ -325,7 +328,7 @@ mtime_t input_clock_GetWakeup( input_clock_t *cl )
  * input_clock_GetTS: manages a PTS or DTS
  *****************************************************************************/
 mtime_t input_clock_GetTS( input_clock_t *cl, int *pi_rate,
-                           mtime_t i_pts_delay, mtime_t i_ts )
+                           mtime_t i_ts, mtime_t i_ts_bound )
 {
     mtime_t i_converted_ts;
 
@@ -347,7 +350,14 @@ mtime_t input_clock_GetTS( input_clock_t *cl, int *pi_rate,
 
     vlc_mutex_unlock( &cl->lock );
 
-    return i_converted_ts + i_pts_delay;
+    i_converted_ts += cl->i_pts_delay;
+
+    /* Check ts validity */
+    if( i_ts_bound != INT64_MAX &&
+        i_converted_ts >= mdate() + cl->i_pts_delay + i_ts_bound )
+        return 0;
+
+    return i_converted_ts;
 }
 /*****************************************************************************
  * input_clock_GetRate: Return current rate
@@ -399,6 +409,28 @@ void input_clock_ChangeSystemOrigin( input_clock_t *cl, mtime_t i_system )
     vlc_mutex_unlock( &cl->lock );
 }
 
+#warning "input_clock_SetJitter needs more work"
+void input_clock_SetJitter( input_clock_t *cl,
+                            mtime_t i_pts_delay, int i_cr_average )
+{
+    vlc_mutex_lock( &cl->lock );
+
+    /* TODO always save the value, and when rebuffering use the new one if smaller
+     * TODO when increasing -> force rebuffering
+     */
+    if( cl->i_pts_delay < i_pts_delay )
+        cl->i_pts_delay = i_pts_delay;
+
+    /* */
+    if( i_cr_average < 10 )
+        i_cr_average = 10;
+
+    if( cl->drift.i_divider != i_cr_average )
+        AvgRescale( &cl->drift, i_cr_average );
+
+    vlc_mutex_unlock( &cl->lock );
+}
+
 /*****************************************************************************
  * ClockStreamToSystem: converts a movie clock to system date
  *****************************************************************************/
@@ -457,4 +489,11 @@ static mtime_t AvgGet( average_t *p_avg )
 {
     return p_avg->i_value;
 }
+static void AvgRescale( average_t *p_avg, int i_divider )
+{
+    const mtime_t i_tmp = p_avg->i_value * p_avg->i_divider + p_avg->i_residue;
 
+    p_avg->i_divider = i_divider;
+    p_avg->i_value   = i_tmp / p_avg->i_divider;
+    p_avg->i_residue = i_tmp % p_avg->i_divider;
+}
index b42f786..7798b13 100644 (file)
@@ -43,7 +43,8 @@
  * This function creates a new input_clock_t.
  * You must use input_clock_Delete to delete it once unused.
  */
-input_clock_t *input_clock_New( int i_cr_average, int i_rate );
+input_clock_t *input_clock_New( int i_rate );
+
 /**
  * This function destroys a input_clock_t created by input_clock_New.
  */
@@ -88,8 +89,10 @@ void    input_clock_ChangeSystemOrigin( input_clock_t *, mtime_t i_system );
  *
  * If pi_rate is provided it will be field with the rate value used for
  * the conversion.
+ * If i_ts_bound is not INT64_MAX, the value will be invalidated if not
+ * before mdate() + i_pts_delay + i_ts_bound.
  */
-mtime_t input_clock_GetTS( input_clock_t *, int *pi_rate, mtime_t i_pts_delay, mtime_t );
+mtime_t input_clock_GetTS( input_clock_t *, int *pi_rate, mtime_t i_ts, mtime_t i_ts_bound );
 
 /**
  * This function returns the current rate.
@@ -104,5 +107,11 @@ int input_clock_GetState( input_clock_t *,
                           mtime_t *pi_stream_start, mtime_t *pi_system_start,
                           mtime_t *pi_stream_duration, mtime_t *pi_system_duration );
 
+/**
+ * This function allows the set the minimal configuration for the jitter estimation algo.
+ */
+void input_clock_SetJitter( input_clock_t *,
+                            mtime_t i_pts_delay, int i_cr_average );
+
 #endif
 
index 8104e85..b3481cd 100644 (file)
@@ -652,7 +652,7 @@ static mtime_t DecoderGetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
     if( !p_owner->p_clock || !i_ts )
         return i_ts;
 
-    return input_clock_GetTS( p_owner->p_clock, NULL, p_owner->p_input->p->i_pts_delay, i_ts );
+    return input_clock_GetTS( p_owner->p_clock, NULL, i_ts, INT64_MAX );
 }
 static int DecoderGetDisplayRate( decoder_t *p_dec )
 {
@@ -1020,7 +1020,7 @@ static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
         *pi_preroll = __MIN( *pi_preroll, p->i_dts );
 }
 
-static mtime_t DecoderTeletextFixTs( mtime_t i_ts, mtime_t i_ts_delay )
+static mtime_t DecoderTeletextFixTs( mtime_t i_ts )
 {
     mtime_t current_date = mdate();
 
@@ -1029,13 +1029,13 @@ static mtime_t DecoderTeletextFixTs( mtime_t i_ts, mtime_t i_ts_delay )
     {
         /* ETSI EN 300 472 Annex A : do not take into account the PTS
          * for teletext streams. */
-        return current_date + 400000 + i_ts_delay;
+        return current_date + 400000;
     }
     return i_ts;
 }
 
 static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1,
-                          mtime_t *pi_duration, int *pi_rate, mtime_t *pi_delay, bool b_telx )
+                          mtime_t *pi_duration, int *pi_rate, mtime_t i_ts_bound, bool b_telx )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
     input_clock_t   *p_clock = p_owner->p_clock;
@@ -1043,7 +1043,6 @@ static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1,
 
     vlc_assert_locked( &p_owner->lock );
 
-    const mtime_t i_ts_delay = p_owner->p_input->p->i_pts_delay;
     const mtime_t i_es_delay = p_owner->i_ts_delay;
 
     if( p_clock )
@@ -1051,11 +1050,14 @@ static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1,
         const bool b_ephemere = pi_ts1 && *pi_ts0 == *pi_ts1;
 
         if( *pi_ts0 > 0 )
-            *pi_ts0 = input_clock_GetTS( p_clock, &i_rate, i_ts_delay,
-                                         *pi_ts0 + i_es_delay );
+            *pi_ts0 = input_clock_GetTS( p_clock, &i_rate, *pi_ts0 + i_es_delay, i_ts_bound );
         if( pi_ts1 && *pi_ts1 > 0 )
-            *pi_ts1 = input_clock_GetTS( p_clock, &i_rate, i_ts_delay,
-                                         *pi_ts1 + i_es_delay );
+        {
+            if( *pi_ts0 > 0 )
+                *pi_ts1 = input_clock_GetTS( p_clock, &i_rate, *pi_ts1 + i_es_delay, INT64_MAX );
+            else
+                *pi_ts1 = 0;
+        }
 
         /* Do not create ephemere data because of rounding errors */
         if( !b_ephemere && pi_ts1 && *pi_ts0 == *pi_ts1 )
@@ -1073,16 +1075,11 @@ static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1,
 
         if( b_telx )
         {
-            *pi_ts0 = DecoderTeletextFixTs( *pi_ts0, i_ts_delay );
+            *pi_ts0 = DecoderTeletextFixTs( *pi_ts0 );
             if( pi_ts1 && *pi_ts1 <= 0 )
                 *pi_ts1 = *pi_ts0;
         }
     }
-    if( pi_delay )
-    {
-        const int r = i_rate > 0 ? i_rate : INPUT_RATE_DEFAULT;
-        *pi_delay = i_ts_delay + i_es_delay * r / INPUT_RATE_DEFAULT;
-    }
 }
 
 static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio,
@@ -1146,19 +1143,16 @@ static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio,
         }
 
         /* */
+        const bool b_dated = p_audio->start_date > 0;
         int i_rate = INPUT_RATE_DEFAULT;
-        mtime_t i_delay;
 
         DecoderFixTs( p_dec, &p_audio->start_date, &p_audio->end_date, NULL,
-                      &i_rate, &i_delay, false );
+                      &i_rate, AOUT_MAX_ADVANCE_TIME, false );
 
         vlc_mutex_unlock( &p_owner->lock );
 
-        /* */
-        const mtime_t i_max_date = mdate() + i_delay + AOUT_MAX_ADVANCE_TIME;
-
         if( !p_aout || !p_aout_input ||
-            p_audio->start_date <= 0 || p_audio->start_date > i_max_date ||
+            p_audio->start_date <= 0 ||
             i_rate < INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE ||
             i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
             b_reject = true;
@@ -1186,15 +1180,11 @@ static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio,
         }
         else
         {
-            if( p_audio->start_date <= 0 )
-            {
+            if( b_dated )
+                msg_Warn( p_aout, "received buffer in the future" );
+            else
                 msg_Warn( p_dec, "non-dated audio buffer received" );
-            }
-            else if( p_audio->start_date > i_max_date )
-            {
-                msg_Warn( p_aout, "received buffer in the future (%"PRId64")",
-                          p_audio->start_date - mdate() );
-            }
+
             *pi_lost_sum += 1;
             aout_BufferFree( p_audio );
         }
@@ -1381,17 +1371,15 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
             p_picture->b_force = true;
         }
 
+        const bool b_dated = p_picture->date > 0;
         int i_rate = INPUT_RATE_DEFAULT;
-        mtime_t i_delay;
         DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
-                      &i_rate, &i_delay, false );
+                      &i_rate, DECODER_BOGUS_VIDEO_DELAY, false );
 
         vlc_mutex_unlock( &p_owner->lock );
 
         /* */
-        const mtime_t i_max_date = mdate() + i_delay + DECODER_BOGUS_VIDEO_DELAY;
-
-        if( !p_picture->b_force && ( p_picture->date <= 0 || p_picture->date >= i_max_date ) )
+        if( !p_picture->b_force && p_picture->date <= 0 )
             b_reject = true;
 
         if( !b_reject )
@@ -1406,15 +1394,11 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
         }
         else
         {
-            if( p_picture->date <= 0 )
-            {
-                msg_Warn( p_vout, "non-dated video buffer received" );
-            }
+            if( b_dated )
+                msg_Warn( p_vout, "early picture skipped" );
             else
-            {
-                msg_Warn( p_vout, "early picture skipped (%"PRId64")",
-                          p_picture->date - mdate() );
-            }
+                msg_Warn( p_vout, "non-dated video buffer received" );
+
             *pi_lost_sum += 1;
             vout_DropPicture( p_vout, p_picture );
         }
@@ -1557,7 +1541,7 @@ static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic,
 
         /* */
         DecoderFixTs( p_dec, &p_subpic->i_start, &p_subpic->i_stop, NULL,
-                      NULL, NULL, b_telx );
+                      NULL, INT64_MAX, b_telx );
 
         vlc_mutex_unlock( &p_owner->lock );
 
@@ -1628,7 +1612,7 @@ static void DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block,
 
         DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts,
                       &p_sout_block->i_length,
-                      &p_sout_block->i_rate, NULL, b_telx );
+                      &p_sout_block->i_rate, INT64_MAX, b_telx );
 
         vlc_mutex_unlock( &p_owner->lock );
 
index da7000c..95a7a7e 100644 (file)
@@ -142,7 +142,9 @@ struct es_out_sys_t
     int64_t i_audio_delay;
     int64_t i_spu_delay;
 
-    /* Rate used for clock */
+    /* Clock configuration */
+    mtime_t     i_pts_delay;
+    int         i_cr_average;
     int         i_rate;
 
     /* */
@@ -305,6 +307,8 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
     p_sys->i_pause_date = -1;
 
     p_sys->i_rate = i_rate;
+    p_sys->i_pts_delay = 0;
+    p_sys->i_cr_average = 0;
 
     p_sys->b_buffering = true;
     p_sys->i_buffering_extra_initial = 0;
@@ -622,7 +626,7 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
     if( p_sys->i_preroll_end >= 0 )
         i_preroll_duration = __MAX( p_sys->i_preroll_end - i_stream_start, 0 );
 
-    const mtime_t i_buffering_duration = p_sys->p_input->p->i_pts_delay +
+    const mtime_t i_buffering_duration = p_sys->i_pts_delay +
                                          i_preroll_duration +
                                          p_sys->i_buffering_extra_stream - p_sys->i_buffering_extra_initial;
 
@@ -787,7 +791,7 @@ static void EsOutFrameNext( es_out_t *out )
         if( i_ret )
             return;
 
-        p_sys->i_buffering_extra_initial = 1 + i_stream_duration - p_sys->p_input->p->i_pts_delay; /* FIXME < 0 ? */
+        p_sys->i_buffering_extra_initial = 1 + i_stream_duration - p_sys->i_pts_delay; /* FIXME < 0 ? */
         p_sys->i_buffering_extra_system =
         p_sys->i_buffering_extra_stream = p_sys->i_buffering_extra_initial;
     }
@@ -842,7 +846,7 @@ static mtime_t EsOutGetBuffering( es_out_t *out )
         }
 
         const mtime_t i_consumed = i_system_duration * INPUT_RATE_DEFAULT / p_sys->i_rate - i_stream_duration;
-        i_delay = p_sys->p_input->p->i_pts_delay - i_consumed;
+        i_delay = p_sys->i_pts_delay - i_consumed;
     }
     if( i_delay < 0 )
         return 0;
@@ -1013,12 +1017,14 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
     p_pgrm->psz_now_playing = NULL;
     p_pgrm->psz_publisher = NULL;
     p_pgrm->p_epg = NULL;
-    p_pgrm->p_clock = input_clock_New( p_input->p->i_cr_average, p_sys->i_rate );
+    p_pgrm->p_clock = input_clock_New( p_sys->i_rate );
     if( !p_pgrm->p_clock )
     {
         free( p_pgrm );
         return NULL;
     }
+    input_clock_SetJitter( p_pgrm->p_clock, p_sys->i_pts_delay, p_sys->i_cr_average );
+
 
     /* Append it */
     TAB_APPEND( p_sys->i_pgrm, p_sys->pgrm, p_pgrm );
@@ -2392,6 +2398,23 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
                 input_SendEventTimes( p_sys->p_input, f_position, i_time, i_length );
             return VLC_SUCCESS;
         }
+        case ES_OUT_SET_JITTER:
+        {
+            mtime_t i_pts_delay = (mtime_t)va_arg( args, mtime_t );
+            int     i_cr_average = (int)va_arg( args, int );
+
+            if( i_pts_delay == p_sys->i_pts_delay &&
+                i_cr_average == p_sys->i_cr_average )
+                return VLC_SUCCESS;
+
+            p_sys->i_pts_delay = i_pts_delay;
+            p_sys->i_cr_average = i_cr_average;
+
+            for( int i = 0; i < p_sys->i_pgrm; i++ )
+                input_clock_SetJitter( p_sys->pgrm[i]->p_clock,
+                                       i_pts_delay, i_cr_average );
+            return VLC_SUCCESS;
+        }
 
         default:
             msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
index 6d97c8d..62818ff 100644 (file)
@@ -74,6 +74,9 @@ enum es_out_query_private_e
 
     /* Set position/time/length */
     ES_OUT_SET_TIMES,                               /* arg1=double f_position arg2=mtime_t i_time arg3=mtime_t i_length res=cannot fail */
+
+    /* Set jitter */
+    ES_OUT_SET_JITTER,                              /* arg1=mtime_t i_pts_delay arg2=int i_cr_average res=cannot fail */
 };
 
 static inline mtime_t es_out_GetWakeup( es_out_t *p_out )
@@ -129,6 +132,11 @@ static inline void es_out_SetTimes( es_out_t *p_out, double f_position, mtime_t
     int i_ret = es_out_Control( p_out, ES_OUT_SET_TIMES, f_position, i_time, i_length );
     assert( !i_ret );
 }
+static inline void es_out_SetJitter( es_out_t *p_out, mtime_t i_pts_delay, int i_cr_average )
+{
+    int i_ret = es_out_Control( p_out, ES_OUT_SET_JITTER, i_pts_delay, i_cr_average );
+    assert( !i_ret );
+}
 
 es_out_t  *input_EsOutNew( input_thread_t *, int i_rate );
 
index 729ed65..c96ed1a 100644 (file)
@@ -128,6 +128,11 @@ typedef struct attribute_packed
             mtime_t i_time;
             mtime_t i_length;
         } times;
+        struct
+        {
+            mtime_t i_pts_delay;
+            int     i_cr_average;
+        } jitter;
     };
 } ts_cmd_control_t;
 
@@ -599,6 +604,7 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
     case ES_OUT_SET_ES_STATE:
     case ES_OUT_SET_ES_FMT:
     case ES_OUT_SET_TIMES:
+    case ES_OUT_SET_JITTER:
     {
         ts_cmd_t cmd;
         if( CmdInitControl( &cmd, i_query, args, p_sys->b_delayed ) )
@@ -1392,6 +1398,15 @@ static int CmdInitControl( ts_cmd_t *p_cmd, int i_query, va_list args, bool b_co
         p_cmd->control.times.i_length = i_length;
         break;
     }
+    case ES_OUT_SET_JITTER:
+    {
+        mtime_t i_pts_delay = (mtime_t)va_arg( args, mtime_t );
+        int     i_cr_average = (int)va_arg( args, int );
+
+        p_cmd->control.jitter.i_pts_delay = i_pts_delay;
+        p_cmd->control.jitter.i_cr_average = i_cr_average;
+        break;
+    }
 
     default:
         assert(0);
@@ -1452,6 +1467,9 @@ static int CmdExecuteControl( es_out_t *p_out, ts_cmd_t *p_cmd )
         return es_out_Control( p_out, i_query, p_cmd->control.times.f_position,
                                                p_cmd->control.times.i_time,
                                                p_cmd->control.times.i_length );
+    case ES_OUT_SET_JITTER:
+        return es_out_Control( p_out, i_query, p_cmd->control.jitter.i_pts_delay,
+                                               p_cmd->control.jitter.i_cr_average );
 
     default:
         assert(0);
index 379fee5..e20d742 100644 (file)
@@ -183,8 +183,6 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
     p_input->p->p_es_out = NULL;
     p_input->p->p_sout   = NULL;
     p_input->p->b_out_pace_control = false;
-    p_input->p->i_pts_delay = 0;
-    p_input->p->i_cr_average = 0;
 
     vlc_gc_incref( p_item ); /* Released in Destructor() */
     p_input->p->p_item = p_item;
@@ -239,8 +237,6 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
     input_ControlVarInit( p_input );
 
     /* */
-    p_input->p->i_cr_average = var_GetInteger( p_input, "cr-average" );
-
     if( !p_input->b_preparsing )
     {
         var_Get( p_input, "bookmarks", &val );
@@ -903,22 +899,6 @@ static void InitTitle( input_thread_t * p_input )
     p_input->p->b_can_pace_control    = p_master->b_can_pace_control;
     p_input->p->b_can_pause        = p_master->b_can_pause;
     p_input->p->b_can_rate_control = p_master->b_can_rate_control;
-
-    /* Fix pts delay */
-    if( p_input->p->i_pts_delay < 0 )
-        p_input->p->i_pts_delay = 0;
-
-    /* If the desynchronisation requested by the user is < 0, we need to
-     * cache more data. */
-    const int i_desynch = var_GetInteger( p_input, "audio-desync" );
-    if( i_desynch < 0 )
-        p_input->p->i_pts_delay -= i_desynch * 1000;
-
-    /* Update cr_average depending on the caching */
-    p_input->p->i_cr_average *= (10 * p_input->p->i_pts_delay / 200000);
-    p_input->p->i_cr_average /= 10;
-    if( p_input->p->i_cr_average < 10 )
-        p_input->p->i_cr_average = 10;
 }
 
 static void StartTitle( input_thread_t * p_input )
@@ -1059,11 +1039,40 @@ static void LoadSlaves( input_thread_t *p_input )
     free( psz_org );
 }
 
+static void UpdatePtsDelay( input_thread_t *p_input )
+{
+    input_thread_private_t *p_sys = p_input->p;
+
+    /* Get max pts delay from input source */
+    mtime_t i_pts_delay = p_sys->input.i_pts_delay;
+    for( int i = 0; i < p_sys->i_slave; i++ )
+        i_pts_delay = __MAX( i_pts_delay, p_sys->slave[i]->i_pts_delay );
+
+    if( i_pts_delay < 0 )
+        i_pts_delay = 0;
+
+    /* Take care of audio/spu delay */
+    const int i_audio_delay = var_GetTime( p_input, "audio-delay" );
+    const int i_spu_delay   = var_GetTime( p_input, "spu-delay" );
+    const int i_extra_delay = __MIN( i_audio_delay, i_spu_delay );
+    if( i_extra_delay < 0 )
+        i_pts_delay -= i_extra_delay * INT64_C(1000);
+
+    /* Update cr_average depending on the caching */
+    const int i_cr_average = var_GetInteger( p_input, "cr-average" ) * i_pts_delay / DEFAULT_PTS_DELAY;
+
+    /* */
+    es_out_SetJitter( p_input->p->p_es_out, i_pts_delay, i_cr_average );
+}
+
 static void InitPrograms( input_thread_t * p_input )
 {
     int i_es_out_mode;
     vlc_value_t val;
 
+    /* Compute correct pts_delay */
+    UpdatePtsDelay( p_input );
+
     /* Set up es_out */
     es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ACTIVE, true );
     i_es_out_mode = ES_OUT_MODE_AUTO;
@@ -1831,12 +1840,18 @@ static bool Control( input_thread_t *p_input, int i_type,
 
         case INPUT_CONTROL_SET_AUDIO_DELAY:
             if( !es_out_SetDelay( p_input->p->p_es_out_display, AUDIO_ES, val.i_time ) )
+            {
                 input_SendEventAudioDelay( p_input, val.i_time );
+                UpdatePtsDelay( p_input );
+            }
             break;
 
         case INPUT_CONTROL_SET_SPU_DELAY:
             if( !es_out_SetDelay( p_input->p->p_es_out_display, SPU_ES, val.i_time ) )
+            {
                 input_SendEventSubtitleDelay( p_input, val.i_time );
+                UpdatePtsDelay( p_input );
+            }
             break;
 
         case INPUT_CONTROL_SET_TITLE:
@@ -2338,12 +2353,9 @@ static int InputSourceInit( input_thread_t *p_input,
 
     if( in->p_demux )
     {
-        int64_t i_pts_delay;
-
         /* Get infos from access_demux */
         demux_Control( in->p_demux,
-                        DEMUX_GET_PTS_DELAY, &i_pts_delay );
-        p_input->p->i_pts_delay = __MAX( p_input->p->i_pts_delay, i_pts_delay );
+                        DEMUX_GET_PTS_DELAY, &in->i_pts_delay );
 
         in->b_title_demux = true;
         if( demux_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
@@ -2385,8 +2397,6 @@ static int InputSourceInit( input_thread_t *p_input,
     }
     else
     {
-        int64_t i_pts_delay;
-
         /* Now try a real access */
         in->p_access = access_New( p_input, psz_access, psz_demux, psz_path );
 
@@ -2416,8 +2426,7 @@ static int InputSourceInit( input_thread_t *p_input,
         if( !p_input->b_preparsing )
         {
             access_Control( in->p_access,
-                             ACCESS_GET_PTS_DELAY, &i_pts_delay );
-            p_input->p->i_pts_delay = __MAX( p_input->p->i_pts_delay, i_pts_delay );
+                             ACCESS_GET_PTS_DELAY, &in->i_pts_delay );
 
             in->b_title_demux = false;
             if( access_Control( in->p_access, ACCESS_GET_TITLE_INFO,
index f98ed42..2cc03e7 100644 (file)
@@ -68,6 +68,9 @@ typedef struct
     bool b_can_stream_record;
     bool b_rescale_ts;
 
+    /* */
+    int64_t i_pts_delay;
+
     bool       b_eof;   /* eof of demuxer */
 
 } input_source_t;
@@ -82,9 +85,6 @@ struct input_thread_private_t
     double      f_fps;
     int         i_state;
 
-    /* Internal caching common to all sources */
-    mtime_t     i_pts_delay;
-
     /* Current state */
     int         i_rate;
     bool        b_recording;
@@ -121,8 +121,7 @@ struct input_thread_private_t
 
     /* Input item */
     input_item_t   *p_item;
-    /* Clock average variation */
-    int            i_cr_average;
+
     /* Main source */
     input_source_t input;
     /* Slave sources (subs, and others) */
index 6274acc..7d5438d 100644 (file)
@@ -774,11 +774,6 @@ static int EsDelayCallback ( vlc_object_t *p_this, char const *psz_cmd,
 
     if( !strcmp( psz_cmd, "audio-delay" ) )
     {
-        /* Change i_pts_delay to make sure es are decoded in time */
-        if( newval.i_int < 0 || oldval.i_int < 0 )
-        {
-            p_input->p->i_pts_delay -= newval.i_int - oldval.i_int;
-        }
         input_ControlPush( p_input, INPUT_CONTROL_SET_AUDIO_DELAY, &newval );
     }
     else if( !strcmp( psz_cmd, "spu-delay" ) )