vlc | branch: master | Rafaël Carré <[email protected]> | Mon Jan 13 16:10:29 2014 +0100| [1e335d5e5e5baf1a5425b56edab27b07713fe7c3] | committer: Rafaël Carré
avcodec video decoder: returns delayed frames at end of stream Closes: #10331 > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=1e335d5e5e5baf1a5425b56edab27b07713fe7c3 --- modules/codec/avcodec/video.c | 126 +++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 50 deletions(-) diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c index 03435fb..83c5954 100644 --- a/modules/codec/avcodec/video.c +++ b/modules/codec/avcodec/video.c @@ -430,7 +430,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) int b_null_size = false; block_t *p_block; - if( !pp_block || !*pp_block ) + if( !pp_block ) return NULL; if( !p_context->extradata_size && p_dec->fmt_in.i_extra ) @@ -444,33 +444,40 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) } p_block = *pp_block; + if(!p_block && !(p_sys->p_codec->capabilities & CODEC_CAP_DELAY) ) + return NULL; + if( p_sys->b_delayed_open ) { - block_Release( p_block ); + if( p_block ) + block_Release( p_block ); return NULL; } - if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) + if( p_block) { - p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */ + if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) + { + p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */ - p_sys->i_late_frames = 0; + p_sys->i_late_frames = 0; - post_mt( p_sys ); - if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) - avcodec_flush_buffers( p_context ); - wait_mt( p_sys ); + post_mt( p_sys ); + if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) + avcodec_flush_buffers( p_context ); + wait_mt( p_sys ); - block_Release( p_block ); - return NULL; - } + block_Release( p_block ); + return NULL; + } - if( p_block->i_flags & BLOCK_FLAG_PREROLL ) - { - /* Do not care about late frames when prerolling - * TODO avoid decoding of non reference frame - * (ie all B except for H264 where it depends only on nal_ref_idc) */ - p_sys->i_late_frames = 0; + if( p_block->i_flags & BLOCK_FLAG_PREROLL ) + { + /* Do not care about late frames when prerolling + * TODO avoid decoding of non reference frame + * (ie all B except for H264 where it depends only on nal_ref_idc) */ + p_sys->i_late_frames = 0; + } } if( !p_dec->b_pace_control && (p_sys->i_late_frames > 0) && @@ -482,7 +489,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) "dropping frame (computer too slow ?)" ); p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */ } - block_Release( p_block ); + if( p_block ) + block_Release( p_block ); p_sys->i_late_frames--; return NULL; } @@ -504,7 +512,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) /* picture too late, won't decode * but break picture until a new I, and for mpeg4 ...*/ p_sys->i_late_frames--; /* needed else it will never be decrease */ - block_Release( p_block ); + if( p_block ) + block_Release( p_block ); return NULL; } } @@ -512,7 +521,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) { if( p_sys->b_hurry_up ) p_context->skip_frame = p_sys->i_skip_frame; - if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) + if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) b_drawpicture = 1; else b_drawpicture = 0; @@ -540,7 +549,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) /* Don't forget that libavcodec requires a little more bytes * that the real frame size */ - if( p_block->i_buffer > 0 ) + if( p_block && p_block->i_buffer > 0 ) { p_sys->b_flush = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0; @@ -554,7 +563,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) FF_INPUT_BUFFER_PADDING_SIZE ); } - while( p_block->i_buffer > 0 || p_sys->b_flush ) + while( !p_block || p_block->i_buffer > 0 || p_sys->b_flush ) { int i_used, b_gotpicture; picture_t *p_pic; @@ -563,10 +572,19 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) post_mt( p_sys ); av_init_packet( &pkt ); - pkt.data = p_block->p_buffer; - pkt.size = p_block->i_buffer; - pkt.pts = p_block->i_pts; - pkt.dts = p_block->i_dts; + if( p_block ) + { + pkt.data = p_block->p_buffer; + pkt.size = p_block->i_buffer; + pkt.pts = p_block->i_pts; + pkt.dts = p_block->i_dts; + } + else + { + /* Return delayed frames if codec has CODEC_CAP_DELAY */ + pkt.data = NULL; + pkt.size = 0; + } #if LIBAVCODEC_VERSION_MAJOR >= 54 if( !p_sys->palette_sent ) @@ -580,8 +598,11 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) #endif /* Make sure we don't reuse the same timestamps twice */ - p_block->i_pts = - p_block->i_dts = VLC_TS_INVALID; + if( p_block ) + { + p_block->i_pts = + p_block->i_dts = VLC_TS_INVALID; + } i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic, &b_gotpicture, &pkt ); @@ -601,26 +622,29 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) if( p_sys->b_flush ) p_sys->b_first_frame = true; - if( p_block->i_buffer <= 0 ) - p_sys->b_flush = false; - - if( i_used < 0 ) - { - if( b_drawpicture ) - msg_Warn( p_dec, "cannot decode one frame (%zu bytes)", - p_block->i_buffer ); - block_Release( p_block ); - return NULL; - } - else if( (unsigned)i_used > p_block->i_buffer || - p_context->thread_count > 1 ) + if( p_block ) { - i_used = p_block->i_buffer; - } + if( p_block->i_buffer <= 0 ) + p_sys->b_flush = false; - /* Consumed bytes */ - p_block->i_buffer -= i_used; - p_block->p_buffer += i_used; + if( i_used < 0 ) + { + if( b_drawpicture ) + msg_Warn( p_dec, "cannot decode one frame (%zu bytes)", + p_block->i_buffer ); + block_Release( p_block ); + return NULL; + } + else if( (unsigned)i_used > p_block->i_buffer || + p_context->thread_count > 1 ) + { + i_used = p_block->i_buffer; + } + + /* Consumed bytes */ + p_block->i_buffer -= i_used; + p_block->p_buffer += i_used; + } /* Nothing to display */ if( !b_gotpicture ) @@ -673,7 +697,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) /* Update frame late count (except when doing preroll) */ mtime_t i_display_date = 0; - if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) + if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) i_display_date = decoder_GetDisplayDate( p_dec, i_pts ); if( i_display_date > 0 && i_display_date <= mdate() ) @@ -696,7 +720,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) p_pic = ffmpeg_NewPictBuf( p_dec, p_context ); if( !p_pic ) { - block_Release( p_block ); + if( p_block ) + block_Release( p_block ); return NULL; } @@ -749,7 +774,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) } } - block_Release( p_block ); + if( p_block ) + block_Release( p_block ); return NULL; } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
