Commit c93354cdd4 for ffmpeg

commit c93354cdd4afbc9da7a9a389c91b473f4a7b43f5
Author: Rainbaby <r@bgr.jp>
Date:   Tue Nov 10 18:49:13 2026 +0900

    avcodec/tests/cavsdsp: test the C inverse transform

    checkasm only checks the SIMD versions against the C version. Check
    the C version against the transform as GB/T 20090.2-2013 9.8.2
    writes it. The old C version fails this.

    Signed-off-by: Rainbaby <r@bgr.jp>

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 4bffc08118..f12ad9c8e8 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1397,6 +1397,7 @@ TESTPROGS-$(CONFIG_AC3DSP)                += ac3
 TESTPROGS-$(CONFIG_APV_DECODER)           += apv
 TESTPROGS-$(CONFIG_AV1_VAAPI_ENCODER)     += av1_levels
 TESTPROGS-$(CONFIG_CABAC)                 += cabac
+TESTPROGS-$(CONFIG_CAVS_DECODER)          += cavsdsp
 TESTPROGS-$(CONFIG_CELP_MATH)             += celp_math
 TESTPROGS-$(CONFIG_ENCODERS)              += hw_base_encode
 TESTPROGS-$(CONFIG_GOLOMB)                += golomb
diff --git a/libavcodec/tests/.gitignore b/libavcodec/tests/.gitignore
index 3e986b00dd..436476bc78 100644
--- a/libavcodec/tests/.gitignore
+++ b/libavcodec/tests/.gitignore
@@ -6,6 +6,7 @@
 /bitstream_be
 /bitstream_le
 /cabac
+/cavsdsp
 /celp_math
 /codec_desc
 /dct
diff --git a/libavcodec/tests/cavsdsp.c b/libavcodec/tests/cavsdsp.c
new file mode 100644
index 0000000000..d91d7ea256
--- /dev/null
+++ b/libavcodec/tests/cavsdsp.c
@@ -0,0 +1,129 @@
+/*
+ * 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
+ */
+
+/*
+ * Check the C inverse transform against the matrix product of
+ * GB/T 20090.2-2013 9.8.2 and GY/T 257.1-2012 9.7.
+ * The SIMD versions are checked against the C version by checkasm.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/common.h"
+#include "libavutil/cpu.h"
+#include "libavutil/lfg.h"
+#include "libavutil/mem_internal.h"
+
+#include "libavcodec/cavsdsp.h"
+#include "libavcodec/idctdsp.h"
+
+#define STRIDE 16
+
+static const int8_t t8[8][8] = {
+    { 8,  10,  10,   9,  8,   6,   4,   2 },
+    { 8,   9,   4,  -2, -8, -10, -10,  -6 },
+    { 8,   6,  -4, -10, -8,   2,  10,   9 },
+    { 8,   2, -10,  -6,  8,   9,  -4, -10 },
+    { 8,  -2, -10,   6,  8,  -9,  -4,  10 },
+    { 8,  -6,  -4,  10, -8,  -2,  10,  -9 },
+    { 8,  -9,   4,   2, -8,  10, -10,   6 },
+    { 8, -10,  10,  -9,  8,  -6,   4,  -2 },
+};
+
+static void idct8_add_ref(uint8_t *dst, const int16_t coeffs[64])
+{
+    int tmp[8][8];
+
+    for (int i = 0; i < 8; i++) {
+        for (int j = 0; j < 8; j++) {
+            int sum = 4;
+            for (int k = 0; k < 8; k++)
+                sum += coeffs[8 * i + k] * t8[j][k];
+            tmp[i][j] = av_clip_int16(sum) >> 3;
+        }
+    }
+    for (int i = 0; i < 8; i++) {
+        for (int j = 0; j < 8; j++) {
+            int sum = 64;
+            for (int k = 0; k < 8; k++)
+                sum += t8[i][k] * tmp[k][j];
+            dst[j] = av_clip_uint8(dst[j] + (av_clip_int16(sum) >> 7));
+        }
+        dst += STRIDE;
+    }
+}
+
+static int check_block(CAVSDSPContext *c, const uint8_t *perm,
+                       const int16_t coeffs[64], AVLFG *lfg, int n)
+{
+    DECLARE_ALIGNED(16, int16_t, block)[64];
+    DECLARE_ALIGNED(16, uint8_t, ref)[8 * STRIDE];
+    DECLARE_ALIGNED(16, uint8_t, out)[8 * STRIDE];
+
+    for (int i = 0; i < 64; i++)
+        block[perm[i]] = coeffs[i];
+    for (int i = 0; i < 8 * STRIDE; i++)
+        ref[i] = out[i] = av_lfg_get(lfg);
+
+    idct8_add_ref(ref, coeffs);
+    c->cavs_idct8_add(out, block, STRIDE);
+    if (memcmp(ref, out, sizeof(ref))) {
+        fprintf(stderr, "cavs_idct8_add: mismatch in block %d\n", n);
+        return 1;
+    }
+    return 0;
+}
+
+int main(void)
+{
+    CAVSDSPContext c;
+    uint8_t perm[64];
+    int16_t coeffs[64];
+    AVLFG lfg;
+    int n = 0, ret = 0;
+
+    av_force_cpu_flags(0);
+    ff_cavsdsp_init(&c);
+    ff_init_scantable_permutation(perm, c.idct_perm);
+    av_lfg_init(&lfg, 1);
+
+    /* drive each first pass sum to both ends of its range */
+    for (int j = 0; j < 8; j++) {
+        for (int sign = -1; sign <= 1; sign += 2) {
+            for (int i = 0; i < 64; i++)
+                coeffs[i] = (t8[j][i & 7] * sign < 0) ? INT16_MIN : INT16_MAX;
+            ret |= check_block(&c, perm, coeffs, &lfg, n++);
+        }
+    }
+
+    /* magnitudes from the whole int16_t range down to single digits */
+    for (int iter = 0; iter < 100000; iter++) {
+        int count = 1 + av_lfg_get(&lfg) % 64;
+
+        memset(coeffs, 0, sizeof(coeffs));
+        for (int k = 0; k < count; k++) {
+            unsigned r = av_lfg_get(&lfg);
+            coeffs[r & 63] = (int16_t)av_lfg_get(&lfg) >> (r >> 6 & 15);
+        }
+        ret |= check_block(&c, perm, coeffs, &lfg, n++);
+    }
+
+    return ret;
+}
diff --git a/tests/fate/libavcodec.mak b/tests/fate/libavcodec.mak
index 82cdb041d1..2e2dabcd14 100644
--- a/tests/fate/libavcodec.mak
+++ b/tests/fate/libavcodec.mak
@@ -36,6 +36,11 @@ fate-cabac: libavcodec/tests/cabac$(EXESUF)
 fate-cabac: CMD = run libavcodec/tests/cabac$(EXESUF)
 fate-cabac: CMP = null

+FATE_LIBAVCODEC-$(CONFIG_CAVS_DECODER) += fate-cavsdsp
+fate-cavsdsp: libavcodec/tests/cavsdsp$(EXESUF)
+fate-cavsdsp: CMD = run libavcodec/tests/cavsdsp$(EXESUF)
+fate-cavsdsp: CMP = null
+
 FATE_LIBAVCODEC-$(CONFIG_CELP_MATH) += fate-celp_math
 fate-celp_math: libavcodec/tests/celp_math$(EXESUF)
 fate-celp_math: CMD = run libavcodec/tests/celp_math$(EXESUF)