RealVideo 4 encoder
[nihav.git] / nihav-realmedia / src / codecs / rv40enc / dsp / blk.rs
CommitLineData
4965a5e5
KS
1use super::super::types::Block;
2use super::clip8;
3
4pub trait BlockOps {
5 fn from_diff(&mut self, new: &[u8], old: &[u8], stride: usize);
6 fn add_to(&self, dst: &mut [u8], stride: usize);
7 fn quant_dcs(&mut self, q_dc: usize, q_ac: usize);
8 fn quant(&mut self, q_dc: usize, q_ac: usize);
9 fn dequant_dcs(&mut self, q_dc: usize, q_ac: usize);
10 fn dequant(&mut self, q_dc: usize, q_ac: usize);
11 fn transform_4x4(&mut self);
12 fn transform_dcs(&mut self);
13 fn itransform_4x4(&mut self);
14 fn itransform_dcs(&mut self);
15}
16
17macro_rules! tx {
18 ($a:expr, $b:expr, $c:expr, $d:expr, $o0:expr, $o1:expr, $o2:expr, $o3:expr) => {
19 let t0 = $a + $d;
20 let t1 = $a - $d;
21 let t2 = $b + $c;
22 let t3 = $b - $c;
23 $o0 = 13 * (t0 + t2);
24 $o2 = 13 * (t0 - t2);
25 $o1 = 17 * t1 + 7 * t3;
26 $o3 = 7 * t1 - 17 * t3;
27 }
28}
29
30macro_rules! itx {
31 ($a:expr, $b:expr, $c:expr, $d:expr, $bias:expr) => {
32 let t0 = 13 * ($a + $c) + $bias;
33 let t1 = 13 * ($a - $c) + $bias;
34 let t2 = 7 * $b - 17 * $d;
35 let t3 = 17 * $b + 7 * $d;
36 $a = t0 + t3;
37 $d = t0 - t3;
38 $b = t1 + t2;
39 $c = t1 - t2;
40 }
41}
42
43impl BlockOps for Block {
44 fn from_diff(&mut self, new: &[u8], old: &[u8], stride: usize) {
45 for (dline, (oline, nline)) in self.coeffs.chunks_mut(4).zip(old.chunks(stride).zip(new.chunks(stride))) {
46 for (dst, (&o, &n)) in dline.iter_mut().zip(oline.iter().zip(nline.iter())) {
47 *dst = i16::from(n) - i16::from(o);
48 }
49 }
50 }
51 fn add_to(&self, dst: &mut [u8], stride: usize) {
52 for (line, row) in dst.chunks_mut(stride).zip(self.coeffs.chunks(4)) {
53 for (dst, &add) in line.iter_mut().zip(row.iter()) {
54 *dst = clip8(i16::from(*dst) + add);
55 }
56 }
57 }
58 fn quant_dcs(&mut self, q_dc: usize, q_ac: usize) {
59 let q_dc = i32::from(RV34_QUANT_TAB[q_dc]);
60 let q_ac = i32::from(RV34_QUANT_TAB[q_ac]);
61 for (i, el) in self.coeffs.iter_mut().enumerate() {
62 if *el != 0 {
63 let q = if matches!(i, 0 | 1 | 4) { q_dc } else { q_ac };
64 *el = (i32::from(*el) * 16 / q).max(-511).min(511) as i16;
65 }
66 }
67 }
68 fn quant(&mut self, q_dc: usize, q_ac: usize) {
69 let q_dc = RV34_QUANT_TAB[q_dc];
70 let q_ac = RV34_QUANT_TAB[q_ac];
71 if self.coeffs[0] != 0 {
72 self.coeffs[0] = self.coeffs[0] * 16 / q_dc;
73 }
74 for el in self.coeffs.iter_mut().skip(1) {
75 if *el != 0 {
76 *el = *el * 16 / q_ac;
77 }
78 }
79 }
80 fn dequant_dcs(&mut self, q_dc: usize, q_ac: usize) {
81 let q_dc = i32::from(RV34_QUANT_TAB[q_dc]);
82 let q_ac = i32::from(RV34_QUANT_TAB[q_ac]);
83 for (i, el) in self.coeffs.iter_mut().enumerate() {
84 if *el != 0 {
85 let q = if matches!(i, 0 | 1 | 4) { q_dc } else { q_ac };
86 *el = ((i32::from(*el) * q + 8) >> 4) as i16;
87 }
88 }
89 }
90 fn dequant(&mut self, q_dc: usize, q_ac: usize) {
91 let q_ac = i32::from(RV34_QUANT_TAB[q_ac]);
92 if self.coeffs[0] != 0 {
93 let q_dc = i32::from(RV34_QUANT_TAB[q_dc]);
94 self.coeffs[0] = ((i32::from(self.coeffs[0]) * q_dc + 8) >> 4) as i16;
95 }
96 for el in self.coeffs.iter_mut().skip(1) {
97 if *el != 0 {
98 *el = ((i32::from(*el) * q_ac + 8) >> 4) as i16;
99 }
100 }
101 }
102 fn transform_4x4(&mut self) {
103 let mut tmp = [0; 16];
104 for (drow, srow) in tmp.chunks_mut(4).zip(self.coeffs.chunks(4)) {
105 tx!(i32::from(srow[0]), i32::from(srow[1]), i32::from(srow[2]), i32::from(srow[3]),
106 drow[0], drow[1], drow[2], drow[3]);
107 }
108 for i in 0..4 {
109 tx!(tmp[i], tmp[i + 4], tmp[i + 8], tmp[i + 12],
110 tmp[i], tmp[i + 4], tmp[i + 8], tmp[i + 12]);
111 }
112 for (dst, &src) in self.coeffs.iter_mut().zip(tmp.iter()) {
113 *dst = ((src + 223) / 446) as i16;
114 }
115 }
116 fn transform_dcs(&mut self) {
117 let mut tmp = [0; 16];
118 for (drow, srow) in tmp.chunks_mut(4).zip(self.coeffs.chunks(4)) {
119 tx!(i32::from(srow[0]), i32::from(srow[1]), i32::from(srow[2]), i32::from(srow[3]),
120 drow[0], drow[1], drow[2], drow[3]);
121 }
122 for i in 0..4 {
123 tx!(tmp[i], tmp[i + 4], tmp[i + 8], tmp[i + 12],
124 tmp[i], tmp[i + 4], tmp[i + 8], tmp[i + 12]);
125 }
126 for (dst, &src) in self.coeffs.iter_mut().zip(tmp.iter()) {
127 *dst = ((src + 334) / 669) as i16;
128 }
129 }
130 fn itransform_4x4(&mut self) {
131 let mut tmp: [i32; 16] = [0; 16];
132 for (dst, &src) in tmp.iter_mut().zip(self.coeffs.iter()) {
133 *dst = i32::from(src);
134 }
135 for row in tmp.chunks_mut(4) {
136 itx!(row[0], row[1], row[2], row[3], 0);
137 }
138 for i in 0..4 {
139 itx!(tmp[i], tmp[i + 4], tmp[i + 2 * 4], tmp[i + 3 * 4], 0x200);
140 }
141 for (dst, &src) in self.coeffs.iter_mut().zip(tmp.iter()) {
142 *dst = (src >> 10) as i16;
143 }
144 }
145 fn itransform_dcs(&mut self) {
146 let mut tmp: [i32; 16] = [0; 16];
147 for (dst, &src) in tmp.iter_mut().zip(self.coeffs.iter()) {
148 *dst = i32::from(src);
149 }
150 for row in tmp.chunks_mut(4) {
151 itx!(row[0], row[1], row[2], row[3], 0);
152 }
153 for i in 0..4 {
154 itx!(tmp[i], tmp[i + 4], tmp[i + 2 * 4], tmp[i + 3 * 4], 0);
155 }
156 for (dst, &src) in self.coeffs.iter_mut().zip(tmp.iter()) {
157 *dst = ((src * 3) >> 11) as i16;
158 }
159 }
160}
161
162const RV34_QUANT_TAB: [i16; 32] = [
163 60, 67, 76, 85, 96, 108, 121, 136,
164 152, 171, 192, 216, 242, 272, 305, 341,
165 383, 432, 481, 544, 606, 683, 767, 854,
166 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211
167];