bool b_paused;
mtime_t i_pause_date;
+ /* Flushing */
+ bool b_flushing;
+
/* CC */
struct
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
block_t *p_null;
- /* Empty the fifo */
if( p_owner->b_own_thread )
+ {
+ /* Empty the fifo */
block_FifoEmpty( p_owner->p_fifo );
+ /* Monitor for flush end */
+ vlc_mutex_lock( &p_owner->lock );
+ p_owner->b_flushing = true;
+ vlc_cond_signal( &p_owner->wait );
+ vlc_mutex_unlock( &p_owner->lock );
+ }
+
/* Send a special block */
p_null = block_New( p_dec, 128 );
+ if( !p_null )
+ return;
p_null->i_flags |= BLOCK_FLAG_DISCONTINUITY;
p_null->i_flags |= BLOCK_FLAG_CORE_FLUSH;
if( !p_dec->fmt_in.b_packetized )
memset( p_null->p_buffer, 0, p_null->i_buffer );
input_DecoderDecode( p_dec, p_null );
+
+ /* */
+ if( p_owner->b_own_thread )
+ {
+ vlc_mutex_lock( &p_owner->lock );
+ while( p_owner->b_flushing )
+ vlc_cond_wait( &p_owner->wait, &p_owner->lock );
+ vlc_mutex_unlock( &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;
return NULL;
}
-static void DecoderWaitUnpause( 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 )
+ 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;
+
+ vlc_mutex_lock( &p_owner->lock );
+
+ if( p_owner->b_flushing )
+ {
+ p_owner->b_flushing = false;
+ vlc_cond_signal( &p_owner->wait );
+ }
+
+ vlc_mutex_unlock( &p_owner->lock );
+}
+
+static bool DecoderIsFlushing( decoder_t *p_dec )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+ bool b_flushing;
+
+ vlc_mutex_lock( &p_owner->lock );
+
+ b_flushing = p_owner->b_flushing;
+
+ vlc_mutex_unlock( &p_owner->lock );
+
+ return 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;
p_owner->i_preroll_end = -1;
}
- DecoderWaitUnpause( p_dec );
+ bool b_reject;
+ DecoderWaitUnpause( p_dec, &b_reject );
int i_rate = INPUT_RATE_DEFAULT;
mtime_t i_ts_delay;
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( !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 )
( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) )
DecoderGetCc( p_dec, p_dec );
- DecoderWaitUnpause( p_dec );
+ bool b_reject;
+ DecoderWaitUnpause( p_dec, &b_reject );
mtime_t i_ts_delay;
mtime_t 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_pic->date > 0 && p_pic->date < i_max_date )
+ if( !b_reject &&
+ p_pic->date > 0 && p_pic->date < i_max_date )
{
if( i_rate != p_owner->i_last_rate )
{
p_sout_block->p_next = NULL;
- DecoderWaitUnpause( p_dec );
+ DecoderWaitUnpause( p_dec, NULL );
mtime_t i_ts_delay;
mtime_t i_es_delay;
{
decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
- if( b_flush && p_owner->p_vout )
- VoutFlushPicture( p_owner->p_vout, 1 );
-
if( p_owner->p_packetizer )
{
block_t *p_packetized_block;
{
DecoderDecodeVideo( p_dec, p_block );
}
+
+ if( b_flush && p_owner->p_vout )
+ VoutFlushPicture( p_owner->p_vout, 1 );
}
/* This function process a audio block
}
else
{
- DecoderWaitUnpause( 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 );
DecoderSpuBufferFixTs( p_spu, p_owner->p_clock, i_ts_delay, i_es_delay, b_telx );
- spu_DisplaySubpicture( p_vout->p_spu, p_spu );
+ if( !b_reject )
+ spu_DisplaySubpicture( p_vout->p_spu, p_spu );
+ else
+ subpicture_Delete( p_spu );
}
}
else
{
- msg_Warn( p_dec, "no vout found, leaking subpicture" );
+ subpicture_Delete( p_spu );
}
if( p_vout )
vlc_object_release( p_vout );
static int DecoderProcess( decoder_t *p_dec, block_t *p_block )
{
decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
+ const bool b_flush_request = p_block && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH);
if( p_block && p_block->i_buffer <= 0 )
{
+ assert( !b_flush_request );
block_Release( p_block );
return VLC_SUCCESS;
}
#ifdef ENABLE_SOUT
if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
{
+ if( p_block )
+ p_block->i_flags &= ~BLOCK_FLAG_CORE_PRIVATE_MASK;
+
DecoderProcessSout( p_dec, p_block );
}
else
const bool b_flushing = p_owner->i_preroll_end == INT64_MAX;
DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
- b_flush = !b_flushing && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH) != 0;
+ b_flush = !b_flushing && b_flush_request;
p_block->i_flags &= ~BLOCK_FLAG_CORE_PRIVATE_MASK;
}
}
}
+ /* */
+ if( b_flush_request )
+ DecoderSignalFlushed( p_dec );
+
return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS;
}
static picture_t *vout_new_buffer( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- picture_t *p_pic;
if( p_owner->p_vout == NULL ||
p_dec->fmt_out.video.i_width != p_owner->video.i_width ||
/* Get a new picture
*/
- for( p_pic = NULL; ; )
+ for( ;; )
{
+ picture_t *p_picture;
int i_pic, i_ready_pic;
if( p_dec->b_die || p_dec->b_error )
*/
if( vout_CountPictureAvailable( p_owner->p_vout ) >= 2 )
{
- p_pic = vout_CreatePicture( p_owner->p_vout, 0, 0, 0 );
- if( p_pic )
- break;
+ p_picture = vout_CreatePicture( p_owner->p_vout, 0, 0, 0 );
+ if( p_picture )
+ return p_picture;
}
+ if( DecoderIsFlushing( p_dec ) )
+ return NULL;
+
/* Check the decoder doesn't leak pictures */
for( i_pic = 0, i_ready_pic = 0; i_pic < p_owner->p_vout->render.i_pictures; i_pic++ )
{
/* Just free all the pictures */
for( i_pic = 0; i_pic < p_owner->p_vout->render.i_pictures; i_pic++ )
{
- const picture_t *p_pic = p_owner->p_vout->render.pp_picture[i_pic];
+ picture_t *p_pic = p_owner->p_vout->render.pp_picture[i_pic];
if( p_pic->i_status == RESERVED_PICTURE )
vout_DestroyPicture( p_owner->p_vout, p_pic );
msleep( VOUT_OUTMEM_SLEEP );
}
-
- return p_pic;
}
static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic )