]> git.nihav.org Git - nihav.git/blobdiff - nihav-core/src/codecs/blockdsp.rs
core/blockdsp: add copy_block()
[nihav.git] / nihav-core / src / codecs / blockdsp.rs
index 33d682afeb860d980cc6ba95def16367b8dd06fc..5ffb212b0b59695a0410a88651b738f519a1b513 100644 (file)
@@ -8,18 +8,18 @@ pub fn put_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[
     let mut idxu = buf.get_offset(1) + xpos *  8 + ypos *  8 * strideu;
     let mut idxv = buf.get_offset(2) + xpos *  8 + ypos *  8 * stridev;
 
-    let mut data = buf.get_data_mut();
+    let data = buf.get_data_mut().unwrap();
     let framebuf: &mut [u8] = data.as_mut_slice();
 
     for j in 0..8 {
         for k in 0..8 {
             let mut v = blk[0][k + j * 8];
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxy + k] = v as u8;
         }
         for k in 0..8 {
             let mut v = blk[1][k + j * 8];
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxy + k + 8] = v as u8;
         }
         idxy += stridey;
@@ -27,12 +27,12 @@ pub fn put_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[
     for j in 0..8 {
         for k in 0..8 {
             let mut v = blk[2][k + j * 8];
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxy + k] = v as u8;
         }
         for k in 0..8 {
             let mut v = blk[3][k + j * 8];
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxy + k + 8] = v as u8;
         }
         idxy += stridey;
@@ -41,12 +41,12 @@ pub fn put_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[
     for j in 0..8 {
         for k in 0..8 {
             let mut v = blk[4][k + j * 8];
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxu + k] = v as u8;
         }
         for k in 0..8 {
             let mut v = blk[5][k + j * 8];
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxv + k] = v as u8;
         }
         idxu += strideu;
@@ -62,31 +62,31 @@ pub fn add_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[
     let mut idxu = buf.get_offset(1) + xpos *  8 + ypos *  8 * strideu;
     let mut idxv = buf.get_offset(2) + xpos *  8 + ypos *  8 * stridev;
 
-    let mut data = buf.get_data_mut();
+    let data = buf.get_data_mut().unwrap();
     let framebuf: &mut [u8] = data.as_mut_slice();
 
     for j in 0..8 {
         for k in 0..8 {
-            let mut v = blk[0][k + j * 8] + (framebuf[idxy + k] as i16);
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            let mut v = blk[0][k + j * 8] + i16::from(framebuf[idxy + k]);
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxy + k] = v as u8;
         }
         for k in 0..8 {
-            let mut v = blk[1][k + j * 8] + (framebuf[idxy + k + 8] as i16);
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            let mut v = blk[1][k + j * 8] + i16::from(framebuf[idxy + k + 8]);
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxy + k + 8] = v as u8;
         }
         idxy += stridey;
     }
     for j in 0..8 {
         for k in 0..8 {
-            let mut v = blk[2][k + j * 8] + (framebuf[idxy + k] as i16);
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            let mut v = blk[2][k + j * 8] + i16::from(framebuf[idxy + k]);
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxy + k] = v as u8;
         }
         for k in 0..8 {
-            let mut v = blk[3][k + j * 8] + (framebuf[idxy + k + 8] as i16);
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            let mut v = blk[3][k + j * 8] + i16::from(framebuf[idxy + k + 8]);
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxy + k + 8] = v as u8;
         }
         idxy += stridey;
@@ -94,13 +94,13 @@ pub fn add_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[
 
     for j in 0..8 {
         for k in 0..8 {
-            let mut v = blk[4][k + j * 8] + (framebuf[idxu + k] as i16);
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            let mut v = blk[4][k + j * 8] + i16::from(framebuf[idxu + k]);
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxu + k] = v as u8;
         }
         for k in 0..8 {
-            let mut v = blk[5][k + j * 8] + (framebuf[idxv + k] as i16);
-            if v < 0 { v = 0; } if v > 255 { v = 255; }
+            let mut v = blk[5][k + j * 8] + i16::from(framebuf[idxv + k]);
+            if v < 0 { v = 0; } else if v > 255 { v = 255; }
             framebuf[idxv + k] = v as u8;
         }
         idxu += strideu;
@@ -131,10 +131,12 @@ pub fn edge_emu(src: &NAVideoBuffer<u8>, xpos: isize, ypos: isize, bw: usize, bh
     }
 }
 
+pub type BlkInterpFunc = fn(&mut [u8], usize, &[u8], usize, usize, usize);
+
 pub fn copy_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>,
                    dx: usize, dy: usize, sx: isize, sy: isize, bw: usize, bh: usize,
                    preborder: usize, postborder: usize,
-                   mode: usize, interp: &[fn(&mut [u8], usize, &[u8], usize, usize, usize)])
+                   mode: usize, interp: &[BlkInterpFunc])
 {
     let pre  = if mode != 0 { preborder  as isize } else { 0 };
     let post = if mode != 0 { postborder as isize } else { 0 };
@@ -143,13 +145,12 @@ pub fn copy_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>,
     if (sx - pre < 0) || ((sx >> 1) - pre < 0) || (sx + (bw as isize) + post > (w as isize)) ||
        (sy - pre < 0) || ((sy >> 1) - pre < 0) || (sy + (bh as isize) + post > (h as isize)) {
         let ebuf_stride: usize = 32;
-        let mut ebuf: Vec<u8> = Vec::with_capacity(ebuf_stride * (bh + ((pre + post) as usize)));
-        ebuf.resize((((pre + post) as usize) + bh) * ebuf_stride, 0);
+        let mut ebuf: Vec<u8> = vec![0; ebuf_stride * (bh + ((pre + post) as usize))];
 
         for comp in 0..3 {
             let dstride = dst.get_stride(comp);
             let doff    = dst.get_offset(comp);
-            let mut ddta    = dst.get_data_mut();
+            let ddta    = dst.get_data_mut().unwrap();
             let dbuf: &mut [u8] = ddta.as_mut_slice();
             let x   = if comp > 0 { dx/2 } else { dx };
             let y   = if comp > 0 { dy/2 } else { dy };
@@ -171,7 +172,7 @@ pub fn copy_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>,
             let sbuf: &[u8] = sdta.as_slice();
             let dstride = dst.get_stride(comp);
             let doff    = dst.get_offset(comp);
-            let mut ddta    = dst.get_data_mut();
+            let ddta    = dst.get_data_mut().unwrap();
             let dbuf: &mut [u8] = ddta.as_mut_slice();
             let x   = if comp > 0 { dx/2 } else { dx };
             let y   = if comp > 0 { dy/2 } else { dy };
@@ -183,3 +184,39 @@ pub fn copy_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>,
         }
     }
 }
+
+pub fn copy_block(dst: &mut NASimpleVideoFrame<u8>, src: NAVideoBufferRef<u8>, comp: usize,
+                  dx: usize, dy: usize, mv_x: i16, mv_y: i16, bw: usize, bh: usize,
+                  preborder: usize, postborder: usize,
+                  mode: usize, interp: &[BlkInterpFunc])
+{
+    let pre  = if mode != 0 { preborder  as isize } else { 0 };
+    let post = if mode != 0 { postborder as isize } else { 0 };
+    let (w, h) = src.get_dimensions(comp);
+    let sx = (dx as isize) + (mv_x as isize);
+    let sy = (dy as isize) + (mv_y as isize);
+
+    if (sx - pre < 0) || (sx + (bw as isize) + post > (w as isize)) ||
+       (sy - pre < 0) || (sy + (bh as isize) + post > (h as isize)) {
+        let ebuf_stride: usize = 32;
+        let mut ebuf: Vec<u8> = vec![0; ebuf_stride * (bh + ((pre + post) as usize))];
+
+        let dstride = dst.stride[comp];
+        let doff    = dst.offset[comp];
+        let edge = (pre + post) as usize;
+        edge_emu(&src, sx - pre, sy - pre, bw + edge, bh + edge,
+                 ebuf.as_mut_slice(), ebuf_stride, comp);
+        (interp[mode])(&mut dst.data[doff + dx + dy * dstride..], dstride,
+                       ebuf.as_slice(), ebuf_stride, bw, bh);
+    } else {
+        let sstride = src.get_stride(comp);
+        let soff    = src.get_offset(comp);
+        let sdta    = src.get_data();
+        let sbuf: &[u8] = sdta.as_slice();
+        let dstride = dst.stride[comp];
+        let doff    = dst.offset[comp];
+        let saddr = soff + ((sx - pre) as usize) + ((sy - pre) as usize) * sstride;
+        (interp[mode])(&mut dst.data[doff + dx + dy * dstride..], dstride,
+                       &sbuf[saddr..], sstride, bw, bh);
+    }
+}