Patches attached. - Andreas
From 19d9f3cfc278a2b442923f1bea505ffb079fe3c1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Thu, 15 May 2025 03:09:45 +0200 Subject: [PATCH 1/7] avcodec/svq3: Factor out decoding extradata
Reduces indentation and avoids an extra variable for whether a sequence header has been found. It also fixes potential undefined behaviour: NULL + 0 is undefined and happens when no extradata is available. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/svq3.c | 259 +++++++++++++++++++++++----------------------- 1 file changed, 132 insertions(+), 127 deletions(-) diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index 6319e9b021..f264140dbc 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -1114,14 +1114,139 @@ static void init_dequant4_coeff_table(SVQ3Context *s) } } +static av_cold int svq3_decode_extradata(AVCodecContext *avctx, SVQ3Context *s, + int seqh_offset) +{ + const uint8_t *extradata = avctx->extradata + seqh_offset; + unsigned int size = AV_RB32(extradata + 4); + GetBitContext gb; + int ret; + + if (size > avctx->extradata_size - seqh_offset - 8) + return AVERROR_INVALIDDATA; + extradata += 8; + init_get_bits(&gb, extradata, size * 8); + + /* 'frame size code' and optional 'width, height' */ + int frame_size_code = get_bits(&gb, 3); + int w, h; + switch (frame_size_code) { + case 0: + w = 160; + h = 120; + break; + case 1: + w = 128; + h = 96; + break; + case 2: + w = 176; + h = 144; + break; + case 3: + w = 352; + h = 288; + break; + case 4: + w = 704; + h = 576; + break; + case 5: + w = 240; + h = 180; + break; + case 6: + w = 320; + h = 240; + break; + case 7: + w = get_bits(&gb, 12); + h = get_bits(&gb, 12); + break; + } + ret = ff_set_dimensions(avctx, w, h); + if (ret < 0) + return ret; + + s->halfpel_flag = get_bits1(&gb); + s->thirdpel_flag = get_bits1(&gb); + + /* unknown fields */ + int unk0 = get_bits1(&gb); + int unk1 = get_bits1(&gb); + int unk2 = get_bits1(&gb); + int unk3 = get_bits1(&gb); + + s->low_delay = get_bits1(&gb); + avctx->has_b_frames = !s->low_delay; + + /* unknown field */ + int unk4 = get_bits1(&gb); + + av_log(avctx, AV_LOG_DEBUG, "Unknown fields %d %d %d %d %d\n", + unk0, unk1, unk2, unk3, unk4); + + if (skip_1stop_8data_bits(&gb) < 0) + return AVERROR_INVALIDDATA; + + s->has_watermark = get_bits1(&gb); + + if (!s->has_watermark) + return 0; + +#if CONFIG_ZLIB + unsigned watermark_width = get_interleaved_ue_golomb(&gb); + unsigned watermark_height = get_interleaved_ue_golomb(&gb); + int u1 = get_interleaved_ue_golomb(&gb); + int u2 = get_bits(&gb, 8); + int u3 = get_bits(&gb, 2); + int u4 = get_interleaved_ue_golomb(&gb); + unsigned long buf_len = watermark_width * + watermark_height * 4; + int offset = get_bits_count(&gb) + 7 >> 3; + + if (watermark_height <= 0 || + get_bits_left(&gb) <= 0 || + (uint64_t)watermark_width * 4 > UINT_MAX / watermark_height) + return AVERROR_INVALIDDATA; + + av_log(avctx, AV_LOG_DEBUG, "watermark size: %ux%u\n", + watermark_width, watermark_height); + av_log(avctx, AV_LOG_DEBUG, + "u1: %x u2: %x u3: %x compressed data size: %d offset: %d\n", + u1, u2, u3, u4, offset); + + uint8_t *buf = av_malloc(buf_len); + if (!buf) + return AVERROR(ENOMEM); + + if (uncompress(buf, &buf_len, extradata + offset, + size - offset) != Z_OK) { + av_log(avctx, AV_LOG_ERROR, + "could not uncompress watermark logo\n"); + av_free(buf); + return -1; + } + s->watermark_key = av_bswap16(av_crc(av_crc_get_table(AV_CRC_16_CCITT), 0, buf, buf_len)); + + s->watermark_key = s->watermark_key << 16 | s->watermark_key; + av_log(avctx, AV_LOG_DEBUG, + "watermark key %#"PRIx32"\n", s->watermark_key); + av_free(buf); + + return 0; +#else + av_log(avctx, AV_LOG_ERROR, + "this svq3 file contains watermark which need zlib support compiled in\n"); + return AVERROR(ENOSYS); +#endif +} + static av_cold int svq3_decode_init(AVCodecContext *avctx) { SVQ3Context *s = avctx->priv_data; int m, x, y; unsigned char *extradata; - unsigned char *extradata_end; - unsigned int size; - int marker_found = 0; int ret; s->cur_pic = &s->frames[0]; @@ -1154,139 +1279,19 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) /* prowl for the "SEQH" marker in the extradata */ extradata = (unsigned char *)avctx->extradata; - extradata_end = avctx->extradata + avctx->extradata_size; if (extradata) { for (m = 0; m + 8 < avctx->extradata_size; m++) { if (!memcmp(extradata, "SEQH", 4)) { - marker_found = 1; + /* if a match was found, parse the extra data */ + ret = svq3_decode_extradata(avctx, s, m); + if (ret < 0) + return ret; break; } extradata++; } } - /* if a match was found, parse the extra data */ - if (marker_found) { - GetBitContext gb; - int frame_size_code; - int unk0, unk1, unk2, unk3, unk4; - int w,h; - - size = AV_RB32(&extradata[4]); - if (size > extradata_end - extradata - 8) - return AVERROR_INVALIDDATA; - init_get_bits(&gb, extradata + 8, size * 8); - - /* 'frame size code' and optional 'width, height' */ - frame_size_code = get_bits(&gb, 3); - switch (frame_size_code) { - case 0: - w = 160; - h = 120; - break; - case 1: - w = 128; - h = 96; - break; - case 2: - w = 176; - h = 144; - break; - case 3: - w = 352; - h = 288; - break; - case 4: - w = 704; - h = 576; - break; - case 5: - w = 240; - h = 180; - break; - case 6: - w = 320; - h = 240; - break; - case 7: - w = get_bits(&gb, 12); - h = get_bits(&gb, 12); - break; - } - ret = ff_set_dimensions(avctx, w, h); - if (ret < 0) - return ret; - - s->halfpel_flag = get_bits1(&gb); - s->thirdpel_flag = get_bits1(&gb); - - /* unknown fields */ - unk0 = get_bits1(&gb); - unk1 = get_bits1(&gb); - unk2 = get_bits1(&gb); - unk3 = get_bits1(&gb); - - s->low_delay = get_bits1(&gb); - - /* unknown field */ - unk4 = get_bits1(&gb); - - av_log(avctx, AV_LOG_DEBUG, "Unknown fields %d %d %d %d %d\n", - unk0, unk1, unk2, unk3, unk4); - - if (skip_1stop_8data_bits(&gb) < 0) - return AVERROR_INVALIDDATA; - - s->has_watermark = get_bits1(&gb); - avctx->has_b_frames = !s->low_delay; - if (s->has_watermark) { -#if CONFIG_ZLIB - unsigned watermark_width = get_interleaved_ue_golomb(&gb); - unsigned watermark_height = get_interleaved_ue_golomb(&gb); - int u1 = get_interleaved_ue_golomb(&gb); - int u2 = get_bits(&gb, 8); - int u3 = get_bits(&gb, 2); - int u4 = get_interleaved_ue_golomb(&gb); - unsigned long buf_len = watermark_width * - watermark_height * 4; - int offset = get_bits_count(&gb) + 7 >> 3; - uint8_t *buf; - - if (watermark_height <= 0 || - get_bits_left(&gb) <= 0 || - (uint64_t)watermark_width * 4 > UINT_MAX / watermark_height) - return AVERROR_INVALIDDATA; - - buf = av_malloc(buf_len); - if (!buf) - return AVERROR(ENOMEM); - - av_log(avctx, AV_LOG_DEBUG, "watermark size: %ux%u\n", - watermark_width, watermark_height); - av_log(avctx, AV_LOG_DEBUG, - "u1: %x u2: %x u3: %x compressed data size: %d offset: %d\n", - u1, u2, u3, u4, offset); - if (uncompress(buf, &buf_len, extradata + 8 + offset, - size - offset) != Z_OK) { - av_log(avctx, AV_LOG_ERROR, - "could not uncompress watermark logo\n"); - av_free(buf); - return -1; - } - s->watermark_key = av_bswap16(av_crc(av_crc_get_table(AV_CRC_16_CCITT), 0, buf, buf_len)); - - s->watermark_key = s->watermark_key << 16 | s->watermark_key; - av_log(avctx, AV_LOG_DEBUG, - "watermark key %#"PRIx32"\n", s->watermark_key); - av_free(buf); -#else - av_log(avctx, AV_LOG_ERROR, - "this svq3 file contains watermark which need zlib support compiled in\n"); - return AVERROR(ENOSYS); -#endif - } - } - s->mb_width = (avctx->width + 15) / 16; s->mb_height = (avctx->height + 15) / 16; s->mb_stride = s->mb_width + 1; -- 2.45.2
From 8bd133619aa4369d69fc091d9cc9d9734ee0f419 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Thu, 15 May 2025 03:24:23 +0200 Subject: [PATCH 2/7] avcodec/svq3: Improve returned error codes Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/svq3.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index f264140dbc..b192eb6c02 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -1225,7 +1225,7 @@ static av_cold int svq3_decode_extradata(AVCodecContext *avctx, SVQ3Context *s, av_log(avctx, AV_LOG_ERROR, "could not uncompress watermark logo\n"); av_free(buf); - return -1; + return AVERROR_EXTERNAL; } s->watermark_key = av_bswap16(av_crc(av_crc_get_table(AV_CRC_16_CCITT), 0, buf, buf_len)); @@ -1403,8 +1403,9 @@ static int svq3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (ret < 0) return ret; - if (svq3_decode_slice_header(avctx)) - return -1; + ret = svq3_decode_slice_header(avctx); + if (ret < 0) + return ret; if (avpkt->size < s->mb_width * s->mb_height / 8) return AVERROR_INVALIDDATA; @@ -1517,8 +1518,9 @@ static int svq3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (((get_bits_count(&s->gb_slice) & 7) == 0 || show_bits(&s->gb_slice, get_bits_left(&s->gb_slice) & 7) == 0)) { - if (svq3_decode_slice_header(avctx)) - return -1; + ret = svq3_decode_slice_header(avctx); + if (ret < 0) + return ret; } if (s->slice_type != s->pict_type) { avpriv_request_sample(avctx, "non constant slice type"); -- 2.45.2
From 71aa71acce5c00faf02c03a2ce6c35a112e4d520 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Thu, 15 May 2025 03:29:43 +0200 Subject: [PATCH 3/7] avcodec/svq3: Deduplicate allocating dummy frame Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/svq3.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index b192eb6c02..e1e65c4766 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -1377,6 +1377,23 @@ fail: return ret; } +static av_cold int alloc_dummy_frame(AVCodecContext *avctx, SVQ3Frame *pic) +{ + av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); + av_frame_unref(pic->f); + int ret = get_buffer(avctx, pic); + if (ret < 0) + return ret; + + memset(pic->f->data[0], 0, avctx->height * pic->f->linesize[0]); + memset(pic->f->data[1], 0x80, (avctx->height / 2) * + pic->f->linesize[1]); + memset(pic->f->data[2], 0x80, (avctx->height / 2) * + pic->f->linesize[2]); + + return 0; +} + static int svq3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { @@ -1441,29 +1458,15 @@ static int svq3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (s->pict_type != AV_PICTURE_TYPE_I) { if (!s->last_pic->f->data[0]) { - av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); - av_frame_unref(s->last_pic->f); - ret = get_buffer(avctx, s->last_pic); + ret = alloc_dummy_frame(avctx, s->last_pic); if (ret < 0) return ret; - memset(s->last_pic->f->data[0], 0, avctx->height * s->last_pic->f->linesize[0]); - memset(s->last_pic->f->data[1], 0x80, (avctx->height / 2) * - s->last_pic->f->linesize[1]); - memset(s->last_pic->f->data[2], 0x80, (avctx->height / 2) * - s->last_pic->f->linesize[2]); } if (s->pict_type == AV_PICTURE_TYPE_B && !s->next_pic->f->data[0]) { - av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); - av_frame_unref(s->next_pic->f); - ret = get_buffer(avctx, s->next_pic); + ret = alloc_dummy_frame(avctx, s->next_pic); if (ret < 0) return ret; - memset(s->next_pic->f->data[0], 0, avctx->height * s->next_pic->f->linesize[0]); - memset(s->next_pic->f->data[1], 0x80, (avctx->height / 2) * - s->next_pic->f->linesize[1]); - memset(s->next_pic->f->data[2], 0x80, (avctx->height / 2) * - s->next_pic->f->linesize[2]); } } -- 2.45.2
From a2a84101c7d056b2d0219a5603ae90aeb3f4ce28 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Thu, 15 May 2025 03:42:06 +0200 Subject: [PATCH 4/7] avcodec/svq3: Allocate motion_val jointly Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/svq3.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index e1e65c4766..cdb2bd323b 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -74,7 +74,7 @@ typedef struct SVQ3Frame { AVFrame *f; - int16_t (*motion_val_buf[2])[2]; + int16_t (*motion_val_buf)[2]; int16_t (*motion_val[2])[2]; uint32_t *mb_type_buf, *mb_type; @@ -1323,10 +1323,7 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) static void free_picture(SVQ3Frame *pic) { - int i; - for (i = 0; i < 2; i++) { - av_freep(&pic->motion_val_buf[i]); - } + av_freep(&pic->motion_val_buf); av_freep(&pic->mb_type_buf); av_frame_unref(pic->f); @@ -1340,23 +1337,19 @@ static int get_buffer(AVCodecContext *avctx, SVQ3Frame *pic) const int b4_array_size = b4_stride * s->mb_height * 4; int ret; - if (!pic->motion_val_buf[0]) { - int i; - + if (!pic->motion_val_buf) { pic->mb_type_buf = av_calloc(big_mb_num + s->mb_stride, sizeof(uint32_t)); if (!pic->mb_type_buf) return AVERROR(ENOMEM); pic->mb_type = pic->mb_type_buf + 2 * s->mb_stride + 1; - for (i = 0; i < 2; i++) { - pic->motion_val_buf[i] = av_calloc(b4_array_size + 4, 2 * sizeof(int16_t)); - if (!pic->motion_val_buf[i]) { - ret = AVERROR(ENOMEM); - goto fail; - } - - pic->motion_val[i] = pic->motion_val_buf[i] + 4; + pic->motion_val_buf = av_calloc(b4_array_size + 4, 2 * sizeof(*pic->motion_val[0])); + if (!pic->motion_val_buf) { + ret = AVERROR(ENOMEM); + goto fail; } + pic->motion_val[0] = pic->motion_val_buf + 4; + pic->motion_val[1] = pic->motion_val[0] + b4_array_size + 4; } ret = ff_get_buffer(avctx, pic->f, -- 2.45.2
From 99780f564486d7feab35f2f15a1a4c0a48145552 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Thu, 15 May 2025 04:28:03 +0200 Subject: [PATCH 5/7] avcodec/svq3: Allocate picture buffers during init Also allocate them jointly. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/svq3.c | 83 ++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index cdb2bd323b..c510d2fb38 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -71,13 +71,14 @@ * svq3 decoder. */ +#define NUM_PICS 3 + typedef struct SVQ3Frame { AVFrame *f; - int16_t (*motion_val_buf)[2]; int16_t (*motion_val[2])[2]; - uint32_t *mb_type_buf, *mb_type; + uint32_t *mb_type; } SVQ3Frame; typedef struct SVQ3Context { @@ -142,7 +143,10 @@ typedef struct SVQ3Context { DECLARE_ALIGNED(8, uint8_t, non_zero_count_cache)[15 * 8]; uint32_t dequant4_coeff[QP_MAX_NUM + 1][16]; int block_offset[2 * (16 * 3)]; - SVQ3Frame frames[3]; + SVQ3Frame frames[NUM_PICS]; + + uint32_t *mb_type_buf; + int16_t (*motion_val_buf)[2]; } SVQ3Context; #define FULLPEL_MODE 1 @@ -1300,6 +1304,34 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) s->h_edge_pos = s->mb_width * 16; s->v_edge_pos = s->mb_height * 16; + const unsigned big_mb_num = s->mb_stride * (s->mb_height + 2) + 1; + + s->mb_type_buf = av_calloc(big_mb_num, NUM_PICS * sizeof(*s->mb_type_buf)); + if (!s->mb_type_buf) + return AVERROR(ENOMEM); + uint32_t *mb_type_buf = s->mb_type_buf + 2 * s->mb_stride + 1; + + const unsigned b4_stride = s->mb_width * 4 + 1; + const unsigned b4_array_size = b4_stride * s->mb_height * 4; + const unsigned motion_val_buf_size = b4_array_size + 4; + + s->motion_val_buf = av_calloc(motion_val_buf_size, + NUM_PICS * 2 * sizeof(*s->motion_val_buf)); + if (!s->motion_val_buf) + return AVERROR(ENOMEM); + int16_t (*motion_val_buf)[2] = s->motion_val_buf + 4; + + for (size_t i = 0; i < NUM_PICS; ++i) { + SVQ3Frame *const pic = &s->frames[i]; + + pic->mb_type = mb_type_buf; + mb_type_buf += big_mb_num; + for (size_t j = 0; j < FF_ARRAY_ELEMS(pic->motion_val); ++j) { + pic->motion_val[j] = motion_val_buf; + motion_val_buf += motion_val_buf_size; + } + } + s->intra4x4_pred_mode = av_mallocz(s->mb_stride * 2 * 8); if (!s->intra4x4_pred_mode) return AVERROR(ENOMEM); @@ -1321,42 +1353,14 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) return 0; } -static void free_picture(SVQ3Frame *pic) -{ - av_freep(&pic->motion_val_buf); - av_freep(&pic->mb_type_buf); - - av_frame_unref(pic->f); -} - static int get_buffer(AVCodecContext *avctx, SVQ3Frame *pic) { SVQ3Context *s = avctx->priv_data; - const int big_mb_num = s->mb_stride * (s->mb_height + 1) + 1; - const int b4_stride = s->mb_width * 4 + 1; - const int b4_array_size = b4_stride * s->mb_height * 4; - int ret; - - if (!pic->motion_val_buf) { - pic->mb_type_buf = av_calloc(big_mb_num + s->mb_stride, sizeof(uint32_t)); - if (!pic->mb_type_buf) - return AVERROR(ENOMEM); - pic->mb_type = pic->mb_type_buf + 2 * s->mb_stride + 1; - - pic->motion_val_buf = av_calloc(b4_array_size + 4, 2 * sizeof(*pic->motion_val[0])); - if (!pic->motion_val_buf) { - ret = AVERROR(ENOMEM); - goto fail; - } - pic->motion_val[0] = pic->motion_val_buf + 4; - pic->motion_val[1] = pic->motion_val[0] + b4_array_size + 4; - } - - ret = ff_get_buffer(avctx, pic->f, - (s->pict_type != AV_PICTURE_TYPE_B) ? - AV_GET_BUFFER_FLAG_REF : 0); + int ret = ff_get_buffer(avctx, pic->f, + (s->pict_type != AV_PICTURE_TYPE_B) ? + AV_GET_BUFFER_FLAG_REF : 0); if (ret < 0) - goto fail; + return ret; if (!s->edge_emu_buffer) { s->edge_emu_buffer = av_calloc(pic->f->linesize[0], 17); @@ -1365,9 +1369,6 @@ static int get_buffer(AVCodecContext *avctx, SVQ3Frame *pic) } return 0; -fail: - free_picture(pic); - return ret; } static av_cold int alloc_dummy_frame(AVCodecContext *avctx, SVQ3Frame *pic) @@ -1586,10 +1587,10 @@ static av_cold int svq3_decode_end(AVCodecContext *avctx) { SVQ3Context *s = avctx->priv_data; - for (int i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) { - free_picture(&s->frames[i]); + for (int i = 0; i < NUM_PICS; i++) av_frame_free(&s->frames[i].f); - } + av_freep(&s->motion_val_buf); + av_freep(&s->mb_type_buf); av_freep(&s->slice_buf); av_freep(&s->intra4x4_pred_mode); av_freep(&s->edge_emu_buffer); -- 2.45.2
From 853dc2c697d8004d6655b84ab9f28aaafc3c2b40 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Thu, 15 May 2025 04:42:46 +0200 Subject: [PATCH 6/7] tests/fate/qt: Use passthrough fps_mode for svq3-watermark The file has buggy timestamps (it uses B-frames, yet pts==dts) and therefore the last frame is currently discarded by FFmpeg cli. Using -fps_mode passthrough avoids this and provides coverage of the SVQ3 draining logic. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- tests/fate/qt.mak | 2 +- tests/ref/fate/svq3-watermark | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fate/qt.mak b/tests/fate/qt.mak index 42e5fd9107..436da172f1 100644 --- a/tests/fate/qt.mak +++ b/tests/fate/qt.mak @@ -57,7 +57,7 @@ fate-svq3-1: CMD = framecrc -i $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3. fate-svq3-2: CMD = framecrc -flags +bitexact -ignore_editlist 1 -i $(TARGET_SAMPLES)/svq3/svq3_decoding_regression.mov -an FATE_SVQ3 += fate-svq3-watermark -fate-svq3-watermark: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/svq3/svq3_watermark.mov +fate-svq3-watermark: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/svq3/svq3_watermark.mov -fps_mode passthrough FATE_QT-$(call FRAMECRC, MOV, SVQ3, ZLIB) += $(FATE_SVQ3) fate-svq3: $(FATE_SVQ3) diff --git a/tests/ref/fate/svq3-watermark b/tests/ref/fate/svq3-watermark index f4068c612e..95d67e3da4 100644 --- a/tests/ref/fate/svq3-watermark +++ b/tests/ref/fate/svq3-watermark @@ -12,3 +12,4 @@ 0, 7, 7, 1, 102240, 0x342bf32f 0, 8, 8, 1, 102240, 0x7b311bf1 0, 9, 9, 1, 102240, 0xf56e0cd3 +0, 9, 9, 1, 102240, 0xfb95c7d3 -- 2.45.2
From b6cfeb10b2f269bb37ecd71338e19927b18f8549 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Thu, 15 May 2025 04:48:54 +0200 Subject: [PATCH 7/7] avcodec/svq3: Improve returning last picture Use av_frame_move_ref() instead of av_frame_ref(). This allows to remove the separate variable for whether we have already returned the delayed last pic. It also makes stream looping work when looping multiple times; previously the delayed pic was only output the first time, because last_frame_output was never reset. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/svq3.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index c510d2fb38..4c4f3018c5 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -104,7 +104,6 @@ typedef struct SVQ3Context { int adaptive_quant; int h_edge_pos; int v_edge_pos; - int last_frame_output; int slice_num; int qscale; int cbp; @@ -1398,11 +1397,8 @@ static int svq3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, /* special case for last picture */ if (buf_size == 0) { - if (s->next_pic->f->data[0] && !s->low_delay && !s->last_frame_output) { - ret = av_frame_ref(rframe, s->next_pic->f); - if (ret < 0) - return ret; - s->last_frame_output = 1; + if (s->next_pic->f->data[0] && !s->low_delay) { + av_frame_move_ref(rframe, s->next_pic->f); *got_frame = 1; } return 0; -- 2.45.2
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".