mirror of
https://gitee.com/open-loongarch/buildroot.git
synced 2026-10-28 14:07:13 +08:00
1751 lines
88 KiB
Diff
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 */
|