FFmpeg
h264_deblock_msa.c
Go to the documentation of this file.
1 /*
2  * MIPS SIMD optimized H.264 deblocking code
3  *
4  * Copyright (c) 2020 Loongson Technology Corporation Limited
5  * Gu Xiwei <guxiwei-hf@loongson.cn>
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
25 #include "h264dsp_mips.h"
28 
29 #define h264_loop_filter_strength_iteration_msa(edges, step, mask_mv, dir, \
30  d_idx, mask_dir) \
31 do { \
32  int b_idx = 0; \
33  int step_x4 = step << 2; \
34  int d_idx_12 = d_idx + 12; \
35  int d_idx_52 = d_idx + 52; \
36  int d_idx_x4 = d_idx << 2; \
37  int d_idx_x4_48 = d_idx_x4 + 48; \
38  int dir_x32 = dir * 32; \
39  uint8_t *ref_t = (uint8_t*)ref; \
40  uint8_t *mv_t = (uint8_t*)mv; \
41  uint8_t *nnz_t = (uint8_t*)nnz; \
42  uint8_t *bS_t = (uint8_t*)bS; \
43  mask_mv <<= 3; \
44  for (; b_idx < edges; b_idx += step) { \
45  out &= mask_dir; \
46  if (!(mask_mv & b_idx)) { \
47  if (bidir) { \
48  ref_2 = LD_SB(ref_t + d_idx_12); \
49  ref_3 = LD_SB(ref_t + d_idx_52); \
50  ref_0 = LD_SB(ref_t + 12); \
51  ref_1 = LD_SB(ref_t + 52); \
52  ref_2 = (v16i8)__msa_ilvr_w((v4i32)ref_3, (v4i32)ref_2); \
53  ref_0 = (v16i8)__msa_ilvr_w((v4i32)ref_0, (v4i32)ref_0); \
54  ref_1 = (v16i8)__msa_ilvr_w((v4i32)ref_1, (v4i32)ref_1); \
55  ref_3 = (v16i8)__msa_shf_h((v8i16)ref_2, 0x4e); \
56  ref_0 -= ref_2; \
57  ref_1 -= ref_3; \
58  ref_0 = (v16i8)__msa_or_v((v16u8)ref_0, (v16u8)ref_1); \
59 \
60  tmp_2 = LD_SH(mv_t + d_idx_x4_48); \
61  tmp_3 = LD_SH(mv_t + 48); \
62  tmp_4 = LD_SH(mv_t + 208); \
63  tmp_5 = tmp_2 - tmp_3; \
64  tmp_6 = tmp_2 - tmp_4; \
65  SAT_SH2_SH(tmp_5, tmp_6, 7); \
66  tmp_0 = __msa_pckev_b((v16i8)tmp_6, (v16i8)tmp_5); \
67  tmp_0 += cnst_1; \
68  tmp_0 = (v16i8)__msa_subs_u_b((v16u8)tmp_0, (v16u8)cnst_0);\
69  tmp_0 = (v16i8)__msa_sat_s_h((v8i16)tmp_0, 7); \
70  tmp_0 = __msa_pckev_b(tmp_0, tmp_0); \
71  out = (v16i8)__msa_or_v((v16u8)ref_0, (v16u8)tmp_0); \
72 \
73  tmp_2 = LD_SH(mv_t + 208 + d_idx_x4); \
74  tmp_5 = tmp_2 - tmp_3; \
75  tmp_6 = tmp_2 - tmp_4; \
76  SAT_SH2_SH(tmp_5, tmp_6, 7); \
77  tmp_1 = __msa_pckev_b((v16i8)tmp_6, (v16i8)tmp_5); \
78  tmp_1 += cnst_1; \
79  tmp_1 = (v16i8)__msa_subs_u_b((v16u8)tmp_1, (v16u8)cnst_0); \
80  tmp_1 = (v16i8)__msa_sat_s_h((v8i16)tmp_1, 7); \
81  tmp_1 = __msa_pckev_b(tmp_1, tmp_1); \
82 \
83  tmp_1 = (v16i8)__msa_shf_h((v8i16)tmp_1, 0x4e); \
84  out = (v16i8)__msa_or_v((v16u8)out, (v16u8)tmp_1); \
85  tmp_0 = (v16i8)__msa_shf_h((v8i16)out, 0x4e); \
86  out = (v16i8)__msa_min_u_b((v16u8)out, (v16u8)tmp_0); \
87  } else { \
88  ref_0 = LD_SB(ref_t + d_idx_12); \
89  ref_3 = LD_SB(ref_t + 12); \
90  tmp_2 = LD_SH(mv_t + d_idx_x4_48); \
91  tmp_3 = LD_SH(mv_t + 48); \
92  tmp_4 = tmp_3 - tmp_2; \
93  tmp_1 = (v16i8)__msa_sat_s_h(tmp_4, 7); \
94  tmp_1 = __msa_pckev_b(tmp_1, tmp_1); \
95  tmp_1 += cnst_1; \
96  out = (v16i8)__msa_subs_u_b((v16u8)tmp_1, (v16u8)cnst_0); \
97  out = (v16i8)__msa_sat_s_h((v8i16)out, 7); \
98  out = __msa_pckev_b(out, out); \
99  ref_0 = ref_3 - ref_0; \
100  out = (v16i8)__msa_or_v((v16u8)out, (v16u8)ref_0); \
101  } \
102  } \
103  tmp_0 = LD_SB(nnz_t + 12); \
104  tmp_1 = LD_SB(nnz_t + d_idx_12); \
105  tmp_0 = (v16i8)__msa_or_v((v16u8)tmp_0, (v16u8)tmp_1); \
106  tmp_0 = (v16i8)__msa_min_u_b((v16u8)tmp_0, (v16u8)cnst_2); \
107  out = (v16i8)__msa_min_u_b((v16u8)out, (v16u8)cnst_2); \
108  tmp_0 = (v16i8)((v8i16)tmp_0 << 1); \
109  tmp_0 = (v16i8)__msa_max_u_b((v16u8)out, (v16u8)tmp_0); \
110  tmp_0 = __msa_ilvr_b(zero, tmp_0); \
111  ST_D1(tmp_0, 0, bS_t + dir_x32); \
112  ref_t += step; \
113  mv_t += step_x4; \
114  nnz_t += step; \
115  bS_t += step; \
116  } \
117 } while(0)
118 
119 void ff_h264_loop_filter_strength_msa(int16_t bS[2][4][4], uint8_t nnz[40],
120  int8_t ref[2][40], int16_t mv[2][40][2],
121  int bidir, int edges, int step,
122  int mask_mv0, int mask_mv1, int field)
123 {
124  v16i8 out;
125  v16i8 ref_0, ref_1, ref_2, ref_3;
126  v16i8 tmp_0, tmp_1;
127  v8i16 tmp_2, tmp_3, tmp_4, tmp_5, tmp_6;
128  v16i8 cnst_0, cnst_1, cnst_2;
129  v16i8 zero = { 0 };
130  v16i8 one = __msa_fill_b(0xff);
131  if (field) {
132  cnst_0 = (v16i8)__msa_fill_h(0x206);
133  cnst_1 = (v16i8)__msa_fill_h(0x103);
134  cnst_2 = (v16i8)__msa_fill_h(0x101);
135  } else {
136  cnst_0 = __msa_fill_b(0x6);
137  cnst_1 = __msa_fill_b(0x3);
138  cnst_2 = __msa_fill_b(0x1);
139  }
140  step <<= 3;
141  edges <<= 3;
142 
143  h264_loop_filter_strength_iteration_msa(edges, step, mask_mv1, 1, -8, zero);
144  h264_loop_filter_strength_iteration_msa(32, 8, mask_mv0, 0, -1, one);
145 
146  LD_SB2((int8_t*)bS, 16, tmp_0, tmp_1);
147  tmp_2 = (v8i16)__msa_ilvl_d((v2i64)tmp_0, (v2i64)tmp_0);
148  tmp_3 = (v8i16)__msa_ilvl_d((v2i64)tmp_1, (v2i64)tmp_1);
149  TRANSPOSE4x4_SH_SH(tmp_0, tmp_2, tmp_1, tmp_3, tmp_2, tmp_3, tmp_4, tmp_5);
150  tmp_0 = (v16i8)__msa_ilvr_d((v2i64)tmp_3, (v2i64)tmp_2);
151  tmp_1 = (v16i8)__msa_ilvr_d((v2i64)tmp_5, (v2i64)tmp_4);
152  ST_SB2(tmp_0, tmp_1, (int8_t*)bS, 16);
153 }
out
FILE * out
Definition: movenc.c:55
mv
static const int8_t mv[256][2]
Definition: 4xm.c:81
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
h264_loop_filter_strength_iteration_msa
#define h264_loop_filter_strength_iteration_msa(edges, step, mask_mv, dir, d_idx, mask_dir)
Definition: h264_deblock_msa.c:29
generic_macros_msa.h
field
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this field
Definition: writing_filters.txt:78
h264dsp_mips.h
TRANSPOSE4x4_SH_SH
#define TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, out0, out1, out2, out3)
Definition: generic_macros_msa.h:2466
bit_depth_template.c
ST_SB2
#define ST_SB2(...)
Definition: generic_macros_msa.h:364
zero
static int zero(InterplayACMContext *s, unsigned ind, unsigned col)
Definition: interplayacm.c:121
ff_h264_loop_filter_strength_msa
void ff_h264_loop_filter_strength_msa(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)
Definition: h264_deblock_msa.c:119
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
LD_SB2
#define LD_SB2(...)
Definition: generic_macros_msa.h:278