]>
Commit | Line | Data |
---|---|---|
1 | use nihav_core::frame::NASimpleVideoFrame; | |
2 | use super::types::SliceState; | |
3 | use super::dsp::*; | |
4 | ||
5 | const ALPHA: [i16; 52] = [ | |
6 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
7 | 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 20, 22, 25, 28, | |
8 | 32, 36, 40, 45, 50, 56, 63, 71, 80, 90, 100, 113, 127, 144, 162, 182, | |
9 | 203, 226, 255, 255 | |
10 | ]; | |
11 | const BETA: [i16; 52] = [ | |
12 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
13 | 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 6, 6, 7, 7, 8, 8, | |
14 | 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, | |
15 | 17, 17, 18, 18 | |
16 | ]; | |
17 | ||
18 | const TC0: [[u8; 3]; 52] = [ | |
19 | [ 0, 0, 0], [ 0, 0, 0], [ 0, 0, 0], [ 0, 0, 0], | |
20 | [ 0, 0, 0], [ 0, 0, 0], [ 0, 0, 0], [ 0, 0, 0], | |
21 | [ 0, 0, 0], [ 0, 0, 0], [ 0, 0, 0], [ 0, 0, 0], | |
22 | [ 0, 0, 0], [ 0, 0, 0], [ 0, 0, 0], [ 0, 0, 0], | |
23 | [ 0, 0, 0], [ 0, 0, 1], [ 0, 0, 1], [ 0, 0, 1], | |
24 | [ 0, 0, 1], [ 0, 1, 1], [ 0, 1, 1], [ 1, 1, 1], | |
25 | [ 1, 1, 1], [ 1, 1, 1], [ 1, 1, 1], [ 1, 1, 2], | |
26 | [ 1, 1, 2], [ 1, 1, 2], [ 1, 1, 2], [ 1, 2, 3], | |
27 | [ 1, 2, 3], [ 2, 2, 3], [ 2, 2, 4], [ 2, 3, 4], | |
28 | [ 2, 3, 4], [ 3, 3, 5], [ 3, 4, 6], [ 3, 4, 6], | |
29 | [ 4, 5, 7], [ 4, 5, 8], [ 4, 6, 9], [ 5, 7, 10], | |
30 | [ 6, 8, 11], [ 6, 8, 13], [ 7, 10, 14], [ 8, 11, 16], | |
31 | [ 9, 12, 18], [10, 13, 20], [11, 15, 23], [13, 17, 25] | |
32 | ]; | |
33 | ||
34 | fn get_lf_idx(qp0: u8, qp1: u8, off: i8) -> usize { | |
35 | (i16::from((qp0 + qp1 + 1) >> 1) + i16::from(off)).max(0).min(51) as usize | |
36 | } | |
37 | ||
38 | fn filter_mb_row4_y(dst: &mut [u8], off: usize, stride: usize, dmodes: [u8; 4], quants: [u8; 3], alpha_off: i8, beta_off: i8) { | |
39 | let q = quants[0]; | |
40 | let qleft = quants[1]; | |
41 | let dmode = dmodes[0] & 0xF; | |
42 | if dmode != 0 { | |
43 | let index_a_y = get_lf_idx(q, qleft, alpha_off); | |
44 | let alpha_y = ALPHA[index_a_y]; | |
45 | let beta_y = BETA[get_lf_idx(q, qleft, beta_off)]; | |
46 | if dmode == 4 { | |
47 | loop_filter_lumaedge_v(dst, off, stride, alpha_y, beta_y); | |
48 | } else { | |
49 | let tc0 = i16::from(TC0[index_a_y][(dmode - 1) as usize]); | |
50 | loop_filter_lumanormal_v(dst, off, stride, alpha_y, beta_y, tc0); | |
51 | } | |
52 | } | |
53 | let index_a_y = get_lf_idx(q, q, alpha_off); | |
54 | let alpha_y = ALPHA[index_a_y]; | |
55 | let beta_y = BETA[get_lf_idx(q, q, beta_off)]; | |
56 | ||
57 | for i in 1..4 { | |
58 | let dmode = dmodes[i] & 0xF; | |
59 | if dmode != 0 { | |
60 | let tc0 = i16::from(TC0[index_a_y][(dmode - 1) as usize]); | |
61 | loop_filter_lumanormal_v(dst, off + i * 4, stride, alpha_y, beta_y, tc0); | |
62 | } | |
63 | } | |
64 | ||
65 | let qtop = quants[2]; | |
66 | let index_a_y = get_lf_idx(q, qtop, alpha_off); | |
67 | let alpha_y = ALPHA[index_a_y]; | |
68 | let beta_y = BETA[get_lf_idx(q, qtop, beta_off)]; | |
69 | for i in 0..4 { | |
70 | let dmode = dmodes[i] >> 4; | |
71 | if dmode == 4 { | |
72 | loop_filter_lumaedge_h(dst, off + i * 4, stride, alpha_y, beta_y); | |
73 | } else if dmode != 0 { | |
74 | let tc0 = i16::from(TC0[index_a_y][(dmode - 1) as usize]); | |
75 | loop_filter_lumanormal_h(dst, off + i * 4, stride, alpha_y, beta_y, tc0); | |
76 | } | |
77 | } | |
78 | } | |
79 | ||
80 | fn filter_mb_row4_c(dst: &mut [u8], off: usize, stride: usize, dmodes: [u8; 4], quants: [u8; 3], alpha_off: i8, beta_off: i8) { | |
81 | let q = quants[0]; | |
82 | let qleft = quants[1]; | |
83 | ||
84 | let dmode = dmodes[0] & 0xF; | |
85 | if dmode != 0 { | |
86 | let index_a_c = get_lf_idx(q, qleft, alpha_off); | |
87 | let alpha_c = ALPHA[index_a_c]; | |
88 | let beta_c = BETA[get_lf_idx(q, qleft, beta_off)]; | |
89 | if dmode == 4 { | |
90 | loop_filter_chromaedge_v(dst, off, stride, alpha_c, beta_c); | |
91 | } else { | |
92 | let tc0 = i16::from(TC0[index_a_c][(dmode - 1) as usize]); | |
93 | loop_filter_chromanormal_v(dst, off, stride, alpha_c, beta_c, tc0); | |
94 | } | |
95 | } | |
96 | let dmode = dmodes[2] & 0xF; | |
97 | if dmode != 0 { | |
98 | let index_a_c = get_lf_idx(q, q, alpha_off); | |
99 | let alpha_c = ALPHA[index_a_c]; | |
100 | let beta_c = BETA[get_lf_idx(q, q, beta_off)]; | |
101 | let tc0 = i16::from(TC0[index_a_c][(dmode - 1) as usize]); | |
102 | loop_filter_chromanormal_v(dst, off + 4, stride, alpha_c, beta_c, tc0); | |
103 | } | |
104 | ||
105 | let qtop = quants[2]; | |
106 | let index_a_c = get_lf_idx(q, qtop, alpha_off); | |
107 | let alpha_c = ALPHA[index_a_c]; | |
108 | let beta_c = BETA[get_lf_idx(q, qtop, beta_off)]; | |
109 | for i in 0..2 { | |
110 | let dmode = dmodes[i * 2] >> 4; | |
111 | if dmode == 4 { | |
112 | loop_filter_chromaedge_h(dst, off + i * 4, stride, alpha_c, beta_c); | |
113 | } else if dmode != 0 { | |
114 | let tc0 = i16::from(TC0[index_a_c][(dmode - 1) as usize]); | |
115 | loop_filter_chromanormal_h(dst, off + i * 4, stride, alpha_c, beta_c, tc0); | |
116 | } | |
117 | } | |
118 | } | |
119 | ||
120 | pub fn loop_filter_row(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, alpha_off: i8, beta_off: i8) { | |
121 | let mut db_idx = sstate.deblock.xpos - sstate.deblock.stride; | |
122 | let mut yoff = frm.offset[0] + sstate.mb_y * 16 * frm.stride[0]; | |
123 | let mut uoff = frm.offset[1] + sstate.mb_y * 8 * frm.stride[1]; | |
124 | let mut voff = frm.offset[2] + sstate.mb_y * 8 * frm.stride[2]; | |
125 | let mut tlq = [0; 3]; | |
126 | let mut lq = [0; 3]; | |
127 | let mut mb_idx = sstate.mb.xpos; | |
128 | for _mb_x in 0..sstate.mb_w { | |
129 | let mut tqy = sstate.mb.data[mb_idx - sstate.mb.stride].qp_y; | |
130 | let tqu = sstate.mb.data[mb_idx - sstate.mb.stride].qp_u; | |
131 | let tqv = sstate.mb.data[mb_idx - sstate.mb.stride].qp_v; | |
132 | if sstate.mb_y > 0 { | |
133 | let dmodes = [sstate.deblock.data[db_idx], | |
134 | sstate.deblock.data[db_idx + 1], | |
135 | sstate.deblock.data[db_idx + 2], | |
136 | sstate.deblock.data[db_idx + 3]]; | |
137 | ||
138 | filter_mb_row4_y(frm.data, yoff - frm.stride[0] * 4, frm.stride[0], dmodes, [tqy, tlq[0], tqy], alpha_off, beta_off); | |
139 | filter_mb_row4_c(frm.data, uoff - frm.stride[1] * 4, frm.stride[1], dmodes, [tqu, tlq[1], tqu], alpha_off, beta_off); | |
140 | filter_mb_row4_c(frm.data, voff - frm.stride[2] * 4, frm.stride[2], dmodes, [tqv, tlq[2], tqv], alpha_off, beta_off); | |
141 | ||
142 | tlq = [tqy, tqu, tqv]; | |
143 | } | |
144 | ||
145 | let qy = sstate.mb.data[mb_idx].qp_y; | |
146 | let qu = sstate.mb.data[mb_idx].qp_u; | |
147 | let qv = sstate.mb.data[mb_idx].qp_v; | |
148 | ||
149 | for y in 0..3 { | |
150 | db_idx += sstate.deblock.stride; | |
151 | let dmodes = [sstate.deblock.data[db_idx], | |
152 | sstate.deblock.data[db_idx + 1], | |
153 | sstate.deblock.data[db_idx + 2], | |
154 | sstate.deblock.data[db_idx + 3]]; | |
155 | ||
156 | filter_mb_row4_y(frm.data, yoff + frm.stride[0] * 4 * y, frm.stride[0], dmodes, [qy, lq[0], tqy], alpha_off, beta_off); | |
157 | if y == 0 { | |
158 | filter_mb_row4_c(frm.data, uoff + frm.stride[1] * 2 * y, frm.stride[1], dmodes, [qu, lq[1], tqu], alpha_off, beta_off); | |
159 | filter_mb_row4_c(frm.data, voff + frm.stride[2] * 2 * y, frm.stride[2], dmodes, [qv, lq[2], tqv], alpha_off, beta_off); | |
160 | } | |
161 | tqy = qy; | |
162 | } | |
163 | db_idx -= sstate.deblock.stride * 3; | |
164 | lq = [qy, qu, qv]; | |
165 | ||
166 | mb_idx += 1; | |
167 | db_idx += 4; | |
168 | yoff += 16; | |
169 | uoff += 8; | |
170 | voff += 8; | |
171 | } | |
172 | } | |
173 | pub fn loop_filter_last(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, alpha_off: i8, beta_off: i8) { | |
174 | let mut db_idx = sstate.deblock.xpos + 3 * sstate.deblock.stride; | |
175 | let mut yoff = frm.offset[0] + (sstate.mb_y * 16 + 12) * frm.stride[0]; | |
176 | let mut uoff = frm.offset[1] + (sstate.mb_y * 8 + 4) * frm.stride[1]; | |
177 | let mut voff = frm.offset[2] + (sstate.mb_y * 8 + 4) * frm.stride[2]; | |
178 | ||
179 | let mut lq = [0; 3]; | |
180 | let mut mb_idx = sstate.mb.xpos; | |
181 | if sstate.mb_y != 0 && sstate.mb_x == 0 { | |
182 | db_idx -= 4 * sstate.deblock.stride; | |
183 | mb_idx -= sstate.mb.stride; | |
184 | yoff -= 16 * frm.stride[0]; | |
185 | uoff -= 8 * frm.stride[1]; | |
186 | voff -= 8 * frm.stride[2]; | |
187 | } | |
188 | for _mb_x in 0..sstate.mb_w { | |
189 | let qy = sstate.mb.data[mb_idx].qp_y; | |
190 | let qu = sstate.mb.data[mb_idx].qp_u; | |
191 | let qv = sstate.mb.data[mb_idx].qp_v; | |
192 | ||
193 | let dmodes = [sstate.deblock.data[db_idx], | |
194 | sstate.deblock.data[db_idx + 1], | |
195 | sstate.deblock.data[db_idx + 2], | |
196 | sstate.deblock.data[db_idx + 3]]; | |
197 | ||
198 | filter_mb_row4_y(frm.data, yoff, frm.stride[0], dmodes, [qy, lq[0], qy], alpha_off, beta_off); | |
199 | filter_mb_row4_c(frm.data, uoff, frm.stride[1], dmodes, [qu, lq[1], qu], alpha_off, beta_off); | |
200 | filter_mb_row4_c(frm.data, voff, frm.stride[2], dmodes, [qv, lq[2], qv], alpha_off, beta_off); | |
201 | ||
202 | lq = [qy, qu, qv]; | |
203 | mb_idx += 1; | |
204 | db_idx += 4; | |
205 | yoff += 16; | |
206 | uoff += 8; | |
207 | voff += 8; | |
208 | } | |
209 | } | |
210 |