]> git.nihav.org Git - nihav.git/commitdiff
nihav_indeo: rewrite some bits of Indeo 4/5 using more modern Rust master
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 30 May 2026 10:15:00 +0000 (12:15 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 30 May 2026 10:15:00 +0000 (12:15 +0200)
nihav-indeo/src/codecs/indeo4.rs
nihav-indeo/src/codecs/indeo5.rs
nihav-indeo/src/codecs/ivibr.rs
nihav-indeo/src/codecs/ividsp.rs

index c403313afd1e4db03d5ffb3704d61db426584b60..6dd20ecc2fd143ade386bb667ab36d5d145a9fe8 100644 (file)
@@ -6,26 +6,13 @@ use nihav_codec_support::codecs::ZIGZAG;
 use super::ivi::*;
 use super::ivibr::*;
 
-#[inline(always)]
-fn mclip8(a: i32) -> u8 {
-    if (a as u16) > 255 { !(a >> 16) as u8 }
-    else { a as u8 }
-}
-
 struct Indeo4Parser {
     mb_cb:          IVICodebook,
     blk_cb:         IVICodebook,
 }
 
 fn calc_quant(glob_q: u32, qd: i16) -> u8 {
-    let q = (glob_q as i16) + qd;
-    if q < 0 {
-        0
-    } else if q > 31 {
-        31
-    } else {
-        q as u8
-    }
+    ((glob_q as i16) + qd).clamp(0, 31) as u8
 }
 
 impl Indeo4Parser {
@@ -309,81 +296,23 @@ impl IndeoXParser for Indeo4Parser {
     }
 
     fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) {
-/*        let mut idx0 = 0;
-        let mut idx1 = w / 2;
-        let mut idx2 = (h / 2) * sstride;
-        let mut idx3 = idx2 + idx1;
-        let mut oidx0 = 0;
-        let mut oidx1 = dstride;
-
-        for _ in 0..(h/2) {
-            for x in 0..(w/2) {
-                let p0 = src[idx0 + x];
-                let p1 = src[idx1 + x];
-                let p2 = src[idx2 + x];
-                let p3 = src[idx3 + x];
+        let (first, second) = src.split_at(sstride * (h / 2));
+        for (dstrip, (line0, line1)) in dst.chunks_exact_mut(dstride * 2)
+                .zip(first.chunks_exact(sstride).zip(second.chunks_exact(sstride))) {
+            let (dline0, dline1) = dstrip.split_at_mut(dstride);
+            let (h00, h01) = line0.split_at(w / 2);
+            let (h10, h11) = line1.split_at(w / 2);
+            for ((dst0, dst1), ((&p0, &p1), (&p2, &p3))) in dline0.chunks_exact_mut(2)
+                    .zip(dline1.chunks_exact_mut(2))
+                    .zip(h00.iter().zip(h01.iter()).zip(h10.iter().zip(h11.iter()))) {
                 let s0 = p0 + p2;
                 let d0 = p0 - p2;
                 let s1 = p1 + p3;
                 let d1 = p1 - p3;
-                dst[oidx0 + x * 2 + 0] = clip8(((s0 + s1 + 2) >> 2) + 128);
-                dst[oidx0 + x * 2 + 1] = clip8(((d0 + d1 + 2) >> 2) + 128);
-                dst[oidx1 + x * 2 + 0] = clip8(((s0 - s1 + 2) >> 2) + 128);
-                dst[oidx1 + x * 2 + 1] = clip8(((d0 - d1 + 2) >> 2) + 128);
-            }
-            idx0 += sstride;
-            idx1 += sstride;
-            idx2 += sstride;
-            idx3 += sstride;
-            oidx0 += dstride * 2;
-            oidx1 += dstride * 2;
-        }*/
-        unsafe {
-            let hw = (w / 2) as isize;
-            let hh = (h / 2) as isize;
-            let mut band0 = src.as_ptr();
-            let mut band1 = band0.offset(hw);
-            let mut band2 = band0.add((h / 2) * sstride);
-            let mut band3 = band2.offset(hw);
-            let mut dst0 = dst.as_mut_ptr();
-            let mut dst1 = dst0.add(dstride);
-            for _ in 0..hh {
-                let mut b0_ptr = band0;
-                let mut b1_ptr = band1;
-                let mut b2_ptr = band2;
-                let mut b3_ptr = band3;
-                let mut d0_ptr = dst0;
-                let mut d1_ptr = dst1;
-                for _ in 0..hw {
-                    let p0 = i32::from(*b0_ptr);
-                    let p1 = i32::from(*b1_ptr);
-                    let p2 = i32::from(*b2_ptr);
-                    let p3 = i32::from(*b3_ptr);
-                    let s0 = p0.wrapping_add(p2);
-                    let s1 = p1.wrapping_add(p3);
-                    let d0 = p0.wrapping_sub(p2);
-                    let d1 = p1.wrapping_sub(p3);
-                    let o0 = s0.wrapping_add(s1).wrapping_add(2);
-                    let o1 = d0.wrapping_add(d1).wrapping_add(2);
-                    let o2 = s0.wrapping_sub(s1).wrapping_add(2);
-                    let o3 = d0.wrapping_sub(d1).wrapping_add(2);
-                    *d0_ptr.offset(0) = mclip8((o0 >> 2).wrapping_add(128));
-                    *d0_ptr.offset(1) = mclip8((o1 >> 2).wrapping_add(128));
-                    *d1_ptr.offset(0) = mclip8((o2 >> 2).wrapping_add(128));
-                    *d1_ptr.offset(1) = mclip8((o3 >> 2).wrapping_add(128));
-                    b0_ptr = b0_ptr.offset(1);
-                    b1_ptr = b1_ptr.offset(1);
-                    b2_ptr = b2_ptr.offset(1);
-                    b3_ptr = b3_ptr.offset(1);
-                    d0_ptr = d0_ptr.offset(2);
-                    d1_ptr = d1_ptr.offset(2);
-                }
-                band0 = band0.add(sstride);
-                band1 = band1.add(sstride);
-                band2 = band2.add(sstride);
-                band3 = band3.add(sstride);
-                dst0 = dst0.add(dstride * 2);
-                dst1 = dst1.add(dstride * 2);
+                dst0[0] = clip8(((s0 + s1 + 2) >> 2) + 128);
+                dst0[1] = clip8(((d0 + d1 + 2) >> 2) + 128);
+                dst1[0] = clip8(((s0 - s1 + 2) >> 2) + 128);
+                dst1[1] = clip8(((d0 - d1 + 2) >> 2) + 128);
             }
         }
     }
index 4f0887d000e06157bc5d780eb93b1d17cbca2661..add682650e688c64fc310c33e2060c061e987f87 100644 (file)
@@ -7,14 +7,7 @@ use super::ivi::*;
 use super::ivibr::*;
 
 fn calc_quant(glob_q: u32, qd: i16) -> usize {
-    let qq = (glob_q as i16) + qd;
-    if qq < 0 {
-        0
-    } else if qq > 23 {
-        23
-    } else {
-        qq as usize
-    }
+    ((glob_q as i16) + qd).clamp(0, 23) as usize
 }
 
 struct Indeo5Parser {
index 89cd4bf84ba7413567d9c4abd080fdf7e56e2929..f820f4aeef1e0b1903ee16cdd773388439d6fc5a 100644 (file)
@@ -1,6 +1,6 @@
 use std::mem;
 use nihav_core::io::bitreader::*;
-//use io::intcode::*;
+//use nihav_core::io::intcode::*;
 use nihav_core::codecs::*;
 use nihav_core::frame::NABufferRef;
 use super::ivi::*;
@@ -31,18 +31,6 @@ impl IVICodebook {
 
 pub const IVI_CB_ZERO: IVICodebook = IVICodebook { len: 0, bits: [0; 16], offs: [0; 16] };
 
-const IVI_REV0: [u32; 1] = [0];
-const IVI_REV1: [u32; 2] = [0, 1];
-const IVI_REV2: [u32; 4] = [0, 2, 1, 3];
-const IVI_REV3: [u32; 8] = [0, 4, 2, 6, 1, 5, 3, 7];
-const IVI_REV4: [u32; 16] = [ 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15];
-const IVI_REV5: [u32; 32] = [ 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31];
-const IVI_REV6: [u32; 64] = [ 0, 32, 16, 48, 8, 40, 24, 56, 4, 36, 20, 52, 12, 44, 28, 60, 2, 34, 18, 50, 10, 42, 26, 58, 6, 38, 22, 54, 14, 46, 30, 62, 1, 33, 17, 49, 9, 41, 25, 57, 5, 37, 21, 53, 13, 45, 29, 61, 3, 35, 19, 51, 11, 43, 27, 59, 7, 39, 23, 55, 15, 47, 31, 63];
-const IVI_REV7: [u32; 128] = [ 0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120, 4, 68, 36, 100, 20, 84, 52, 116, 12, 76, 44, 108, 28, 92, 60, 124, 2, 66, 34, 98, 18, 82, 50, 114, 10, 74, 42, 106, 26, 90, 58, 122, 6, 70, 38, 102, 22, 86, 54, 118, 14, 78, 46, 110, 30, 94, 62, 126, 1, 65, 33, 97, 17, 81, 49, 113, 9, 73, 41, 105, 25, 89, 57, 121, 5, 69, 37, 101, 21, 85, 53, 117, 13, 77, 45, 109, 29, 93, 61, 125, 3, 67, 35, 99, 19, 83, 51, 115, 11, 75, 43, 107, 27, 91, 59, 123, 7, 71, 39, 103, 23, 87, 55, 119, 15, 79, 47, 111, 31, 95, 63, 127];
-const IVI_REV8: [u32; 256] = [ 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255];
-
-const IVI_REVS: [&[u32]; 9] = [ &IVI_REV0, &IVI_REV1, &IVI_REV2, &IVI_REV3, &IVI_REV4, &IVI_REV5, &IVI_REV6, &IVI_REV7, &IVI_REV8];
-
 pub trait IVICodebookReader {
     fn read_ivi_codebook_desc(&mut self, mb_cb: bool, try_default: bool) -> DecoderResult<IVICodebook>;
     fn read_ivi_cb(&mut self, cb: &IVICodebook) -> BitReaderResult<u32>;
@@ -98,11 +86,11 @@ impl<'a> IVICodebookReader for BitReader<'a> {
             let nbits = cb.bits[pfx];
             let base = cb.offs[pfx];
             let rval = self.read(nbits)?;
-            let add = IVI_REVS[nbits as usize][rval as usize];
+            let add = reverse_bits(rval, nbits);
             Ok(base + add)
         } else {
             let nbits = cb.bits[0];
-            Ok(IVI_REVS[nbits as usize][self.read(nbits)? as usize])
+            Ok(reverse_bits(self.read(nbits)?, nbits))
         }
     }
     #[inline(always)]
@@ -173,7 +161,8 @@ fn read_trans_band_header(br: &mut BitReader, w: usize, h: usize, dst: &mut [i16
     cb = cb.init();
     br.align();
 
-let tile_start = br.tell();
+    let tile_start = br.tell();
+
     let empty = br.read_bool()?;
     if !empty {
         br.read_bool()?;
@@ -182,7 +171,8 @@ let tile_start = br.tell();
            len = br.read(24)? as usize;
         }
         br.align();
-let tile_end = tile_start + len * 8;
+
+        let tile_end = tile_start + len * 8;
 
         let first_val = br.read_bool()?;
 
@@ -226,7 +216,6 @@ let tile_end = tile_start + len * 8;
     Ok(())
 }
 
-#[allow(clippy::collapsible_else_if)]
 fn decode_block8x8(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tables: &TxParams8x8, is_intra: bool, is_2d: bool, prev_dc: &mut i32, quant: u8, coeffs: &mut [i32; 64], transform: TrFunc) -> DecoderResult<()> {
     let mut idx: isize = -1;
     let quant_mat = if is_intra { tables.quant_intra } else { tables.quant_inter };
@@ -278,7 +267,6 @@ fn decode_block8x8(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tabl
     Ok(())
 }
 
-#[allow(clippy::collapsible_else_if)]
 fn decode_block4x4(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tables: &TxParams4x4, is_intra: bool, is_2d: bool, prev_dc: &mut i32, quant: u8, coeffs: &mut [i32; 64], transform: TrFunc) -> DecoderResult<()> {
     let mut idx: isize = -1;
     let quant_mat = if is_intra { tables.quant_intra } else { tables.quant_inter };
@@ -299,10 +287,11 @@ fn decode_block4x4(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tabl
             if v == 0 {
                 val = 0; // should not happen but still...
             } else {
+                let vv = (v >> 1) as i32;
                 if (v & 1) != 0 {
-                    val = ((v >> 1) as i32) + 1;
+                    val = vv + 1;
                 } else {
-                    val = -((v >> 1) as i32);
+                    val = -vv;
                 }
             }
         }
@@ -330,25 +319,17 @@ fn decode_block4x4(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tabl
 }
 
 fn put_block(frame: &mut [i16], offs: usize, stride: usize, blk: &[i32], blk_size: usize) {
-    unsafe {
-        let mut dptr = frame.as_mut_ptr().add(offs);
-        for y in 0..blk_size {
-            for x in 0..blk_size {
-                *dptr.add(x) = blk[x + y * blk_size] as i16;
-            }
-            dptr = dptr.add(stride);
+    for (dline, row) in frame[offs..].chunks_mut(stride).zip(blk.chunks(blk_size)).take(blk_size) {
+        for (dst, &src) in dline.iter_mut().zip(row.iter()) {
+            *dst = src as i16;
         }
     }
 }
 
 fn add_block(frame: &mut [i16], offs: usize, stride: usize, blk: &[i32], blk_size: usize) {
-    unsafe {
-        let mut dptr = frame.as_mut_ptr().add(offs);
-        for y in 0..blk_size {
-            for x in 0..blk_size {
-                *dptr.add(x) = (*dptr.add(x)).wrapping_add(blk[x + y * blk_size] as i16);
-            }
-            dptr = dptr.add(stride);
+    for (dline, row) in frame[offs..].chunks_mut(stride).zip(blk.chunks(blk_size)).take(blk_size) {
+        for (dst, &src) in dline.iter_mut().zip(row.iter()) {
+            *dst = dst.wrapping_add(src as i16);
         }
     }
 }
@@ -393,18 +374,15 @@ impl FrameData {
     fn fill_plane(&mut self, vb: &mut NAVideoBuffer<u8>, plane: usize) {
         let dplane = if (plane == 1) || (plane == 2) { plane ^ 3 } else { plane };
         let (w, h)   = vb.get_dimensions(dplane);
-        let mut didx = vb.get_offset(dplane);
+        let didx     = vb.get_offset(dplane);
         let dstride  = vb.get_stride(dplane);
         let dst      = vb.get_data_mut().unwrap();
         let src      = &self.plane_buf[plane];
-        let mut sidx = 0;
         let sstride  = self.plane_stride[plane];
-        for _ in 0..h {
-            for x in 0..w {
-                dst[didx + x] = clip8(src[sidx + x] + 128);
+        for (dline, sline) in dst[didx..].chunks_mut(dstride).zip(src.chunks_exact(sstride)).take(h) {
+            for (dst, &src) in dline.iter_mut().zip(sline.iter()).take(w) {
+                *dst = clip8(src + 128);
             }
-            didx += dstride;
-            sidx += sstride;
         }
     }
 }
@@ -608,7 +586,7 @@ impl IVIDecoder {
                 validate!(tile_end > br.tell());
                 validate!(tile_end <= br.tell() + (br.left() as usize));
                 {
-                    let ref_tile: Option<&IVITile>;
+                    let mut ref_tile: Option<&IVITile> = None;
                     let mv_scale = if (plane_no == 0) && (band_no == 0) { 0 } else {
                             (((self.bands[0].mb_size >> 3) as i8) - ((band.mb_size >> 3) as i8)) as u8
                         };
@@ -616,21 +594,18 @@ impl IVIDecoder {
                     let tile = &mut cur_tiles[0];
                     if plane_no != 0 || band_no != 0 {
                         let rtile = &ref_tiles[tile_no % self.band_tiles];
-                        if (tile.mb_w != rtile.mb_w) || (tile.mb_h != rtile.mb_h) {
-                            ref_tile = None;
-                        } else {
+                        if (tile.mb_w == rtile.mb_w) && (tile.mb_h == rtile.mb_h) {
                             ref_tile = Some(rtile);
                         }
-                    } else {
-                        ref_tile = None;
                     }
                     dec.decode_mb_info(br, pic_hdr, &band, tile, ref_tile, mv_scale)?;
                 }
 
                 self.decode_tile(br, &band, tile_no, tr, tr_dc)?;
                 br.align();
-let skip_part = tile_end - br.tell();
-br.skip(skip_part as u32)?;
+
+                let skip_part = tile_end - br.tell();
+                br.skip(skip_part as u32)?;
             } else {
                 {
                     let ref_tile: Option<&IVITile>;
index 8a19391449a748939333a06fb8ebe9395c2373b5..36cad587756b6acf4df6c860d89953e48a2c0fcd 100644 (file)
@@ -304,96 +304,34 @@ pub fn ivi_get_transform4x4_funcs(ttype: IVITransformType) -> (TrFunc, TrFuncDC)
 }
 
 pub fn ivi_mc_put(dst: &mut [i16], dstride: usize, src: &[i16], sstride: usize, mode: u8, w: usize, h: usize) {
-    let mut sidx = 0;
-    let mut didx = 0;
     if src.len() < w + h * sstride { return; }
     match mode {
         0 => {
-            for _ in 0..h {
-                let dest = &mut dst[didx..didx+w];
-                dest.copy_from_slice(&src[sidx..sidx+w]);
-                sidx += sstride;
-                didx += dstride;
+            for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(h) {
+                dline[..w].copy_from_slice(&sline[..w]);
             }
         },
         1 => {
-            /*for _ in 0..h {
-                for x in 0..w {
-                    let val = (src[sidx + x] + src[sidx + x + 1]) >> 1;
-                    dst[didx + x] = val;
-                }
-                sidx += sstride;
-                didx += dstride;
-            }*/
-            unsafe {
-                let mut sptr = src.as_ptr();
-                let mut dptr = dst.as_mut_ptr();
-                for _ in 0..h {
-                    let mut last = *sptr;
-                    for x in 0..w {
-                        let nv = *sptr.add(x + 1);
-                        *dptr.add(x) = nv.wrapping_add(last) >> 1;
-                        last = nv;
-                    }
-                    sptr = sptr.add(sstride);
-                    dptr = dptr.add(dstride);
+            for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(h) {
+                for (dpix, pair) in dline.iter_mut().zip(sline.windows(2)).take(w) {
+                    *dpix = (pair[0] + pair[1]) >> 1;
                 }
             }
         },
         2 => {
-            /*for _ in 0..h {
-                for x in 0..w {
-                    let val = (src[sidx + x] + src[sidx + x + sstride]) >> 1;
-                    dst[didx + x] = val;
-                }
-                sidx += sstride;
-                didx += dstride;
-            }*/
-            unsafe {
-                let mut sptr0 = src.as_ptr();
-                let mut sptr1 = sptr0.add(sstride);
-                let mut dptr = dst.as_mut_ptr();
-                for _ in 0..h {
-                    for x in 0..w {
-                        let a = *sptr0.add(x);
-                        let b = *sptr1.add(x);
-                        *dptr.add(x) = a.wrapping_add(b) >> 1;
-                    }
-                    sptr0 = sptr0.add(sstride);
-                    sptr1 = sptr1.add(sstride);
-                    dptr = dptr.add(sstride);
+            for (dline, (sline0, sline1)) in dst.chunks_mut(dstride)
+                    .zip(src.chunks(sstride).zip(src.chunks(sstride).skip(1))).take(h) {
+                for (dpix, (&s0, &s1)) in dline.iter_mut().zip(sline0.iter().zip(sline1.iter())).take(w) {
+                    *dpix = (s0 + s1) >> 1;
                 }
             }
         },
         3 => {
-            /*for _ in 0..h {
-                for x in 0..w {
-                    let val = (src[sidx + x + 0] + src[sidx + x + sstride + 0] +
-                               src[sidx + x + 1] + src[sidx + x + sstride + 1]) >> 2;
-                    dst[didx + x] = val;
-                }
-                sidx += sstride;
-                didx += dstride;
-            }*/
-            unsafe {
-                let mut sptr0 = src.as_ptr();
-                let mut sptr1 = sptr0.add(sstride);
-                let mut dptr = dst.as_mut_ptr();
-                for _ in 0..h {
-                    let mut la = *sptr0;
-                    let mut lb = *sptr1;
-                    for x in 0..w {
-                        let a = *sptr0.add(x + 1);
-                        let b = *sptr1.add(x + 1);
-                        let aas = a.wrapping_add(la);
-                        let bbs = b.wrapping_add(lb);
-                        *dptr.add(x) = aas.wrapping_add(bbs) >> 2;
-                        la = a;
-                        lb = b;
-                    }
-                    sptr0 = sptr0.add(sstride);
-                    sptr1 = sptr1.add(sstride);
-                    dptr = dptr.add(dstride);
+            for (dline, (sline0, sline1)) in dst.chunks_mut(dstride)
+                    .zip(src.chunks(sstride).zip(src.chunks(sstride).skip(1))).take(h) {
+                for (dpix, (pair0, pair1)) in dline.iter_mut()
+                        .zip(sline0.windows(2).zip(sline1.windows(2))).take(w) {
+                    *dpix = (pair0[0] + pair0[1] + pair1[0] + pair1[1]) >> 2;
                 }
             }
         },
@@ -401,47 +339,36 @@ pub fn ivi_mc_put(dst: &mut [i16], dstride: usize, src: &[i16], sstride: usize,
     }
 }
 fn ivi_mc_add(dst: &mut [i16], dstride: usize, src: &[i16], sstride: usize, mode: u8, w: usize, h: usize) {
-    let mut sidx = 0;
-    let mut didx = 0;
     match mode {
         0 => {
-            for _ in 0..h {
-                for x in 0..w {
-                    dst[didx + x] += src[sidx + x];
+            for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(h) {
+                for (dst, &src) in dline.iter_mut().zip(sline.iter()).take(w) {
+                    *dst += src;
                 }
-                sidx += sstride;
-                didx += dstride;
             }
         },
         1 => {
-            for _ in 0..h {
-                for x in 0..w {
-                    let val = (src[sidx + x] + src[sidx + x + 1]) >> 1;
-                    dst[didx + x] += val;
+            for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(h) {
+                for (dpix, pair) in dline.iter_mut().zip(sline.windows(2)).take(w) {
+                    *dpix += (pair[0] + pair[1]) >> 1;
                 }
-                sidx += sstride;
-                didx += dstride;
             }
         },
         2 => {
-            for _ in 0..h {
-                for x in 0..w {
-                    let val = (src[sidx + x] + src[sidx + x + sstride]) >> 1;
-                    dst[didx + x] += val;
+            for (dline, (sline0, sline1)) in dst.chunks_mut(dstride)
+                    .zip(src.chunks(sstride).zip(src.chunks(sstride).skip(1))).take(h) {
+                for (dpix, (&s0, &s1)) in dline.iter_mut().zip(sline0.iter().zip(sline1.iter())).take(w) {
+                    *dpix += (s0 + s1) >> 1;
                 }
-                sidx += sstride;
-                didx += dstride;
             }
         },
         3 => {
-            for _ in 0..h {
-                for x in 0..w {
-                    let val = (src[sidx + x + 0] + src[sidx + x + sstride + 0] +
-                               src[sidx + x + 1] + src[sidx + x + sstride + 1]) >> 2;
-                    dst[didx + x] += val;
+            for (dline, (sline0, sline1)) in dst.chunks_mut(dstride)
+                    .zip(src.chunks(sstride).zip(src.chunks(sstride).skip(1))).take(h) {
+                for (dpix, (pair0, pair1)) in dline.iter_mut()
+                        .zip(sline0.windows(2).zip(sline1.windows(2))).take(w) {
+                    *dpix += (pair0[0] + pair0[1] + pair1[0] + pair1[1]) >> 2;
                 }
-                sidx += sstride;
-                didx += dstride;
             }
         },
         _ => {},
@@ -451,15 +378,13 @@ pub fn ivi_mc_avg(dst: &mut [i16], dstride: usize,
                   src1: &[i16], sstride1: usize, mode1: u8,
                   src2: &[i16], sstride2: usize, mode2: u8,
                   w: usize, h: usize) {
-    let mut tidx = 0;
-    let tstride = 8;
-    let mut didx = 0;
-    let mut tmp: [i16; 64] = [0; 64];
-    ivi_mc_add(&mut tmp, tstride, src1, sstride1, mode1, w, h);
-    ivi_mc_add(&mut tmp, tstride, src2, sstride2, mode2, w, h);
-    for _ in 0..h {
-       for x in 0..w { dst[didx + x] = tmp[tidx + x] >> 1; }
-       tidx += tstride;
-       didx += dstride;
+    const TSTRIDE: usize = 8;
+    let mut tmp: [i16; 8 * TSTRIDE] = [0; 8 * TSTRIDE];
+    ivi_mc_add(&mut tmp, TSTRIDE, src1, sstride1, mode1, w, h);
+    ivi_mc_add(&mut tmp, TSTRIDE, src2, sstride2, mode2, w, h);
+    for (dline, row) in dst.chunks_mut(dstride).zip(tmp.chunks_exact(TSTRIDE)).take(h) {
+        for (dpix, &src) in dline.iter_mut().zip(row.iter()).take(w) {
+            *dpix = src >> 1;
+        }
     }
 }