Commit 2f9d9766 authored by Laurent Aimar's avatar 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.
parent 43aab246
......@@ -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;
......
......@@ -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.
*
......
......@@ -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 )
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment