static void *DecoderThread( void * );
static void DecoderProcess( decoder_t *, block_t * );
static void DecoderFlush( decoder_t * );
-static void DecoderSignalWait( decoder_t *, bool );
+static void DecoderSignalWait( decoder_t * );
static void DecoderUnsupportedCodec( decoder_t *, vlc_fourcc_t );
} pause;
/* Waiting */
+ bool b_woken;
bool b_waiting;
bool b_first;
bool b_has_data;
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- if( b_do_pace )
- {
- /* The fifo is not consumed when waiting and so will
- * deadlock vlc.
- * There is no need to lock as b_waiting is never modified
- * inside decoder thread. */
- if( !p_owner->b_waiting )
- block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX );
- }
-#ifdef __arm__
- else if( block_FifoSize( p_owner->p_fifo ) > 50*1024*1024 /* 50 MiB */ )
-#else
- else if( block_FifoSize( p_owner->p_fifo ) > 400*1024*1024 /* 400 MiB, ie ~ 50mb/s for 60s */ )
-#endif
+ vlc_fifo_Lock( p_owner->p_fifo );
+ if( !b_do_pace )
{
/* FIXME: ideally we would check the time amount of data
* in the FIFO instead of its size. */
- msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
- "consumed quickly enough), resetting fifo!" );
- block_FifoEmpty( p_owner->p_fifo );
+ /* 400 MiB, i.e. ~ 50mb/s for 60s */
+ if( vlc_fifo_GetBytes( p_owner->p_fifo ) > 400*1024*1024 )
+ {
+ msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
+ "consumed quickly enough), resetting fifo!" );
+ block_ChainRelease( vlc_fifo_DequeueAllUnlocked( p_owner->p_fifo ) );
+ }
+ }
+ else
+ if( !p_owner->b_waiting )
+ { /* The FIFO is not consumed when waiting, so pacing would deadlock VLC.
+ * Locking is not necessary as b_waiting is only read, not written by
+ * the decoder thread. */
+ while( vlc_fifo_GetCount( p_owner->p_fifo ) >= 10 )
+ vlc_fifo_WaitCond( p_owner->p_fifo, &p_owner->wait_acknowledge );
}
- block_FifoPut( p_owner->p_fifo, p_block );
+ vlc_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
+ vlc_fifo_Unlock( p_owner->p_fifo );
}
bool input_DecoderIsEmpty( decoder_t * p_dec )
{
vlc_mutex_lock( &p_owner->lock );
/* TODO subtitles support */
- if( p_dec->fmt_out.i_cat == VIDEO_ES && p_owner->p_vout )
+ if( p_owner->fmt.i_cat == VIDEO_ES && p_owner->p_vout )
b_empty = vout_IsEmpty( p_owner->p_vout );
- else if( p_dec->fmt_out.i_cat == AUDIO_ES && p_owner->p_aout )
+ else if( p_owner->fmt.i_cat == AUDIO_ES && p_owner->p_aout )
b_empty = aout_DecIsEmpty( p_owner->p_aout );
vlc_mutex_unlock( &p_owner->lock );
}
vlc_mutex_unlock( &p_owner->lock );
}
-void input_DecoderStartWait( decoder_t *p_dec )
+/**
+ * Requests that the decoder immediately discard all pending buffers.
+ * This is useful at end of stream, when seeking or when deselecting a stream.
+ */
+void input_DecoderFlush( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_mutex_lock( &p_owner->lock );
-
DecoderFlush( p_dec );
+ vlc_mutex_unlock( &p_owner->lock );
+}
+
+void input_DecoderStartWait( decoder_t *p_dec )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+ assert( !p_owner->b_waiting );
+ vlc_mutex_lock( &p_owner->lock );
p_owner->b_first = true;
p_owner->b_has_data = false;
-
p_owner->b_waiting = true;
-
vlc_cond_signal( &p_owner->wait_request );
-
vlc_mutex_unlock( &p_owner->lock );
}
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- vlc_mutex_lock( &p_owner->lock );
+ assert( p_owner->b_waiting );
+ vlc_mutex_lock( &p_owner->lock );
p_owner->b_waiting = false;
-
vlc_cond_signal( &p_owner->wait_request );
-
vlc_mutex_unlock( &p_owner->lock );
}
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- vlc_mutex_lock( &p_owner->lock );
+ assert( p_owner->b_waiting );
- while( p_owner->b_waiting && !p_owner->b_has_data )
+ vlc_mutex_lock( &p_owner->lock );
+ while( !p_owner->b_has_data )
{
- block_FifoWake( p_owner->p_fifo );
+ vlc_fifo_Lock( p_owner->p_fifo );
+ p_owner->b_woken = true;
+ vlc_fifo_Signal( p_owner->p_fifo );
+ vlc_fifo_Unlock( p_owner->p_fifo );
vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
}
-
vlc_mutex_unlock( &p_owner->lock );
}
else
{
/* TODO subtitle should not be flushed */
+ p_owner->b_waiting = false;
DecoderFlush( p_dec );
}
vlc_mutex_unlock( &p_owner->lock );
es_format_Init( &p_owner->fmt, UNKNOWN_ES, 0 );
/* decoder fifo */
+ p_owner->b_woken = false;
p_owner->p_fifo = block_FifoNew();
if( unlikely(p_owner->p_fifo == NULL) )
{
/* The decoder's main loop */
for( ;; )
{
- block_t *p_block = block_FifoGet( p_owner->p_fifo );
+ block_t *p_block;
+
+ vlc_fifo_Lock( p_owner->p_fifo );
+ vlc_fifo_CleanupPush( p_owner->p_fifo );
- /* Make sure there is no cancellation point other than this one^^.
- * If you need one, be sure to push cleanup of p_block. */
- bool end_wait = !p_block || p_block->i_flags & BLOCK_FLAG_CORE_EOS;
- DecoderSignalWait( p_dec, end_wait );
- if (end_wait)
- input_DecoderStopWait( p_dec );
+ while( vlc_fifo_IsEmpty( p_owner->p_fifo ) )
+ {
+ if( p_owner->b_woken )
+ break;
+ vlc_fifo_Wait( p_owner->p_fifo );
+ /* Make sure there is no cancellation point other than this one^^.
+ * If you need one, be sure to push cleanup of p_block. */
+ }
+
+ p_block = vlc_fifo_DequeueUnlocked( p_owner->p_fifo );
+ if( p_block != NULL )
+ vlc_cond_signal( &p_owner->wait_acknowledge );
+
+ p_owner->b_woken = false;
+ vlc_cleanup_run();
+
+ if( p_block == NULL || p_block->i_flags & BLOCK_FLAG_CORE_EOS )
+ DecoderSignalWait( p_dec );
if( p_block )
{
/* Empty the fifo */
block_FifoEmpty( p_owner->p_fifo );
- p_owner->b_waiting = false;
/* Monitor for flush end */
p_owner->b_flushing = true;
vlc_cond_signal( &p_owner->wait_request );
vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
}
-static void DecoderSignalWait( decoder_t *p_dec, bool b_has_data )
+static void DecoderSignalWait( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
if( p_owner->b_waiting )
{
- if( b_has_data )
- p_owner->b_has_data = true;
+ p_owner->b_has_data = true;
vlc_cond_signal( &p_owner->wait_acknowledge );
}
(unsigned)block_FifoCount( p_owner->p_fifo ) );
/* Free all packets still in the decoder fifo. */
- block_FifoEmpty( p_owner->p_fifo );
block_FifoRelease( p_owner->p_fifo );
/* Cleanup */
return NULL;
/* */
- DecoderSignalWait( p_dec, true );
+ DecoderSignalWait( p_dec );
/* Check the decoder doesn't leak pictures */
vout_FixLeaks( p_owner->p_vout );
while( i_attempts-- )
{
- if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
+ if( DecoderIsExitRequested( p_dec ) || DecoderIsFlushing( p_dec )
+ || p_dec->b_error )
break;
p_vout = input_resource_HoldVout( p_owner->p_resource );