h264: drop unneeded mut
[nihav.git] / nihav-itu / src / codecs / h264 / loopfilter.rs
CommitLineData
696e4e20
KS
1use nihav_core::frame::NASimpleVideoFrame;
2use super::types::SliceState;
3use super::dsp::*;
4
5const 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];
11const 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
18const 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
34fn 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
38fn 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
80fn 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
120pub 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}
173pub 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