]> git.nihav.org Git - nihav.git/blobdiff - nihav-duck/src/codecs/vpcommon.rs
VP4 decoder
[nihav.git] / nihav-duck / src / codecs / vpcommon.rs
index cac264b8c51301060a45e860085799f26a19ceed..05b07d19eadda854fef417aa8a4c267c387cfcac 100644 (file)
@@ -1,4 +1,5 @@
 use nihav_core::codecs::*;
+use nihav_core::codecs::blockdsp::*;
 
 #[derive(Clone,Copy,Debug,PartialEq)]
 #[allow(dead_code)]
@@ -186,3 +187,65 @@ pub fn vp_add_block_dc(coeffs: &mut [i16; 64], bx: usize, by: usize, plane: usiz
         off += frm.stride[plane];
     }
 }
+
+pub fn vp31_loop_filter(data: &mut [u8], mut off: usize, step: usize, stride: usize,
+                        len: usize, loop_str: i16) {
+    for _ in 0..len {
+        let a = data[off - step * 2] as i16;
+        let b = data[off - step] as i16;
+        let c = data[off] as i16;
+        let d = data[off + step] as i16;
+        let mut diff = ((a - d) + 3 * (c - b) + 4) >> 3;
+        if diff.abs() >= 2 * loop_str {
+            diff = 0;
+        } else if diff.abs() >= loop_str {
+            if diff < 0 {
+                diff = -diff - 2 * loop_str;
+            } else {
+                diff = -diff + 2 * loop_str;
+            }
+        }
+        if diff != 0 {
+            data[off - step] = (b + diff).max(0).min(255) as u8;
+            data[off]        = (c - diff).max(0).min(255) as u8;
+        }
+
+        off += stride;
+    }
+}
+
+pub fn vp_copy_block(dst: &mut NASimpleVideoFrame<u8>, src: NAVideoBufferRef<u8>, comp: usize,
+                     dx: usize, dy: usize, mv_x: i16, mv_y: i16,
+                     preborder: usize, postborder: usize, loop_str: i16,
+                     mode: usize, interp: &[BlkInterpFunc], mut mc_buf: NAVideoBufferRef<u8>)
+{
+    let sx = (dx as isize) + (mv_x as isize);
+    let sy = (dy as isize) + (mv_y as isize);
+    if ((sx | sy) & 7) == 0 {
+        copy_block(dst, src, comp, dx, dy, mv_x, mv_y, 8, 8, preborder, postborder, mode, interp);
+        return;
+    }
+    let pre = preborder.max(2);
+    let post = postborder.max(1);
+    let bsize = 8 + pre + post;
+    let src_x = sx - (pre as isize);
+    let src_y = sy - (pre as isize);
+    {
+        let mut tmp_buf = NASimpleVideoFrame::from_video_buf(&mut mc_buf).unwrap();
+        copy_block(&mut tmp_buf, src, comp, 0, 0, src_x as i16, src_y as i16,
+                   bsize, bsize, 0, 0, 0, interp);
+        if (sy & 7) != 0 {
+            let foff = (8 - (sy & 7)) as usize;
+            let off = (pre + foff) * tmp_buf.stride[comp];
+            vp31_loop_filter(tmp_buf.data, off, tmp_buf.stride[comp], 1, bsize, loop_str);
+        }
+        if (sx & 7) != 0 {
+            let foff = (8 - (sx & 7)) as usize;
+            let off = pre + foff;
+            vp31_loop_filter(tmp_buf.data, off, 1, tmp_buf.stride[comp], bsize, loop_str);
+        }
+    }
+    let dxoff = (pre as i16) - (dx as i16);
+    let dyoff = (pre as i16) - (dy as i16);
+    copy_block(dst, mc_buf, comp, dx, dy, dxoff, dyoff, 8, 8, preborder, postborder, 0/* mode*/, interp);
+}