RealVideo 4 encoder
[nihav.git] / nihav-realmedia / src / codecs / rv40enc / dsp / mod.rs
1 use super::types::Block;
2
3 mod blk;
4 pub use blk::*;
5 mod ipred;
6 pub use ipred::*;
7 mod loopfilt;
8 pub use loopfilt::*;
9 mod mc;
10 pub use mc::*;
11
12 fn clip8(a: i16) -> u8 {
13 if a < 0 { 0 }
14 else if a > 255 { 255 }
15 else { a as u8 }
16 }
17
18 pub struct RefMBData {
19 pub y: [u8; 16 * 16],
20 pub u: [u8; 8 * 8],
21 pub v: [u8; 8 * 8],
22 }
23
24 impl 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
95 fn 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
99 pub fn chroma_quants(q: usize) -> (usize, usize) {
100 (RV34_CHROMA_QUANT_DC[q].into(), RV34_CHROMA_QUANT_AC[q].into())
101 }
102
103 const 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 ];
107 const 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 ];