Commit 1e335d5e authored by Rafaël Carré's avatar Rafaël Carré

avcodec video decoder: returns delayed frames at end of stream

Closes: #10331
parent fc3d0d50
...@@ -430,7 +430,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -430,7 +430,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
int b_null_size = false; int b_null_size = false;
block_t *p_block; block_t *p_block;
if( !pp_block || !*pp_block ) if( !pp_block )
return NULL; return NULL;
if( !p_context->extradata_size && p_dec->fmt_in.i_extra ) 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 ) ...@@ -444,33 +444,40 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
} }
p_block = *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 ) if( p_sys->b_delayed_open )
{ {
block_Release( p_block ); if( p_block )
block_Release( p_block );
return NULL; 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 ); post_mt( p_sys );
if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
avcodec_flush_buffers( p_context ); avcodec_flush_buffers( p_context );
wait_mt( p_sys ); wait_mt( p_sys );
block_Release( p_block ); block_Release( p_block );
return NULL; return NULL;
} }
if( p_block->i_flags & BLOCK_FLAG_PREROLL ) if( p_block->i_flags & BLOCK_FLAG_PREROLL )
{ {
/* Do not care about late frames when prerolling /* Do not care about late frames when prerolling
* TODO avoid decoding of non reference frame * TODO avoid decoding of non reference frame
* (ie all B except for H264 where it depends only on nal_ref_idc) */ * (ie all B except for H264 where it depends only on nal_ref_idc) */
p_sys->i_late_frames = 0; p_sys->i_late_frames = 0;
}
} }
if( !p_dec->b_pace_control && (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 ) ...@@ -482,7 +489,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
"dropping frame (computer too slow ?)" ); "dropping frame (computer too slow ?)" );
p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */ 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--; p_sys->i_late_frames--;
return NULL; return NULL;
} }
...@@ -504,7 +512,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -504,7 +512,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
/* picture too late, won't decode /* picture too late, won't decode
* but break picture until a new I, and for mpeg4 ...*/ * but break picture until a new I, and for mpeg4 ...*/
p_sys->i_late_frames--; /* needed else it will never be decrease */ 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; return NULL;
} }
} }
...@@ -512,7 +521,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -512,7 +521,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
{ {
if( p_sys->b_hurry_up ) if( p_sys->b_hurry_up )
p_context->skip_frame = p_sys->i_skip_frame; 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; b_drawpicture = 1;
else else
b_drawpicture = 0; b_drawpicture = 0;
...@@ -540,7 +549,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -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 /* Don't forget that libavcodec requires a little more bytes
* that the real frame size */ * 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; 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 ) ...@@ -554,7 +563,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
FF_INPUT_BUFFER_PADDING_SIZE ); 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; int i_used, b_gotpicture;
picture_t *p_pic; picture_t *p_pic;
...@@ -563,10 +572,19 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -563,10 +572,19 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
post_mt( p_sys ); post_mt( p_sys );
av_init_packet( &pkt ); av_init_packet( &pkt );
pkt.data = p_block->p_buffer; if( p_block )
pkt.size = p_block->i_buffer; {
pkt.pts = p_block->i_pts; pkt.data = p_block->p_buffer;
pkt.dts = p_block->i_dts; 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 LIBAVCODEC_VERSION_MAJOR >= 54
if( !p_sys->palette_sent ) if( !p_sys->palette_sent )
...@@ -580,8 +598,11 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -580,8 +598,11 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
#endif #endif
/* Make sure we don't reuse the same timestamps twice */ /* Make sure we don't reuse the same timestamps twice */
p_block->i_pts = if( p_block )
p_block->i_dts = VLC_TS_INVALID; {
p_block->i_pts =
p_block->i_dts = VLC_TS_INVALID;
}
i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic, i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
&b_gotpicture, &pkt ); &b_gotpicture, &pkt );
...@@ -601,26 +622,29 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -601,26 +622,29 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
if( p_sys->b_flush ) if( p_sys->b_flush )
p_sys->b_first_frame = true; p_sys->b_first_frame = true;
if( p_block->i_buffer <= 0 ) if( p_block )
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 )
{ {
i_used = p_block->i_buffer; if( p_block->i_buffer <= 0 )
} p_sys->b_flush = false;
/* Consumed bytes */ if( i_used < 0 )
p_block->i_buffer -= i_used; {
p_block->p_buffer += i_used; 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 */ /* Nothing to display */
if( !b_gotpicture ) if( !b_gotpicture )
...@@ -673,7 +697,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -673,7 +697,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
/* Update frame late count (except when doing preroll) */ /* Update frame late count (except when doing preroll) */
mtime_t i_display_date = 0; 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 ); i_display_date = decoder_GetDisplayDate( p_dec, i_pts );
if( i_display_date > 0 && i_display_date <= mdate() ) if( i_display_date > 0 && i_display_date <= mdate() )
...@@ -696,7 +720,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -696,7 +720,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
p_pic = ffmpeg_NewPictBuf( p_dec, p_context ); p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
if( !p_pic ) if( !p_pic )
{ {
block_Release( p_block ); if( p_block )
block_Release( p_block );
return NULL; return NULL;
} }
...@@ -749,7 +774,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -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; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment