1 use nihav_core::frame::*;
2 use nihav_codec_support::codecs::blockdsp::edge_emu;
4 #[allow(clippy::too_many_arguments)]
5 pub fn get_block(dst: &mut [u8], dstride: usize, src: NAVideoBufferRef<u8>, comp: usize,
6 dx: usize, dy: usize, mv_x: i16, mv_y: i16)
8 let (w, h) = src.get_dimensions(comp);
9 let sx = (dx as isize) + (mv_x as isize);
10 let sy = (dy as isize) + (mv_y as isize);
12 if (sx - 2 < 0) || (sx + 8 + 2 > (w as isize)) ||
13 (sy - 2 < 0) || (sy + 8 + 2 > (h as isize)) {
14 edge_emu(&src, sx - 2, sy - 2, 8 + 2 + 2, 8 + 2 + 2,
15 dst, dstride, comp, 0);
17 let sstride = src.get_stride(comp);
18 let soff = src.get_offset(comp);
19 let sdta = src.get_data();
20 let sbuf: &[u8] = sdta.as_slice();
21 let saddr = soff + ((sx - 2) as usize) + ((sy - 2) as usize) * sstride;
22 let src = &sbuf[saddr..];
23 for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(12) {
24 dline[..12].copy_from_slice(&sline[..12]);
29 pub fn calc_variance(src: &[u8], stride: usize) -> u16 {
32 for line in src.chunks(stride * 2).take(4) {
33 for el in line.iter().take(8).step_by(2) {
34 let pix = u32::from(*el);
39 ((ssum * 16 - sum * sum) >> 8) as u16
42 macro_rules! mc_filter {
43 (bilinear; $a: expr, $b: expr, $c: expr) => {
44 ((u16::from($a) * (8 - $c) + u16::from($b) * $c + 4) >> 3) as u8
46 (bicubic; $src: expr, $off: expr, $step: expr, $coeffs: expr) => {
47 ((i32::from($src[$off - $step] ) * i32::from($coeffs[0]) +
48 i32::from($src[$off] ) * i32::from($coeffs[1]) +
49 i32::from($src[$off + $step] ) * i32::from($coeffs[2]) +
50 i32::from($src[$off + $step * 2]) * i32::from($coeffs[3]) + 64) >> 7).min(255).max(0) as u8
54 //#[allow(snake_case)]
55 pub fn mc_bilinear(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, mx: u16, my: u16) {
57 for dline in dst.chunks_mut(dstride).take(8) {
59 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
64 for dline in dst.chunks_mut(dstride).take(8) {
66 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + sstride], my);
71 let mut tmp = [0u8; 8];
73 tmp[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
76 for dline in dst.chunks_mut(dstride).take(8) {
78 let cur = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
79 dline[i] = mc_filter!(bilinear; tmp[i], cur, my);
87 #[allow(clippy::trivially_copy_pass_by_ref)]
88 pub fn mc_bicubic(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, coeffs_w: &[i16; 4], coeffs_h: &[i16; 4]) {
89 if coeffs_h[1] == 128 {
90 for dline in dst.chunks_mut(dstride).take(8) {
92 dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w);
96 } else if coeffs_w[1] == 128 { // horizontal-only interpolation
97 for dline in dst.chunks_mut(dstride).take(8) {
99 dline[i] = mc_filter!(bicubic; src, soff + i, sstride, coeffs_h);
104 let mut buf = [0u8; 16 * 11];
106 for dline in buf.chunks_mut(16) {
108 dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w);
113 for dline in dst.chunks_mut(dstride).take(8) {
115 dline[i] = mc_filter!(bicubic; buf, soff + i, 16, coeffs_h);