[FFmpeg-devel] [PATCH 4/4] avcodec/nuv: Avoid duplicating frames
Michael Niedermayer
michael at niedermayer.cc
Thu May 30 17:04:00 EEST 2019
Fixes: Timeout (14sec -> 133ms)
Fixes: 14843/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_NUV_fuzzer-5661969614372864
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
---
libavcodec/nuv.c | 35 ++++++++++++++++++++++++++++++++---
tests/ref/fate/nuv-rtjpeg | 1 -
2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c
index 75b14bce5b..043b299080 100644
--- a/libavcodec/nuv.c
+++ b/libavcodec/nuv.c
@@ -42,6 +42,8 @@ typedef struct NuvContext {
unsigned char *decomp_buf;
uint32_t lq[64], cq[64];
RTJpegContext rtj;
+ int need_flush;
+ AVPacket flush_pkt;
} NuvContext;
static const uint8_t fallback_lquant[] = {
@@ -66,6 +68,12 @@ static const uint8_t fallback_cquant[] = {
99, 99, 99, 99, 99, 99, 99, 99
};
+static void decode_flush(AVCodecContext *avctx){
+ NuvContext *s = avctx->priv_data;
+
+ s->need_flush = 0;
+}
+
/**
* @brief copy frame data from buffer to AVFrame, handling stride.
* @param f destination AVFrame
@@ -172,6 +180,25 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
NUV_COPY_LAST = 'L'
} comptype;
+ if (!avpkt->data) {
+ if (c->need_flush) {
+ c->need_flush = 0;
+ if ((ret = ff_reget_buffer(avctx, c->pic)) < 0)
+ return ret;
+ c->pic->pkt_pos = c->flush_pkt.pos;
+ c->pic->pkt_duration = c->flush_pkt.duration;
+ c->pic->pkt_dts = c->flush_pkt.dts;
+ c->pic->pkt_pts =
+ c->pic->pts = c->flush_pkt.pts;
+ if ((ret = av_frame_ref(data, c->pic)) < 0)
+ return ret;
+ *got_frame = 1;
+ }
+ return 0;
+ }
+ c->flush_pkt = *avpkt;
+
+
if (buf_size < 12) {
av_log(avctx, AV_LOG_ERROR, "coded frame too small\n");
return AVERROR_INVALIDDATA;
@@ -204,8 +231,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
}
break;
case NUV_COPY_LAST:
- keyframe = 0;
- break;
+ c->need_flush = 1;
+ return buf_size;
default:
keyframe = 1;
break;
@@ -313,6 +340,7 @@ retry:
if ((result = av_frame_ref(picture, c->pic)) < 0)
return result;
+ c->need_flush = 0;
*got_frame = 1;
return orig_size;
}
@@ -364,6 +392,7 @@ AVCodec ff_nuv_decoder = {
.init = decode_init,
.close = decode_end,
.decode = decode_frame,
- .capabilities = AV_CODEC_CAP_DR1,
+ .flush = decode_flush,
+ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
};
diff --git a/tests/ref/fate/nuv-rtjpeg b/tests/ref/fate/nuv-rtjpeg
index b6f3b080dc..0914b985ec 100644
--- a/tests/ref/fate/nuv-rtjpeg
+++ b/tests/ref/fate/nuv-rtjpeg
@@ -6,7 +6,6 @@
0, 118, 118, 0, 460800, 0x54aedafe
0, 152, 152, 0, 460800, 0xb7aa8b56
0, 177, 177, 0, 460800, 0x283ea3b5
-0, 202, 202, 0, 460800, 0x283ea3b5
0, 235, 235, 0, 460800, 0x10e577de
0, 269, 269, 0, 460800, 0x4e091ee2
0, 302, 302, 0, 460800, 0x2ea88828
--
2.21.0
More information about the ffmpeg-devel
mailing list