X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Fdecoder.c;h=d0fdd1422945d69276357d49235d100a1dd2fc80;hb=b5277240aa78e2515cc4f32ca4b582160b2ee8d8;hp=45e2e784f4c6394a56437c290a754887b4b40ce3;hpb=57c3ecd2292588c7312afbb6935d414bfbe2e826;p=vlc diff --git a/src/input/decoder.c b/src/input/decoder.c index 45e2e784f4..d0fdd14229 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -463,7 +463,10 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, /* 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 ) + { + vlc_object_release( p_dec ); return NULL; + } p_dec->p_owner->b_own_thread = true; p_dec->p_owner->i_preroll_end = -1; p_dec->p_owner->p_input = p_input; @@ -478,7 +481,11 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, /* decoder fifo */ if( ( p_dec->p_owner->p_fifo = block_FifoNew() ) == NULL ) + { + free( p_dec->p_owner ); + vlc_object_release( p_dec ); return NULL; + } /* Set buffers allocation callbacks for the decoders */ p_dec->pf_aout_buffer_new = aout_new_buffer; @@ -612,20 +619,30 @@ static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p ) } static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block ) { - input_thread_t *p_input = p_dec->p_owner->p_input; - const int i_rate = p_block->i_rate; - aout_buffer_t *p_aout_buf; + input_thread_t *p_input = p_dec->p_owner->p_input; + const int i_rate = p_block->i_rate; + aout_buffer_t *p_aout_buf; while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) ) { + aout_instance_t *p_aout = p_dec->p_owner->p_aout; + aout_input_t *p_aout_input = p_dec->p_owner->p_aout_input; + + if( p_dec->b_die ) + { + /* It prevent freezing VLC in case of broken decoder */ + aout_DecDeleteBuffer( p_aout, p_aout_input, p_aout_buf ); + if( p_block ) + block_Release( p_block ); + break; + } vlc_mutex_lock( &p_input->p->counters.counters_lock ); stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_audio, 1, NULL ); vlc_mutex_unlock( &p_input->p->counters.counters_lock ); if( p_aout_buf->start_date < p_dec->p_owner->i_preroll_end ) { - aout_DecDeleteBuffer( p_dec->p_owner->p_aout, - p_dec->p_owner->p_aout_input, p_aout_buf ); + aout_DecDeleteBuffer( p_aout, p_aout_input, p_aout_buf ); continue; } @@ -635,9 +652,7 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block ) msg_Dbg( p_dec, "End of audio preroll" ); p_dec->p_owner->i_preroll_end = -1; } - aout_DecPlay( p_dec->p_owner->p_aout, - p_dec->p_owner->p_aout_input, - p_aout_buf, i_rate ); + aout_DecPlay( p_aout, p_aout_input, p_aout_buf, i_rate ); } } static void DecoderGetCc( decoder_t *p_dec, decoder_t *p_dec_cc ) @@ -818,25 +833,35 @@ static void optimize_video_pts( decoder_t *p_dec ) static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) { input_thread_t *p_input = p_dec->p_owner->p_input; - picture_t *p_pic; + picture_t *p_pic; while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) ) { + vout_thread_t *p_vout = p_dec->p_owner->p_vout; + if( p_dec->b_die ) + { + /* It prevent freezing VLC in case of broken decoder */ + VoutDisplayedPicture( p_vout, p_pic ); + if( p_block ) + block_Release( p_block ); + break; + } + vlc_mutex_lock( &p_input->p->counters.counters_lock ); stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_video, 1, NULL ); vlc_mutex_unlock( &p_input->p->counters.counters_lock ); if( p_pic->date < p_dec->p_owner->i_preroll_end ) { - VoutDisplayedPicture( p_dec->p_owner->p_vout, p_pic ); + VoutDisplayedPicture( p_vout, p_pic ); continue; } if( p_dec->p_owner->i_preroll_end > 0 ) { msg_Dbg( p_dec, "End of video preroll" ); - if( p_dec->p_owner->p_vout ) - VoutFlushPicture( p_dec->p_owner->p_vout ); + if( p_vout ) + VoutFlushPicture( p_vout ); /* */ p_dec->p_owner->i_preroll_end = -1; } @@ -844,12 +869,11 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) if( ( !p_dec->p_owner->p_packetizer || !p_dec->p_owner->p_packetizer->pf_get_cc ) && p_dec->pf_get_cc ) DecoderGetCc( p_dec, p_dec ); - vout_DatePicture( p_dec->p_owner->p_vout, p_pic, - p_pic->date ); + vout_DatePicture( p_vout, p_pic, p_pic->date ); optimize_video_pts( p_dec ); - vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic ); + vout_DisplayPicture( p_vout, p_pic ); } } @@ -1211,6 +1235,9 @@ static void aout_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer ) p_dec->p_owner->p_aout_input, p_buffer ); } + +int vout_CountPictureAvailable( vout_thread_t *p_vout ); + static picture_t *vout_new_buffer( decoder_t *p_dec ) { decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner; @@ -1293,14 +1320,25 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) p_sys->p_vout->render.i_bmask = p_sys->video.i_bmask; } - /* Get a new picture */ - while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) ) + /* Get a new picture + */ + for( p_pic = NULL; ; ) { int i_pic, i_ready_pic = 0; if( p_dec->b_die || p_dec->b_error ) - { return NULL; + + /* The video filter chain required that there is always 1 free buffer + * that it will use as temporary one. It will release the temporary + * buffer once its work is done, so this check is safe even if we don't + * lock around both count() and create(). + */ + if( vout_CountPictureAvailable( p_sys->p_vout ) >= 2 ) + { + p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ); + if( p_pic ) + break; } #define p_pic p_dec->p_owner->p_vout->render.pp_picture[i_pic]