[vlc-commits] codec: avcodec: really drain video (ref #22929)
Francois Cartegnie
git at videolan.org
Fri Oct 11 17:28:35 CEST 2019
vlc/vlc-3.0 | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Oct 10 16:51:12 2019 +0200| [f7fa484b8ef5c2bbd96d24a85dc731a016affae1] | committer: Francois Cartegnie
codec: avcodec: really drain video (ref #22929)
could only drain once because of double drain
request/null pkt enqueuing.
> http://git.videolan.org/gitweb.cgi/vlc/vlc-3.0.git/?a=commit;h=f7fa484b8ef5c2bbd96d24a85dc731a016affae1
---
modules/codec/avcodec/video.c | 95 +++++++++++++++++++++++++------------------
1 file changed, 55 insertions(+), 40 deletions(-)
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index c5899fd736..b99eb56e4a 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -80,6 +80,7 @@ struct decoder_sys_t
/* Hack to force display of still pictures */
bool b_first_frame;
+ bool b_draining;
/* */
bool palette_sent;
@@ -603,6 +604,7 @@ int InitVideoDec( vlc_object_t *obj )
p_sys->b_first_frame = true;
p_sys->i_late_frames = 0;
p_sys->b_from_preroll = false;
+ p_sys->b_draining = false;
/* Set output properties */
if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS )
@@ -655,6 +657,7 @@ static void Flush( decoder_t *p_dec )
date_Set(&p_sys->pts, VLC_TS_INVALID); /* To make sure we recover properly */
p_sys->i_late_frames = 0;
+ p_sys->b_draining = false;
cc_Flush( &p_sys->cc );
/* Abort pictures in order to unblock all avcodec workers threads waiting
@@ -1001,57 +1004,61 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
FF_INPUT_BUFFER_PADDING_SIZE );
}
- while( !p_block || p_block->i_buffer > 0 || eos_spotted )
+ do
{
- int i_used;
- AVPacket pkt;
+ int ret;
+ int i_used = 0;
+ const bool b_has_data = ( p_block && p_block->i_buffer > 0 );
+ const bool b_start_drain = ((pp_block == NULL) || eos_spotted) && !p_sys->b_draining;
post_mt( p_sys );
- av_init_packet( &pkt );
- if( p_block && p_block->i_buffer > 0 )
+ if( b_has_data || b_start_drain )
{
- pkt.data = p_block->p_buffer;
- pkt.size = p_block->i_buffer;
- pkt.pts = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : AV_NOPTS_VALUE;
- pkt.dts = p_block->i_dts > VLC_TS_INVALID ? p_block->i_dts : AV_NOPTS_VALUE;
- }
- else
- {
- /* Return delayed frames if codec has CODEC_CAP_DELAY */
- pkt.data = NULL;
- pkt.size = 0;
- }
-
- if( !p_sys->palette_sent )
- {
- uint8_t *pal = av_packet_new_side_data(&pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
- if (pal) {
- memcpy(pal, p_dec->fmt_in.video.p_palette->palette, AVPALETTE_SIZE);
- p_sys->palette_sent = true;
+ AVPacket pkt;
+ av_init_packet( &pkt );
+ if( b_has_data )
+ {
+ pkt.data = p_block->p_buffer;
+ pkt.size = p_block->i_buffer;
+ pkt.pts = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : AV_NOPTS_VALUE;
+ pkt.dts = p_block->i_dts > VLC_TS_INVALID ? p_block->i_dts : AV_NOPTS_VALUE;
+
+ /* Make sure we don't reuse the same timestamps twice */
+ p_block->i_pts =
+ p_block->i_dts = VLC_TS_INVALID;
+ }
+ else /* start drain */
+ {
+ /* Return delayed frames if codec has CODEC_CAP_DELAY */
+ pkt.data = NULL;
+ pkt.size = 0;
+ p_sys->b_draining = true;
}
- }
- /* Make sure we don't reuse the same timestamps twice */
- if( p_block )
- {
- p_block->i_pts =
- p_block->i_dts = VLC_TS_INVALID;
- }
+ if( !p_sys->palette_sent )
+ {
+ uint8_t *pal = av_packet_new_side_data(&pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
+ if (pal) {
+ memcpy(pal, p_dec->fmt_in.video.p_palette->palette, AVPALETTE_SIZE);
+ p_sys->palette_sent = true;
+ }
+ }
- int ret = avcodec_send_packet(p_context, &pkt);
- if( ret != 0 && ret != AVERROR(EAGAIN) )
- {
- if (ret == AVERROR(ENOMEM) || ret == AVERROR(EINVAL))
+ ret = avcodec_send_packet(p_context, &pkt);
+ if( ret != 0 && ret != AVERROR(EAGAIN) )
{
- msg_Err(p_dec, "avcodec_send_packet critical error");
- *error = true;
+ if (ret == AVERROR(ENOMEM) || ret == AVERROR(EINVAL))
+ {
+ msg_Err(p_dec, "avcodec_send_packet critical error");
+ *error = true;
+ }
+ av_packet_unref( &pkt );
+ break;
}
+ i_used = ret != AVERROR(EAGAIN) ? pkt.size : 0;
av_packet_unref( &pkt );
- break;
}
- i_used = ret != AVERROR(EAGAIN) ? pkt.size : 0;
- av_packet_unref( &pkt );
AVFrame *frame = av_frame_alloc();
if (unlikely(frame == NULL))
@@ -1071,7 +1078,10 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
av_frame_free(&frame);
/* After draining, we need to reset decoder with a flush */
if( ret == AVERROR_EOF )
+ {
avcodec_flush_buffers( p_sys->p_context );
+ p_sys->b_draining = false;
+ }
break;
}
bool not_received_frame = ret;
@@ -1232,10 +1242,15 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
}
else
picture_Release( p_pic );
- }
+ } while( true );
if( p_block )
block_Release( p_block );
+ if( p_sys->b_draining )
+ {
+ avcodec_flush_buffers( p_sys->p_context );
+ p_sys->b_draining = false;
+ }
return NULL;
}
More information about the vlc-commits
mailing list