Commit f704dfc6 authored by Laurent Aimar's avatar Laurent Aimar

Fixed annoying lates frame when slowing speed.

parent f1e16994
...@@ -78,6 +78,7 @@ struct decoder_owner_sys_t ...@@ -78,6 +78,7 @@ struct decoder_owner_sys_t
input_thread_t *p_input; input_thread_t *p_input;
input_clock_t *p_clock; input_clock_t *p_clock;
int i_last_rate;
vout_thread_t *p_spu_vout; vout_thread_t *p_spu_vout;
int i_spu_channel; int i_spu_channel;
...@@ -546,6 +547,7 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, ...@@ -546,6 +547,7 @@ static decoder_t * CreateDecoder( input_thread_t *p_input,
} }
p_dec->p_owner->b_own_thread = true; p_dec->p_owner->b_own_thread = true;
p_dec->p_owner->i_preroll_end = -1; p_dec->p_owner->i_preroll_end = -1;
p_dec->p_owner->i_last_rate = INPUT_RATE_DEFAULT;
p_dec->p_owner->p_input = p_input; p_dec->p_owner->p_input = p_input;
p_dec->p_owner->p_aout = NULL; p_dec->p_owner->p_aout = NULL;
p_dec->p_owner->p_aout_input = NULL; p_dec->p_owner->p_aout_input = NULL;
...@@ -657,7 +659,7 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, ...@@ -657,7 +659,7 @@ static decoder_t * CreateDecoder( input_thread_t *p_input,
* *
* \param p_dec the decoder * \param p_dec the decoder
*/ */
static void* DecoderThread( vlc_object_t *p_this ) static void *DecoderThread( vlc_object_t *p_this )
{ {
decoder_t *p_dec = (decoder_t *)p_this; decoder_t *p_dec = (decoder_t *)p_this;
decoder_owner_sys_t *p_owner = p_dec->p_owner; decoder_owner_sys_t *p_owner = p_dec->p_owner;
...@@ -705,17 +707,17 @@ static void DecoderWaitUnpause( decoder_t *p_dec ) ...@@ -705,17 +707,17 @@ static void DecoderWaitUnpause( decoder_t *p_dec )
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
} }
static mtime_t DecoderGetTotalDelay( decoder_t *p_dec ) static void DecoderGetDelays( decoder_t *p_dec, mtime_t *pi_ts_delay, mtime_t *pi_es_delay )
{ {
decoder_owner_sys_t *p_owner = p_dec->p_owner; decoder_owner_sys_t *p_owner = p_dec->p_owner;
*pi_ts_delay = p_owner->p_input->i_pts_delay;
vlc_mutex_lock( &p_owner->lock ); vlc_mutex_lock( &p_owner->lock );
mtime_t i_delay = p_owner->i_ts_delay; *pi_es_delay = p_owner->i_ts_delay;
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
return p_owner->p_input->i_pts_delay + i_delay;
} }
static void DecoderOutputChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date ) static void DecoderOutputChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date )
...@@ -765,20 +767,22 @@ static mtime_t DecoderTeletextFixTs( mtime_t i_ts, mtime_t i_ts_delay ) ...@@ -765,20 +767,22 @@ static mtime_t DecoderTeletextFixTs( mtime_t i_ts, mtime_t i_ts_delay )
} }
static void DecoderSoutBufferFixTs( block_t *p_block, static void DecoderSoutBufferFixTs( block_t *p_block,
input_clock_t *p_clock, mtime_t i_ts_delay, input_clock_t *p_clock,
mtime_t i_ts_delay, mtime_t i_es_delay,
bool b_teletext ) bool b_teletext )
{ {
assert( p_clock ); assert( p_clock );
p_block->i_rate = 0; if( !p_block->i_dts && !p_block->i_pts )
p_block->i_rate = input_clock_GetRate( p_clock );
if( p_block->i_dts > 0 ) if( p_block->i_dts > 0 )
p_block->i_dts = input_clock_GetTS( p_clock, &p_block->i_rate, p_block->i_dts = input_clock_GetTS( p_clock, &p_block->i_rate,
i_ts_delay, p_block->i_dts ); i_ts_delay, p_block->i_dts + i_es_delay);
if( p_block->i_pts > 0 ) if( p_block->i_pts > 0 )
p_block->i_pts = input_clock_GetTS( p_clock, &p_block->i_rate, p_block->i_pts = input_clock_GetTS( p_clock, &p_block->i_rate,
i_ts_delay, p_block->i_pts ); i_ts_delay, p_block->i_pts + i_es_delay );
if( p_block->i_length > 0 ) if( p_block->i_length > 0 )
p_block->i_length = ( p_block->i_length * p_block->i_rate + p_block->i_length = ( p_block->i_length * p_block->i_rate +
...@@ -788,7 +792,8 @@ static void DecoderSoutBufferFixTs( block_t *p_block, ...@@ -788,7 +792,8 @@ static void DecoderSoutBufferFixTs( block_t *p_block,
p_block->i_pts = DecoderTeletextFixTs( p_block->i_pts, i_ts_delay ); p_block->i_pts = DecoderTeletextFixTs( p_block->i_pts, i_ts_delay );
} }
static void DecoderAoutBufferFixTs( aout_buffer_t *p_buffer, int *pi_rate, static void DecoderAoutBufferFixTs( aout_buffer_t *p_buffer, int *pi_rate,
input_clock_t *p_clock, mtime_t i_ts_delay ) input_clock_t *p_clock,
mtime_t i_ts_delay, mtime_t i_es_delay )
{ {
/* sout display module does not set clock */ /* sout display module does not set clock */
if( !p_clock ) if( !p_clock )
...@@ -798,26 +803,31 @@ static void DecoderAoutBufferFixTs( aout_buffer_t *p_buffer, int *pi_rate, ...@@ -798,26 +803,31 @@ static void DecoderAoutBufferFixTs( aout_buffer_t *p_buffer, int *pi_rate,
*pi_rate = input_clock_GetRate( p_clock ); *pi_rate = input_clock_GetRate( p_clock );
if( p_buffer->start_date ) if( p_buffer->start_date )
p_buffer->start_date = input_clock_GetTS( p_clock, pi_rate, p_buffer->start_date =
i_ts_delay, p_buffer->start_date ); input_clock_GetTS( p_clock, pi_rate,
i_ts_delay, p_buffer->start_date + i_es_delay );
if( p_buffer->end_date ) if( p_buffer->end_date )
p_buffer->end_date = input_clock_GetTS( p_clock, pi_rate, p_buffer->end_date =
i_ts_delay, p_buffer->end_date ); input_clock_GetTS( p_clock, pi_rate,
i_ts_delay, p_buffer->end_date + i_es_delay );
} }
static void DecoderVoutBufferFixTs( picture_t *p_picture, static void DecoderVoutBufferFixTs( picture_t *p_picture, int *pi_rate,
input_clock_t *p_clock, mtime_t i_ts_delay ) input_clock_t *p_clock,
mtime_t i_ts_delay, mtime_t i_es_delay )
{ {
/* sout display module does not set clock */ /* sout display module does not set clock */
if( !p_clock ) if( !p_clock )
return; return;
if( p_picture->date ) if( p_picture->date )
p_picture->date = input_clock_GetTS( p_clock, NULL, p_picture->date =
i_ts_delay, p_picture->date ); input_clock_GetTS( p_clock, pi_rate,
i_ts_delay, p_picture->date + i_es_delay );
} }
static void DecoderSpuBufferFixTs( subpicture_t *p_subpic, static void DecoderSpuBufferFixTs( subpicture_t *p_subpic,
input_clock_t *p_clock, mtime_t i_ts_delay, input_clock_t *p_clock,
mtime_t i_ts_delay, mtime_t i_es_delay,
bool b_teletext ) bool b_teletext )
{ {
bool b_ephemere = p_subpic->i_start == p_subpic->i_stop; bool b_ephemere = p_subpic->i_start == p_subpic->i_stop;
...@@ -827,12 +837,14 @@ static void DecoderSpuBufferFixTs( subpicture_t *p_subpic, ...@@ -827,12 +837,14 @@ static void DecoderSpuBufferFixTs( subpicture_t *p_subpic,
return; return;
if( p_subpic->i_start ) if( p_subpic->i_start )
p_subpic->i_start = input_clock_GetTS( p_clock, NULL, p_subpic->i_start =
i_ts_delay, p_subpic->i_start ); input_clock_GetTS( p_clock, NULL,
i_ts_delay, p_subpic->i_start + i_es_delay );
if( p_subpic->i_stop ) if( p_subpic->i_stop )
p_subpic->i_stop = input_clock_GetTS( p_clock, NULL, p_subpic->i_stop =
i_ts_delay, p_subpic->i_stop ); input_clock_GetTS( p_clock, NULL,
i_ts_delay, p_subpic->i_stop + i_es_delay );
/* Do not create ephemere picture because of rounding errors */ /* Do not create ephemere picture because of rounding errors */
if( !b_ephemere && p_subpic->i_start == p_subpic->i_stop ) if( !b_ephemere && p_subpic->i_start == p_subpic->i_stop )
...@@ -884,16 +896,19 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block ) ...@@ -884,16 +896,19 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
DecoderWaitUnpause( p_dec ); DecoderWaitUnpause( p_dec );
const mtime_t i_delay = DecoderGetTotalDelay( p_dec );
int i_rate = INPUT_RATE_DEFAULT; int i_rate = INPUT_RATE_DEFAULT;
mtime_t i_ts_delay;
mtime_t i_es_delay;
DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
DecoderAoutBufferFixTs( p_aout_buf, &i_rate, p_clock, i_delay ); DecoderAoutBufferFixTs( p_aout_buf, &i_rate, p_clock, i_ts_delay, i_es_delay );
if( !p_clock && p_block && p_block->i_rate > 0 ) if( !p_clock && p_block && p_block->i_rate > 0 )
i_rate = p_block->i_rate; i_rate = p_block->i_rate;
/* FIXME TODO take care of audio-delay for mdate check */ /* FIXME TODO take care of audio-delay for mdate check */
const mtime_t i_max_date = mdate() + i_delay + AOUT_MAX_ADVANCE_TIME; const mtime_t i_max_date = mdate() + i_ts_delay +
i_es_delay * i_rate / INPUT_RATE_DEFAULT + AOUT_MAX_ADVANCE_TIME;
if( p_aout_buf->start_date > 0 && if( p_aout_buf->start_date > 0 &&
p_aout_buf->start_date <= i_max_date && p_aout_buf->start_date <= i_max_date &&
...@@ -1001,7 +1016,7 @@ static void VoutDisplayedPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1001,7 +1016,7 @@ static void VoutDisplayedPicture( vout_thread_t *p_vout, picture_t *p_pic )
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
} }
static void VoutFlushPicture( vout_thread_t *p_vout ) static void VoutFlushPicture( vout_thread_t *p_vout, mtime_t i_max_date )
{ {
int i; int i;
vlc_mutex_lock( &p_vout->picture_lock ); vlc_mutex_lock( &p_vout->picture_lock );
...@@ -1014,7 +1029,8 @@ static void VoutFlushPicture( vout_thread_t *p_vout ) ...@@ -1014,7 +1029,8 @@ static void VoutFlushPicture( vout_thread_t *p_vout )
{ {
/* We cannot change picture status if it is in READY_PICTURE state, /* We cannot change picture status if it is in READY_PICTURE state,
* Just make sure they won't be displayed */ * Just make sure they won't be displayed */
p_pic->date = 1; if( p_pic->date > i_max_date )
p_pic->date = i_max_date;
} }
} }
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
...@@ -1152,7 +1168,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) ...@@ -1152,7 +1168,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
{ {
msg_Dbg( p_dec, "End of video preroll" ); msg_Dbg( p_dec, "End of video preroll" );
if( p_vout ) if( p_vout )
VoutFlushPicture( p_vout ); VoutFlushPicture( p_vout, 1 );
/* */ /* */
p_owner->i_preroll_end = -1; p_owner->i_preroll_end = -1;
} }
...@@ -1163,15 +1179,26 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) ...@@ -1163,15 +1179,26 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
DecoderWaitUnpause( p_dec ); DecoderWaitUnpause( p_dec );
const mtime_t i_delay = DecoderGetTotalDelay( p_dec ); mtime_t i_ts_delay;
mtime_t i_es_delay;
DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
int i_rate = INPUT_RATE_DEFAULT;
DecoderVoutBufferFixTs( p_pic, p_owner->p_clock, i_delay ); DecoderVoutBufferFixTs( p_pic, &i_rate, p_owner->p_clock, i_ts_delay, i_es_delay );
/* Video is never delayed so simple */ /* */
const mtime_t i_max_date = mdate() + i_delay + VOUT_BOGUS_DELAY; const mtime_t i_max_date = mdate() + i_ts_delay +
i_es_delay * i_rate / INPUT_RATE_DEFAULT + VOUT_BOGUS_DELAY;
if( p_pic->date > 0 && p_pic->date < i_max_date ) if( p_pic->date > 0 && p_pic->date < i_max_date )
{ {
if( i_rate != p_owner->i_last_rate )
{
/* Be sure to not display old picture after our own */
VoutFlushPicture( p_vout, p_pic->date );
p_owner->i_last_rate = i_rate;
}
vout_DatePicture( p_vout, p_pic, p_pic->date ); vout_DatePicture( p_vout, p_pic, p_pic->date );
/* Re-enable it but do it right this time */ /* Re-enable it but do it right this time */
...@@ -1283,10 +1310,12 @@ static int DecoderDecode( decoder_t *p_dec, block_t *p_block ) ...@@ -1283,10 +1310,12 @@ static int DecoderDecode( decoder_t *p_dec, block_t *p_block )
DecoderWaitUnpause( p_dec ); DecoderWaitUnpause( p_dec );
const mtime_t i_delay = DecoderGetTotalDelay( p_dec ); mtime_t i_ts_delay;
mtime_t i_es_delay;
DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
DecoderSoutBufferFixTs( p_sout_block, DecoderSoutBufferFixTs( p_sout_block, p_owner->p_clock,
p_owner->p_clock, i_delay, b_telx ); i_ts_delay, i_es_delay, b_telx );
sout_InputSendBuffer( p_owner->p_sout_input, sout_InputSendBuffer( p_owner->p_sout_input,
p_sout_block ); p_sout_block );
...@@ -1429,7 +1458,11 @@ static int DecoderDecode( decoder_t *p_dec, block_t *p_block ) ...@@ -1429,7 +1458,11 @@ static int DecoderDecode( decoder_t *p_dec, block_t *p_block )
{ {
DecoderWaitUnpause( p_dec ); DecoderWaitUnpause( p_dec );
DecoderSpuBufferFixTs( p_spu, p_owner->p_clock, p_input->i_pts_delay, b_telx ); mtime_t i_ts_delay;
mtime_t i_es_delay;
DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
DecoderSpuBufferFixTs( p_spu, p_owner->p_clock, i_ts_delay, i_es_delay, b_telx );
spu_DisplaySubpicture( p_vout->p_spu, p_spu ); spu_DisplaySubpicture( p_vout->p_spu, p_spu );
} }
} }
......
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