aout_buffer_t *p_audio;
aout_buffer_t **pp_audio_next;
+
+ block_t *p_block;
+ block_t **pp_block_next;
} buffer;
/* Flushing */
#define DECODER_MAX_BUFFERING_AUDIO_DURATION (AOUT_MAX_PREPARE_TIME)
#define DECODER_MAX_BUFFERING_VIDEO_DURATION (1*CLOCK_FREQ)
+/* Pictures which are DECODER_BOGUS_VIDEO_DELAY or more in advance probably have
+ * a bogus PTS and won't be displayed */
+#define DECODER_BOGUS_VIDEO_DELAY ((mtime_t)(DEFAULT_PTS_DELAY * 30))
+
+/* */
+#define DECODER_SPU_VOUT_WAIT_DURATION ((int)(0.200*CLOCK_FREQ))
+
+
/*****************************************************************************
* Public functions
*****************************************************************************/
+picture_t *decoder_NewPicture( decoder_t *p_decoder )
+{
+ picture_t *p_picture = p_decoder->pf_vout_buffer_new( p_decoder );
+ if( !p_picture )
+ msg_Warn( p_decoder, "can't get output picture" );
+ return p_picture;
+}
+void decoder_DeletePicture( decoder_t *p_decoder, picture_t *p_picture )
+{
+ p_decoder->pf_vout_buffer_del( p_decoder, p_picture );
+}
+void decoder_LinkPicture( decoder_t *p_decoder, picture_t *p_picture )
+{
+ p_decoder->pf_picture_link( p_decoder, p_picture );
+}
+void decoder_UnlinkPicture( decoder_t *p_decoder, picture_t *p_picture )
+{
+ p_decoder->pf_picture_unlink( p_decoder, p_picture );
+}
+
aout_buffer_t *decoder_NewAudioBuffer( decoder_t *p_decoder, int i_size )
{
if( !p_decoder->pf_aout_buffer_new )
}
void decoder_DeleteAudioBuffer( decoder_t *p_decoder, aout_buffer_t *p_buffer )
{
- if( !p_decoder->pf_aout_buffer_del )
- return;
p_decoder->pf_aout_buffer_del( p_decoder, p_buffer );
}
}
vlc_mutex_unlock( &p_owner->lock );
- /* Make sure the thread leaves the function */
- block_FifoWake( p_owner->p_fifo );
-
vlc_thread_join( p_dec );
-
- /* Don't module_unneed() here because of the dll loader that wants
- * close() in the same thread than decode() */
+ module_unneed( p_dec, p_dec->p_module );
/* */
if( p_dec->p_owner->cc.b_supported )
if( p_owner->p_input->p->b_out_pace_control )
{
- block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX );
+ /* The fifo is not consummed when buffering and so will
+ * deadlock vlc.
+ * There is no need to lock as b_buffering is never modify
+ * inside decoder thread. */
+ if( !p_owner->b_buffering )
+ block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX );
}
else if( block_FifoSize( p_owner->p_fifo ) > 50000000 /* 50 MB */ )
{
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 );
+ assert( !p_owner->buffer.p_picture && !p_owner->buffer.p_subpic &&
+ !p_owner->buffer.p_audio && !p_owner->buffer.p_block );
p_owner->buffer.p_picture = NULL;
p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture;
p_owner->buffer.p_audio = NULL;
p_owner->buffer.pp_audio_next = &p_owner->buffer.p_audio;
+ p_owner->buffer.p_block = NULL;
+ p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;
+
+
p_owner->b_buffering = true;
vlc_cond_signal( &p_owner->wait );
p_owner->buffer.p_picture = NULL;
p_owner->buffer.p_subpic = NULL;
p_owner->buffer.p_audio = NULL;
+ p_owner->buffer.p_block = NULL;
p_owner->b_flushing = false;
decoder_t *p_dec = (decoder_t *)p_this;
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- int canc = vlc_savecancel();
-
/* The decoder's main loop */
- while( vlc_object_alive( p_dec ) )
+ for( ;; )
{
block_t *p_block = block_FifoGet( 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. */
DecoderSignalBuffering( p_dec, p_block == NULL );
if( p_block )
{
if( p_dec->b_error )
- { /* Trash all received PES packets */
block_Release( p_block );
- }
- else if( DecoderProcess( p_dec, p_block ) != VLC_SUCCESS )
- {
- break;
- }
+ else
+ DecoderProcess( p_dec, p_block );
}
}
DecoderSignalBuffering( p_dec, true );
-
- /* We do it here because of the dll loader that wants close() in the
- * same thread than decode() */
- module_unneed( p_dec, p_dec->p_module );
- vlc_restorecancel( canc );
return NULL;
}
vlc_mutex_unlock( &p_owner->lock );
/* */
- const mtime_t i_max_date = mdate() + i_delay + VOUT_BOGUS_DELAY;
+ const mtime_t i_max_date = mdate() + i_delay + DECODER_BOGUS_VIDEO_DELAY;
if( !p_picture->b_force && ( p_picture->date <= 0 || p_picture->date >= i_max_date ) )
b_reject = true;
decoder_owner_sys_t *p_owner = p_dec->p_owner;
assert( p_owner->p_clock );
+ assert( !p_sout_block->p_next );
vlc_mutex_lock( &p_owner->lock );
- bool b_reject;
- DecoderWaitUnblock( p_dec, &b_reject );
+ if( p_owner->b_buffering || p_owner->buffer.p_block )
+ {
+ block_ChainLastAppend( &p_owner->buffer.pp_block_next, p_sout_block );
+
+ p_owner->buffer.i_count++;
+ /* XXX it is important to be full after the first one */
+ if( p_owner->buffer.i_count > 0 )
+ {
+ p_owner->buffer.b_full = true;
+ vlc_cond_signal( &p_owner->wait );
+ }
+ }
+
+ for( ;; )
+ {
+ bool b_has_more = false;
+ bool b_reject;
+ DecoderWaitUnblock( p_dec, &b_reject );
+
+ if( p_owner->b_buffering )
+ {
+ vlc_mutex_unlock( &p_owner->lock );
+ return;
+ }
+
+ /* */
+ if( p_owner->buffer.p_block )
+ {
+ p_sout_block = p_owner->buffer.p_block;
- DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts, &p_sout_block->i_length,
- &p_sout_block->i_rate, NULL, b_telx );
+ p_owner->buffer.p_block = p_sout_block->p_next;
+ p_owner->buffer.i_count--;
- vlc_mutex_unlock( &p_owner->lock );
+ b_has_more = p_owner->buffer.p_block != NULL;
+ if( !b_has_more )
+ p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;
+ }
+ p_sout_block->p_next = NULL;
+
+ DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts,
+ &p_sout_block->i_length,
+ &p_sout_block->i_rate, NULL, b_telx );
+
+ vlc_mutex_unlock( &p_owner->lock );
+
+ if( !b_reject )
+ sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block );
+ else
+ block_Release( p_sout_block );
- sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block );
+ if( !b_has_more )
+ break;
+ vlc_mutex_lock( &p_owner->lock );
+ if( !p_owner->buffer.p_block )
+ {
+ vlc_mutex_unlock( &p_owner->lock );
+ break;
+ }
+ }
}
/* */
if( !p_owner->buffer.p_subpic )
p_owner->buffer.pp_subpic_next = &p_owner->buffer.p_subpic;
}
+ if( p_owner->buffer.p_block )
+ {
+ block_ChainRelease( p_owner->buffer.p_block );
+
+ p_owner->buffer.i_count = 0;
+ p_owner->buffer.p_block = NULL;
+ p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;
+ }
}
/* This function process a block for sout
return VLC_SUCCESS;
}
+ int canc = vlc_savecancel();
#ifdef ENABLE_SOUT
if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
{
DecoderSignalFlushed( p_dec );
}
+ vlc_restorecancel( canc );
return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS;
}
/* We are about to die. Reattach video output to p_vlc. */
vout_Request( p_dec, p_owner->p_vout, NULL );
- var_SetBool( p_owner->p_input, "intf-change-vout", true );
+ input_SendEventVout( p_owner->p_input );
}
#ifdef ENABLE_SOUT
p_owner->audio = p_dec->fmt_out.audio;
memcpy( &format, &p_owner->audio, sizeof( audio_sample_format_t ) );
- if ( i_force_dolby && (format.i_original_channels&AOUT_CHAN_PHYSMASK)
- == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
+ if( i_force_dolby &&
+ (format.i_original_channels&AOUT_CHAN_PHYSMASK) ==
+ (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
{
- if ( i_force_dolby == 1 )
+ if( i_force_dolby == 1 )
{
format.i_original_channels = format.i_original_channels |
AOUT_CHAN_DOLBYSTEREO;
p_owner->p_vout = p_vout;
vlc_mutex_unlock( &p_owner->lock );
- var_SetBool( p_owner->p_input, "intf-change-vout", true );
+ input_SendEventVout( p_owner->p_input );
if( p_vout == NULL )
{
msg_Err( p_dec, "failed to create video output" );
if( p_vout )
break;
- msleep( VOUT_DISPLAY_DELAY );
+ msleep( DECODER_SPU_VOUT_WAIT_DURATION );
}
if( !p_vout )