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);