[vlc-devel] commit: Let the input bufferize more data when possible. (Laurent Aimar )

git version control git at videolan.org
Thu Jul 16 21:23:54 CEST 2009


vlc | branch: master | Laurent Aimar <fenrir at videolan.org> | Thu Jul 16 14:50:16 2009 +0200| [2f9d9766dfe25f100ef04d0d812aebdd18401c0d] | committer: Laurent Aimar 

Let the input bufferize more data when possible.

 The input will try to read 20% faster the source until a certain amount
of data is buffered by the fifo of the decoders (for now 10Mbytes or
500kbytes when OPTIMIZE_MEMORY is defined for the sum of all fifos).
 This buffering adds up to pts_delay without any additional delay but can
only work when VLC controls the source pace.

 It has a drawback with the current way the meta data works: they are seen
too soon.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2f9d9766dfe25f100ef04d0d812aebdd18401c0d
---

 src/input/clock.c  |   47 ++++++++++++++++++++++++++++++++++++++++++++---
 src/input/clock.h  |    6 +++++-
 src/input/es_out.c |   31 ++++++++++++++++++++++++++++++-
 3 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/src/input/clock.c b/src/input/clock.c
index 9608546..a797299 100644
--- a/src/input/clock.c
+++ b/src/input/clock.c
@@ -86,6 +86,17 @@
  * my dice --Meuuh */
 #define CR_MEAN_PTS_GAP (300000)
 
+/* Rate (in 1/256) at which we will read faster to try to increase our
+ * internal buffer (if we control the pace of the source).
+ */
+#define CR_BUFFERING_RATE (48)
+
+/* Extra internal buffer value (in CLOCK_FREQ)
+ * It is 60s max, remember as it is limited by the size it takes by es_out.c
+ * it can be really large.
+ */
+#define CR_BUFFERING_TARGET (60000000)
+
 /*****************************************************************************
  * Structures
  *****************************************************************************/
@@ -142,6 +153,9 @@ struct input_clock_t
     /* Maximal timestamp returned by input_clock_ConvertTS (in system unit) */
     mtime_t i_ts_max;
 
+    /* Amount of extra buffering expressed in stream clock */
+    mtime_t i_buffering_duration;
+
     /* Clock drift */
     mtime_t i_next_drift_update;
     average_t drift;
@@ -182,6 +196,8 @@ input_clock_t *input_clock_New( int i_rate )
 
     cl->i_ts_max = VLC_TS_INVALID;
 
+    cl->i_buffering_duration = 0;
+
     cl->i_next_drift_update = VLC_TS_INVALID;
     AvgInit( &cl->drift, 10 );
 
@@ -215,7 +231,7 @@ void input_clock_Delete( input_clock_t *cl )
  *****************************************************************************/
 void input_clock_Update( input_clock_t *cl, vlc_object_t *p_log,
                          bool *pb_late,
-                         bool b_can_pace_control,
+                         bool b_can_pace_control, bool b_buffering_allowed,
                          mtime_t i_ck_stream, mtime_t i_ck_system )
 {
     bool b_reset_reference = false;
@@ -243,6 +259,8 @@ void input_clock_Update( input_clock_t *cl, vlc_object_t *p_log,
         msg_Warn( p_log, "feeding synchro with a new reference point trying to recover from clock gap" );
         b_reset_reference= true;
     }
+
+    /* */
     if( b_reset_reference )
     {
         cl->i_next_drift_update = VLC_TS_INVALID;
@@ -254,6 +272,8 @@ void input_clock_Update( input_clock_t *cl, vlc_object_t *p_log,
                                       __MAX( cl->i_ts_max + CR_MEAN_PTS_GAP, i_ck_system ) );
     }
 
+    /* Compute the drift between the stream clock and the system clock
+     * when we don't control the source pace */
     if( !b_can_pace_control && cl->i_next_drift_update < i_ck_system )
     {
         const mtime_t i_converted = ClockSystemToStream( cl, i_ck_system );
@@ -262,6 +282,26 @@ void input_clock_Update( input_clock_t *cl, vlc_object_t *p_log,
 
         cl->i_next_drift_update = i_ck_system + CLOCK_FREQ/5; /* FIXME why that */
     }
+
+    /* Update the extra buffering value */
+    if( !b_can_pace_control || b_reset_reference )
+    {
+        cl->i_buffering_duration = 0;
+    }
+    else if( b_buffering_allowed )
+    {
+        /* Try to bufferize more than necessary by reading
+         * CR_BUFFERING_RATE/256 faster until we have CR_BUFFERING_TARGET.
+         */
+        const mtime_t i_duration = __MAX( i_ck_stream - cl->last.i_stream, 0 );
+
+        cl->i_buffering_duration += ( i_duration * CR_BUFFERING_RATE + 255 ) / 256;
+        if( cl->i_buffering_duration > CR_BUFFERING_TARGET )
+            cl->i_buffering_duration = CR_BUFFERING_TARGET;
+    }
+    //fprintf( stderr, "input_clock_Update: %d :: %lld\n", b_buffering_allowed, cl->i_buffering_duration/1000 );
+
+    /* */
     cl->last = clock_point_Create( i_ck_stream, i_ck_system );
 
     /* It does not take the decoder latency into account but it is not really
@@ -345,7 +385,7 @@ mtime_t input_clock_GetWakeup( input_clock_t *cl )
 
     /* Synchronized, we can wait */
     if( cl->b_has_reference )
-        i_wakeup = ClockStreamToSystem( cl, cl->last.i_stream + AvgGet( &cl->drift ) );
+        i_wakeup = ClockStreamToSystem( cl, cl->last.i_stream + AvgGet( &cl->drift ) - cl->i_buffering_duration );
 
     vlc_mutex_unlock( &cl->lock );
 
@@ -375,6 +415,7 @@ int input_clock_ConvertTS( input_clock_t *cl,
     }
 
     /* */
+    const mtime_t i_ts_buffering = cl->i_buffering_duration * cl->i_rate / INPUT_RATE_DEFAULT;
     const mtime_t i_ts_delay = cl->i_pts_delay + ClockGetTsOffset( cl );
 
     /* */
@@ -397,7 +438,7 @@ int input_clock_ConvertTS( input_clock_t *cl,
 
     /* Check ts validity */
     if( i_ts_bound != INT64_MAX &&
-        *pi_ts0 > VLC_TS_INVALID && *pi_ts0 >= mdate() + i_ts_delay + i_ts_bound )
+        *pi_ts0 > VLC_TS_INVALID && *pi_ts0 >= mdate() + i_ts_delay + i_ts_buffering + i_ts_bound )
         return VLC_EGENERIC;
 
     return VLC_SUCCESS;
diff --git a/src/input/clock.h b/src/input/clock.h
index abe23aa..ff50c82 100644
--- a/src/input/clock.h
+++ b/src/input/clock.h
@@ -53,10 +53,14 @@ void           input_clock_Delete( input_clock_t * );
 /**
  * This function will update a input_clock_t with a new clock reference point.
  * It will also tell if the clock point is late regarding our buffering.
+ *
+ * \param b_buffering_allowed tells if we are allowed to bufferize more data in
+ * advanced (if possible).
  */
 void    input_clock_Update( input_clock_t *, vlc_object_t *p_log,
                             bool *pb_late,
-                            bool b_can_pace_control, mtime_t i_clock, mtime_t i_system );
+                            bool b_can_pace_control, bool b_buffering_allowed,
+                            mtime_t i_clock, mtime_t i_system );
 /**
  * This function will reset the drift of a input_clock_t.
  *
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 3762e84..df8a692 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -187,6 +187,7 @@ static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_da
 static void EsOutProgramChangePause( es_out_t *out, bool b_paused, mtime_t i_date );
 static void EsOutProgramsChangeRate( es_out_t *out );
 static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced );
+
 static char *LanguageGetName( const char *psz_code );
 static char *LanguageGetCode( const char *psz_lang );
 static char **LanguageSplit( const char *psz_langs );
@@ -705,6 +706,32 @@ static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_da
         }
     }
 }
+
+static bool EsOutIsExtraBufferingAllowed( es_out_t *out )
+{
+    es_out_sys_t *p_sys = out->p_sys;
+
+    size_t i_size = 0;
+    for( int i = 0; i < p_sys->i_es; i++ )
+    {
+        es_out_id_t *p_es = p_sys->es[i];
+
+        if( p_es->p_dec )
+            i_size += input_DecoderGetFifoSize( p_es->p_dec );
+        if( p_es->p_dec_record )
+            i_size += input_DecoderGetFifoSize( p_es->p_dec_record );
+    }
+    //fprintf( stderr, "----- EsOutIsExtraBufferingAllowed =% 5d kbytes -- ", i_size / 1024 );
+
+    /* TODO maybe we want to be able to tune it ? */
+#if defined(OPTIMIZE_MEMORY)
+    const size_t i_level_high = 500000;  /* 0.5 Mbytes */
+#else
+    const size_t i_level_high = 10000000; /* 10 Mbytes */
+#endif
+    return i_size < i_level_high;
+}
+
 static void EsOutProgramChangePause( es_out_t *out, bool b_paused, mtime_t i_date )
 {
     es_out_sys_t *p_sys = out->p_sys;
@@ -2236,7 +2263,9 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
             bool b_late;
             input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input),
                                 &b_late,
-                                p_sys->p_input->p->b_can_pace_control || p_sys->b_buffering, i_pcr, mdate() );
+                                p_sys->p_input->p->b_can_pace_control || p_sys->b_buffering,
+                                EsOutIsExtraBufferingAllowed( out ),
+                                i_pcr, mdate() );
 
             if( p_pgrm == p_sys->p_pgrm )
             {




More information about the vlc-devel mailing list