1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * MIPS SIMD optimized H.264 deblocking code
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * Copyright (c) 2020 Loongson Technology Corporation Limited
5cabdff1aSopenharmony_ci *                    Gu Xiwei <guxiwei-hf@loongson.cn>
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * This file is part of FFmpeg.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17cabdff1aSopenharmony_ci * Lesser General Public License for more details.
18cabdff1aSopenharmony_ci *
19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22cabdff1aSopenharmony_ci */
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include "libavcodec/bit_depth_template.c"
25cabdff1aSopenharmony_ci#include "h264dsp_mips.h"
26cabdff1aSopenharmony_ci#include "libavutil/mips/generic_macros_msa.h"
27cabdff1aSopenharmony_ci#include "libavcodec/mips/h264dsp_mips.h"
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#define h264_loop_filter_strength_iteration_msa(edges, step, mask_mv, dir, \
30cabdff1aSopenharmony_ci                                                d_idx, mask_dir)           \
31cabdff1aSopenharmony_cido {                                                                       \
32cabdff1aSopenharmony_ci    int b_idx = 0; \
33cabdff1aSopenharmony_ci    int step_x4 = step << 2; \
34cabdff1aSopenharmony_ci    int d_idx_12 = d_idx + 12; \
35cabdff1aSopenharmony_ci    int d_idx_52 = d_idx + 52; \
36cabdff1aSopenharmony_ci    int d_idx_x4 = d_idx << 2; \
37cabdff1aSopenharmony_ci    int d_idx_x4_48 = d_idx_x4 + 48; \
38cabdff1aSopenharmony_ci    int dir_x32  = dir * 32; \
39cabdff1aSopenharmony_ci    uint8_t *ref_t = (uint8_t*)ref; \
40cabdff1aSopenharmony_ci    uint8_t *mv_t  = (uint8_t*)mv; \
41cabdff1aSopenharmony_ci    uint8_t *nnz_t = (uint8_t*)nnz; \
42cabdff1aSopenharmony_ci    uint8_t *bS_t  = (uint8_t*)bS; \
43cabdff1aSopenharmony_ci    mask_mv <<= 3; \
44cabdff1aSopenharmony_ci    for (; b_idx < edges; b_idx += step) { \
45cabdff1aSopenharmony_ci        out &= mask_dir; \
46cabdff1aSopenharmony_ci        if (!(mask_mv & b_idx)) { \
47cabdff1aSopenharmony_ci            if (bidir) { \
48cabdff1aSopenharmony_ci                ref_2 = LD_SB(ref_t + d_idx_12); \
49cabdff1aSopenharmony_ci                ref_3 = LD_SB(ref_t + d_idx_52); \
50cabdff1aSopenharmony_ci                ref_0 = LD_SB(ref_t + 12); \
51cabdff1aSopenharmony_ci                ref_1 = LD_SB(ref_t + 52); \
52cabdff1aSopenharmony_ci                ref_2 = (v16i8)__msa_ilvr_w((v4i32)ref_3, (v4i32)ref_2); \
53cabdff1aSopenharmony_ci                ref_0 = (v16i8)__msa_ilvr_w((v4i32)ref_0, (v4i32)ref_0); \
54cabdff1aSopenharmony_ci                ref_1 = (v16i8)__msa_ilvr_w((v4i32)ref_1, (v4i32)ref_1); \
55cabdff1aSopenharmony_ci                ref_3 = (v16i8)__msa_shf_h((v8i16)ref_2, 0x4e); \
56cabdff1aSopenharmony_ci                ref_0 -= ref_2; \
57cabdff1aSopenharmony_ci                ref_1 -= ref_3; \
58cabdff1aSopenharmony_ci                ref_0 = (v16i8)__msa_or_v((v16u8)ref_0, (v16u8)ref_1); \
59cabdff1aSopenharmony_ci\
60cabdff1aSopenharmony_ci                tmp_2 = LD_SH(mv_t + d_idx_x4_48);   \
61cabdff1aSopenharmony_ci                tmp_3 = LD_SH(mv_t + 48); \
62cabdff1aSopenharmony_ci                tmp_4 = LD_SH(mv_t + 208); \
63cabdff1aSopenharmony_ci                tmp_5 = tmp_2 - tmp_3; \
64cabdff1aSopenharmony_ci                tmp_6 = tmp_2 - tmp_4; \
65cabdff1aSopenharmony_ci                SAT_SH2_SH(tmp_5, tmp_6, 7); \
66cabdff1aSopenharmony_ci                tmp_0 = __msa_pckev_b((v16i8)tmp_6, (v16i8)tmp_5); \
67cabdff1aSopenharmony_ci                tmp_0 += cnst_1; \
68cabdff1aSopenharmony_ci                tmp_0 = (v16i8)__msa_subs_u_b((v16u8)tmp_0, (v16u8)cnst_0);\
69cabdff1aSopenharmony_ci                tmp_0 = (v16i8)__msa_sat_s_h((v8i16)tmp_0, 7); \
70cabdff1aSopenharmony_ci                tmp_0 = __msa_pckev_b(tmp_0, tmp_0); \
71cabdff1aSopenharmony_ci                out   = (v16i8)__msa_or_v((v16u8)ref_0, (v16u8)tmp_0); \
72cabdff1aSopenharmony_ci\
73cabdff1aSopenharmony_ci                tmp_2 = LD_SH(mv_t + 208 + d_idx_x4); \
74cabdff1aSopenharmony_ci                tmp_5 = tmp_2 - tmp_3; \
75cabdff1aSopenharmony_ci                tmp_6 = tmp_2 - tmp_4; \
76cabdff1aSopenharmony_ci                SAT_SH2_SH(tmp_5, tmp_6, 7); \
77cabdff1aSopenharmony_ci                tmp_1 = __msa_pckev_b((v16i8)tmp_6, (v16i8)tmp_5); \
78cabdff1aSopenharmony_ci                tmp_1 += cnst_1; \
79cabdff1aSopenharmony_ci                tmp_1 = (v16i8)__msa_subs_u_b((v16u8)tmp_1, (v16u8)cnst_0); \
80cabdff1aSopenharmony_ci                tmp_1 = (v16i8)__msa_sat_s_h((v8i16)tmp_1, 7); \
81cabdff1aSopenharmony_ci                tmp_1 = __msa_pckev_b(tmp_1, tmp_1); \
82cabdff1aSopenharmony_ci\
83cabdff1aSopenharmony_ci                tmp_1 = (v16i8)__msa_shf_h((v8i16)tmp_1, 0x4e); \
84cabdff1aSopenharmony_ci                out   = (v16i8)__msa_or_v((v16u8)out, (v16u8)tmp_1); \
85cabdff1aSopenharmony_ci                tmp_0 = (v16i8)__msa_shf_h((v8i16)out, 0x4e); \
86cabdff1aSopenharmony_ci                out   = (v16i8)__msa_min_u_b((v16u8)out, (v16u8)tmp_0); \
87cabdff1aSopenharmony_ci            } else { \
88cabdff1aSopenharmony_ci                ref_0 = LD_SB(ref_t + d_idx_12); \
89cabdff1aSopenharmony_ci                ref_3 = LD_SB(ref_t + 12); \
90cabdff1aSopenharmony_ci                tmp_2 = LD_SH(mv_t + d_idx_x4_48); \
91cabdff1aSopenharmony_ci                tmp_3 = LD_SH(mv_t + 48); \
92cabdff1aSopenharmony_ci                tmp_4 = tmp_3 - tmp_2; \
93cabdff1aSopenharmony_ci                tmp_1 = (v16i8)__msa_sat_s_h(tmp_4, 7); \
94cabdff1aSopenharmony_ci                tmp_1 = __msa_pckev_b(tmp_1, tmp_1); \
95cabdff1aSopenharmony_ci                tmp_1 += cnst_1; \
96cabdff1aSopenharmony_ci                out   = (v16i8)__msa_subs_u_b((v16u8)tmp_1, (v16u8)cnst_0); \
97cabdff1aSopenharmony_ci                out   = (v16i8)__msa_sat_s_h((v8i16)out, 7); \
98cabdff1aSopenharmony_ci                out   = __msa_pckev_b(out, out); \
99cabdff1aSopenharmony_ci                ref_0 = ref_3 - ref_0; \
100cabdff1aSopenharmony_ci                out   = (v16i8)__msa_or_v((v16u8)out, (v16u8)ref_0); \
101cabdff1aSopenharmony_ci            } \
102cabdff1aSopenharmony_ci        } \
103cabdff1aSopenharmony_ci        tmp_0 = LD_SB(nnz_t + 12); \
104cabdff1aSopenharmony_ci        tmp_1 = LD_SB(nnz_t + d_idx_12); \
105cabdff1aSopenharmony_ci        tmp_0 = (v16i8)__msa_or_v((v16u8)tmp_0, (v16u8)tmp_1); \
106cabdff1aSopenharmony_ci        tmp_0 = (v16i8)__msa_min_u_b((v16u8)tmp_0, (v16u8)cnst_2); \
107cabdff1aSopenharmony_ci        out   = (v16i8)__msa_min_u_b((v16u8)out, (v16u8)cnst_2); \
108cabdff1aSopenharmony_ci        tmp_0 = (v16i8)((v8i16)tmp_0 << 1); \
109cabdff1aSopenharmony_ci        tmp_0 = (v16i8)__msa_max_u_b((v16u8)out, (v16u8)tmp_0); \
110cabdff1aSopenharmony_ci        tmp_0 = __msa_ilvr_b(zero, tmp_0); \
111cabdff1aSopenharmony_ci        ST_D1(tmp_0, 0, bS_t + dir_x32); \
112cabdff1aSopenharmony_ci        ref_t += step; \
113cabdff1aSopenharmony_ci        mv_t  += step_x4; \
114cabdff1aSopenharmony_ci        nnz_t += step; \
115cabdff1aSopenharmony_ci        bS_t  += step; \
116cabdff1aSopenharmony_ci    } \
117cabdff1aSopenharmony_ci} while(0)
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_civoid ff_h264_loop_filter_strength_msa(int16_t bS[2][4][4], uint8_t nnz[40],
120cabdff1aSopenharmony_ci                                      int8_t ref[2][40], int16_t mv[2][40][2],
121cabdff1aSopenharmony_ci                                      int bidir, int edges, int step,
122cabdff1aSopenharmony_ci                                      int mask_mv0, int mask_mv1, int field)
123cabdff1aSopenharmony_ci{
124cabdff1aSopenharmony_ci    v16i8 out;
125cabdff1aSopenharmony_ci    v16i8 ref_0, ref_1, ref_2, ref_3;
126cabdff1aSopenharmony_ci    v16i8 tmp_0, tmp_1;
127cabdff1aSopenharmony_ci    v8i16 tmp_2, tmp_3, tmp_4, tmp_5, tmp_6;
128cabdff1aSopenharmony_ci    v16i8 cnst_0, cnst_1, cnst_2;
129cabdff1aSopenharmony_ci    v16i8 zero = { 0 };
130cabdff1aSopenharmony_ci    v16i8 one  = __msa_fill_b(0xff);
131cabdff1aSopenharmony_ci    if (field) {
132cabdff1aSopenharmony_ci        cnst_0 = (v16i8)__msa_fill_h(0x206);
133cabdff1aSopenharmony_ci        cnst_1 = (v16i8)__msa_fill_h(0x103);
134cabdff1aSopenharmony_ci        cnst_2 = (v16i8)__msa_fill_h(0x101);
135cabdff1aSopenharmony_ci    } else {
136cabdff1aSopenharmony_ci        cnst_0 = __msa_fill_b(0x6);
137cabdff1aSopenharmony_ci        cnst_1 = __msa_fill_b(0x3);
138cabdff1aSopenharmony_ci        cnst_2 = __msa_fill_b(0x1);
139cabdff1aSopenharmony_ci    }
140cabdff1aSopenharmony_ci    step  <<= 3;
141cabdff1aSopenharmony_ci    edges <<= 3;
142cabdff1aSopenharmony_ci
143cabdff1aSopenharmony_ci    h264_loop_filter_strength_iteration_msa(edges, step, mask_mv1, 1, -8, zero);
144cabdff1aSopenharmony_ci    h264_loop_filter_strength_iteration_msa(32, 8, mask_mv0, 0, -1, one);
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_ci    LD_SB2((int8_t*)bS, 16, tmp_0, tmp_1);
147cabdff1aSopenharmony_ci    tmp_2 = (v8i16)__msa_ilvl_d((v2i64)tmp_0, (v2i64)tmp_0);
148cabdff1aSopenharmony_ci    tmp_3 = (v8i16)__msa_ilvl_d((v2i64)tmp_1, (v2i64)tmp_1);
149cabdff1aSopenharmony_ci    TRANSPOSE4x4_SH_SH(tmp_0, tmp_2, tmp_1, tmp_3, tmp_2, tmp_3, tmp_4, tmp_5);
150cabdff1aSopenharmony_ci    tmp_0 = (v16i8)__msa_ilvr_d((v2i64)tmp_3, (v2i64)tmp_2);
151cabdff1aSopenharmony_ci    tmp_1 = (v16i8)__msa_ilvr_d((v2i64)tmp_5, (v2i64)tmp_4);
152cabdff1aSopenharmony_ci    ST_SB2(tmp_0, tmp_1, (int8_t*)bS, 16);
153cabdff1aSopenharmony_ci}
154