RealVideo 4 encoder
[nihav.git] / nihav-realmedia / src / codecs / rv40enc / dsp / mod.rs
CommitLineData
4965a5e5
KS
1use super::types::Block;
2
3mod blk;
4pub use blk::*;
5mod ipred;
6pub use ipred::*;
7mod loopfilt;
8pub use loopfilt::*;
9mod mc;
10pub use mc::*;
11
12fn clip8(a: i16) -> u8 {
13 if a < 0 { 0 }
14 else if a > 255 { 255 }
15 else { a as u8 }
16}
17
18pub struct RefMBData {
19 pub y: [u8; 16 * 16],
20 pub u: [u8; 8 * 8],
21 pub v: [u8; 8 * 8],
22}
23
24impl RefMBData {
25 pub fn new() -> Self {
26 Self {
27 y: [0; 16 * 16],
28 u: [0; 8 * 8],
29 v: [0; 8 * 8],
30 }
31 }
32 pub fn copy_from(&mut self, other: &Self) {
33 self.y.copy_from_slice(&other.y);
34 self.u.copy_from_slice(&other.u);
35 self.v.copy_from_slice(&other.v);
36 }
37 pub fn calc_coeffs(&self, new: &Self, coeffs: &mut [Block; 25], q_dc: usize, q_ac: usize, is16: bool) {
38 let (blocks, dcs) = coeffs.split_at_mut(24);
39 let mut dblocks = blocks.iter_mut();
40 let dcs = &mut dcs[0];
41 for (y, (dstripe, sstripe)) in self.y.chunks(16 * 4).zip(new.y.chunks(16 * 4)).enumerate() {
42 for x in (0..16).step_by(4) {
43 let dst = dblocks.next().unwrap();
44 Self::diff_blk(&sstripe[x..], &dstripe[x..], 16, dst);
45 dst.transform_4x4();
46 if is16 {
47 dcs.coeffs[x / 4 + y * 4] = dst.coeffs[0];
48 dst.coeffs[0] = 0;
49 }
50 dst.quant(q_ac, q_ac);
51 }
52 }
53 let (cq_dc, cq_ac) = chroma_quants(q_ac);
54 for (dstripe, sstripe) in self.u.chunks(8 * 4).zip(new.u.chunks(8 * 4)) {
55 for x in (0..8).step_by(4) {
56 let dst = dblocks.next().unwrap();
57 Self::diff_blk(&sstripe[x..], &dstripe[x..], 8, dst);
58 dst.transform_4x4();
59 dst.quant(cq_dc, cq_ac);
60 }
61 }
62 for (dstripe, sstripe) in self.v.chunks(8 * 4).zip(new.v.chunks(8 * 4)) {
63 for x in (0..8).step_by(4) {
64 let dst = dblocks.next().unwrap();
65 Self::diff_blk(&sstripe[x..], &dstripe[x..], 8, dst);
66 dst.transform_4x4();
67 dst.quant(cq_dc, cq_ac);
68 }
69 }
70 if is16 {
71 coeffs[24].transform_dcs();
72 coeffs[24].quant_dcs(q_dc, q_ac);
73 }
74 }
75 fn diff_blk(src: &[u8], new: &[u8], stride: usize, dst: &mut Block) {
76 for (drow, (sline, nline)) in dst.coeffs.chunks_mut(4).zip(src.chunks(stride).zip(new.chunks(stride))) {
77 for (dst, (&a, &b)) in drow.iter_mut().zip(sline.iter().zip(nline.iter())) {
78 *dst = i16::from(a) - i16::from(b);
79 }
80 }
81 }
82 pub fn avg(&mut self, ref1: &Self, weight1: u32, ref2: &Self, weight2: u32) {
83 for (dst, (&src1, &src2)) in self.y.iter_mut().zip(ref1.y.iter().zip(ref2.y.iter())) {
84 *dst = weight(src1, weight1, src2, weight2);
85 }
86 for (dst, (&src1, &src2)) in self.u.iter_mut().zip(ref1.u.iter().zip(ref2.u.iter())) {
87 *dst = weight(src1, weight1, src2, weight2);
88 }
89 for (dst, (&src1, &src2)) in self.v.iter_mut().zip(ref1.v.iter().zip(ref2.v.iter())) {
90 *dst = weight(src1, weight1, src2, weight2);
91 }
92 }
93}
94
95fn weight(pix1: u8, weight1: u32, pix2: u8, weight2: u32) -> u8 {
96 ((((u32::from(pix1) * weight1) >> 9) + ((u32::from(pix2) * weight2) >> 9) + 0x10) >> 5) as u8
97}
98
99pub fn chroma_quants(q: usize) -> (usize, usize) {
100 (RV34_CHROMA_QUANT_DC[q].into(), RV34_CHROMA_QUANT_AC[q].into())
101}
102
103const RV34_CHROMA_QUANT_DC: [u8; 32] = [
104 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
105 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23
106];
107const RV34_CHROMA_QUANT_AC: [u8; 32] = [
108 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
109 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25
110];