Commit 72e6a089 authored by Laurent Aimar's avatar Laurent Aimar

No functional changes (decoder).

parent d15101ee
......@@ -115,7 +115,27 @@ struct decoder_owner_sys_t
/* */
/* Pause */
bool b_paused;
mtime_t i_pause_date;
struct
{
mtime_t i_date;
} pause;
/* Buffering */
bool b_buffering;
struct
{
bool b_full;
int i_count;
picture_t *p_picture;
picture_t **pp_picture_next;
subpicture_t *p_subpic;
subpicture_t **pp_subpic_next;
aout_buffer_t *p_audio;
aout_buffer_t **pp_audio_next;
} buffer;
/* Flushing */
bool b_flushing;
......@@ -281,9 +301,10 @@ void input_DecoderDelete( decoder_t *p_dec )
{
/* Make sure we aren't paused anymore */
vlc_mutex_lock( &p_owner->lock );
if( p_owner->b_paused )
if( p_owner->b_paused || p_owner->b_buffering )
{
p_owner->b_paused = false;
p_owner->b_buffering = false;
vlc_cond_signal( &p_owner->wait );
}
vlc_mutex_unlock( &p_owner->lock );
......@@ -468,7 +489,7 @@ void input_DecoderChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date )
assert( !p_owner->b_paused || !b_paused );
p_owner->b_paused = b_paused;
p_owner->i_pause_date = i_date;
p_owner->pause.i_date = i_date;
if( p_owner->b_own_thread )
vlc_cond_signal( &p_owner->wait );
......@@ -493,11 +514,38 @@ void input_DecoderStartBuffering( decoder_t *p_dec )
DecoderFlush( p_dec );
p_owner->buffer.b_full = false;
p_owner->buffer.i_count = 0;
assert( !p_owner->buffer.p_picture && !p_owner->buffer.p_subpic && !p_owner->buffer.p_audio );
p_owner->buffer.p_picture = NULL;
p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture;
p_owner->buffer.p_subpic = NULL;
p_owner->buffer.pp_subpic_next = &p_owner->buffer.p_subpic;
p_owner->buffer.p_audio = NULL;
p_owner->buffer.pp_audio_next = &p_owner->buffer.p_audio;
p_owner->b_buffering = true;
vlc_cond_signal( &p_owner->wait );
vlc_mutex_unlock( &p_owner->lock );
}
void input_DecoderStopBuffering( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_mutex_lock( &p_owner->lock );
p_owner->b_buffering = false;
vlc_cond_signal( &p_owner->wait );
vlc_mutex_unlock( &p_owner->lock );
}
/*****************************************************************************
......@@ -641,6 +689,23 @@ static decoder_t * CreateDecoder( input_thread_t *p_input,
}
}
}
/* */
vlc_mutex_init( &p_owner->lock );
vlc_cond_init( &p_owner->wait );
p_owner->b_paused = false;
p_owner->pause.i_date = 0;
p_owner->b_buffering = false;
p_owner->buffer.b_full = false;
p_owner->buffer.i_count = 0;
p_owner->buffer.p_picture = NULL;
p_owner->buffer.p_subpic = NULL;
p_owner->buffer.p_audio = NULL;
p_owner->b_flushing = false;
/* */
p_owner->cc.b_supported = false;
if( i_object_type == VLC_OBJECT_DECODER )
......@@ -651,11 +716,6 @@ static decoder_t * CreateDecoder( input_thread_t *p_input,
p_owner->cc.b_supported = true;
}
vlc_mutex_init( &p_owner->lock );
vlc_cond_init( &p_owner->wait );
p_owner->b_paused = false;
p_owner->i_pause_date = 0;
p_owner->b_flushing = false;
for( i = 0; i < 4; i++ )
{
p_owner->cc.pb_present[i] = false;
......@@ -740,21 +800,6 @@ static void DecoderFlush( decoder_t *p_dec )
}
}
static void DecoderWaitUnpause( decoder_t *p_dec, bool *pb_reject )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_mutex_lock( &p_owner->lock );
while( p_owner->b_paused && !p_owner->b_flushing )
vlc_cond_wait( &p_owner->wait, &p_owner->lock );
if( pb_reject )
*pb_reject = p_owner->b_flushing;
vlc_mutex_unlock( &p_owner->lock );
}
static void DecoderSignalFlushed( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
......@@ -784,17 +829,32 @@ static bool DecoderIsFlushing( decoder_t *p_dec )
return b_flushing;
}
static void DecoderWaitUnblock( decoder_t *p_dec, bool *pb_reject )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_assert_locked( &p_owner->lock );
while( !p_owner->b_flushing )
{
if( !p_owner->b_paused && ( !p_owner->b_buffering || !p_owner->buffer.b_full ) )
break;
vlc_cond_wait( &p_owner->wait, &p_owner->lock );
}
if( pb_reject )
*pb_reject = p_owner->b_flushing;
}
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;
*pi_ts_delay = p_owner->p_input->i_pts_delay;
vlc_assert_locked( &p_owner->lock );
vlc_mutex_lock( &p_owner->lock );
*pi_ts_delay = p_owner->p_input->i_pts_delay;
*pi_es_delay = p_owner->i_ts_delay;
vlc_mutex_unlock( &p_owner->lock );
}
static void DecoderOutputChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date )
......@@ -843,28 +903,47 @@ static mtime_t DecoderTeletextFixTs( mtime_t i_ts, mtime_t i_ts_delay )
return i_ts;
}
static void DecoderSoutBufferFixTs( block_t *p_block,
input_clock_t *p_clock,
mtime_t i_ts_delay, mtime_t i_es_delay,
bool b_teletext )
static void DecoderFixTs( mtime_t *pi_ts0, mtime_t *pi_ts1, mtime_t *pi_duration, int *pi_rate,
input_clock_t *p_clock, mtime_t i_ts_delay, mtime_t i_es_delay )
{
assert( p_clock );
int i_rate = 0;
if( !p_clock )
return;
const bool b_ephemere = pi_ts1 && *pi_ts0 == *pi_ts1;
if( !p_block->i_dts && !p_block->i_pts )
p_block->i_rate = input_clock_GetRate( p_clock );
if( *pi_ts0 > 0 )
*pi_ts0 = input_clock_GetTS( p_clock, &i_rate, i_ts_delay,
*pi_ts0 + i_es_delay );
if( pi_ts1 && *pi_ts1 > 0 )
*pi_ts1 = input_clock_GetTS( p_clock, &i_rate, i_ts_delay,
*pi_ts1 + i_es_delay );
if( p_block->i_dts > 0 )
p_block->i_dts = input_clock_GetTS( p_clock, &p_block->i_rate,
i_ts_delay, p_block->i_dts + i_es_delay);
/* Do not create ephemere data because of rounding errors */
if( !b_ephemere && pi_ts1 && *pi_ts0 == *pi_ts1 )
*pi_ts1 += 1;
if( p_block->i_pts > 0 )
p_block->i_pts = input_clock_GetTS( p_clock, &p_block->i_rate,
i_ts_delay, p_block->i_pts + i_es_delay );
if( i_rate <= 0 )
i_rate = input_clock_GetRate( p_clock );
if( p_block->i_length > 0 )
p_block->i_length = ( p_block->i_length * p_block->i_rate +
if( pi_duration )
*pi_duration = ( *pi_duration * i_rate +
INPUT_RATE_DEFAULT-1 ) / INPUT_RATE_DEFAULT;
if( pi_rate )
*pi_rate = i_rate;
}
static void DecoderSoutBufferFixTs( block_t *p_block,
input_clock_t *p_clock,
mtime_t i_ts_delay, mtime_t i_es_delay,
bool b_teletext )
{
assert( p_clock );
DecoderFixTs( &p_block->i_dts, &p_block->i_pts, &p_block->i_length,
&p_block->i_rate, p_clock, i_ts_delay, i_es_delay );
if( b_teletext )
p_block->i_pts = DecoderTeletextFixTs( p_block->i_pts, i_ts_delay );
}
......@@ -872,70 +951,94 @@ static void DecoderAoutBufferFixTs( aout_buffer_t *p_buffer, int *pi_rate,
input_clock_t *p_clock,
mtime_t i_ts_delay, mtime_t i_es_delay )
{
/* sout display module does not set clock */
if( !p_clock )
return;
if( !p_buffer->start_date && !p_buffer->end_date )
*pi_rate = input_clock_GetRate( p_clock );
if( p_buffer->start_date > 0 )
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 > 0 )
p_buffer->end_date =
input_clock_GetTS( p_clock, pi_rate,
i_ts_delay, p_buffer->end_date + i_es_delay );
DecoderFixTs( &p_buffer->start_date, &p_buffer->end_date, NULL,
pi_rate, p_clock, i_ts_delay, i_es_delay );
}
static void DecoderVoutBufferFixTs( picture_t *p_picture, int *pi_rate,
input_clock_t *p_clock,
mtime_t i_ts_delay, mtime_t i_es_delay )
{
/* sout display module does not set clock */
if( !p_clock )
return;
if( p_picture->date > 0 )
p_picture->date =
input_clock_GetTS( p_clock, pi_rate,
i_ts_delay, p_picture->date + i_es_delay );
DecoderFixTs( &p_picture->date, NULL, NULL,
pi_rate, p_clock, i_ts_delay, i_es_delay );
}
static void DecoderSpuBufferFixTs( subpicture_t *p_subpic,
input_clock_t *p_clock,
mtime_t i_ts_delay, mtime_t i_es_delay,
bool b_teletext )
{
bool b_ephemere = p_subpic->i_start == p_subpic->i_stop;
DecoderFixTs( &p_subpic->i_start, &p_subpic->i_stop, NULL,
NULL, p_clock, i_ts_delay, i_es_delay );
/* sout display module does not set clock */
if( !p_clock )
return;
if( b_teletext )
p_subpic->i_start = DecoderTeletextFixTs( p_subpic->i_start, i_ts_delay );
}
if( p_subpic->i_start > 0 )
p_subpic->i_start =
input_clock_GetTS( p_clock, NULL,
i_ts_delay, p_subpic->i_start + i_es_delay );
static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio, int i_block_rate,
int *pi_played_sum, int *pi_lost_sum )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
input_clock_t *p_clock = p_owner->p_clock;
aout_instance_t *p_aout = p_owner->p_aout;
aout_input_t *p_aout_input = p_owner->p_aout_input;
if( p_subpic->i_stop > 0 )
p_subpic->i_stop =
input_clock_GetTS( p_clock, NULL,
i_ts_delay, p_subpic->i_stop + i_es_delay );
vlc_mutex_lock( &p_owner->lock );
/* Do not create ephemere picture because of rounding errors */
if( !b_ephemere && p_subpic->i_start == p_subpic->i_stop )
p_subpic->i_stop++;
bool b_reject;
DecoderWaitUnblock( p_dec, &b_reject );
if( b_teletext )
p_subpic->i_start = DecoderTeletextFixTs( p_subpic->i_start, i_ts_delay );
mtime_t i_ts_delay;
mtime_t i_es_delay;
DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
vlc_mutex_unlock( &p_owner->lock );
int i_rate = INPUT_RATE_DEFAULT;
DecoderAoutBufferFixTs( p_audio, &i_rate, p_clock, i_ts_delay, i_es_delay );
if( !p_clock && i_block_rate > 0 )
i_rate = i_block_rate;
/* FIXME TODO take care of audio-delay for mdate check */
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 || !p_aout_input ||
p_audio->start_date <= 0 || p_audio->start_date > i_max_date ||
i_rate < INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE ||
i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
b_reject = true;
if( !b_reject )
{
/* Wait if we are too early
* FIXME that's plain ugly to do it here */
mwait( p_audio->start_date - AOUT_MAX_PREPARE_TIME );
if( !aout_DecPlay( p_aout, p_aout_input, p_audio, i_rate ) )
*pi_played_sum += 1;
*pi_lost_sum += aout_DecGetResetLost( p_aout, p_aout_input );
}
else
{
if( p_audio->start_date <= 0 )
{
msg_Warn( p_dec, "non-dated audio buffer received" );
}
else if( p_audio->start_date > i_max_date )
{
msg_Warn( p_aout, "received buffer in the future (%"PRId64")",
p_audio->start_date - mdate() );
}
*pi_lost_sum += 1;
aout_BufferFree( p_audio );
}
}
static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
input_thread_t *p_input = p_owner->p_input;
input_clock_t *p_clock = p_owner->p_clock;
aout_buffer_t *p_aout_buf;
int i_decoded = 0;
int i_lost = 0;
......@@ -973,52 +1076,8 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
p_owner->i_preroll_end = -1;
}
bool b_reject;
DecoderWaitUnpause( p_dec, &b_reject );
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_ts_delay, i_es_delay );
if( !p_clock && p_block && p_block->i_rate > 0 )
i_rate = p_block->i_rate;
/* FIXME TODO take care of audio-delay for mdate check */
const mtime_t i_max_date = mdate() + i_ts_delay +
i_es_delay * i_rate / INPUT_RATE_DEFAULT + AOUT_MAX_ADVANCE_TIME;
if( !b_reject &&
p_aout_buf->start_date > 0 &&
p_aout_buf->start_date <= i_max_date &&
i_rate >= INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE &&
i_rate <= INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
{
/* Wait if we are too early
* FIXME that's plain ugly to do it here */
mwait( p_aout_buf->start_date - AOUT_MAX_PREPARE_TIME );
if( !aout_DecPlay( p_aout, p_aout_input, p_aout_buf, i_rate ) )
i_played++;
i_lost += aout_DecGetResetLost( p_aout, p_aout_input );
}
else
{
if( p_aout_buf->start_date <= 0 )
{
msg_Warn( p_dec, "non-dated audio buffer received" );
}
else if( p_aout_buf->start_date > i_max_date )
{
msg_Warn( p_aout, "received buffer in the future (%"PRId64")",
p_aout_buf->start_date - mdate() );
}
i_lost++;
aout_DecDeleteBuffer( p_aout, p_aout_input, p_aout_buf );
}
DecoderPlayAudio( p_dec, p_aout_buf, p_block ? p_block->i_rate : 0,
&i_played, &i_lost );
}
/* Update ugly stat */
......@@ -1117,6 +1176,69 @@ static void VoutFlushPicture( vout_thread_t *p_vout, mtime_t i_max_date )
vlc_mutex_unlock( &p_vout->picture_lock );
}
static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
int *pi_played_sum, int *pi_lost_sum )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vout_thread_t *p_vout = p_owner->p_vout;
vlc_mutex_lock( &p_owner->lock );
bool b_reject;
DecoderWaitUnblock( p_dec, &b_reject );
mtime_t i_ts_delay;
mtime_t i_es_delay;
DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
vlc_mutex_unlock( &p_owner->lock );
int i_rate = INPUT_RATE_DEFAULT;
DecoderVoutBufferFixTs( p_picture, &i_rate, p_owner->p_clock, i_ts_delay, i_es_delay );
/* */
const mtime_t i_max_date = mdate() + i_ts_delay +
i_es_delay * i_rate / INPUT_RATE_DEFAULT + VOUT_BOGUS_DELAY;
if( p_picture->date <= 0 || p_picture->date >= i_max_date )
b_reject = true;
if( !b_reject )
{
if( i_rate != p_owner->i_last_rate )
{
/* Be sure to not display old picture after our own */
VoutFlushPicture( p_vout, p_picture->date );
p_owner->i_last_rate = i_rate;
}
vout_DatePicture( p_vout, p_picture, p_picture->date );
vout_DisplayPicture( p_vout, p_picture );
}
else
{
if( p_picture->date <= 0 )
{
msg_Warn( p_vout, "non-dated video buffer received" );
}
else
{
msg_Warn( p_vout, "early picture skipped (%"PRId64")",
p_picture->date - mdate() );
}
*pi_lost_sum += 1;
VoutDisplayedPicture( p_vout, p_picture );
}
int i_tmp_display;
int i_tmp_lost;
vout_GetResetStatistic( p_vout, &i_tmp_display, &i_tmp_lost );
*pi_played_sum += i_tmp_display;
*pi_lost_sum += i_tmp_lost;
}
static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
......@@ -1159,54 +1281,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) )
DecoderGetCc( p_dec, p_dec );
bool b_reject;
DecoderWaitUnpause( p_dec, &b_reject );
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, &i_rate, p_owner->p_clock, i_ts_delay, i_es_delay );
/* */
const mtime_t i_max_date = mdate() + i_ts_delay +
i_es_delay * i_rate / INPUT_RATE_DEFAULT + VOUT_BOGUS_DELAY;
if( !b_reject &&
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_DisplayPicture( p_vout, p_pic );
}
else
{
if( p_pic->date <= 0 )
{
msg_Warn( p_vout, "non-dated video buffer received" );
}
else
{
msg_Warn( p_vout, "early picture skipped (%"PRId64")",
p_pic->date - mdate() );
}
i_lost++;
VoutDisplayedPicture( p_vout, p_pic );
}
int i_tmp_display;
int i_tmp_lost;
vout_GetResetStatistic( p_vout, &i_tmp_display, &i_tmp_lost );
i_displayed += i_tmp_display;
i_lost += i_tmp_lost;
DecoderPlayVideo( p_dec, p_pic, &i_displayed, &i_lost );
}
if( i_decoded > 0 || i_lost > 0 || i_displayed > 0 )
{
......@@ -1224,6 +1299,54 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
}
}
static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic,
bool b_telx )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vout_thread_t *p_vout = p_owner->p_spu_vout;
/* Preroll does not work very well with subtitle */
vlc_mutex_lock( &p_owner->lock );
bool b_reject;
DecoderWaitUnblock( p_dec, &b_reject );
mtime_t i_ts_delay;
mtime_t i_es_delay;
DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
vlc_mutex_unlock( &p_owner->lock );
DecoderSpuBufferFixTs( p_subpic, p_owner->p_clock,
i_ts_delay, i_es_delay, b_telx );
if( !b_reject )
spu_DisplaySubpicture( p_vout->p_spu, p_subpic );
else
subpicture_Delete( p_subpic );
}
static void DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block,
bool b_telx )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_mutex_lock( &p_owner->lock );
bool b_reject;
DecoderWaitUnblock( p_dec, &b_reject );
mtime_t i_ts_delay;
mtime_t i_es_delay;
DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
vlc_mutex_unlock( &p_owner->lock );
DecoderSoutBufferFixTs( p_sout_block, p_owner->p_clock,
i_ts_delay, i_es_delay, b_telx );
sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block );
}
/* This function process a block for sout
*/
static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
......@@ -1275,17 +1398,7 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
p_sout_block->p_next = NULL;
DecoderWaitUnpause( p_dec, NULL );
mtime_t i_ts_delay;
mtime_t i_es_delay;
DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
DecoderSoutBufferFixTs( p_sout_block, p_owner->p_clock,
i_ts_delay, i_es_delay, b_telx );
sout_InputSendBuffer( p_owner->p_sout_input,
p_sout_block );
DecoderPlaySout( p_dec, p_block, b_telx );
p_sout_block = p_next;
}
......@@ -1392,7 +1505,7 @@ static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block, bool b_flus
*/
static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush )
{
decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
decoder_owner_sys_t *p_owner = p_dec->p_owner;
const bool b_telx = p_dec->fmt_in.i_codec == VLC_FOURCC('t','e','l','x');
input_thread_t *p_input = p_owner->p_input;
......@@ -1429,18 +1542,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
}
else
{
bool b_reject;
DecoderWaitUnpause( p_dec, &b_reject );
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 );
if( !b_reject )
spu_DisplaySubpicture( p_vout->p_spu, p_spu );
else
subpicture_Delete( p_spu );
DecoderPlaySpu( p_dec, p_spu, b_telx );
}
}
else
......
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