| 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 | ]; |