Commit ea89b9c2 authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

input: Add --auto-adjust-pts-delay, this allows to stream/receive with an extremely low latency.

Simple demo:
vlc --sout="#duplicate{dst=display,dst='transcode{vcodec=mp4v}:std{access=http,dst=0.0.0.0:8080,mux=ts}'}" --ignore-config  --use-stream-immediate movie.avi &
vlc --use-stream-immediate http://127.0.0.1:8080
and
vlc --use-stream-immediate http://127.0.0.1:8080 --auto-adjust-pts-delay

You'll have to wait a bit until the pts delay is auto adjusted. Generally it takes 2-4 seconds, because access set a very high default pts delay value. One amelioration would be to lower the pts_delay when this option is set to allow a quicker convergence.

The general algorithm requires some tuning, but results are here.

Note, this only works if there is a video track. A similar function could be developped for the audio tracks.
parent 6f8ce7ca
......@@ -726,6 +726,96 @@ static void VoutFlushPicture( vout_thread_t *p_vout )
}
vlc_mutex_unlock( &p_vout->picture_lock );
}
static void optimize_video_pts( decoder_t *p_dec )
{
picture_t * oldest_pict = NULL;
picture_t * youngest_pict = NULL;
int i;
input_thread_t * p_input = p_dec->p_owner->p_input;
vout_thread_t * p_vout = p_dec->p_owner->p_vout;
input_thread_private_t * p_priv = p_input->p;
if( !p_priv->pts_adjust.auto_adjust ) return;
for( i = 0; i < I_RENDERPICTURES; i++ )
{
picture_t * pic = PP_RENDERPICTURE[i];
if( pic->i_status != READY_PICTURE )
continue;
if( !oldest_pict || pic->date < oldest_pict->date )
oldest_pict = pic;
if( !youngest_pict || pic->date > youngest_pict->date )
youngest_pict = pic;
}
if( !youngest_pict || !oldest_pict )
return;
/* Try to find if we can reduce the pts
* This first draft is way to simple, and we can't say if the
* algo will converge. It's also full of constants.
* But this simple algo allows to reduce the latency
* to the minimum. */
mtime_t buffer_size = youngest_pict->date - oldest_pict->date;
int64_t pts_slide = 0;
if( buffer_size < 10000 )
{
if( p_priv->pts_adjust.i_num_faulty > 10 )
{
pts_slide = __MAX(p_input->i_pts_delay *3 / 2, 10000);
p_priv->pts_adjust.i_num_faulty = 0;
}
if( p_priv->pts_adjust.to_high )
{
p_priv->pts_adjust.to_high = !p_priv->pts_adjust.to_high;
p_priv->pts_adjust.i_num_faulty = 0;
}
p_priv->pts_adjust.i_num_faulty++;
}
else if( buffer_size > 100000 )
{
if( p_priv->pts_adjust.i_num_faulty > 25 )
{
pts_slide = -buffer_size/2;
p_priv->pts_adjust.i_num_faulty = 0;
}
if( p_priv->pts_adjust.to_high )
{
p_priv->pts_adjust.to_high = !p_priv->pts_adjust.to_high;
p_priv->pts_adjust.i_num_faulty = 0;
}
p_priv->pts_adjust.i_num_faulty++;
}
if( pts_slide )
{
mtime_t origi_delay = p_input->i_pts_delay;
p_input->i_pts_delay += pts_slide;
/* Don't play with the pts delay for more than -2<->3sec */
if( p_input->i_pts_delay < -2000000 )
p_input->i_pts_delay = -2000000;
else if( p_input->i_pts_delay > 3000000 )
p_input->i_pts_delay = 3000000;
pts_slide = p_input->i_pts_delay - origi_delay;
msg_Dbg( p_input, "Sliding the pts by %dms pts delay at %dms picture buffer was %dms",
(int)pts_slide/1000, (int)p_input->i_pts_delay/1000, (int)buffer_size/1000);
vlc_mutex_lock( &p_vout->picture_lock );
/* Slide all the picture */
for( i = 0; i < I_RENDERPICTURES; i++ )
PP_RENDERPICTURE[i]->date += pts_slide;
/* FIXME: slide aout/spu */
vlc_mutex_unlock( &p_vout->picture_lock );
}
}
static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
{
input_thread_t *p_input = p_dec->p_owner->p_input;
......@@ -757,6 +847,9 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
vout_DatePicture( p_dec->p_owner->p_vout, p_pic,
p_pic->date );
optimize_video_pts( p_dec );
vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
}
}
......
......@@ -112,6 +112,13 @@ struct input_thread_private_t
int i_slave;
input_source_t **slave;
/* pts delay fixup */
struct {
int i_num_faulty;
bool to_high;
bool auto_adjust;
} pts_adjust;
/* Stats counters */
struct {
counter_t *p_read_packets;
......
......@@ -165,6 +165,9 @@ void input_ControlVarInit ( input_thread_t *p_input )
var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, &val, NULL );
ADD_CALLBACK( "spu-delay", EsDelayCallback );
p_input->p->pts_adjust.auto_adjust = var_CreateGetBool(
p_input, "auto-adjust-pts-delay" );
/* Video ES */
var_Create( p_input, "video-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
text.psz_string = _("Video Track");
......
......@@ -1822,6 +1822,8 @@ vlc_module_begin();
add_bool( "use-stream-immediate", false, NULL,
USE_STREAM_IMMEDIATE, USE_STREAM_IMMEDIATE_LONGTEXT, false );
add_bool( "auto-adjust-pts-delay", false, NULL,
"auto-adjust-pts-delay", "auto-adjust-pts-delay", false );
#if !defined(__APPLE__) && !defined(SYS_BEOS) && defined(LIBVLC_USE_PTHREAD)
add_bool( "rt-priority", false, NULL, RT_PRIORITY_TEXT,
......
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