Commit 94edc9d37a for ffmpeg

commit 94edc9d37adf75bfc5d00d1fe5768587b6c08f62
Author: Zuxy Meng <zuxy.meng@gmail.com>
Date:   Sun Sep 6 19:49:40 2026 -0700

    avcodec/mips/h264dsp_msa: Fix edge cases for bi-weight on MSA

    S16 saturating sum must be computed dot-product-first. The MSA code
    accumulated the offset into the dot product with wrapping
    multiply-accumate, so large-magnitude sums wrapped instead of saturating.

    Accumulate the dot product from zero (wrapping is exact: the dot product
    cannot overflow S16 for 8-bit with log2_denom < 7), then add the offset
    with a saturating add.

    Signed-off-by: Zuxy Meng <zuxy.meng@gmail.com>

diff --git a/libavcodec/mips/h264dsp_msa.c b/libavcodec/mips/h264dsp_msa.c
index 9d815f8faa..5f039626ac 100644
--- a/libavcodec/mips/h264dsp_msa.c
+++ b/libavcodec/mips/h264dsp_msa.c
@@ -234,7 +234,7 @@ static void avc_biwgt_4x2_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     uint32_t tp0, tp1;
     v16i8 src_wgt, dst_wgt, wgt, vec0;
     v16u8 src0 = { 0 }, dst0 = { 0 };
-    v8i16 tmp0, denom, offset, max255 = __msa_ldi_h(255);
+    v8i16 tmp0, denom, offset, zero = { 0 }, max255 = __msa_ldi_h(255);

     offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom;
     offset_in += (128 * (src_weight + dst_weight));
@@ -252,7 +252,8 @@ static void avc_biwgt_4x2_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     INSERT_W2_UB(tp0, tp1, dst0);
     XORI_B2_128_UB(src0, dst0);
     vec0 = (v16i8) __msa_ilvr_b((v16i8) dst0, (v16i8) src0);
-    tmp0 = __msa_dpadd_s_h(offset, wgt, vec0);
+    tmp0 = __msa_dpadd_s_h(zero, wgt, vec0);
+    tmp0 = __msa_adds_s_h(tmp0, offset);
     tmp0 >>= denom;
     tmp0 = __msa_maxi_s_h(tmp0, 0);
     tmp0 = __msa_min_s_h(max255, tmp0);
@@ -267,7 +268,7 @@ static void avc_biwgt_4x4_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     uint32_t tp0, tp1, tp2, tp3;
     v16i8 src_wgt, dst_wgt, wgt, vec0, vec1;
     v16u8 src0, dst0;
-    v8i16 tmp0, tmp1, denom, offset;
+    v8i16 tmp0, tmp1, denom, offset, zero = { 0 };

     offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom;
     offset_in += (128 * (src_weight + dst_weight));
@@ -285,8 +286,10 @@ static void avc_biwgt_4x4_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0);
     XORI_B2_128_UB(src0, dst0);
     ILVRL_B2_SB(dst0, src0, vec0, vec1);
-    tmp0 = __msa_dpadd_s_h(offset, wgt, vec0);
-    tmp1 = __msa_dpadd_s_h(offset, wgt, vec1);
+    tmp0 = __msa_dpadd_s_h(zero, wgt, vec0);
+    tmp1 = __msa_dpadd_s_h(zero, wgt, vec1);
+    tmp0 = __msa_adds_s_h(tmp0, offset);
+    tmp1 = __msa_adds_s_h(tmp1, offset);
     tmp0 >>= denom;
     tmp1 >>= denom;
     CLIP_SH2_0_255(tmp0, tmp1);
@@ -301,7 +304,7 @@ static void avc_biwgt_4x8_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     uint32_t tp0, tp1, tp2, tp3;
     v16i8 src_wgt, dst_wgt, wgt, vec0, vec1, vec2, vec3;
     v16u8 src0, src1, dst0, dst1;
-    v8i16 tmp0, tmp1, tmp2, tmp3, denom, offset;
+    v8i16 tmp0, tmp1, tmp2, tmp3, denom, offset, zero = { 0 };

     offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom;
     offset_in += (128 * (src_weight + dst_weight));
@@ -324,10 +327,14 @@ static void avc_biwgt_4x8_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     XORI_B4_128_UB(src0, src1, dst0, dst1);
     ILVRL_B2_SB(dst0, src0, vec0, vec1);
     ILVRL_B2_SB(dst1, src1, vec2, vec3);
-    tmp0 = __msa_dpadd_s_h(offset, wgt, vec0);
-    tmp1 = __msa_dpadd_s_h(offset, wgt, vec1);
-    tmp2 = __msa_dpadd_s_h(offset, wgt, vec2);
-    tmp3 = __msa_dpadd_s_h(offset, wgt, vec3);
+    tmp0 = __msa_dpadd_s_h(zero, wgt, vec0);
+    tmp1 = __msa_dpadd_s_h(zero, wgt, vec1);
+    tmp2 = __msa_dpadd_s_h(zero, wgt, vec2);
+    tmp3 = __msa_dpadd_s_h(zero, wgt, vec3);
+    tmp0 = __msa_adds_s_h(tmp0, offset);
+    tmp1 = __msa_adds_s_h(tmp1, offset);
+    tmp2 = __msa_adds_s_h(tmp2, offset);
+    tmp3 = __msa_adds_s_h(tmp3, offset);
     SRA_4V(tmp0, tmp1, tmp2, tmp3, denom);
     CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3);
     PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, dst0, dst1);
@@ -341,7 +348,7 @@ static void avc_biwgt_8x4_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     uint64_t tp0, tp1, tp2, tp3;
     v16i8 src_wgt, dst_wgt, wgt, vec0, vec1, vec2, vec3;
     v16u8 src0, src1, dst0, dst1;
-    v8i16 tmp0, tmp1, tmp2, tmp3, denom, offset;
+    v8i16 tmp0, tmp1, tmp2, tmp3, denom, offset, zero = { 0 };

     offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom;
     offset_in += (128 * (src_weight + dst_weight));
@@ -362,10 +369,14 @@ static void avc_biwgt_8x4_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     XORI_B4_128_UB(src0, src1, dst0, dst1);
     ILVRL_B2_SB(dst0, src0, vec0, vec1);
     ILVRL_B2_SB(dst1, src1, vec2, vec3);
-    tmp0 = __msa_dpadd_s_h(offset, wgt, vec0);
-    tmp1 = __msa_dpadd_s_h(offset, wgt, vec1);
-    tmp2 = __msa_dpadd_s_h(offset, wgt, vec2);
-    tmp3 = __msa_dpadd_s_h(offset, wgt, vec3);
+    tmp0 = __msa_dpadd_s_h(zero, wgt, vec0);
+    tmp1 = __msa_dpadd_s_h(zero, wgt, vec1);
+    tmp2 = __msa_dpadd_s_h(zero, wgt, vec2);
+    tmp3 = __msa_dpadd_s_h(zero, wgt, vec3);
+    tmp0 = __msa_adds_s_h(tmp0, offset);
+    tmp1 = __msa_adds_s_h(tmp1, offset);
+    tmp2 = __msa_adds_s_h(tmp2, offset);
+    tmp3 = __msa_adds_s_h(tmp3, offset);
     SRA_4V(tmp0, tmp1, tmp2, tmp3, denom);
     CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3);
     PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, dst0, dst1);
@@ -379,7 +390,8 @@ static void avc_biwgt_8x8_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     uint64_t tp0, tp1, tp2, tp3;
     v16i8 src_wgt, dst_wgt, wgt, vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7;
     v16u8 src0, src1, src2, src3, dst0, dst1, dst2, dst3;
-    v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, denom, offset;
+    v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, denom, offset,
+          zero = { 0 };

     offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom;
     offset_in += (128 * (src_weight + dst_weight));
@@ -407,14 +419,22 @@ static void avc_biwgt_8x8_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     ILVRL_B2_SB(dst1, src1, vec2, vec3);
     ILVRL_B2_SB(dst2, src2, vec4, vec5);
     ILVRL_B2_SB(dst3, src3, vec6, vec7);
-    tmp0 = __msa_dpadd_s_h(offset, wgt, vec0);
-    tmp1 = __msa_dpadd_s_h(offset, wgt, vec1);
-    tmp2 = __msa_dpadd_s_h(offset, wgt, vec2);
-    tmp3 = __msa_dpadd_s_h(offset, wgt, vec3);
-    tmp4 = __msa_dpadd_s_h(offset, wgt, vec4);
-    tmp5 = __msa_dpadd_s_h(offset, wgt, vec5);
-    tmp6 = __msa_dpadd_s_h(offset, wgt, vec6);
-    tmp7 = __msa_dpadd_s_h(offset, wgt, vec7);
+    tmp0 = __msa_dpadd_s_h(zero, wgt, vec0);
+    tmp1 = __msa_dpadd_s_h(zero, wgt, vec1);
+    tmp2 = __msa_dpadd_s_h(zero, wgt, vec2);
+    tmp3 = __msa_dpadd_s_h(zero, wgt, vec3);
+    tmp4 = __msa_dpadd_s_h(zero, wgt, vec4);
+    tmp5 = __msa_dpadd_s_h(zero, wgt, vec5);
+    tmp6 = __msa_dpadd_s_h(zero, wgt, vec6);
+    tmp7 = __msa_dpadd_s_h(zero, wgt, vec7);
+    tmp0 = __msa_adds_s_h(tmp0, offset);
+    tmp1 = __msa_adds_s_h(tmp1, offset);
+    tmp2 = __msa_adds_s_h(tmp2, offset);
+    tmp3 = __msa_adds_s_h(tmp3, offset);
+    tmp4 = __msa_adds_s_h(tmp4, offset);
+    tmp5 = __msa_adds_s_h(tmp5, offset);
+    tmp6 = __msa_adds_s_h(tmp6, offset);
+    tmp7 = __msa_adds_s_h(tmp7, offset);
     SRA_4V(tmp0, tmp1, tmp2, tmp3, denom);
     SRA_4V(tmp4, tmp5, tmp6, tmp7, denom);
     CLIP_SH8_0_255(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
@@ -434,6 +454,7 @@ static void avc_biwgt_8x16_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
     v16u8 dst0, dst1, dst2, dst3;
     v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7;
     v8i16 temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+    v8i16 zero = { 0 };
     v8i16 denom, offset;

     offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom;
@@ -467,14 +488,22 @@ static void avc_biwgt_8x16_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
         ILVL_B4_SB(dst0, src0, dst1, src1, dst2, src2, dst3, src3,
                    vec1, vec3, vec5, vec7);

-        temp0 = __msa_dpadd_s_h(offset, wgt, vec0);
-        temp1 = __msa_dpadd_s_h(offset, wgt, vec1);
-        temp2 = __msa_dpadd_s_h(offset, wgt, vec2);
-        temp3 = __msa_dpadd_s_h(offset, wgt, vec3);
-        temp4 = __msa_dpadd_s_h(offset, wgt, vec4);
-        temp5 = __msa_dpadd_s_h(offset, wgt, vec5);
-        temp6 = __msa_dpadd_s_h(offset, wgt, vec6);
-        temp7 = __msa_dpadd_s_h(offset, wgt, vec7);
+        temp0 = __msa_dpadd_s_h(zero, wgt, vec0);
+        temp1 = __msa_dpadd_s_h(zero, wgt, vec1);
+        temp2 = __msa_dpadd_s_h(zero, wgt, vec2);
+        temp3 = __msa_dpadd_s_h(zero, wgt, vec3);
+        temp4 = __msa_dpadd_s_h(zero, wgt, vec4);
+        temp5 = __msa_dpadd_s_h(zero, wgt, vec5);
+        temp6 = __msa_dpadd_s_h(zero, wgt, vec6);
+        temp7 = __msa_dpadd_s_h(zero, wgt, vec7);
+        temp0 = __msa_adds_s_h(temp0, offset);
+        temp1 = __msa_adds_s_h(temp1, offset);
+        temp2 = __msa_adds_s_h(temp2, offset);
+        temp3 = __msa_adds_s_h(temp3, offset);
+        temp4 = __msa_adds_s_h(temp4, offset);
+        temp5 = __msa_adds_s_h(temp5, offset);
+        temp6 = __msa_adds_s_h(temp6, offset);
+        temp7 = __msa_adds_s_h(temp7, offset);

         SRA_4V(temp0, temp1, temp2, temp3, denom);
         SRA_4V(temp4, temp5, temp6, temp7, denom);
@@ -2343,7 +2372,7 @@ void ff_biweight_h264_pixels16_8_msa(uint8_t *dst, uint8_t *src,
     v16u8 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7;
     v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7;
     v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15;
-    v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+    v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, zero = { 0 };
     v8i16 tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
     v8i16 denom, offset;

@@ -2370,22 +2399,38 @@ void ff_biweight_h264_pixels16_8_msa(uint8_t *dst, uint8_t *src,
                vec12, vec14);
     ILVL_B4_SB(dst4, src4, dst5, src5, dst6, src6, dst7, src7, vec9, vec11,
                vec13, vec15);
-    tmp0 = __msa_dpadd_s_h(offset, wgt, vec0);
-    tmp1 = __msa_dpadd_s_h(offset, wgt, vec1);
-    tmp2 = __msa_dpadd_s_h(offset, wgt, vec2);
-    tmp3 = __msa_dpadd_s_h(offset, wgt, vec3);
-    tmp4 = __msa_dpadd_s_h(offset, wgt, vec4);
-    tmp5 = __msa_dpadd_s_h(offset, wgt, vec5);
-    tmp6 = __msa_dpadd_s_h(offset, wgt, vec6);
-    tmp7 = __msa_dpadd_s_h(offset, wgt, vec7);
-    tmp8 = __msa_dpadd_s_h(offset, wgt, vec8);
-    tmp9 = __msa_dpadd_s_h(offset, wgt, vec9);
-    tmp10 = __msa_dpadd_s_h(offset, wgt, vec10);
-    tmp11 = __msa_dpadd_s_h(offset, wgt, vec11);
-    tmp12 = __msa_dpadd_s_h(offset, wgt, vec12);
-    tmp13 = __msa_dpadd_s_h(offset, wgt, vec13);
-    tmp14 = __msa_dpadd_s_h(offset, wgt, vec14);
-    tmp15 = __msa_dpadd_s_h(offset, wgt, vec15);
+    tmp0 = __msa_dpadd_s_h(zero, wgt, vec0);
+    tmp1 = __msa_dpadd_s_h(zero, wgt, vec1);
+    tmp2 = __msa_dpadd_s_h(zero, wgt, vec2);
+    tmp3 = __msa_dpadd_s_h(zero, wgt, vec3);
+    tmp4 = __msa_dpadd_s_h(zero, wgt, vec4);
+    tmp5 = __msa_dpadd_s_h(zero, wgt, vec5);
+    tmp6 = __msa_dpadd_s_h(zero, wgt, vec6);
+    tmp7 = __msa_dpadd_s_h(zero, wgt, vec7);
+    tmp8 = __msa_dpadd_s_h(zero, wgt, vec8);
+    tmp9 = __msa_dpadd_s_h(zero, wgt, vec9);
+    tmp10 = __msa_dpadd_s_h(zero, wgt, vec10);
+    tmp11 = __msa_dpadd_s_h(zero, wgt, vec11);
+    tmp12 = __msa_dpadd_s_h(zero, wgt, vec12);
+    tmp13 = __msa_dpadd_s_h(zero, wgt, vec13);
+    tmp14 = __msa_dpadd_s_h(zero, wgt, vec14);
+    tmp15 = __msa_dpadd_s_h(zero, wgt, vec15);
+    tmp0 = __msa_adds_s_h(tmp0, offset);
+    tmp1 = __msa_adds_s_h(tmp1, offset);
+    tmp2 = __msa_adds_s_h(tmp2, offset);
+    tmp3 = __msa_adds_s_h(tmp3, offset);
+    tmp4 = __msa_adds_s_h(tmp4, offset);
+    tmp5 = __msa_adds_s_h(tmp5, offset);
+    tmp6 = __msa_adds_s_h(tmp6, offset);
+    tmp7 = __msa_adds_s_h(tmp7, offset);
+    tmp8 = __msa_adds_s_h(tmp8, offset);
+    tmp9 = __msa_adds_s_h(tmp9, offset);
+    tmp10 = __msa_adds_s_h(tmp10, offset);
+    tmp11 = __msa_adds_s_h(tmp11, offset);
+    tmp12 = __msa_adds_s_h(tmp12, offset);
+    tmp13 = __msa_adds_s_h(tmp13, offset);
+    tmp14 = __msa_adds_s_h(tmp14, offset);
+    tmp15 = __msa_adds_s_h(tmp15, offset);
     SRA_4V(tmp0, tmp1, tmp2, tmp3, denom);
     SRA_4V(tmp4, tmp5, tmp6, tmp7, denom);
     SRA_4V(tmp8, tmp9, tmp10, tmp11, denom);
@@ -2412,22 +2457,38 @@ void ff_biweight_h264_pixels16_8_msa(uint8_t *dst, uint8_t *src,
                    vec12, vec14);
         ILVL_B4_SB(dst4, src4, dst5, src5, dst6, src6, dst7, src7, vec9, vec11,
                    vec13, vec15);
-        tmp0 = __msa_dpadd_s_h(offset, wgt, vec0);
-        tmp1 = __msa_dpadd_s_h(offset, wgt, vec1);
-        tmp2 = __msa_dpadd_s_h(offset, wgt, vec2);
-        tmp3 = __msa_dpadd_s_h(offset, wgt, vec3);
-        tmp4 = __msa_dpadd_s_h(offset, wgt, vec4);
-        tmp5 = __msa_dpadd_s_h(offset, wgt, vec5);
-        tmp6 = __msa_dpadd_s_h(offset, wgt, vec6);
-        tmp7 = __msa_dpadd_s_h(offset, wgt, vec7);
-        tmp8 = __msa_dpadd_s_h(offset, wgt, vec8);
-        tmp9 = __msa_dpadd_s_h(offset, wgt, vec9);
-        tmp10 = __msa_dpadd_s_h(offset, wgt, vec10);
-        tmp11 = __msa_dpadd_s_h(offset, wgt, vec11);
-        tmp12 = __msa_dpadd_s_h(offset, wgt, vec12);
-        tmp13 = __msa_dpadd_s_h(offset, wgt, vec13);
-        tmp14 = __msa_dpadd_s_h(offset, wgt, vec14);
-        tmp15 = __msa_dpadd_s_h(offset, wgt, vec15);
+        tmp0 = __msa_dpadd_s_h(zero, wgt, vec0);
+        tmp1 = __msa_dpadd_s_h(zero, wgt, vec1);
+        tmp2 = __msa_dpadd_s_h(zero, wgt, vec2);
+        tmp3 = __msa_dpadd_s_h(zero, wgt, vec3);
+        tmp4 = __msa_dpadd_s_h(zero, wgt, vec4);
+        tmp5 = __msa_dpadd_s_h(zero, wgt, vec5);
+        tmp6 = __msa_dpadd_s_h(zero, wgt, vec6);
+        tmp7 = __msa_dpadd_s_h(zero, wgt, vec7);
+        tmp8 = __msa_dpadd_s_h(zero, wgt, vec8);
+        tmp9 = __msa_dpadd_s_h(zero, wgt, vec9);
+        tmp10 = __msa_dpadd_s_h(zero, wgt, vec10);
+        tmp11 = __msa_dpadd_s_h(zero, wgt, vec11);
+        tmp12 = __msa_dpadd_s_h(zero, wgt, vec12);
+        tmp13 = __msa_dpadd_s_h(zero, wgt, vec13);
+        tmp14 = __msa_dpadd_s_h(zero, wgt, vec14);
+        tmp15 = __msa_dpadd_s_h(zero, wgt, vec15);
+        tmp0 = __msa_adds_s_h(tmp0, offset);
+        tmp1 = __msa_adds_s_h(tmp1, offset);
+        tmp2 = __msa_adds_s_h(tmp2, offset);
+        tmp3 = __msa_adds_s_h(tmp3, offset);
+        tmp4 = __msa_adds_s_h(tmp4, offset);
+        tmp5 = __msa_adds_s_h(tmp5, offset);
+        tmp6 = __msa_adds_s_h(tmp6, offset);
+        tmp7 = __msa_adds_s_h(tmp7, offset);
+        tmp8 = __msa_adds_s_h(tmp8, offset);
+        tmp9 = __msa_adds_s_h(tmp9, offset);
+        tmp10 = __msa_adds_s_h(tmp10, offset);
+        tmp11 = __msa_adds_s_h(tmp11, offset);
+        tmp12 = __msa_adds_s_h(tmp12, offset);
+        tmp13 = __msa_adds_s_h(tmp13, offset);
+        tmp14 = __msa_adds_s_h(tmp14, offset);
+        tmp15 = __msa_adds_s_h(tmp15, offset);
         SRA_4V(tmp0, tmp1, tmp2, tmp3, denom);
         SRA_4V(tmp4, tmp5, tmp6, tmp7, denom);
         SRA_4V(tmp8, tmp9, tmp10, tmp11, denom);