PR #22645 opened by Priyanshuthapliyal URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22645 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22645.patch
This patch adds FATE coverage for the PDV decoder using generated PDV samples, bringing `libavcodec/pdvdec.c` from 0% to 88.2% line coverage and 0% to 75% function coverage. Signed-off-by: Priyanshu Thapliyal <[email protected]> >From ba5c1f177c7bac0d398c5c6cfa81d6816bd9b08f Mon Sep 17 00:00:00 2001 From: Priyanshu Thapliyal <[email protected]> Date: Sat, 28 Mar 2026 01:35:17 +0530 Subject: [PATCH] tests/pdv: add FATE tests for pdvdec Signed-off-by: Priyanshu Thapliyal <[email protected]> --- Makefile | 2 +- tests/Makefile | 6 +- tests/fate/pdv.mak | 23 +++ tests/pdvgen.c | 275 ++++++++++++++++++++++++++++++++++ tests/ref/fate/pdv-corrupt | 6 + tests/ref/fate/pdv-delta | 8 + tests/ref/fate/pdv-key | 6 + tests/ref/fate/pdv-skip-all | 5 + tests/ref/fate/pdv-skip-nokey | 7 + 9 files changed, 336 insertions(+), 2 deletions(-) create mode 100644 tests/fate/pdv.mak create mode 100644 tests/pdvgen.c create mode 100644 tests/ref/fate/pdv-corrupt create mode 100644 tests/ref/fate/pdv-delta create mode 100644 tests/ref/fate/pdv-key create mode 100644 tests/ref/fate/pdv-skip-all create mode 100644 tests/ref/fate/pdv-skip-nokey diff --git a/Makefile b/Makefile index f296e87ed4..39653b6e40 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ vpath %.ptx $(SRC_PATH) vpath %.metal $(SRC_PATH) vpath %/fate_config.sh.template $(SRC_PATH) -TESTTOOLS = audiogen videogen rotozoom tiny_psnr tiny_ssim base64 audiomatch +TESTTOOLS = audiogen videogen rotozoom pdvgen tiny_psnr tiny_ssim base64 audiomatch HOSTPROGS := $(TESTTOOLS:%=tests/%) doc/print_options ALLFFLIBS = \ diff --git a/tests/Makefile b/tests/Makefile index 4b3fa6a54a..9e097c29ad 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -47,11 +47,14 @@ tests/data/vsynth_lena.yuv: tests/rotozoom$(HOSTEXESUF) | tests/data tests/data/vsynth3.yuv: tests/videogen$(HOSTEXESUF) | tests/data $(M)$< $@ $(FATEW) $(FATEH) +tests/data/pdv-%.pdv: tests/pdvgen$(HOSTEXESUF) | tests/data + $(M)./$< $@ $* + tests/test_copy.ffmeta: TAG = COPY tests/test_copy.ffmeta: tests/data $(M)cp -f $(SRC_PATH)/tests/test.ffmeta tests/test_copy.ffmeta -tests/data/%.sw tests/data/asynth% tests/data/vsynth%.yuv tests/vsynth%/00.pgm tests/data/%.nut: TAG = GEN +tests/data/%.sw tests/data/asynth% tests/data/vsynth%.yuv tests/data/pdv-%.pdv tests/vsynth%/00.pgm tests/data/%.nut: TAG = GEN tests/data/filtergraphs/%: TAG = COPY tests/data/filtergraphs/%: $(SRC_PATH)/tests/filtergraphs/% | tests/data/filtergraphs @@ -232,6 +235,7 @@ include $(SRC_PATH)/tests/fate/ogg-opus.mak include $(SRC_PATH)/tests/fate/oma.mak include $(SRC_PATH)/tests/fate/opus.mak include $(SRC_PATH)/tests/fate/pcm.mak +include $(SRC_PATH)/tests/fate/pdv.mak include $(SRC_PATH)/tests/fate/pixfmt.mak include $(SRC_PATH)/tests/fate/pixlet.mak include $(SRC_PATH)/tests/fate/probe.mak diff --git a/tests/fate/pdv.mak b/tests/fate/pdv.mak new file mode 100644 index 0000000000..efbfe28db1 --- /dev/null +++ b/tests/fate/pdv.mak @@ -0,0 +1,23 @@ +FATE_PDV += fate-pdv-key +fate-pdv-key: tests/data/pdv-key.pdv +fate-pdv-key: CMD = framecrc -i $(TARGET_PATH)/tests/data/pdv-key.pdv -frames:v 1 + +FATE_PDV += fate-pdv-delta +fate-pdv-delta: tests/data/pdv-delta.pdv +fate-pdv-delta: CMD = framecrc -i $(TARGET_PATH)/tests/data/pdv-delta.pdv -frames:v 3 + +FATE_PDV += fate-pdv-skip-nokey +fate-pdv-skip-nokey: tests/data/pdv-mixed.pdv +fate-pdv-skip-nokey: CMD = framecrc -skip_frame nokey -i $(TARGET_PATH)/tests/data/pdv-mixed.pdv -frames:v 4 + +FATE_PDV += fate-pdv-skip-all +fate-pdv-skip-all: tests/data/pdv-mixed.pdv +fate-pdv-skip-all: CMD = framecrc -skip_frame all -i $(TARGET_PATH)/tests/data/pdv-mixed.pdv -frames:v 4 + +FATE_PDV += fate-pdv-corrupt +fate-pdv-corrupt: tests/data/pdv-corrupt.pdv +fate-pdv-corrupt: CMD = framecrc -err_detect ignore_err -i $(TARGET_PATH)/tests/data/pdv-corrupt.pdv -frames:v 2 + +FATE_PDV-$(call FRAMECRC, PDV, PDV) += $(FATE_PDV) +FATE_AVCONV += $(FATE_PDV-yes) +fate-pdv: $(FATE_PDV-yes) diff --git a/tests/pdvgen.c b/tests/pdvgen.c new file mode 100644 index 0000000000..6f874ee9ce --- /dev/null +++ b/tests/pdvgen.c @@ -0,0 +1,275 @@ +/* + * Generate synthetic PDV samples for FATE. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define PDV_WIDTH 16 +#define PDV_HEIGHT 8 + +#define PDV_FPS_30_FLOAT_BITS 0x41F00000U + +typedef struct FramePayload { + int key; + uint8_t *data; + int size; +} FramePayload; + +static void put_le16(FILE *f, uint16_t v) +{ + fputc(v & 0xFF, f); + fputc((v >> 8) & 0xFF, f); +} + +static void put_le32(FILE *f, uint32_t v) +{ + fputc(v & 0xFF, f); + fputc((v >> 8) & 0xFF, f); + fputc((v >> 16) & 0xFF, f); + fputc((v >> 24) & 0xFF, f); +} + +static uint32_t adler32_sum(const uint8_t *src, int size) +{ + uint32_t a = 1; + uint32_t b = 0; + int i; + + for (i = 0; i < size; i++) { + a += src[i]; + if (a >= 65521) + a -= 65521; + b += a; + if (b >= 65521) + b -= 65521; + } + + return (b << 16) | a; +} + +static int make_zlib_stored_packet(const uint8_t *src, int src_size, + int corrupt, uint8_t **dst, int *dst_size) +{ + uint8_t *out; + uint8_t *p; + uint32_t adler; + int blocks; + int max_size; + int remaining; + int offset; + + blocks = (src_size + 65534) / 65535; + max_size = 2 + blocks * 5 + src_size + 4; + + out = malloc(max_size); + if (!out) + return 1; + + p = out; + + *p++ = 0x78; + *p++ = 0x01; + + remaining = src_size; + offset = 0; + while (remaining > 0) { + int final = remaining <= 65535; + int len = final ? remaining : 65535; + uint16_t nlen = (uint16_t)~len; + + *p++ = final ? 0x01 : 0x00; + *p++ = len & 0xFF; + *p++ = (len >> 8) & 0xFF; + + if (corrupt && final) + nlen ^= 1; + + *p++ = nlen & 0xFF; + *p++ = (nlen >> 8) & 0xFF; + + memcpy(p, src + offset, len); + p += len; + + offset += len; + remaining -= len; + } + + adler = adler32_sum(src, src_size); + *p++ = (adler >> 24) & 0xFF; + *p++ = (adler >> 16) & 0xFF; + *p++ = (adler >> 8) & 0xFF; + *p++ = adler & 0xFF; + + *dst = out; + *dst_size = (int)(p - out); + + return 0; +} + +static void fill_absolute_frame(uint8_t *dst, int width, int height, int pattern) +{ + int row_size = (width + 7) >> 3; + int x, y; + + memset(dst, 0, row_size * height); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + int bit = ((x * (pattern + 1) + y * (pattern + 3) + pattern) ^ (x >> 1)) & 1; + if (bit) + dst[y * row_size + (x >> 3)] |= 0x80 >> (x & 7); + } + } +} + +static int configure_mode(const char *mode, int *nb_frames, int *corrupt_index, int key[4]) +{ + *corrupt_index = -1; + + if (!strcmp(mode, "key")) { + *nb_frames = 1; + key[0] = 1; + } else if (!strcmp(mode, "delta")) { + *nb_frames = 3; + key[0] = 1; + key[1] = 0; + key[2] = 0; + } else if (!strcmp(mode, "mixed")) { + *nb_frames = 4; + key[0] = 1; + key[1] = 0; + key[2] = 1; + key[3] = 0; + } else if (!strcmp(mode, "corrupt")) { + *nb_frames = 2; + key[0] = 1; + key[1] = 0; + *corrupt_index = 1; + } else { + return 1; + } + + return 0; +} + +static int write_pdv_file(const char *path, int nb_frames, const FramePayload *frames) +{ + FILE *f; + static const uint8_t pdv_magic[16] = { + 'P', 'l', 'a', 'y', 'd', 'a', 't', 'e', ' ', 'V', 'I', 'D', 0, 0, 0, 0 + }; + uint32_t offset = 0; + int i; + + f = fopen(path, "wb"); + if (!f) + return 1; + + fwrite(pdv_magic, 1, sizeof(pdv_magic), f); + put_le16(f, nb_frames); + put_le16(f, 0); + put_le32(f, PDV_FPS_30_FLOAT_BITS); + put_le16(f, PDV_WIDTH); + put_le16(f, PDV_HEIGHT); + + for (i = 0; i < nb_frames; i++) { + uint32_t flag = frames[i].key ? 1 : 2; + put_le32(f, (offset << 2) | flag); + offset += frames[i].size; + } + put_le32(f, offset << 2); + + for (i = 0; i < nb_frames; i++) { + if (fwrite(frames[i].data, 1, frames[i].size, f) != (size_t)frames[i].size) { + fclose(f); + return 1; + } + } + + fclose(f); + return 0; +} + +int main(int argc, char **argv) +{ + FramePayload frames[4] = { 0 }; + uint8_t *abs = NULL; + uint8_t *prev = NULL; + uint8_t *raw = NULL; + int key[4] = { 0 }; + int nb_frames; + int corrupt_index; + int row_size = (PDV_WIDTH + 7) >> 3; + int raw_size = row_size * PDV_HEIGHT; + int ret = 1; + int i, j; + + if (argc != 3) { + fprintf(stderr, "usage: %s <output.pdv> <key|delta|mixed|corrupt>\n", argv[0]); + return 1; + } + + if (configure_mode(argv[2], &nb_frames, &corrupt_index, key)) { + fprintf(stderr, "unknown mode '%s'\n", argv[2]); + return 1; + } + + abs = malloc(raw_size); + prev = malloc(raw_size); + raw = malloc(raw_size); + if (!abs || !prev || !raw) + goto end; + + memset(prev, 0, raw_size); + + for (i = 0; i < nb_frames; i++) { + fill_absolute_frame(abs, PDV_WIDTH, PDV_HEIGHT, i + 1); + + if (key[i]) { + memcpy(raw, abs, raw_size); + } else { + for (j = 0; j < raw_size; j++) + raw[j] = abs[j] ^ prev[j]; + } + + frames[i].key = key[i]; + if (make_zlib_stored_packet(raw, raw_size, i == corrupt_index, + &frames[i].data, &frames[i].size)) + goto end; + + memcpy(prev, abs, raw_size); + } + + if (write_pdv_file(argv[1], nb_frames, frames)) + goto end; + + ret = 0; + +end: + for (i = 0; i < 4; i++) + free(frames[i].data); + free(abs); + free(prev); + free(raw); + + return ret; +} diff --git a/tests/ref/fate/pdv-corrupt b/tests/ref/fate/pdv-corrupt new file mode 100644 index 0000000000..983d82e247 --- /dev/null +++ b/tests/ref/fate/pdv-corrupt @@ -0,0 +1,6 @@ +#tb 0: 1/30 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 16x8 +#sar 0: 0/1 +0, 0, 0, 1, 16, 0x6c600cc0 diff --git a/tests/ref/fate/pdv-delta b/tests/ref/fate/pdv-delta new file mode 100644 index 0000000000..d5d4c53af2 --- /dev/null +++ b/tests/ref/fate/pdv-delta @@ -0,0 +1,8 @@ +#tb 0: 1/30 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 16x8 +#sar 0: 0/1 +0, 0, 0, 1, 16, 0x6c600cc0 +0, 1, 1, 1, 16, 0x422407f8 +0, 2, 2, 1, 16, 0x6c600cc0 diff --git a/tests/ref/fate/pdv-key b/tests/ref/fate/pdv-key new file mode 100644 index 0000000000..983d82e247 --- /dev/null +++ b/tests/ref/fate/pdv-key @@ -0,0 +1,6 @@ +#tb 0: 1/30 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 16x8 +#sar 0: 0/1 +0, 0, 0, 1, 16, 0x6c600cc0 diff --git a/tests/ref/fate/pdv-skip-all b/tests/ref/fate/pdv-skip-all new file mode 100644 index 0000000000..84d7ad7b3f --- /dev/null +++ b/tests/ref/fate/pdv-skip-all @@ -0,0 +1,5 @@ +#tb 0: 1/30 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 16x8 +#sar 0: 0/1 diff --git a/tests/ref/fate/pdv-skip-nokey b/tests/ref/fate/pdv-skip-nokey new file mode 100644 index 0000000000..d824b2a4df --- /dev/null +++ b/tests/ref/fate/pdv-skip-nokey @@ -0,0 +1,7 @@ +#tb 0: 1/30 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 16x8 +#sar 0: 0/1 +0, 0, 0, 1, 16, 0x6c600cc0 +0, 2, 2, 1, 16, 0x6c600cc0 -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
