This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 338316f0a3c397dcb87cb7e77f74e7cab05648c0 Author: Andreas Rheinhardt <[email protected]> AuthorDate: Tue Mar 17 05:33:13 2026 +0100 Commit: Andreas Rheinhardt <[email protected]> CommitDate: Thu Mar 19 14:44:30 2026 +0100 tests/checkasm: Add test for mpeg4videodsp It already uncovered a bug in the MMX version of gmc. Reviewed-by: Lynne <[email protected]> Signed-off-by: Andreas Rheinhardt <[email protected]> --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 + tests/checkasm/checkasm.h | 1 + tests/checkasm/mpeg4videodsp.c | 156 +++++++++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 162 insertions(+) diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 1e23587de9..6c525356aa 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -41,6 +41,7 @@ AVCODECOBJS-$(CONFIG_DIRAC_DECODER) += diracdsp.o AVCODECOBJS-$(CONFIG_EXR_DECODER) += exrdsp.o AVCODECOBJS-$(CONFIG_FLAC_DECODER) += flacdsp.o AVCODECOBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dsp.o +AVCODECOBJS-$(CONFIG_MPEG4_DECODER) += mpeg4videodsp.o AVCODECOBJS-$(CONFIG_OPUS_DECODER) += opusdsp.o AVCODECOBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_deblock.o hevc_dequant.o hevc_idct.o hevc_sao.o hevc_pel.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 8b2f648b3d..b1504b14bb 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -222,6 +222,9 @@ static const struct { #if CONFIG_ME_CMP { "motion", checkasm_check_motion }, #endif + #if CONFIG_MPEG4_DECODER + { "mpeg4videodsp", checkasm_check_mpeg4videodsp }, + #endif #if CONFIG_MPEGVIDEO { "mpegvideo_unquantize", checkasm_check_mpegvideo_unquantize }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 25654b20ba..f653207363 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -126,6 +126,7 @@ void checkasm_check_llviddsp(void); void checkasm_check_llvidencdsp(void); void checkasm_check_lpc(void); void checkasm_check_motion(void); +void checkasm_check_mpeg4videodsp(void); void checkasm_check_mpegvideo_unquantize(void); void checkasm_check_mpegvideoencdsp(void); void checkasm_check_nlmeans(void); diff --git a/tests/checkasm/mpeg4videodsp.c b/tests/checkasm/mpeg4videodsp.c new file mode 100644 index 0000000000..79a3ac5805 --- /dev/null +++ b/tests/checkasm/mpeg4videodsp.c @@ -0,0 +1,156 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 <assert.h> + +#include "checkasm.h" +#include "libavcodec/mpeg4videodsp.h" +#include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + +enum { + MAX_WIDTH = 1024, + MAX_HEIGHT = 64, + MAX_STRIDE = MAX_WIDTH, + MAX_BLOCK_HEIGHT = 16, + W = 8, +}; + +static_assert(MAX_WIDTH <= MAX_STRIDE, "stride needs to be >= width"); + +#define randomize_buffer(buf) \ + do { \ + static_assert(!(sizeof(buf) % 4), "Tail handling needed"); \ + for (size_t k = 0; k < sizeof(buf); k += 4) { \ + uint32_t r = rnd(); \ + AV_WN32A(buf + k, r); \ + } \ + } while (0) + +static int get_signed_rnd(int nb_bits) +{ + int32_t r = rnd(); + return r >> (32 - nb_bits); +} + +static int get_mv_delta(int shift, int is_diag) +{ + // The coordinates of the motion vector differences are fixed point numbers + // whose fractional part has 16+shift bits. We use 5+shift+4 bit mantissa + // for the deviation from the normal, so that the absolute value corresponds + // to < 2^(-7). For height 16, the maximum absolute deviation is < 1/8. + // Additionally, we always use zero for the four least significant bits, + // as the x86 implementation always falls back to the C one if it is not so. + return get_signed_rnd(6 + shift) * 16 + (is_diag ? (1 << (16 + shift)) : 0); +} + +static int modify_fpel(int coordinate, int size, int block_size, int type) +{ + switch (type) { + default: av_unreachable("impossible"); + // fallthrough + case 2: return coordinate; // do nothing + // modify coordinate so that it requires pixel replication to the left/top + case 1: return coordinate % block_size - block_size; + // modify coordinate so that it requires pixel replication to the right/down + case 0: return coordinate + block_size + (size - (block_size + 1) - coordinate) / block_size * block_size; + } +} + +static void checkasm_check_gmc(const Mpeg4VideoDSPContext *const mdsp) +{ + DECLARE_ALIGNED_8(uint8_t, buf_new)[MAX_BLOCK_HEIGHT * MAX_STRIDE]; + DECLARE_ALIGNED_8(uint8_t, buf_ref)[MAX_BLOCK_HEIGHT * MAX_STRIDE]; + DECLARE_ALIGNED_4(uint8_t, srcbuf)[MAX_STRIDE * MAX_HEIGHT]; + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const uint8_t *src, + int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, + int shift, int r, int width, int height); + + randomize_buffer(srcbuf); + randomize_buffer(buf_ref); + memcpy(buf_new, buf_ref, sizeof(buf_new)); + + int shift = 1 + rnd() % 4; // range 1..4 + const int h = rnd() & 1 ? 16 : 8; + const int r = (1 << (2 * shift - 1)) - (rnd() & 1); + const int width = FFALIGN(W + rnd() % (MAX_WIDTH - W + 1), 16); // range 8..MAX_WIDTH + const int height = FFALIGN(h + rnd() % (MAX_HEIGHT - h + 1), 8); // range h..MAX_HEIGHT + ptrdiff_t stride = FFALIGN(width + rnd() % (MAX_STRIDE - width + 1), 8); + const uint8_t *src = srcbuf; + uint8_t *dst_new = buf_new, *dst_ref = buf_ref; + + if (rnd() & 1) { // negate stride + dst_new += stride * (h - 1); + dst_ref += stride * (h - 1); + src += stride * (height - 1); + stride *= -1; + } + // Get the fullpel component of the motion vector. + // Restrict the range so that a (W+1)x(h+1) buffer fits in srcbuf + // (if possible) in order to test the non-edge-emulation codepath. + int fpel_x = width == W ? 0 : rnd() % (width - W); + int fpel_y = height == h ? 0 : rnd() % (height - h); + int dxx = get_mv_delta(shift, 1), dxy = get_mv_delta(shift, 0); + int dyx = get_mv_delta(shift, 0), dyy = get_mv_delta(shift, 1); + + int ox = fpel_x << (16 + shift) | rnd() & ((1 << (16 + shift)) - 1); + int oy = fpel_y << (16 + shift) | rnd() & ((1 << (16 + shift)) - 1); + + call_ref(dst_ref, src, stride, h, ox, oy, + dxx, dxy, dyx, dyy, shift, r, width, height); + call_new(dst_new, src, stride, h, ox, oy, + dxx, dxy, dyx, dyy, shift, r, width, height); + if (memcmp(buf_new, buf_ref, sizeof(buf_new))) + fail(); + + bench_new(dst_new, src, stride, h, ox, oy, + dxx, dxy, dyx, dyy, shift, r, width, height); + + // Now test the case of src being partially outside of the actual picture. + if (!check_func(mdsp->gmc, "gmc_edge_emulation")) + return; // shouldn't happen + int type = rnd() % 8; + fpel_x = modify_fpel(fpel_x, width, 8, type % 3); + fpel_y = modify_fpel(fpel_y, height, h, type / 3); + ox = fpel_x * (1 << (16 + shift)) | rnd() & ((1 << (16 + shift)) - 1); + oy = fpel_y * (1 << (16 + shift)) | rnd() & ((1 << (16 + shift)) - 1); + call_ref(dst_ref, src, stride, h, ox, oy, + dxx, dxy, dyx, dyy, shift, r, width, height); + call_new(dst_new, src, stride, h, ox, oy, + dxx, dxy, dyx, dyy, shift, r, width, height); + if (memcmp(buf_new, buf_ref, sizeof(buf_new))) + fail(); + + bench_new(dst_new, src, stride, h, ox, oy, + dxx, dxy, dyx, dyy, shift, r, width, height); +} + +void checkasm_check_mpeg4videodsp(void) +{ + Mpeg4VideoDSPContext mdsp; + + ff_mpeg4videodsp_init(&mdsp); + + if (check_func(mdsp.gmc, "gmc")) { + checkasm_check_gmc(&mdsp); + report("gmc"); + } +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index bd44bfd536..8441bb3719 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -42,6 +42,7 @@ FATE_CHECKASM = fate-checkasm-aacencdsp \ fate-checkasm-llvidencdsp \ fate-checkasm-lpc \ fate-checkasm-motion \ + fate-checkasm-mpeg4videodsp \ fate-checkasm-mpegvideo_unquantize \ fate-checkasm-mpegvideoencdsp \ fate-checkasm-opusdsp \ _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
