[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