X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Fdecoder.c;h=8104e856f860d910d6a951cc6ae30e52051c61fb;hb=1e1fa17174226b07fddeab7930b81e72b1764b65;hp=c7e300a42bafece15c64f9bf90a2786d9b5fadf6;hpb=0357e2cf82ad87897a43ea3b5a2540aacff504a7;p=vlc diff --git a/src/input/decoder.c b/src/input/decoder.c index c7e300a42b..8104e856f8 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "audio_output/aout_internal.h" @@ -46,6 +47,8 @@ #include "input_internal.h" #include "clock.h" #include "decoder.h" +#include "event.h" +#include "ressource.h" #include "../video_output/vout_control.h" @@ -53,7 +56,8 @@ static decoder_t *CreateDecoder( input_thread_t *, es_format_t *, int, sout_inst static void DeleteDecoder( decoder_t * ); static void *DecoderThread( vlc_object_t * ); -static int DecoderProcess( decoder_t *, block_t * ); +static void DecoderProcess( decoder_t *, block_t * ); +static void DecoderError( decoder_t *p_dec, block_t *p_block ); static void DecoderOutputChangePause( decoder_t *, bool b_paused, mtime_t i_date ); static void DecoderFlush( decoder_t * ); static void DecoderSignalBuffering( decoder_t *, bool ); @@ -98,6 +102,11 @@ struct decoder_owner_sys_t audio_format_t audio; es_format_t sout; + /* */ + bool b_fmt_description; + es_format_t fmt_description; + vlc_meta_t *p_description; + /* fifo */ block_fifo_t *p_fifo; @@ -137,6 +146,9 @@ struct decoder_owner_sys_t aout_buffer_t *p_audio; aout_buffer_t **pp_audio_next; + + block_t *p_block; + block_t **pp_block_next; } buffer; /* Flushing */ @@ -158,9 +170,48 @@ struct decoder_owner_sys_t #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 ) + return NULL; + return p_decoder->pf_aout_buffer_new( p_decoder, i_size ); +} +void decoder_DeleteAudioBuffer( decoder_t *p_decoder, aout_buffer_t *p_buffer ) +{ + p_decoder->pf_aout_buffer_del( p_decoder, p_buffer ); +} + subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder ) { subpicture_t *p_subpicture = p_decoder->pf_spu_buffer_new( p_decoder ); @@ -261,8 +312,7 @@ decoder_t *input_DecoderNew( input_thread_t *p_input, i_priority = VLC_THREAD_PRIORITY_VIDEO; /* Spawn the decoder thread */ - if( vlc_thread_create( p_dec, "decoder", DecoderThread, - i_priority, false ) ) + if( vlc_thread_create( p_dec, "decoder", DecoderThread, i_priority ) ) { msg_Err( p_dec, "cannot spawn decoder thread" ); module_unneed( p_dec, p_dec->p_module ); @@ -287,14 +337,12 @@ void input_DecoderDelete( decoder_t *p_dec ) vlc_object_kill( p_dec ); - /* Make sure we aren't paused anymore */ + /* Make sure we aren't paused/buffering/waiting anymore */ vlc_mutex_lock( &p_owner->lock ); - 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 ); - } + p_owner->b_paused = false; + p_owner->b_buffering = false; + p_owner->b_flushing = true; + vlc_cond_signal( &p_owner->wait ); vlc_mutex_unlock( &p_owner->lock ); vlc_thread_join( p_dec ); @@ -328,7 +376,12 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block ) 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 */ ) { @@ -474,7 +527,8 @@ void input_DecoderStartBuffering( decoder_t *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 ); + 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; @@ -485,6 +539,10 @@ void input_DecoderStartBuffering( decoder_t *p_dec ) 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 ); @@ -519,6 +577,7 @@ void input_DecoderWaitBuffering( decoder_t *p_dec ) vlc_mutex_unlock( &p_owner->lock ); } + void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration ) { decoder_owner_sys_t *p_owner = p_dec->p_owner; @@ -543,6 +602,34 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration ) vlc_mutex_unlock( &p_owner->lock ); } +bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_meta_t **pp_meta ) +{ + decoder_owner_sys_t *p_owner = p_dec->p_owner; + bool b_changed; + + vlc_mutex_lock( &p_owner->lock ); + b_changed = p_owner->b_fmt_description; + if( b_changed ) + { + if( p_fmt ) + es_format_Copy( p_fmt, &p_owner->fmt_description ); + + if( pp_meta ) + { + *pp_meta = NULL; + if( p_owner->p_description ) + { + *pp_meta = vlc_meta_New(); + if( *pp_meta ) + vlc_meta_Merge( *pp_meta, p_owner->p_description ); + } + } + p_owner->b_fmt_description = false; + } + vlc_mutex_unlock( &p_owner->lock ); + return b_changed; +} + /***************************************************************************** * Internal functions *****************************************************************************/ @@ -565,7 +652,7 @@ static mtime_t DecoderGetDisplayDate( decoder_t *p_dec, mtime_t i_ts ) if( !p_owner->p_clock || !i_ts ) return i_ts; - return input_clock_GetTS( p_owner->p_clock, NULL, p_owner->p_input->i_pts_delay, i_ts ); + return input_clock_GetTS( p_owner->p_clock, NULL, p_owner->p_input->p->i_pts_delay, i_ts ); } static int DecoderGetDisplayRate( decoder_t *p_dec ) { @@ -613,13 +700,15 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, p_dec->pf_get_cc = NULL; p_dec->pf_packetize = NULL; - /* Initialize the decoder fifo */ + /* Initialize the decoder */ p_dec->p_module = NULL; memset( &null_es_format, 0, sizeof(es_format_t) ); es_format_Copy( &p_dec->fmt_in, fmt ); es_format_Copy( &p_dec->fmt_out, &null_es_format ); + p_dec->p_description = NULL; + /* Allocate our private structure for the decoder */ p_dec->p_owner = p_owner = malloc( sizeof( decoder_owner_sys_t ) ); if( p_dec->p_owner == NULL ) @@ -666,9 +755,9 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, /* Find a suitable decoder/packetizer module */ if( i_object_type == VLC_OBJECT_DECODER ) - p_dec->p_module = module_need( p_dec, "decoder", "$codec", 0 ); + p_dec->p_module = module_need( p_dec, "decoder", "$codec", false ); else - p_dec->p_module = module_need( p_dec, "packetizer", "$packetizer", 0 ); + p_dec->p_module = module_need( p_dec, "packetizer", "$packetizer", false ); /* Check if decoder requires already packetized data */ if( i_object_type == VLC_OBJECT_DECODER && @@ -688,7 +777,7 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, p_dec->p_owner->p_packetizer->p_module = module_need( p_dec->p_owner->p_packetizer, - "packetizer", "$packetizer", 0 ); + "packetizer", "$packetizer", false ); if( !p_dec->p_owner->p_packetizer->p_module ) { @@ -721,6 +810,10 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, vlc_mutex_init( &p_owner->lock ); vlc_cond_init( &p_owner->wait ); + p_owner->b_fmt_description = false; + es_format_Init( &p_owner->fmt_description, UNKNOWN_ES, 0 ); + p_owner->p_description = NULL; + p_owner->b_paused = false; p_owner->pause.i_date = 0; p_owner->pause.i_ignore = 0; @@ -732,6 +825,7 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, 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; @@ -765,27 +859,26 @@ static void *DecoderThread( vlc_object_t *p_this ) decoder_owner_sys_t *p_owner = p_dec->p_owner; /* The decoder's main loop */ - for (;;) + 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 ) { + int canc = vlc_savecancel(); + if( p_dec->b_error ) - { /* Trash all received PES packets */ - block_Release( p_block ); - } - else if( DecoderProcess( p_dec, p_block ) != VLC_SUCCESS ) - { - break; - } + DecoderError( p_dec, p_block ); + else + DecoderProcess( p_dec, p_block ); + + vlc_restorecancel( canc ); } } - - DecoderSignalBuffering( p_dec, true ); return NULL; } @@ -950,7 +1043,7 @@ static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1, vlc_assert_locked( &p_owner->lock ); - const mtime_t i_ts_delay = p_owner->p_input->i_pts_delay; + const mtime_t i_ts_delay = p_owner->p_input->p->i_pts_delay; const mtime_t i_es_delay = p_owner->i_ts_delay; if( p_clock ) @@ -1070,12 +1163,23 @@ static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio, i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE ) b_reject = true; - if( !b_reject ) + /* Do not wait against unprotected date */ + const mtime_t i_deadline = p_audio->start_date - AOUT_MAX_PREPARE_TIME; + while( !b_reject && i_deadline > mdate() ) { - /* Wait if we are too early - * FIXME that's plain ugly to do it here */ - mwait( p_audio->start_date - AOUT_MAX_PREPARE_TIME ); + vlc_mutex_lock( &p_owner->lock ); + if( p_owner->b_flushing || p_dec->b_die ) + { + b_reject = true; + vlc_mutex_unlock( &p_owner->lock ); + break; + } + vlc_cond_timedwait( &p_owner->wait, &p_owner->lock, i_deadline ); + vlc_mutex_unlock( &p_owner->lock ); + } + if( !b_reject ) + { 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 ); @@ -1120,8 +1224,6 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block ) { aout_instance_t *p_aout = p_owner->p_aout; aout_input_t *p_aout_input = p_owner->p_aout_input; - int i_lost = 0; - int i_played; if( p_dec->b_die ) { @@ -1270,9 +1372,6 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, } /* */ - int i_rate = INPUT_RATE_DEFAULT; - mtime_t i_delay; - if( b_buffering_first ) { assert( p_owner->buffer.b_first ); @@ -1280,17 +1379,17 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, msg_Dbg( p_dec, "Received first picture" ); p_owner->buffer.b_first = false; p_picture->b_force = true; - i_delay = 0; - if( p_owner->p_clock ) - i_rate = input_clock_GetRate( p_owner->p_clock ); } + + int i_rate = INPUT_RATE_DEFAULT; + mtime_t i_delay; DecoderFixTs( p_dec, &p_picture->date, NULL, NULL, &i_rate, &i_delay, false ); 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; @@ -1484,18 +1583,69 @@ static void DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block, 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 ); - 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.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 ); + } + } - vlc_mutex_unlock( &p_owner->lock ); + 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; + + p_owner->buffer.p_block = p_sout_block->p_next; + p_owner->buffer.i_count--; + + 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; + } + } } /* */ @@ -1542,6 +1692,14 @@ static void DecoderFlushBuffering( decoder_t *p_dec ) 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 @@ -1715,7 +1873,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL ); vlc_mutex_unlock( &p_input->p->counters.counters_lock ); - p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); + p_vout = input_ressource_HoldVout( p_input->p->p_ressource ); if( p_vout && p_owner->p_spu_vout == p_vout ) { /* Preroll does not work very well with subtitle */ @@ -1740,7 +1898,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush if( b_flush && p_owner->p_spu_vout ) { - p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); + p_vout = input_ressource_HoldVout( p_input->p->p_ressource ); if( p_vout && p_owner->p_spu_vout == p_vout ) spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, @@ -1751,6 +1909,17 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush } } +/* */ +static void DecoderProcessOnFlush( decoder_t *p_dec ) +{ + decoder_owner_sys_t *p_owner = p_dec->p_owner; + + vlc_mutex_lock( &p_owner->lock ); + DecoderFlushBuffering( p_dec ); + vlc_mutex_unlock( &p_owner->lock ); + + DecoderSignalFlushed( p_dec ); +} /** * Decode a block * @@ -1758,7 +1927,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush * \param p_block the block to decode * \return VLC_SUCCESS or an error code */ -static int DecoderProcess( decoder_t *p_dec, block_t *p_block ) +static void 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); @@ -1767,12 +1936,11 @@ static int DecoderProcess( decoder_t *p_dec, block_t *p_block ) { assert( !b_flush_request ); block_Release( p_block ); - return VLC_SUCCESS; + return; } - int canc = vlc_savecancel (); #ifdef ENABLE_SOUT - if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER ) + if( vlc_internals( p_dec )->i_object_type == VLC_OBJECT_PACKETIZER ) { if( p_block ) p_block->i_flags &= ~BLOCK_FLAG_CORE_PRIVATE_MASK; @@ -1815,18 +1983,22 @@ static int DecoderProcess( decoder_t *p_dec, block_t *p_block ) /* */ if( b_flush_request ) - { - vlc_mutex_lock( &p_owner->lock ); - DecoderFlushBuffering( p_dec ); - vlc_mutex_unlock( &p_owner->lock ); + DecoderProcessOnFlush( p_dec ); +} - DecoderSignalFlushed( p_dec ); - } - vlc_restorecancel(canc); +static void DecoderError( decoder_t *p_dec, block_t *p_block ) +{ + const bool b_flush_request = p_block && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH); - return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS; + /* */ + if( p_block ) + block_Release( p_block ); + + if( b_flush_request ) + DecoderProcessOnFlush( p_dec ); } + /** * Destroys a decoder object * @@ -1855,7 +2027,9 @@ static void DeleteDecoder( decoder_t * p_dec ) aout_DecDelete( p_owner->p_aout, p_owner->p_aout_input ); if( p_owner->p_aout ) { - vlc_object_release( p_owner->p_aout ); + input_ressource_RequestAout( p_owner->p_input->p->p_ressource, + p_owner->p_aout ); + input_SendEventAout( p_owner->p_input ); p_owner->p_aout = NULL; } if( p_owner->p_vout ) @@ -1863,9 +2037,9 @@ static void DeleteDecoder( decoder_t * p_dec ) /* Hack to make sure all the the pictures are freed by the decoder */ vout_FixLeaks( p_owner->p_vout, true ); - /* 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_ressource_RequestVout( p_owner->p_input->p->p_ressource, p_owner->p_vout, NULL ); + input_SendEventVout( p_owner->p_input ); } #ifdef ENABLE_SOUT @@ -1880,17 +2054,22 @@ static void DeleteDecoder( decoder_t * p_dec ) { vout_thread_t *p_vout; - p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); - if( p_vout && p_owner->p_spu_vout == p_vout ) + p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource ); + if( p_vout ) { - spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, - p_owner->i_spu_channel ); + if( p_owner->p_spu_vout == p_vout ) + spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, p_owner->i_spu_channel ); vlc_object_release( p_vout ); } } es_format_Clean( &p_dec->fmt_in ); es_format_Clean( &p_dec->fmt_out ); + if( p_dec->p_description ) + vlc_meta_Delete( p_dec->p_description ); + es_format_Clean( &p_owner->fmt_description ); + if( p_owner->p_description ) + vlc_meta_Delete( p_owner->p_description ); if( p_owner->p_packetizer ) { @@ -1898,6 +2077,8 @@ static void DeleteDecoder( decoder_t * p_dec ) p_owner->p_packetizer->p_module ); es_format_Clean( &p_owner->p_packetizer->fmt_in ); es_format_Clean( &p_owner->p_packetizer->fmt_out ); + if( p_owner->p_packetizer->p_description ) + vlc_meta_Delete( p_owner->p_packetizer->p_description ); vlc_object_detach( p_owner->p_packetizer ); vlc_object_release( p_owner->p_packetizer ); } @@ -1913,6 +2094,35 @@ static void DeleteDecoder( decoder_t * p_dec ) /***************************************************************************** * Buffers allocation callbacks for the decoders *****************************************************************************/ +static void DecoderUpdateFormatLocked( decoder_t *p_dec ) +{ + decoder_owner_sys_t *p_owner = p_dec->p_owner; + + vlc_assert_locked( &p_owner->lock ); + + p_owner->b_fmt_description = true; + + /* Copy es_format */ + es_format_Clean( &p_owner->fmt_description ); + es_format_Copy( &p_owner->fmt_description, &p_dec->fmt_out ); + + /* Move p_description */ + if( p_owner->p_description && p_dec->p_description ) + vlc_meta_Delete( p_owner->p_description ); + p_owner->p_description = p_dec->p_description; + p_dec->p_description = NULL; +} +static vout_thread_t *aout_request_vout( void *p_private, + vout_thread_t *p_vout, video_format_t *p_fmt ) +{ + decoder_t *p_dec = p_private; + + p_vout = input_ressource_RequestVout( p_dec->p_owner->p_input->p->p_ressource, p_vout, p_fmt ); + input_SendEventVout( p_dec->p_owner->p_input ); + + return p_vout; +} + static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) { decoder_owner_sys_t *p_owner = p_dec->p_owner; @@ -1944,15 +2154,17 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) audio_sample_format_t format; aout_input_t *p_aout_input; aout_instance_t *p_aout; + aout_request_vout_t request_vout; p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec; 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; @@ -1964,15 +2176,25 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) } } + request_vout.pf_request_vout = aout_request_vout; + request_vout.p_private = p_dec; + p_aout = p_owner->p_aout; + if( !p_aout ) + p_aout = input_ressource_RequestAout( p_owner->p_input->p->p_ressource, NULL ); p_aout_input = aout_DecNew( p_dec, &p_aout, - &format, &p_dec->fmt_out.audio_replay_gain ); + &format, &p_dec->fmt_out.audio_replay_gain, &request_vout ); vlc_mutex_lock( &p_owner->lock ); + p_owner->p_aout = p_aout; p_owner->p_aout_input = p_aout_input; + DecoderUpdateFormatLocked( p_dec ); + vlc_mutex_unlock( &p_owner->lock ); + input_SendEventAout( p_owner->p_input ); + if( p_owner->p_aout_input == NULL ) { msg_Err( p_dec, "failed to create audio output" ); @@ -2073,13 +2295,17 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) p_owner->p_vout = NULL; vlc_mutex_unlock( &p_owner->lock ); - p_vout = vout_Request( p_dec, p_vout, &p_dec->fmt_out.video ); + p_vout = input_ressource_RequestVout( p_owner->p_input->p->p_ressource, + p_vout, &p_dec->fmt_out.video ); vlc_mutex_lock( &p_owner->lock ); p_owner->p_vout = p_vout; + + DecoderUpdateFormatLocked( p_dec ); + 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" ); @@ -2157,11 +2383,11 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec ) if( p_dec->b_die || p_dec->b_error ) break; - p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); + p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource ); if( p_vout ) break; - msleep( VOUT_DISPLAY_DELAY ); + msleep( DECODER_SPU_VOUT_WAIT_DURATION ); } if( !p_vout ) @@ -2202,7 +2428,7 @@ static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic ) decoder_owner_sys_t *p_owner = p_dec->p_owner; vout_thread_t *p_vout = NULL; - p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); + p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource ); if( !p_vout || p_owner->p_spu_vout != p_vout ) { if( p_vout )