Files
2024-06-17 20:39:36 +08:00

1751 lines
88 KiB
Diff

diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c
index 815149a501..d4ddcba9e7 100644
--- a/libavcodec/h264_cabac.c
+++ b/libavcodec/h264_cabac.c
@@ -44,6 +44,8 @@
#if ARCH_X86
#include "x86/h264_cabac.c"
+#elif ARCH_LOONGARCH64
+#include "loongarch/h264_cabac.c"
#endif
/* Cabac pre state table */
diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c
index 5632a58fd7..718f2819ce 100644
--- a/libavcodec/h264pred.c
+++ b/libavcodec/h264pred.c
@@ -600,4 +600,6 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id,
ff_h264_pred_init_x86(h, codec_id, bit_depth, chroma_format_idc);
if (ARCH_MIPS)
ff_h264_pred_init_mips(h, codec_id, bit_depth, chroma_format_idc);
+ if (ARCH_LOONGARCH)
+ ff_h264_pred_init_loongarch(h, codec_id, bit_depth, chroma_format_idc);
}
diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h
index 2863dc9bd1..4583052dfe 100644
--- a/libavcodec/h264pred.h
+++ b/libavcodec/h264pred.h
@@ -122,5 +122,7 @@ void ff_h264_pred_init_x86(H264PredContext *h, int codec_id,
const int bit_depth, const int chroma_format_idc);
void ff_h264_pred_init_mips(H264PredContext *h, int codec_id,
const int bit_depth, const int chroma_format_idc);
+void ff_h264_pred_init_loongarch(H264PredContext *h, int codec_id,
+ const int bit_depth, const int chroma_format_idc);
#endif /* AVCODEC_H264PRED_H */
diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile
index d82eef4fd0..583e3545eb 100644
--- a/libavcodec/loongarch/Makefile
+++ b/libavcodec/loongarch/Makefile
@@ -8,6 +8,7 @@ OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_init_loongarch.o
OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8dsp_init_loongarch.o
OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9dsp_init_loongarch.o
OBJS-$(CONFIG_VIDEODSP) += loongarch/videodsp_init.o
+OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_init_loongarch.o
LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \
loongarch/h264idct_lasx.o \
loongarch/h264_deblock_lasx.o
@@ -17,6 +18,7 @@ LASX-OBJS-$(CONFIG_IDCTDSP) += loongarch/simple_idct_lasx.o \
loongarch/idctdsp_lasx.o
LASX-OBJS-$(CONFIG_VC1_DECODER) += loongarch/vc1dsp_lasx.o
LASX-OBJS-$(CONFIG_HPELDSP) += loongarch/hpeldsp_lasx.o
+LASX-OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_lasx.o
LSX-OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_lsx.o
LSX-OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevc_idct_lsx.o
LSX-OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevc_mc_bi_lsx.o
diff --git a/libavcodec/loongarch/cabac.h b/libavcodec/loongarch/cabac.h
index c0e17e3462..ea937665b4 100644
--- a/libavcodec/loongarch/cabac.h
+++ b/libavcodec/loongarch/cabac.h
@@ -28,67 +28,105 @@
#include "libavcodec/cabac.h"
#include "config.h"
+#define GET_CABAC_LOONGARCH \
+ "ld.bu %[bit], %[state], 0x0 \n\t" \
+ "andi %[tmp0], %[c_range], 0xC0 \n\t" \
+ "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \
+ "add.d %[tmp0], %[tmp0], %[tables] \n\t" \
+ "add.d %[tmp0], %[tmp0], %[bit] \n\t" \
+ /* tmp1: RangeLPS */ \
+ "ld.bu %[tmp1], %[tmp0], %[lps_off] \n\t" \
+ \
+ "sub.d %[c_range], %[c_range], %[tmp1] \n\t" \
+ "slli.d %[tmp0], %[c_range], 0x11 \n\t" \
+ "bge %[tmp0], %[c_low], 1f \n\t" \
+ "move %[c_range], %[tmp1] \n\t" \
+ "nor %[bit], %[bit], %[bit] \n\t" \
+ "sub.d %[c_low], %[c_low], %[tmp0] \n\t" \
+ \
+ "1: \n\t" \
+ /* tmp1: *state */ \
+ "add.d %[tmp0], %[tables], %[bit] \n\t" \
+ "ld.bu %[tmp1], %[tmp0], %[mlps_off] \n\t" \
+ /* tmp2: lps_mask */ \
+ "add.d %[tmp0], %[tables], %[c_range] \n\t" \
+ "ld.bu %[tmp2], %[tmp0], %[norm_off] \n\t" \
+ \
+ "andi %[bit], %[bit], 0x01 \n\t" \
+ "st.b %[tmp1], %[state], 0x0 \n\t" \
+ "sll.d %[c_range], %[c_range], %[tmp2] \n\t" \
+ "sll.d %[c_low], %[c_low], %[tmp2] \n\t" \
+ \
+ "and %[tmp1], %[c_low], %[cabac_mask] \n\t" \
+ "bnez %[tmp1], 1f \n\t" \
+ "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" \
+ "ctz.d %[tmp0], %[c_low] \n\t" \
+ "addi.d %[tmp2], %[tmp0], -16 \n\t" \
+ "revb.2h %[tmp0], %[tmp1] \n\t" \
+ "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \
+ "sub.d %[tmp0], %[tmp0], %[cabac_mask] \n\t" \
+ "sll.d %[tmp0], %[tmp0], %[tmp2] \n\t" \
+ "add.d %[c_low], %[c_low], %[tmp0] \n\t" \
+ "addi.d %[c_bytestream], %[c_bytestream], 0x02 \n\t" \
+ "1: \n\t" \
+
+#define GET_CABAC_LOONGARCH_END \
+ "ld.bu %[bit], %[state], 0x0 \n\t" \
+ "andi %[tmp0], %[c_range], 0xC0 \n\t" \
+ "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \
+ "add.d %[tmp0], %[tmp0], %[tables] \n\t" \
+ "add.d %[tmp0], %[tmp0], %[bit] \n\t" \
+ /* tmp1: RangeLPS */ \
+ "ld.bu %[tmp1], %[tmp0], %[lps_off] \n\t" \
+ \
+ "sub.d %[c_range], %[c_range], %[tmp1] \n\t" \
+ "slli.d %[tmp0], %[c_range], 0x11 \n\t" \
+ "bge %[tmp0], %[c_low], 1f \n\t" \
+ "move %[c_range], %[tmp1] \n\t" \
+ "nor %[bit], %[bit], %[bit] \n\t" \
+ "sub.d %[c_low], %[c_low], %[tmp0] \n\t" \
+ \
+ "1: \n\t" \
+ /* tmp1: *state */ \
+ "add.d %[tmp0], %[tables], %[bit] \n\t" \
+ "ld.bu %[tmp1], %[tmp0], %[mlps_off] \n\t" \
+ /* tmp2: lps_mask */ \
+ "add.d %[tmp0], %[tables], %[c_range] \n\t" \
+ "ld.bu %[tmp2], %[tmp0], %[norm_off] \n\t" \
+ \
+ "andi %[bit], %[bit], 0x01 \n\t" \
+ "st.b %[tmp1], %[state], 0x0 \n\t" \
+ "sll.d %[c_range], %[c_range], %[tmp2] \n\t" \
+ "sll.d %[c_low], %[c_low], %[tmp2] \n\t" \
+ \
+ "and %[tmp1], %[c_low], %[cabac_mask] \n\t" \
+ "bnez %[tmp1], 1f \n\t" \
+ "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" \
+ "ctz.d %[tmp0], %[c_low] \n\t" \
+ "addi.d %[tmp2], %[tmp0], -16 \n\t" \
+ "revb.2h %[tmp0], %[tmp1] \n\t" \
+ "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \
+ "sub.d %[tmp0], %[tmp0], %[cabac_mask] \n\t" \
+ "sll.d %[tmp0], %[tmp0], %[tmp2] \n\t" \
+ \
+ "add.d %[c_low], %[c_low], %[tmp0] \n\t" \
+ \
+ "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" \
+ "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" \
+ "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" \
+ "1: \n\t" \
+
#define get_cabac_inline get_cabac_inline_loongarch
static av_always_inline int get_cabac_inline_loongarch(CABACContext *c,
uint8_t * const state){
int64_t tmp0, tmp1, tmp2, bit;
__asm__ volatile (
- "ld.bu %[bit], %[state], 0x0 \n\t"
- "andi %[tmp0], %[c_range], 0xC0 \n\t"
- "slli.d %[tmp0], %[tmp0], 0x01 \n\t"
- "add.d %[tmp0], %[tmp0], %[tables] \n\t"
- "add.d %[tmp0], %[tmp0], %[bit] \n\t"
- /* tmp1: RangeLPS */
- "ld.bu %[tmp1], %[tmp0], %[lps_off] \n\t"
-
- "sub.d %[c_range], %[c_range], %[tmp1] \n\t"
- "slli.d %[tmp0], %[c_range], 0x11 \n\t"
- "bge %[tmp0], %[c_low], 1f \n\t"
- "move %[c_range], %[tmp1] \n\t"
- "nor %[bit], %[bit], %[bit] \n\t"
- "sub.d %[c_low], %[c_low], %[tmp0] \n\t"
-
- "1: \n\t"
- /* tmp1: *state */
- "add.d %[tmp0], %[tables], %[bit] \n\t"
- "ld.bu %[tmp1], %[tmp0], %[mlps_off] \n\t"
- /* tmp2: lps_mask */
- "add.d %[tmp0], %[tables], %[c_range] \n\t"
- "ld.bu %[tmp2], %[tmp0], %[norm_off] \n\t"
-
- "andi %[bit], %[bit], 0x01 \n\t"
- "st.b %[tmp1], %[state], 0x0 \n\t"
- "sll.d %[c_range], %[c_range], %[tmp2] \n\t"
- "sll.d %[c_low], %[c_low], %[tmp2] \n\t"
-
- "and %[tmp1], %[c_low], %[cabac_mask] \n\t"
- "bnez %[tmp1], 1f \n\t"
- "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t"
- "addi.d %[tmp0], %[c_low], -0X01 \n\t"
- "xor %[tmp0], %[c_low], %[tmp0] \n\t"
- "srai.d %[tmp0], %[tmp0], 0x0f \n\t"
- "add.d %[tmp0], %[tmp0], %[tables] \n\t"
- /* tmp2: ff_h264_norm_shift[x >> (CABAC_BITS - 1)] */
- "ld.bu %[tmp2], %[tmp0], %[norm_off] \n\t"
-
- "revb.2h %[tmp0], %[tmp1] \n\t"
- "slli.d %[tmp0], %[tmp0], 0x01 \n\t"
- "sub.d %[tmp0], %[tmp0], %[cabac_mask] \n\t"
-
- "li.d %[tmp1], 0x07 \n\t"
- "sub.d %[tmp1], %[tmp1], %[tmp2] \n\t"
- "sll.d %[tmp0], %[tmp0], %[tmp1] \n\t"
- "add.d %[c_low], %[c_low], %[tmp0] \n\t"
-
#if UNCHECKED_BITSTREAM_READER
- "addi.d %[c_bytestream], %[c_bytestream], 0x02 \n\t"
+ GET_CABAC_LOONGARCH
#else
- "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t"
- "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t"
- "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t"
+ GET_CABAC_LOONGARCH_END
#endif
- "1: \n\t"
: [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2),
[c_range]"+&r"(c->range), [c_low]"+&r"(c->low),
[c_bytestream]"+&r"(c->bytestream)
diff --git a/libavcodec/loongarch/h264_cabac.c b/libavcodec/loongarch/h264_cabac.c
new file mode 100644
index 0000000000..d3ea8a884c
--- /dev/null
+++ b/libavcodec/loongarch/h264_cabac.c
@@ -0,0 +1,136 @@
+/*
+ * Loongson optimized cabac
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ * Contributed by Hao Chen <chenhao@loongson.cn>
+ *
+ * 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 "libavcodec/cabac.h"
+#include "cabac.h"
+
+#define decode_significance decode_significance_loongarch
+static int decode_significance_loongarch(CABACContext *c, int max_coeff,
+ uint8_t *significant_coeff_ctx_base,
+ int *index, int64_t last_off)
+{
+ void *end = significant_coeff_ctx_base + max_coeff - 1;
+ int64_t minusstart = -(int64_t)significant_coeff_ctx_base;
+ int64_t minusindex = 4 - (int64_t)index;
+ int64_t bit, tmp0, tmp1, tmp2, one = 1;
+ uint8_t *state = significant_coeff_ctx_base;
+
+ __asm__ volatile(
+ "3:"
+#if UNCHECKED_BITSTREAM_READER
+ GET_CABAC_LOONGARCH
+#else
+ GET_CABAC_LOONGARCH_END
+#endif
+ "blt %[bit], %[one], 4f \n\t"
+ "add.d %[state], %[state], %[last_off] \n\t"
+#if UNCHECKED_BITSTREAM_READER
+ GET_CABAC_LOONGARCH
+#else
+ GET_CABAC_LOONGARCH_END
+#endif
+ "sub.d %[state], %[state], %[last_off] \n\t"
+ "add.d %[tmp0], %[state], %[minusstart] \n\t"
+ "st.w %[tmp0], %[index], 0 \n\t"
+ "bge %[bit], %[one], 5f \n\t"
+ "addi.d %[index], %[index], 4 \n\t"
+ "4: \n\t"
+ "addi.d %[state], %[state], 1 \n\t"
+ "blt %[state], %[end], 3b \n\t"
+ "add.d %[tmp0], %[state], %[minusstart] \n\t"
+ "st.w %[tmp0], %[index], 0 \n\t"
+ "5: \n\t"
+ "add.d %[tmp0], %[index], %[minusindex] \n\t"
+ "srli.d %[tmp0], %[tmp0], 2 \n\t"
+ : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [c_range]"+&r"(c->range),
+ [c_low]"+&r"(c->low), [state]"+&r"(state),
+ [c_bytestream]"+&r"(c->bytestream), [index]"+&r"(index)
+ : [tables]"r"(ff_h264_cabac_tables), [end]"r"(end), [one]"r"(one),
+ [minusstart]"r"(minusstart), [minusindex]"r"(minusindex), [last_off]"r"(last_off),
+#if !UNCHECKED_BITSTREAM_READER
+ [c_bytestream_end]"r"(c->bytestream_end),
+#endif
+ [lps_off]"i"(H264_LPS_RANGE_OFFSET),
+ [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128),
+ [norm_off]"i"(H264_NORM_SHIFT_OFFSET),
+ [cabac_mask]"r"(CABAC_MASK)
+ : "memory"
+ );
+
+ return (int)tmp0;
+}
+
+#define decode_significance_8x8 decode_significance_8x8_loongarch
+static int decode_significance_8x8_loongarch(CABACContext *c,
+ uint8_t *significant_coeff_ctx_base,
+ int *index, uint8_t *last_coeff_ctx_base, const uint8_t *sig_off)
+{
+ int64_t minusindex = 4 - (int64_t)index;
+ int64_t bit, tmp0, tmp1, tmp2, one = 1, end = 63, last = 0;
+ uint8_t *state = 0;
+ int64_t flag_offset = H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET;
+
+ __asm__ volatile(
+ "3: \n\t"
+ "ldx.bu %[tmp0], %[sig_off], %[last] \n\t"
+ "add.d %[state], %[tmp0], %[significant_coeff_ctx_base] \n\t"
+#if UNCHECKED_BITSTREAM_READER
+ GET_CABAC_LOONGARCH
+#else
+ GET_CABAC_LOONGARCH_END
+#endif
+ "blt %[bit], %[one], 4f \n\t"
+ "add.d %[tmp0], %[tables], %[flag_offset] \n\t"
+ "ldx.bu %[tmp1], %[tmp0], %[last] \n\t"
+ "add.d %[state], %[tmp1], %[last_coeff_ctx_base] \n\t"
+#if UNCHECKED_BITSTREAM_READER
+ GET_CABAC_LOONGARCH
+#else
+ GET_CABAC_LOONGARCH_END
+#endif
+ "st.w %[last], %[index], 0 \n\t"
+ "bge %[bit], %[one], 5f \n\t"
+ "addi.d %[index], %[index], 4 \n\t"
+ "4: \n\t"
+ "addi.d %[last], %[last], 1 \n\t"
+ "blt %[last], %[end], 3b \n\t"
+ "st.w %[last], %[index], 0 \n\t"
+ "5: \n\t"
+ "add.d %[tmp0], %[index], %[minusindex] \n\t"
+ "srli.d %[tmp0], %[tmp0], 2 \n\t"
+ : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [c_range]"+&r"(c->range),
+ [c_low]"+&r"(c->low), [state]"+&r"(state), [last]"+&r"(last),
+ [c_bytestream]"+&r"(c->bytestream), [index]"+&r"(index)
+ : [tables]"r"(ff_h264_cabac_tables), [end]"r"(end), [one]"r"(one), [minusindex]"r"(minusindex),
+ [last_coeff_ctx_base]"r"(last_coeff_ctx_base), [flag_offset]"r"(flag_offset),
+#if !UNCHECKED_BITSTREAM_READER
+ [c_bytestream_end]"r"(c->bytestream_end),
+#endif
+ [lps_off]"i"(H264_LPS_RANGE_OFFSET), [sig_off]"r"(sig_off),
+ [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128),
+ [norm_off]"i"(H264_NORM_SHIFT_OFFSET),
+ [cabac_mask]"r"(CABAC_MASK), [significant_coeff_ctx_base]"r"(significant_coeff_ctx_base)
+ );
+
+ return (int)tmp0;
+}
diff --git a/libavcodec/loongarch/h264_intrapred_init_loongarch.c b/libavcodec/loongarch/h264_intrapred_init_loongarch.c
new file mode 100644
index 0000000000..12620bd842
--- /dev/null
+++ b/libavcodec/loongarch/h264_intrapred_init_loongarch.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ * Contributed by Hao Chen <chenhao@loongson.cn>
+ *
+ * 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 "libavutil/loongarch/cpu.h"
+#include "libavcodec/h264pred.h"
+#include "h264_intrapred_lasx.h"
+
+av_cold void ff_h264_pred_init_loongarch(H264PredContext *h, int codec_id,
+ const int bit_depth,
+ const int chroma_format_idc)
+{
+ int cpu_flags = av_get_cpu_flags();
+
+ if (bit_depth == 8) {
+ if (have_lasx(cpu_flags)) {
+ if (chroma_format_idc <= 1) {
+ }
+ if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {
+ } else {
+ if (chroma_format_idc <= 1) {
+ }
+ if (codec_id == AV_CODEC_ID_SVQ3) {
+ h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_svq3_8_lasx;
+ } else if (codec_id == AV_CODEC_ID_RV40) {
+ h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_rv40_8_lasx;
+ } else {
+ h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_h264_8_lasx;
+ }
+ }
+ }
+ }
+}
diff --git a/libavcodec/loongarch/h264_intrapred_lasx.c b/libavcodec/loongarch/h264_intrapred_lasx.c
new file mode 100644
index 0000000000..c38cd611b8
--- /dev/null
+++ b/libavcodec/loongarch/h264_intrapred_lasx.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ * Contributed by Hao Chen <chenhao@loongson.cn>
+ *
+ * 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 "libavutil/loongarch/loongson_intrinsics.h"
+#include "h264_intrapred_lasx.h"
+
+#define PRED16X16_PLANE \
+ ptrdiff_t stride_1, stride_2, stride_3, stride_4, stride_5, stride_6; \
+ ptrdiff_t stride_8, stride_15; \
+ int32_t res0, res1, res2, res3, cnt; \
+ uint8_t *src0, *src1; \
+ __m256i reg0, reg1, reg2, reg3, reg4; \
+ __m256i tmp0, tmp1, tmp2, tmp3; \
+ __m256i shuff = {0x0B040A0509060807, 0x0F000E010D020C03, 0, 0}; \
+ __m256i mult = {0x0004000300020001, 0x0008000700060005, 0, 0}; \
+ __m256i int_mult1 = {0x0000000100000000, 0x0000000300000002, \
+ 0x0000000500000004, 0x0000000700000006}; \
+ \
+ stride_1 = -stride; \
+ stride_2 = stride << 1; \
+ stride_3 = stride_2 + stride; \
+ stride_4 = stride_2 << 1; \
+ stride_5 = stride_4 + stride; \
+ stride_6 = stride_3 << 1; \
+ stride_8 = stride_4 << 1; \
+ stride_15 = (stride_8 << 1) - stride; \
+ src0 = src - 1; \
+ src1 = src0 + stride_8; \
+ \
+ reg0 = __lasx_xvldx(src0, -stride); \
+ reg1 = __lasx_xvldx(src, (8 - stride)); \
+ reg0 = __lasx_xvilvl_d(reg1, reg0); \
+ reg0 = __lasx_xvshuf_b(reg0, reg0, shuff); \
+ reg0 = __lasx_xvhsubw_hu_bu(reg0, reg0); \
+ reg0 = __lasx_xvmul_h(reg0, mult); \
+ res1 = (src1[0] - src0[stride_6]) + \
+ 2 * (src1[stride] - src0[stride_5]) + \
+ 3 * (src1[stride_2] - src0[stride_4]) + \
+ 4 * (src1[stride_3] - src0[stride_3]) + \
+ 5 * (src1[stride_4] - src0[stride_2]) + \
+ 6 * (src1[stride_5] - src0[stride]) + \
+ 7 * (src1[stride_6] - src0[0]) + \
+ 8 * (src0[stride_15] - src0[stride_1]); \
+ reg0 = __lasx_xvhaddw_w_h(reg0, reg0); \
+ reg0 = __lasx_xvhaddw_d_w(reg0, reg0); \
+ reg0 = __lasx_xvhaddw_q_d(reg0, reg0); \
+ res0 = __lasx_xvpickve2gr_w(reg0, 0); \
+
+#define PRED16X16_PLANE_END \
+ res2 = (src0[stride_15] + src[15 - stride] + 1) << 4; \
+ res3 = 7 * (res0 + res1); \
+ res2 -= res3; \
+ reg0 = __lasx_xvreplgr2vr_w(res0); \
+ reg1 = __lasx_xvreplgr2vr_w(res1); \
+ reg2 = __lasx_xvreplgr2vr_w(res2); \
+ reg3 = __lasx_xvmul_w(reg0, int_mult1); \
+ reg4 = __lasx_xvslli_w(reg0, 3); \
+ reg4 = __lasx_xvadd_w(reg4, reg3); \
+ for (cnt = 8; cnt--;) { \
+ tmp0 = __lasx_xvadd_w(reg2, reg3); \
+ tmp1 = __lasx_xvadd_w(reg2, reg4); \
+ tmp0 = __lasx_xvssrani_hu_w(tmp1, tmp0, 5); \
+ tmp0 = __lasx_xvpermi_d(tmp0, 0xD8); \
+ reg2 = __lasx_xvadd_w(reg2, reg1); \
+ tmp2 = __lasx_xvadd_w(reg2, reg3); \
+ tmp3 = __lasx_xvadd_w(reg2, reg4); \
+ tmp1 = __lasx_xvssrani_hu_w(tmp3, tmp2, 5); \
+ tmp1 = __lasx_xvpermi_d(tmp1, 0xD8); \
+ tmp0 = __lasx_xvssrani_bu_h(tmp1, tmp0, 0); \
+ reg2 = __lasx_xvadd_w(reg2, reg1); \
+ __lasx_xvstelm_d(tmp0, src, 0, 0); \
+ __lasx_xvstelm_d(tmp0, src, 8, 2); \
+ src += stride; \
+ __lasx_xvstelm_d(tmp0, src, 0, 1); \
+ __lasx_xvstelm_d(tmp0, src, 8, 3); \
+ src += stride; \
+ }
+
+
+void ff_h264_pred16x16_plane_h264_8_lasx(uint8_t *src, ptrdiff_t stride)
+{
+ PRED16X16_PLANE
+ res0 = (5 * res0 + 32) >> 6;
+ res1 = (5 * res1 + 32) >> 6;
+ PRED16X16_PLANE_END
+}
+
+void ff_h264_pred16x16_plane_rv40_8_lasx(uint8_t *src, ptrdiff_t stride)
+{
+ PRED16X16_PLANE
+ res0 = (res0 + (res0 >> 2)) >> 4;
+ res1 = (res1 + (res1 >> 2)) >> 4;
+ PRED16X16_PLANE_END
+}
+
+void ff_h264_pred16x16_plane_svq3_8_lasx(uint8_t *src, ptrdiff_t stride)
+{
+ PRED16X16_PLANE
+ cnt = (5 * (res0/4)) / 16;
+ res0 = (5 * (res1/4)) / 16;
+ res1 = cnt;
+ PRED16X16_PLANE_END
+}
diff --git a/libavcodec/loongarch/h264_intrapred_lasx.h b/libavcodec/loongarch/h264_intrapred_lasx.h
new file mode 100644
index 0000000000..0c2653300c
--- /dev/null
+++ b/libavcodec/loongarch/h264_intrapred_lasx.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ * Contributed by Hao Chen <chenhao@loongson.cn>
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_LOONGARCH_H264_INTRAPRED_LASX_H
+#define AVCODEC_LOONGARCH_H264_INTRAPRED_LASX_H
+
+#include "libavcodec/avcodec.h"
+
+void ff_h264_pred16x16_plane_h264_8_lasx(uint8_t *src, ptrdiff_t stride);
+void ff_h264_pred16x16_plane_rv40_8_lasx(uint8_t *src, ptrdiff_t stride);
+void ff_h264_pred16x16_plane_svq3_8_lasx(uint8_t *src, ptrdiff_t stride);
+
+#endif // #ifndef AVCODEC_LOONGARCH_H264_INTRAPRED_LASX_H
diff --git a/libavcodec/loongarch/h264chroma_init_loongarch.c b/libavcodec/loongarch/h264chroma_init_loongarch.c
index 5789b5f573..7f1aa4d848 100644
--- a/libavcodec/loongarch/h264chroma_init_loongarch.c
+++ b/libavcodec/loongarch/h264chroma_init_loongarch.c
@@ -30,6 +30,7 @@ av_cold void ff_h264chroma_init_loongarch(H264ChromaContext *c, int bit_depth)
if (bit_depth <= 8) {
c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_lasx;
c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_lasx;
+ c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_lasx;
}
}
}
diff --git a/libavcodec/loongarch/h264chroma_lasx.c b/libavcodec/loongarch/h264chroma_lasx.c
index 82cef77a95..824a78dfc8 100644
--- a/libavcodec/loongarch/h264chroma_lasx.c
+++ b/libavcodec/loongarch/h264chroma_lasx.c
@@ -26,9 +26,11 @@
#include "libavutil/avassert.h"
#include "libavutil/loongarch/loongson_intrinsics.h"
-static const uint8_t chroma_mask_arr[32] = {
+static const uint8_t chroma_mask_arr[64] = {
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
+ 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20,
+ 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20
};
static av_always_inline void avc_chroma_hv_8x4_lasx(uint8_t *src, uint8_t *dst,
@@ -38,6 +40,7 @@ static av_always_inline void avc_chroma_hv_8x4_lasx(uint8_t *src, uint8_t *dst,
{
ptrdiff_t stride_2x = stride << 1;
ptrdiff_t stride_3x = stride_2x + stride;
+ ptrdiff_t stride_4x = stride_2x << 1;
__m256i src0, src1, src2, src3, src4, out;
__m256i res_hz0, res_hz1, res_hz2, res_vt0, res_vt1;
__m256i mask;
@@ -48,8 +51,7 @@ static av_always_inline void avc_chroma_hv_8x4_lasx(uint8_t *src, uint8_t *dst,
__m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1);
DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0);
- src += stride;
- DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x,
src1, src2, src3, src4);
DUP2_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src1, src3);
src0 = __lasx_xvshuf_b(src0, src0, mask);
@@ -60,14 +62,9 @@ static av_always_inline void avc_chroma_hv_8x4_lasx(uint8_t *src, uint8_t *dst,
res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0);
res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20);
res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3);
- res_hz0 = __lasx_xvmul_h(res_hz0, coeff_vt_vec1);
- res_hz1 = __lasx_xvmul_h(res_hz1, coeff_vt_vec1);
- res_vt0 = __lasx_xvadd_h(res_vt0, res_hz0);
- res_vt1 = __lasx_xvadd_h(res_vt1, res_hz1);
- DUP2_ARG2(__lasx_xvsrari_h, res_vt0, 6, res_vt1, 6, res_vt0, res_vt1);
- res_vt0 = __lasx_xvsat_hu(res_vt0, 7);
- res_vt1 = __lasx_xvsat_hu(res_vt1, 7);
- out = __lasx_xvpickev_b(res_vt1, res_vt0);
+ res_vt0 = __lasx_xvmadd_h(res_vt0, res_hz0, coeff_vt_vec1);
+ res_vt1 = __lasx_xvmadd_h(res_vt1, res_hz1, coeff_vt_vec1);
+ out = __lasx_xvssrarni_bu_h(res_vt1, res_vt0, 6);
__lasx_xvstelm_d(out, dst, 0, 0);
__lasx_xvstelm_d(out, dst + stride, 0, 2);
__lasx_xvstelm_d(out, dst + stride_2x, 0, 1);
@@ -94,11 +91,10 @@ static av_always_inline void avc_chroma_hv_8x8_lasx(uint8_t *src, uint8_t *dst,
__m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1);
DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0);
- src += stride;
- DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x,
src1, src2, src3, src4);
src += stride_4x;
- DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x,
src5, src6, src7, src8);
DUP4_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src6, src5, 0x20,
src8, src7, 0x20, src1, src3, src5, src7);
@@ -116,21 +112,10 @@ static av_always_inline void avc_chroma_hv_8x8_lasx(uint8_t *src, uint8_t *dst,
res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3);
res_hz2 = __lasx_xvpermi_q(res_hz2, res_hz3, 0x3);
res_hz3 = __lasx_xvpermi_q(res_hz3, res_hz4, 0x3);
- res_hz0 = __lasx_xvmul_h(res_hz0, coeff_vt_vec1);
- res_hz1 = __lasx_xvmul_h(res_hz1, coeff_vt_vec1);
- res_hz2 = __lasx_xvmul_h(res_hz2, coeff_vt_vec1);
- res_hz3 = __lasx_xvmul_h(res_hz3, coeff_vt_vec1);
- res_vt0 = __lasx_xvadd_h(res_vt0, res_hz0);
- res_vt1 = __lasx_xvadd_h(res_vt1, res_hz1);
- res_vt2 = __lasx_xvadd_h(res_vt2, res_hz2);
- res_vt3 = __lasx_xvadd_h(res_vt3, res_hz3);
- DUP4_ARG2(__lasx_xvsrari_h, res_vt0, 6, res_vt1, 6, res_vt2, 6, res_vt3, 6,
+ DUP4_ARG3(__lasx_xvmadd_h, res_vt0, res_hz0, coeff_vt_vec1, res_vt1, res_hz1, coeff_vt_vec1,
+ res_vt2, res_hz2, coeff_vt_vec1, res_vt3, res_hz3, coeff_vt_vec1,
res_vt0, res_vt1, res_vt2, res_vt3);
- res_vt0 = __lasx_xvsat_hu(res_vt0, 7);
- res_vt1 = __lasx_xvsat_hu(res_vt1, 7);
- res_vt2 = __lasx_xvsat_hu(res_vt2, 7);
- res_vt3 = __lasx_xvsat_hu(res_vt3, 7);
- DUP2_ARG2(__lasx_xvpickev_b, res_vt1, res_vt0, res_vt3, res_vt2, out0, out1);
+ DUP2_ARG3(__lasx_xvssrarni_bu_h, res_vt1, res_vt0, 6, res_vt3, res_vt2, 6, out0, out1);
__lasx_xvstelm_d(out0, dst, 0, 0);
__lasx_xvstelm_d(out0, dst + stride, 0, 2);
__lasx_xvstelm_d(out0, dst + stride_2x, 0, 1);
@@ -154,18 +139,14 @@ static av_always_inline void avc_chroma_hz_8x4_lasx(uint8_t *src, uint8_t *dst,
__m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
__m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
- mask = __lasx_xvld(chroma_mask_arr, 0);
- DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
- src0, src1, src2, src3);
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
+ DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0);
+ DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src1, src2);
+ src3 = __lasx_xvldx(src, stride_3x);
DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src2);
DUP2_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src0, src2);
DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1);
- res0 = __lasx_xvslli_h(res0, 3);
- res1 = __lasx_xvslli_h(res1, 3);
- DUP2_ARG2(__lasx_xvsrari_h, res0, 6, res1, 6, res0, res1);
- res0 = __lasx_xvsat_hu(res0, 7);
- res1 = __lasx_xvsat_hu(res1, 7);
- out = __lasx_xvpickev_b(res1, res0);
+ out = __lasx_xvssrarni_bu_h(res1, res0, 6);
__lasx_xvstelm_d(out, dst, 0, 0);
__lasx_xvstelm_d(out, dst + stride, 0, 2);
__lasx_xvstelm_d(out, dst + stride_2x, 0, 1);
@@ -187,28 +168,20 @@ static av_always_inline void avc_chroma_hz_8x8_lasx(uint8_t *src, uint8_t *dst,
__m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
__m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
- mask = __lasx_xvld(chroma_mask_arr, 0);
- DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
- src0, src1, src2, src3);
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
+ DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0);
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x,
+ src1, src2, src3, src4);
src += stride_4x;
- DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
- src4, src5, src6, src7);
+ DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src5, src6);
+ src7 = __lasx_xvldx(src, stride_3x);
DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, 0x20,
src7, src6, 0x20, src0, src2, src4, src6);
DUP4_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src4, src4, mask,
src6, src6, mask, src0, src2, src4, src6);
DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, src6,
coeff_vec, res0, res1, res2, res3);
- res0 = __lasx_xvslli_h(res0, 3);
- res1 = __lasx_xvslli_h(res1, 3);
- res2 = __lasx_xvslli_h(res2, 3);
- res3 = __lasx_xvslli_h(res3, 3);
- DUP4_ARG2(__lasx_xvsrari_h, res0, 6, res1, 6, res2, 6, res3, 6, res0, res1, res2, res3);
- res0 = __lasx_xvsat_hu(res0, 7);
- res1 = __lasx_xvsat_hu(res1, 7);
- res2 = __lasx_xvsat_hu(res2, 7);
- res3 = __lasx_xvsat_hu(res3, 7);
- DUP2_ARG2(__lasx_xvpickev_b, res1, res0, res3, res2, out0, out1);
+ DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1);
__lasx_xvstelm_d(out0, dst, 0, 0);
__lasx_xvstelm_d(out0, dst + stride, 0, 2);
__lasx_xvstelm_d(out0, dst + stride_2x, 0, 1);
@@ -236,6 +209,7 @@ static av_always_inline void avc_chroma_hz_nonmult_lasx(uint8_t *src,
__m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
mask = __lasx_xvld(chroma_mask_arr, 0);
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
for (row = height >> 2; row--;) {
DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
@@ -244,12 +218,7 @@ static av_always_inline void avc_chroma_hz_nonmult_lasx(uint8_t *src,
DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src2);
DUP2_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src0, src2);
DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1);
- res0 = __lasx_xvslli_h(res0, 3);
- res1 = __lasx_xvslli_h(res1, 3);
- DUP2_ARG2(__lasx_xvsrari_h, res0, 6, res1, 6, res0, res1);
- res0 = __lasx_xvsat_hu(res0, 7);
- res1 = __lasx_xvsat_hu(res1, 7);
- out = __lasx_xvpickev_b(res1, res0);
+ out = __lasx_xvssrarni_bu_h(res1, res0, 6);
__lasx_xvstelm_d(out, dst, 0, 0);
__lasx_xvstelm_d(out, dst + stride, 0, 2);
__lasx_xvstelm_d(out, dst + stride_2x, 0, 1);
@@ -258,18 +227,15 @@ static av_always_inline void avc_chroma_hz_nonmult_lasx(uint8_t *src,
}
if ((height & 3)) {
- for (row = (height & 3); row--;) {
- src0 = __lasx_xvld(src, 0);
- src += stride;
- src0 = __lasx_xvshuf_b(src0, src0, mask);
- res0 = __lasx_xvdp2_h_bu(src0, coeff_vec);
- res0 = __lasx_xvslli_h(res0, 3);
- res0 = __lasx_xvsrari_h(res0, 6);
- res0 = __lasx_xvsat_hu(res0, 7);
- out = __lasx_xvpickev_b(res0, res0);
- __lasx_xvstelm_d(out, dst, 0, 0);
- dst += stride;
- }
+ src0 = __lasx_xvld(src, 0);
+ src1 = __lasx_xvldx(src, stride);
+ src1 = __lasx_xvpermi_q(src1, src0, 0x20);
+ src0 = __lasx_xvshuf_b(src1, src1, mask);
+ res0 = __lasx_xvdp2_h_bu(src0, coeff_vec);
+ out = __lasx_xvssrarni_bu_h(res0, res0, 6);
+ __lasx_xvstelm_d(out, dst, 0, 0);
+ dst += stride;
+ __lasx_xvstelm_d(out, dst, 0, 2);
}
}
@@ -284,6 +250,7 @@ static av_always_inline void avc_chroma_vt_8x4_lasx(uint8_t *src, uint8_t *dst,
__m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
__m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
src0 = __lasx_xvld(src, 0);
src += stride;
DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
@@ -292,12 +259,7 @@ static av_always_inline void avc_chroma_vt_8x4_lasx(uint8_t *src, uint8_t *dst,
src4, src3, 0x20, src0, src1, src2, src3);
DUP2_ARG2(__lasx_xvilvl_b, src1, src0, src3, src2, src0, src2);
DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1);
- res0 = __lasx_xvslli_h(res0, 3);
- res1 = __lasx_xvslli_h(res1, 3);
- DUP2_ARG2(__lasx_xvsrari_h, res0, 6, res1, 6, res0, res1);
- res0 = __lasx_xvsat_hu(res0, 7);
- res1 = __lasx_xvsat_hu(res1, 7);
- out = __lasx_xvpickev_b(res1, res0);
+ out = __lasx_xvssrarni_bu_h(res1, res0, 6);
__lasx_xvstelm_d(out, dst, 0, 0);
__lasx_xvstelm_d(out, dst + stride, 0, 2);
__lasx_xvstelm_d(out, dst + stride_2x, 0, 1);
@@ -317,6 +279,7 @@ static av_always_inline void avc_chroma_vt_8x8_lasx(uint8_t *src, uint8_t *dst,
__m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
__m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
src0 = __lasx_xvld(src, 0);
src += stride;
DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
@@ -332,16 +295,7 @@ static av_always_inline void avc_chroma_vt_8x8_lasx(uint8_t *src, uint8_t *dst,
src0, src2, src4, src6);
DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec,
src6, coeff_vec, res0, res1, res2, res3);
- res0 = __lasx_xvslli_h(res0, 3);
- res1 = __lasx_xvslli_h(res1, 3);
- res2 = __lasx_xvslli_h(res2, 3);
- res3 = __lasx_xvslli_h(res3, 3);
- DUP4_ARG2(__lasx_xvsrari_h, res0, 6, res1, 6, res2, 6, res3, 6, res0, res1, res2, res3);
- res0 = __lasx_xvsat_hu(res0, 7);
- res1 = __lasx_xvsat_hu(res1, 7);
- res2 = __lasx_xvsat_hu(res2, 7);
- res3 = __lasx_xvsat_hu(res3, 7);
- DUP2_ARG2(__lasx_xvpickev_b, res1, res0, res3, res2, out0, out1);
+ DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1);
__lasx_xvstelm_d(out0, dst, 0, 0);
__lasx_xvstelm_d(out0, dst + stride, 0, 2);
__lasx_xvstelm_d(out0, dst + stride_2x, 0, 1);
@@ -357,43 +311,37 @@ static av_always_inline void copy_width8x8_lasx(uint8_t *src, uint8_t *dst,
ptrdiff_t stride)
{
uint64_t tmp[8];
+ ptrdiff_t stride_2, stride_3, stride_4;
__asm__ volatile (
- "ld.d %[tmp0], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp1], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp2], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp3], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp4], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp5], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp6], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp7], %[src], 0x0 \n\t"
-
- "st.d %[tmp0], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp1], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp2], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp3], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp4], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp5], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp6], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp7], %[dst], 0x0 \n\t"
+ "slli.d %[stride_2], %[stride], 1 \n\t"
+ "add.d %[stride_3], %[stride_2], %[stride] \n\t"
+ "slli.d %[stride_4], %[stride_2], 1 \n\t"
+ "ld.d %[tmp0], %[src], 0x0 \n\t"
+ "ldx.d %[tmp1], %[src], %[stride] \n\t"
+ "ldx.d %[tmp2], %[src], %[stride_2] \n\t"
+ "ldx.d %[tmp3], %[src], %[stride_3] \n\t"
+ "add.d %[src], %[src], %[stride_4] \n\t"
+ "ld.d %[tmp4], %[src], 0x0 \n\t"
+ "ldx.d %[tmp5], %[src], %[stride] \n\t"
+ "ldx.d %[tmp6], %[src], %[stride_2] \n\t"
+ "ldx.d %[tmp7], %[src], %[stride_3] \n\t"
+
+ "st.d %[tmp0], %[dst], 0x0 \n\t"
+ "stx.d %[tmp1], %[dst], %[stride] \n\t"
+ "stx.d %[tmp2], %[dst], %[stride_2] \n\t"
+ "stx.d %[tmp3], %[dst], %[stride_3] \n\t"
+ "add.d %[dst], %[dst], %[stride_4] \n\t"
+ "st.d %[tmp4], %[dst], 0x0 \n\t"
+ "stx.d %[tmp5], %[dst], %[stride] \n\t"
+ "stx.d %[tmp6], %[dst], %[stride_2] \n\t"
+ "stx.d %[tmp7], %[dst], %[stride_3] \n\t"
: [tmp0]"=&r"(tmp[0]), [tmp1]"=&r"(tmp[1]),
[tmp2]"=&r"(tmp[2]), [tmp3]"=&r"(tmp[3]),
[tmp4]"=&r"(tmp[4]), [tmp5]"=&r"(tmp[5]),
[tmp6]"=&r"(tmp[6]), [tmp7]"=&r"(tmp[7]),
- [dst]"+&r"(dst), [src]"+&r"(src)
+ [dst]"+&r"(dst), [src]"+&r"(src),
+ [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3),
+ [stride_4]"=&r"(stride_4)
: [stride]"r"(stride)
: "memory"
);
@@ -403,26 +351,23 @@ static av_always_inline void copy_width8x4_lasx(uint8_t *src, uint8_t *dst,
ptrdiff_t stride)
{
uint64_t tmp[4];
+ ptrdiff_t stride_2, stride_3;
__asm__ volatile (
- "ld.d %[tmp0], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp1], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp2], %[src], 0x0 \n\t"
- "add.d %[src], %[src], %[stride] \n\t"
- "ld.d %[tmp3], %[src], 0x0 \n\t"
-
- "st.d %[tmp0], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp1], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp2], %[dst], 0x0 \n\t"
- "add.d %[dst], %[dst], %[stride] \n\t"
- "st.d %[tmp3], %[dst], 0x0 \n\t"
+ "slli.d %[stride_2], %[stride], 1 \n\t"
+ "add.d %[stride_3], %[stride_2], %[stride] \n\t"
+ "ld.d %[tmp0], %[src], 0x0 \n\t"
+ "ldx.d %[tmp1], %[src], %[stride] \n\t"
+ "ldx.d %[tmp2], %[src], %[stride_2] \n\t"
+ "ldx.d %[tmp3], %[src], %[stride_3] \n\t"
+
+ "st.d %[tmp0], %[dst], 0x0 \n\t"
+ "stx.d %[tmp1], %[dst], %[stride] \n\t"
+ "stx.d %[tmp2], %[dst], %[stride_2] \n\t"
+ "stx.d %[tmp3], %[dst], %[stride_3] \n\t"
: [tmp0]"=&r"(tmp[0]), [tmp1]"=&r"(tmp[1]),
[tmp2]"=&r"(tmp[2]), [tmp3]"=&r"(tmp[3]),
- [dst]"+&r"(dst), [src]"+&r"(src)
- : [stride]"r"(stride)
+ [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3)
+ : [stride]"r"(stride), [dst]"r"(dst), [src]"r"(src)
: "memory"
);
}
@@ -441,6 +386,221 @@ static void avc_chroma_hv_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
}
}
+static void avc_chroma_hv_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coef_hor0, uint32_t coef_hor1,
+ uint32_t coef_ver0, uint32_t coef_ver1)
+{
+ ptrdiff_t stride_2 = stride << 1;
+ __m256i src0, src1, src2;
+ __m256i res_hz, res_vt;
+ __m256i mask;
+ __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0);
+ __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1);
+ __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1);
+ __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0);
+ __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1);
+ __m256i coeff_vt_vec = __lasx_xvpermi_q(coeff_vt_vec1, coeff_vt_vec0, 0x02);
+
+ DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0);
+ DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2, src1, src2);
+ DUP2_ARG3(__lasx_xvshuf_b, src1, src0, mask, src2, src1, mask, src0, src1);
+ src0 = __lasx_xvpermi_q(src0, src1, 0x02);
+ res_hz = __lasx_xvdp2_h_bu(src0, coeff_hz_vec);
+ res_vt = __lasx_xvmul_h(res_hz, coeff_vt_vec);
+ res_hz = __lasx_xvpermi_q(res_hz, res_vt, 0x01);
+ res_vt = __lasx_xvadd_h(res_hz, res_vt);
+ res_vt = __lasx_xvssrarni_bu_h(res_vt, res_vt, 6);
+ __lasx_xvstelm_w(res_vt, dst, 0, 0);
+ __lasx_xvstelm_w(res_vt, dst + stride, 0, 1);
+}
+
+static void avc_chroma_hv_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coef_hor0, uint32_t coef_hor1,
+ uint32_t coef_ver0, uint32_t coef_ver1)
+{
+ ptrdiff_t stride_2 = stride << 1;
+ ptrdiff_t stride_3 = stride_2 + stride;
+ ptrdiff_t stride_4 = stride_2 << 1;
+ __m256i src0, src1, src2, src3, src4;
+ __m256i res_hz0, res_hz1, res_vt0, res_vt1;
+ __m256i mask;
+ __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0);
+ __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1);
+ __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1);
+ __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0);
+ __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1);
+
+ DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0);
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3,
+ src, stride_4, src1, src2, src3, src4);
+ DUP4_ARG3(__lasx_xvshuf_b, src1, src0, mask, src2, src1, mask, src3, src2, mask,
+ src4, src3, mask, src0, src1, src2, src3);
+ DUP2_ARG3(__lasx_xvpermi_q, src0, src2, 0x02, src1, src3, 0x02, src0, src1);
+ DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, res_hz0, res_hz1);
+ DUP2_ARG2(__lasx_xvmul_h, res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_vt0, res_vt1);
+ res_hz0 = __lasx_xvadd_h(res_vt0, res_vt1);
+ res_hz0 = __lasx_xvssrarni_bu_h(res_hz0, res_hz0, 6);
+ __lasx_xvstelm_w(res_hz0, dst, 0, 0);
+ __lasx_xvstelm_w(res_hz0, dst + stride, 0, 1);
+ __lasx_xvstelm_w(res_hz0, dst + stride_2, 0, 4);
+ __lasx_xvstelm_w(res_hz0, dst + stride_3, 0, 5);
+}
+
+static void avc_chroma_hv_4x8_lasx(uint8_t *src, uint8_t * dst, ptrdiff_t stride,
+ uint32_t coef_hor0, uint32_t coef_hor1,
+ uint32_t coef_ver0, uint32_t coef_ver1)
+{
+ ptrdiff_t stride_2 = stride << 1;
+ ptrdiff_t stride_3 = stride_2 + stride;
+ ptrdiff_t stride_4 = stride_2 << 1;
+ __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8;
+ __m256i res_hz0, res_hz1, res_hz2, res_hz3;
+ __m256i res_vt0, res_vt1, res_vt2, res_vt3;
+ __m256i mask;
+ __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0);
+ __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1);
+ __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1);
+ __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0);
+ __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1);
+
+ DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0);
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3,
+ src, stride_4, src1, src2, src3, src4);
+ src += stride_4;
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3,
+ src, stride_4, src5, src6, src7, src8);
+ DUP4_ARG3(__lasx_xvshuf_b, src1, src0, mask, src2, src1, mask, src3, src2, mask,
+ src4, src3, mask, src0, src1, src2, src3);
+ DUP4_ARG3(__lasx_xvshuf_b, src5, src4, mask, src6, src5, mask, src7, src6, mask,
+ src8, src7, mask, src4, src5, src6, src7);
+ DUP4_ARG3(__lasx_xvpermi_q, src0, src2, 0x02, src1, src3, 0x02, src4, src6, 0x02,
+ src5, src7, 0x02, src0, src1, src4, src5);
+ DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, src4, coeff_hz_vec,
+ src5, coeff_hz_vec, res_hz0, res_hz1, res_hz2, res_hz3);
+ DUP4_ARG2(__lasx_xvmul_h, res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_hz2,
+ coeff_vt_vec1, res_hz3, coeff_vt_vec0, res_vt0, res_vt1, res_vt2, res_vt3);
+ DUP2_ARG2(__lasx_xvadd_h, res_vt0, res_vt1, res_vt2, res_vt3, res_vt0, res_vt2);
+ res_hz0 = __lasx_xvssrarni_bu_h(res_vt2, res_vt0, 6);
+ __lasx_xvstelm_w(res_hz0, dst, 0, 0);
+ __lasx_xvstelm_w(res_hz0, dst + stride, 0, 1);
+ __lasx_xvstelm_w(res_hz0, dst + stride_2, 0, 4);
+ __lasx_xvstelm_w(res_hz0, dst + stride_3, 0, 5);
+ dst += stride_4;
+ __lasx_xvstelm_w(res_hz0, dst, 0, 2);
+ __lasx_xvstelm_w(res_hz0, dst + stride, 0, 3);
+ __lasx_xvstelm_w(res_hz0, dst + stride_2, 0, 6);
+ __lasx_xvstelm_w(res_hz0, dst + stride_3, 0, 7);
+}
+
+static void avc_chroma_hv_4w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coef_hor0, uint32_t coef_hor1,
+ uint32_t coef_ver0, uint32_t coef_ver1,
+ int32_t height)
+{
+ if (8 == height) {
+ avc_chroma_hv_4x8_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0,
+ coef_ver1);
+ } else if (4 == height) {
+ avc_chroma_hv_4x4_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0,
+ coef_ver1);
+ } else if (2 == height) {
+ avc_chroma_hv_4x2_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0,
+ coef_ver1);
+ }
+}
+
+static void avc_chroma_hz_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coeff0, uint32_t coeff1)
+{
+ __m256i src0, src1;
+ __m256i res, mask;
+ __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0);
+ __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
+ __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+
+ DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0);
+ src1 = __lasx_xvldx(src, stride);
+ src0 = __lasx_xvshuf_b(src1, src0, mask);
+ res = __lasx_xvdp2_h_bu(src0, coeff_vec);
+ res = __lasx_xvslli_h(res, 3);
+ res = __lasx_xvssrarni_bu_h(res, res, 6);
+ __lasx_xvstelm_w(res, dst, 0, 0);
+ __lasx_xvstelm_w(res, dst + stride, 0, 1);
+}
+
+static void avc_chroma_hz_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coeff0, uint32_t coeff1)
+{
+ ptrdiff_t stride_2 = stride << 1;
+ ptrdiff_t stride_3 = stride_2 + stride;
+ __m256i src0, src1, src2, src3;
+ __m256i res, mask;
+ __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0);
+ __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
+ __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+
+ DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0);
+ DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2, src1, src2);
+ src3 = __lasx_xvldx(src, stride_3);
+ DUP2_ARG3(__lasx_xvshuf_b, src1, src0, mask, src3, src2, mask, src0, src2);
+ src0 = __lasx_xvpermi_q(src0, src2, 0x02);
+ res = __lasx_xvdp2_h_bu(src0, coeff_vec);
+ res = __lasx_xvslli_h(res, 3);
+ res = __lasx_xvssrarni_bu_h(res, res, 6);
+ __lasx_xvstelm_w(res, dst, 0, 0);
+ __lasx_xvstelm_w(res, dst + stride, 0, 1);
+ __lasx_xvstelm_w(res, dst + stride_2, 0, 4);
+ __lasx_xvstelm_w(res, dst + stride_3, 0, 5);
+}
+
+static void avc_chroma_hz_4x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coeff0, uint32_t coeff1)
+{
+ ptrdiff_t stride_2 = stride << 1;
+ ptrdiff_t stride_3 = stride_2 + stride;
+ ptrdiff_t stride_4 = stride_2 << 1;
+ __m256i src0, src1, src2, src3, src4, src5, src6, src7;
+ __m256i res0, res1, mask;
+ __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0);
+ __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
+ __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
+ DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0);
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3,
+ src, stride_4, src1, src2, src3, src4);
+ src += stride_4;
+ DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2, src5, src6);
+ src7 = __lasx_xvldx(src, stride_3);
+ DUP4_ARG3(__lasx_xvshuf_b, src1, src0, mask, src3, src2, mask, src5, src4, mask,
+ src7, src6, mask, src0, src2, src4, src6);
+ DUP2_ARG3(__lasx_xvpermi_q, src0, src2, 0x02, src4, src6, 0x02, src0, src4);
+ DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src4, coeff_vec, res0, res1);
+ res0 = __lasx_xvssrarni_bu_h(res1, res0, 6);
+ __lasx_xvstelm_w(res0, dst, 0, 0);
+ __lasx_xvstelm_w(res0, dst + stride, 0, 1);
+ __lasx_xvstelm_w(res0, dst + stride_2, 0, 4);
+ __lasx_xvstelm_w(res0, dst + stride_3, 0, 5);
+ dst += stride_4;
+ __lasx_xvstelm_w(res0, dst, 0, 2);
+ __lasx_xvstelm_w(res0, dst + stride, 0, 3);
+ __lasx_xvstelm_w(res0, dst + stride_2, 0, 6);
+ __lasx_xvstelm_w(res0, dst + stride_3, 0, 7);
+}
+
+static void avc_chroma_hz_4w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coeff0, uint32_t coeff1,
+ int32_t height)
+{
+ if (8 == height) {
+ avc_chroma_hz_4x8_lasx(src, dst, stride, coeff0, coeff1);
+ } else if (4 == height) {
+ avc_chroma_hz_4x4_lasx(src, dst, stride, coeff0, coeff1);
+ } else if (2 == height) {
+ avc_chroma_hz_4x2_lasx(src, dst, stride, coeff0, coeff1);
+ }
+}
+
static void avc_chroma_hz_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
uint32_t coeff0, uint32_t coeff1,
int32_t height)
@@ -454,6 +614,110 @@ static void avc_chroma_hz_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
}
}
+static void avc_chroma_vt_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coeff0, uint32_t coeff1)
+{
+ __m256i src0, src1, src2;
+ __m256i tmp0, tmp1;
+ __m256i res;
+ __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0);
+ __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
+ __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+
+ src0 = __lasx_xvld(src, 0);
+ DUP2_ARG2(__lasx_xvldx, src, stride, src, stride << 1, src1, src2);
+ DUP2_ARG2(__lasx_xvilvl_b, src1, src0, src2, src1, tmp0, tmp1);
+ tmp0 = __lasx_xvilvl_d(tmp1, tmp0);
+ res = __lasx_xvdp2_h_bu(tmp0, coeff_vec);
+ res = __lasx_xvslli_h(res, 3);
+ res = __lasx_xvssrarni_bu_h(res, res, 6);
+ __lasx_xvstelm_w(res, dst, 0, 0);
+ __lasx_xvstelm_w(res, dst + stride, 0, 1);
+}
+
+static void avc_chroma_vt_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coeff0, uint32_t coeff1)
+{
+ ptrdiff_t stride_2 = stride << 1;
+ ptrdiff_t stride_3 = stride_2 + stride;
+ ptrdiff_t stride_4 = stride_2 << 1;
+ __m256i src0, src1, src2, src3, src4;
+ __m256i tmp0, tmp1, tmp2, tmp3;
+ __m256i res;
+ __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0);
+ __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
+ __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+
+ src0 = __lasx_xvld(src, 0);
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3,
+ src, stride_4, src1, src2, src3, src4);
+ DUP4_ARG2(__lasx_xvilvl_b, src1, src0, src2, src1, src3, src2, src4, src3,
+ tmp0, tmp1, tmp2, tmp3);
+ DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp2);
+ tmp0 = __lasx_xvpermi_q(tmp0, tmp2, 0x02);
+ res = __lasx_xvdp2_h_bu(tmp0, coeff_vec);
+ res = __lasx_xvslli_h(res, 3);
+ res = __lasx_xvssrarni_bu_h(res, res, 6);
+ __lasx_xvstelm_w(res, dst, 0, 0);
+ __lasx_xvstelm_w(res, dst + stride, 0, 1);
+ __lasx_xvstelm_w(res, dst + stride_2, 0, 4);
+ __lasx_xvstelm_w(res, dst + stride_3, 0, 5);
+}
+
+static void avc_chroma_vt_4x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coeff0, uint32_t coeff1)
+{
+ ptrdiff_t stride_2 = stride << 1;
+ ptrdiff_t stride_3 = stride_2 + stride;
+ ptrdiff_t stride_4 = stride_2 << 1;
+ __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8;
+ __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ __m256i res0, res1;
+ __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0);
+ __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
+ __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
+ src0 = __lasx_xvld(src, 0);
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3,
+ src, stride_4, src1, src2, src3, src4);
+ src += stride_4;
+ DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3,
+ src, stride_4, src5, src6, src7, src8);
+ DUP4_ARG2(__lasx_xvilvl_b, src1, src0, src2, src1, src3, src2, src4, src3,
+ tmp0, tmp1, tmp2, tmp3);
+ DUP4_ARG2(__lasx_xvilvl_b, src5, src4, src6, src5, src7, src6, src8, src7,
+ tmp4, tmp5, tmp6, tmp7);
+ DUP4_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6,
+ tmp0, tmp2, tmp4, tmp6);
+ tmp0 = __lasx_xvpermi_q(tmp0, tmp2, 0x02);
+ tmp4 = __lasx_xvpermi_q(tmp4, tmp6, 0x02);
+ DUP2_ARG2(__lasx_xvdp2_h_bu, tmp0, coeff_vec, tmp4, coeff_vec, res0, res1);
+ res0 = __lasx_xvssrarni_bu_h(res1, res0, 6);
+ __lasx_xvstelm_w(res0, dst, 0, 0);
+ __lasx_xvstelm_w(res0, dst + stride, 0, 1);
+ __lasx_xvstelm_w(res0, dst + stride_2, 0, 4);
+ __lasx_xvstelm_w(res0, dst + stride_3, 0, 5);
+ dst += stride_4;
+ __lasx_xvstelm_w(res0, dst, 0, 2);
+ __lasx_xvstelm_w(res0, dst + stride, 0, 3);
+ __lasx_xvstelm_w(res0, dst + stride_2, 0, 6);
+ __lasx_xvstelm_w(res0, dst + stride_3, 0, 7);
+}
+
+static void avc_chroma_vt_4w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ uint32_t coeff0, uint32_t coeff1,
+ int32_t height)
+{
+ if (8 == height) {
+ avc_chroma_vt_4x8_lasx(src, dst, stride, coeff0, coeff1);
+ } else if (4 == height) {
+ avc_chroma_vt_4x4_lasx(src, dst, stride, coeff0, coeff1);
+ } else if (2 == height) {
+ avc_chroma_vt_4x2_lasx(src, dst, stride, coeff0, coeff1);
+ }
+}
+
static void avc_chroma_vt_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
uint32_t coeff0, uint32_t coeff1,
int32_t height)
@@ -465,6 +729,76 @@ static void avc_chroma_vt_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
}
}
+static void copy_width4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
+ int32_t height)
+{
+ uint32_t tp0, tp1, tp2, tp3, tp4, tp5, tp6, tp7;
+
+ if (8 == height) {
+ ptrdiff_t stride_2, stride_3, stride_4;
+
+ __asm__ volatile (
+ "slli.d %[stride_2], %[stride], 1 \n\t"
+ "add.d %[stride_3], %[stride_2], %[stride] \n\t"
+ "slli.d %[stride_4], %[stride_2], 1 \n\t"
+ "ld.wu %[tp0], %[src], 0 \n\t"
+ "ldx.wu %[tp1], %[src], %[stride] \n\t"
+ "ldx.wu %[tp2], %[src], %[stride_2] \n\t"
+ "ldx.wu %[tp3], %[src], %[stride_3] \n\t"
+ "add.d %[src], %[src], %[stride_4] \n\t"
+ "ld.wu %[tp4], %[src], 0 \n\t"
+ "ldx.wu %[tp5], %[src], %[stride] \n\t"
+ "ldx.wu %[tp6], %[src], %[stride_2] \n\t"
+ "ldx.wu %[tp7], %[src], %[stride_3] \n\t"
+ "st.w %[tp0], %[dst], 0 \n\t"
+ "stx.w %[tp1], %[dst], %[stride] \n\t"
+ "stx.w %[tp2], %[dst], %[stride_2] \n\t"
+ "stx.w %[tp3], %[dst], %[stride_3] \n\t"
+ "add.d %[dst], %[dst], %[stride_4] \n\t"
+ "st.w %[tp4], %[dst], 0 \n\t"
+ "stx.w %[tp5], %[dst], %[stride] \n\t"
+ "stx.w %[tp6], %[dst], %[stride_2] \n\t"
+ "stx.w %[tp7], %[dst], %[stride_3] \n\t"
+ : [stride_2]"+&r"(stride_2), [stride_3]"+&r"(stride_3), [stride_4]"+&r"(stride_4),
+ [src]"+&r"(src), [dst]"+&r"(dst), [tp0]"+&r"(tp0), [tp1]"+&r"(tp1),
+ [tp2]"+&r"(tp2), [tp3]"+&r"(tp3), [tp4]"+&r"(tp4), [tp5]"+&r"(tp5),
+ [tp6]"+&r"(tp6), [tp7]"+&r"(tp7)
+ : [stride]"r"(stride)
+ : "memory"
+ );
+ } else if (4 == height) {
+ ptrdiff_t stride_2, stride_3;
+
+ __asm__ volatile (
+ "slli.d %[stride_2], %[stride], 1 \n\t"
+ "add.d %[stride_3], %[stride_2], %[stride] \n\t"
+ "ld.wu %[tp0], %[src], 0 \n\t"
+ "ldx.wu %[tp1], %[src], %[stride] \n\t"
+ "ldx.wu %[tp2], %[src], %[stride_2] \n\t"
+ "ldx.wu %[tp3], %[src], %[stride_3] \n\t"
+ "st.w %[tp0], %[dst], 0 \n\t"
+ "stx.w %[tp1], %[dst], %[stride] \n\t"
+ "stx.w %[tp2], %[dst], %[stride_2] \n\t"
+ "stx.w %[tp3], %[dst], %[stride_3] \n\t"
+ : [stride_2]"+&r"(stride_2), [stride_3]"+&r"(stride_3),
+ [src]"+&r"(src), [dst]"+&r"(dst), [tp0]"+&r"(tp0), [tp1]"+&r"(tp1),
+ [tp2]"+&r"(tp2), [tp3]"+&r"(tp3)
+ : [stride]"r"(stride)
+ : "memory"
+ );
+ } else if (2 == height) {
+ __asm__ volatile (
+ "ld.wu %[tp0], %[src], 0 \n\t"
+ "ldx.wu %[tp1], %[src], %[stride] \n\t"
+ "st.w %[tp0], %[dst], 0 \n\t"
+ "stx.w %[tp1], %[dst], %[stride] \n\t"
+ : [tp0]"+&r"(tp0), [tp1]"+&r"(tp1)
+ : [src]"r"(src), [dst]"r"(dst), [stride]"r"(stride)
+ : "memory"
+ );
+ }
+}
+
static void copy_width8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
int32_t height)
{
@@ -475,6 +809,22 @@ static void copy_width8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
}
}
+void ff_put_h264_chroma_mc4_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
+ int height, int x, int y)
+{
+ av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0);
+
+ if(x && y) {
+ avc_chroma_hv_4w_lasx(src, dst, stride, x, (8 - x), y, (8 - y), height);
+ } else if (x) {
+ avc_chroma_hz_4w_lasx(src, dst, stride, x, (8 - x), height);
+ } else if (y) {
+ avc_chroma_vt_4w_lasx(src, dst, stride, y, (8 - y), height);
+ } else {
+ copy_width4_lasx(src, dst, stride, height);
+ }
+}
+
void ff_put_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
int height, int x, int y)
{
@@ -521,14 +871,9 @@ static av_always_inline void avc_chroma_hv_and_aver_dst_8x4_lasx(uint8_t *src,
res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0);
res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20);
res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3);
- res_hz0 = __lasx_xvmul_h(res_hz0, coeff_vt_vec1);
- res_hz1 = __lasx_xvmul_h(res_hz1, coeff_vt_vec1);
- res_vt0 = __lasx_xvadd_h(res_vt0, res_hz0);
- res_vt1 = __lasx_xvadd_h(res_vt1, res_hz1);
- DUP2_ARG2(__lasx_xvsrari_h, res_vt0, 6, res_vt1, 6, res_vt0, res_vt1);
- res_vt0 = __lasx_xvsat_hu(res_vt0, 7);
- res_vt1 = __lasx_xvsat_hu(res_vt1, 7);
- out = __lasx_xvpickev_b(res_vt1, res_vt0);
+ res_vt0 = __lasx_xvmadd_h(res_vt0, res_hz0, coeff_vt_vec1);
+ res_vt1 = __lasx_xvmadd_h(res_vt1, res_hz1, coeff_vt_vec1);
+ out = __lasx_xvssrarni_bu_h(res_vt1, res_vt0, 6);
DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x,
tp0, tp1, tp2, tp3);
DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2);
@@ -583,21 +928,12 @@ static av_always_inline void avc_chroma_hv_and_aver_dst_8x8_lasx(uint8_t *src,
res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3);
res_hz2 = __lasx_xvpermi_q(res_hz2, res_hz3, 0x3);
res_hz3 = __lasx_xvpermi_q(res_hz3, res_hz4, 0x3);
- res_hz0 = __lasx_xvmul_h(res_hz0, coeff_vt_vec1);
- res_hz1 = __lasx_xvmul_h(res_hz1, coeff_vt_vec1);
- res_hz2 = __lasx_xvmul_h(res_hz2, coeff_vt_vec1);
- res_hz3 = __lasx_xvmul_h(res_hz3, coeff_vt_vec1);
- res_vt0 = __lasx_xvadd_h(res_vt0, res_hz0);
- res_vt1 = __lasx_xvadd_h(res_vt1, res_hz1);
- res_vt2 = __lasx_xvadd_h(res_vt2, res_hz2);
- res_vt3 = __lasx_xvadd_h(res_vt3, res_hz3);
- DUP4_ARG2(__lasx_xvsrari_h, res_vt0, 6, res_vt1, 6, res_vt2, 6, res_vt3, 6,
- res_vt0, res_vt1, res_vt2, res_vt3);
- res_vt0 = __lasx_xvsat_hu(res_vt0, 7);
- res_vt1 = __lasx_xvsat_hu(res_vt1, 7);
- res_vt2 = __lasx_xvsat_hu(res_vt2, 7);
- res_vt3 = __lasx_xvsat_hu(res_vt3, 7);
- DUP2_ARG2(__lasx_xvpickev_b, res_vt1, res_vt0, res_vt3, res_vt2, out0, out1);
+ res_vt0 = __lasx_xvmadd_h(res_vt0, res_hz0, coeff_vt_vec1);
+ res_vt1 = __lasx_xvmadd_h(res_vt1, res_hz1, coeff_vt_vec1);
+ res_vt2 = __lasx_xvmadd_h(res_vt2, res_hz2, coeff_vt_vec1);
+ res_vt3 = __lasx_xvmadd_h(res_vt3, res_hz3, coeff_vt_vec1);
+ DUP2_ARG3(__lasx_xvssrarni_bu_h, res_vt1, res_vt0, 6, res_vt3, res_vt2, 6,
+ out0, out1);
DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x,
tp0, tp1, tp2, tp3);
DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2);
@@ -635,18 +971,14 @@ static av_always_inline void avc_chroma_hz_and_aver_dst_8x4_lasx(uint8_t *src,
__m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
__m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
mask = __lasx_xvld(chroma_mask_arr, 0);
DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
src0, src1, src2, src3);
DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src2);
DUP2_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src0, src2);
DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1);
- res0 = __lasx_xvslli_h(res0, 3);
- res1 = __lasx_xvslli_h(res1, 3);
- DUP2_ARG2(__lasx_xvsrari_h, res0, 6, res1, 6, res0, res1);
- res0 = __lasx_xvsat_hu(res0, 7);
- res1 = __lasx_xvsat_hu(res1, 7);
- out = __lasx_xvpickev_b(res1, res0);
+ out = __lasx_xvssrarni_bu_h(res1, res0, 6);
DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x,
tp0, tp1, tp2, tp3);
DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2);
@@ -674,6 +1006,7 @@ static av_always_inline void avc_chroma_hz_and_aver_dst_8x8_lasx(uint8_t *src,
__m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
__m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
mask = __lasx_xvld(chroma_mask_arr, 0);
DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
src0, src1, src2, src3);
@@ -686,16 +1019,7 @@ static av_always_inline void avc_chroma_hz_and_aver_dst_8x8_lasx(uint8_t *src,
mask, src6, src6, mask, src0, src2, src4, src6);
DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, src6,
coeff_vec, res0, res1, res2, res3);
- res0 = __lasx_xvslli_h(res0, 3);
- res1 = __lasx_xvslli_h(res1, 3);
- res2 = __lasx_xvslli_h(res2, 3);
- res3 = __lasx_xvslli_h(res3, 3);
- DUP4_ARG2(__lasx_xvsrari_h, res0, 6, res1, 6, res2, 6, res3, 6, res0, res1, res2, res3);
- res0 = __lasx_xvsat_hu(res0, 7);
- res1 = __lasx_xvsat_hu(res1, 7);
- res2 = __lasx_xvsat_hu(res2, 7);
- res3 = __lasx_xvsat_hu(res3, 7);
- DUP2_ARG2(__lasx_xvpickev_b, res1, res0, res3, res2, out0, out1);
+ DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1);
DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x,
tp0, tp1, tp2, tp3);
DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2);
@@ -733,6 +1057,7 @@ static av_always_inline void avc_chroma_vt_and_aver_dst_8x4_lasx(uint8_t *src,
__m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
__m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
src0 = __lasx_xvld(src, 0);
DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x,
src1, src2, src3, src4);
@@ -740,12 +1065,7 @@ static av_always_inline void avc_chroma_vt_and_aver_dst_8x4_lasx(uint8_t *src,
src4, src3, 0x20, src0, src1, src2, src3);
DUP2_ARG2(__lasx_xvilvl_b, src1, src0, src3, src2, src0, src2);
DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1);
- res0 = __lasx_xvslli_h(res0, 3);
- res1 = __lasx_xvslli_h(res1, 3);
- DUP2_ARG2(__lasx_xvsrari_h, res0, 6, res1, 6, res0, res1)
- res0 = __lasx_xvsat_hu(res0, 7);
- res1 = __lasx_xvsat_hu(res1, 7);
- out = __lasx_xvpickev_b(res1, res0);
+ out = __lasx_xvssrarni_bu_h(res1, res0, 6);
DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x,
tp0, tp1, tp2, tp3);
DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2);
@@ -772,6 +1092,7 @@ static av_always_inline void avc_chroma_vt_and_aver_dst_8x8_lasx(uint8_t *src,
__m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1);
__m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1);
+ coeff_vec = __lasx_xvslli_b(coeff_vec, 3);
src0 = __lasx_xvld(src, 0);
src += stride;
DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x,
@@ -787,17 +1108,7 @@ static av_always_inline void avc_chroma_vt_and_aver_dst_8x8_lasx(uint8_t *src,
src0, src2, src4, src6);
DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, src6,
coeff_vec, res0, res1, res2, res3);
- res0 = __lasx_xvslli_h(res0, 3);
- res1 = __lasx_xvslli_h(res1, 3);
- res2 = __lasx_xvslli_h(res2, 3);
- res3 = __lasx_xvslli_h(res3, 3);
- DUP4_ARG2(__lasx_xvsrari_h, res0, 6, res1, 6, res2, 6, res3, 6,
- res0, res1, res2, res3);
- res0 = __lasx_xvsat_hu(res0, 7);
- res1 = __lasx_xvsat_hu(res1, 7);
- res2 = __lasx_xvsat_hu(res2, 7);
- res3 = __lasx_xvsat_hu(res3, 7);
- DUP2_ARG2(__lasx_xvpickev_b, res1, res0, res3, res2, out0, out1);
+ DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1);
DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x,
tp0, tp1, tp2, tp3);
DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2);
diff --git a/libavcodec/loongarch/h264chroma_lasx.h b/libavcodec/loongarch/h264chroma_lasx.h
index 3b70e1dccb..4aac8db8cb 100644
--- a/libavcodec/loongarch/h264chroma_lasx.h
+++ b/libavcodec/loongarch/h264chroma_lasx.h
@@ -26,6 +26,8 @@
#include <stddef.h>
#include "libavcodec/h264.h"
+void ff_put_h264_chroma_mc4_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
+ int h, int x, int y);
void ff_put_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
int h, int x, int y);
void ff_avg_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
diff --git a/libavcodec/loongarch/h264dsp_init_loongarch.c b/libavcodec/loongarch/h264dsp_init_loongarch.c
index f1b927c72e..e02e3d7fa9 100644
--- a/libavcodec/loongarch/h264dsp_init_loongarch.c
+++ b/libavcodec/loongarch/h264dsp_init_loongarch.c
@@ -32,6 +32,8 @@ av_cold void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth,
if (chroma_format_idc <= 1)
c->h264_loop_filter_strength = ff_h264_loop_filter_strength_lasx;
if (bit_depth == 8) {
+ c->h264_add_pixels4_clear = ff_h264_add_pixels4_8_lasx;
+ c->h264_add_pixels8_clear = ff_h264_add_pixels8_8_lasx;
c->h264_v_loop_filter_luma = ff_h264_v_lpf_luma_8_lasx;
c->h264_h_loop_filter_luma = ff_h264_h_lpf_luma_8_lasx;
c->h264_v_loop_filter_luma_intra = ff_h264_v_lpf_luma_intra_8_lasx;
diff --git a/libavcodec/loongarch/h264dsp_lasx.c b/libavcodec/loongarch/h264dsp_lasx.c
index 873c109413..b6f8b158e9 100644
--- a/libavcodec/loongarch/h264dsp_lasx.c
+++ b/libavcodec/loongarch/h264dsp_lasx.c
@@ -2000,3 +2000,85 @@ void ff_weight_h264_pixels4_8_lasx(uint8_t *src, ptrdiff_t stride,
avc_wgt_4x8_lasx(src, stride, log2_denom, weight_src, offset);
}
}
+
+void ff_h264_add_pixels4_8_lasx(uint8_t *_dst, int16_t *_src, int stride)
+{
+ __m256i src0, dst0, dst1, dst2, dst3, zero;
+ __m256i tmp0, tmp1;
+ uint8_t* _dst1 = _dst + stride;
+ uint8_t* _dst2 = _dst1 + stride;
+ uint8_t* _dst3 = _dst2 + stride;
+
+ src0 = __lasx_xvld(_src, 0);
+ dst0 = __lasx_xvldrepl_w(_dst, 0);
+ dst1 = __lasx_xvldrepl_w(_dst1, 0);
+ dst2 = __lasx_xvldrepl_w(_dst2, 0);
+ dst3 = __lasx_xvldrepl_w(_dst3, 0);
+ tmp0 = __lasx_xvilvl_w(dst1, dst0);
+ tmp1 = __lasx_xvilvl_w(dst3, dst2);
+ dst0 = __lasx_xvilvl_d(tmp1, tmp0);
+ tmp0 = __lasx_vext2xv_hu_bu(dst0);
+ zero = __lasx_xvldi(0);
+ tmp1 = __lasx_xvadd_h(src0, tmp0);
+ dst0 = __lasx_xvpickev_b(tmp1, tmp1);
+ __lasx_xvstelm_w(dst0, _dst, 0, 0);
+ __lasx_xvstelm_w(dst0, _dst1, 0, 1);
+ __lasx_xvstelm_w(dst0, _dst2, 0, 4);
+ __lasx_xvstelm_w(dst0, _dst3, 0, 5);
+ __lasx_xvst(zero, _src, 0);
+}
+
+void ff_h264_add_pixels8_8_lasx(uint8_t *_dst, int16_t *_src, int stride)
+{
+ __m256i src0, src1, src2, src3;
+ __m256i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7;
+ __m256i tmp0, tmp1, tmp2, tmp3;
+ __m256i zero = __lasx_xvldi(0);
+ uint8_t *_dst1 = _dst + stride;
+ uint8_t *_dst2 = _dst1 + stride;
+ uint8_t *_dst3 = _dst2 + stride;
+ uint8_t *_dst4 = _dst3 + stride;
+ uint8_t *_dst5 = _dst4 + stride;
+ uint8_t *_dst6 = _dst5 + stride;
+ uint8_t *_dst7 = _dst6 + stride;
+
+ src0 = __lasx_xvld(_src, 0);
+ src1 = __lasx_xvld(_src, 32);
+ src2 = __lasx_xvld(_src, 64);
+ src3 = __lasx_xvld(_src, 96);
+ dst0 = __lasx_xvldrepl_d(_dst, 0);
+ dst1 = __lasx_xvldrepl_d(_dst1, 0);
+ dst2 = __lasx_xvldrepl_d(_dst2, 0);
+ dst3 = __lasx_xvldrepl_d(_dst3, 0);
+ dst4 = __lasx_xvldrepl_d(_dst4, 0);
+ dst5 = __lasx_xvldrepl_d(_dst5, 0);
+ dst6 = __lasx_xvldrepl_d(_dst6, 0);
+ dst7 = __lasx_xvldrepl_d(_dst7, 0);
+ tmp0 = __lasx_xvilvl_d(dst1, dst0);
+ tmp1 = __lasx_xvilvl_d(dst3, dst2);
+ tmp2 = __lasx_xvilvl_d(dst5, dst4);
+ tmp3 = __lasx_xvilvl_d(dst7, dst6);
+ dst0 = __lasx_vext2xv_hu_bu(tmp0);
+ dst1 = __lasx_vext2xv_hu_bu(tmp1);
+ dst1 = __lasx_vext2xv_hu_bu(tmp1);
+ dst2 = __lasx_vext2xv_hu_bu(tmp2);
+ dst3 = __lasx_vext2xv_hu_bu(tmp3);
+ tmp0 = __lasx_xvadd_h(src0, dst0);
+ tmp1 = __lasx_xvadd_h(src1, dst1);
+ tmp2 = __lasx_xvadd_h(src2, dst2);
+ tmp3 = __lasx_xvadd_h(src3, dst3);
+ dst1 = __lasx_xvpickev_b(tmp1, tmp0);
+ dst2 = __lasx_xvpickev_b(tmp3, tmp2);
+ __lasx_xvst(zero, _src, 0);
+ __lasx_xvst(zero, _src, 32);
+ __lasx_xvst(zero, _src, 64);
+ __lasx_xvst(zero, _src, 96);
+ __lasx_xvstelm_d(dst1, _dst, 0, 0);
+ __lasx_xvstelm_d(dst1, _dst1, 0, 2);
+ __lasx_xvstelm_d(dst1, _dst2, 0, 1);
+ __lasx_xvstelm_d(dst1, _dst3, 0, 3);
+ __lasx_xvstelm_d(dst2, _dst4, 0, 0);
+ __lasx_xvstelm_d(dst2, _dst5, 0, 2);
+ __lasx_xvstelm_d(dst2, _dst6, 0, 1);
+ __lasx_xvstelm_d(dst2, _dst7, 0, 3);
+}
diff --git a/libavcodec/loongarch/h264dsp_lasx.h b/libavcodec/loongarch/h264dsp_lasx.h
index 54c57853a2..f3dcc0f3e3 100644
--- a/libavcodec/loongarch/h264dsp_lasx.h
+++ b/libavcodec/loongarch/h264dsp_lasx.h
@@ -96,4 +96,8 @@ void ff_h264_loop_filter_strength_lasx(int16_t bS[2][4][4], uint8_t nnz[40],
int8_t ref[2][40], int16_t mv[2][40][2],
int bidir, int edges, int step,
int mask_mv0, int mask_mv1, int field);
+
+void ff_h264_add_pixels4_8_lasx(uint8_t *_dst, int16_t *_src, int stride);
+
+void ff_h264_add_pixels8_8_lasx(uint8_t *_dst, int16_t *_src, int stride);
#endif // #ifndef AVCODEC_LOONGARCH_H264DSP_LASX_H
diff --git a/libavutil/intmath.h b/libavutil/intmath.h
index 9573109e9d..6d35a6f9e0 100644
--- a/libavutil/intmath.h
+++ b/libavutil/intmath.h
@@ -32,6 +32,9 @@
#if ARCH_X86
# include "x86/intmath.h"
#endif
+#if ARCH_LOONGARCH64
+# include "loongarch/intmath.h"
+#endif
#if HAVE_FAST_CLZ
#if AV_GCC_VERSION_AT_LEAST(3,4)
diff --git a/libavutil/loongarch/intmath.h b/libavutil/loongarch/intmath.h
new file mode 100644
index 0000000000..c095b3a3e4
--- /dev/null
+++ b/libavutil/loongarch/intmath.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ * Contributed by Hao Chen <chenhao@loongson.cn>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_LOONGARCH_INTMATH_H
+#define AVUTIL_LOONGARCH_INTMATH_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "config.h"
+
+#if HAVE_FAST_CLZ
+
+static av_always_inline unsigned ff_loongarch_clz(unsigned _1)
+{
+ unsigned out;
+ __asm__ volatile (
+ "clz.w %[out], %[in] \n\t"
+ : [out]"=&r"(out)
+ : [in]"r"(_1)
+ );
+ return out;
+}
+
+static av_always_inline int ff_loongarch_ctz_w(int _1)
+{
+ int out;
+ __asm__ volatile (
+ "ctz.w %[out], %[in] \n\t"
+ "andi %[out], %[out], 31 \n\t"
+ : [out]"=&r"(out)
+ : [in]"r"(_1)
+ );
+ return out;
+}
+
+static av_always_inline int ff_loongarch_ctz_d(long long _1)
+{
+ int out;
+ __asm__ volatile (
+ "ctz.d %[out], %[in] \n\t"
+ "andi %[out], %[out], 63 \n\t"
+ : [out]"=&r"(out)
+ : [in]"r"(_1)
+ );
+ return out;
+}
+
+#define ff_log2(x) (31 - ff_loongarch_clz((x)|1))
+
+#define ff_clz(x) ff_loongarch_clz(x)
+#define ff_ctz(x) ff_loongarch_ctz_w(x)
+#define ff_ctzll(x) ff_loongarch_ctz_d(x)
+
+#endif /* HAVE_FAST_CLZ */
+#endif /* AVUTIL_LOONGARCH_INTMATH_H */