diff --git a/crates/h264/src/inter.rs b/crates/h264/src/inter.rs
--- a/crates/h264/src/inter.rs
+++ b/crates/h264/src/inter.rs
@@ -72,21 +72,41 @@ fn avg(a: u8, b: u8) -> u8 {
     ((a as u16 + b as u16 + 1) >> 1) as u8
 }
 
-/// Horizontal 6-tap (unclipped) at every position of `row` for `n` outputs: out[c] uses row[c..c + 6].
+/// 6-tap filter in i16: the unclipped result of a first pass lies in -2550..=10710.
 #[inline(always)]
-fn htap_row(row: &[u8], out: &mut [i32], n: usize) {
-    let row = &row[..n + 5];
-    for (o, w) in out[..n].iter_mut().zip(row.windows(6)) {
-        *o = tap6(w[0] as i32, w[1] as i32, w[2] as i32, w[3] as i32, w[4] as i32, w[5] as i32);
+fn tap6_16(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> i16 {
+    let [a, b, c, d, e, f] = [a, b, c, d, e, f].map(i16::from);
+    a - 5 * b + 20 * c + 20 * d - 5 * e + f
+}
+
+/// Round and clip a first-pass value: Clip1((v + 16) >> 5).
+#[inline(always)]
+fn round5(v: i16) -> u8 {
+    ((v + 16) >> 5).clamp(0, 255) as u8
+}
+
+/// Horizontal 6-tap (unclipped) for `BW` outputs: out[c] uses row[c..c + 6].
+#[inline(always)]
+fn htap_row<const BW: usize>(row: &[u8], out: &mut [i16; 16]) {
+    let row = &row[..BW + 5];
+    for c in 0..BW {
+        out[c] = tap6_16(row[c], row[c + 1], row[c + 2], row[c + 3], row[c + 4], row[c + 5]);
+    }
+}
+
+/// Vertical 6-tap (unclipped) over six rows at columns 0..BW.
+#[inline(always)]
+fn vtap_row<const BW: usize>(rows: [&[u8]; 6], out: &mut [i16; 16]) {
+    let [a, b, c, d, e, f] = rows.map(|r| &r[..BW]);
+    for i in 0..BW {
+        out[i] = tap6_16(a[i], b[i], c[i], d[i], e[i], f[i]);
     }
 }
 
-/// Vertical 6-tap (unclipped) over six rows at columns 0..n.
 #[inline(always)]
-fn vtap_row(rows: [&[u8]; 6], out: &mut [i32], n: usize) {
-    let [a, b, c, d, e, f] = rows.map(|r| &r[..n]);
-    for i in 0..n {
-        out[i] = tap6(a[i] as i32, b[i] as i32, c[i] as i32, d[i] as i32, e[i] as i32, f[i] as i32);
+fn copy_fixed<const BW: usize>(dst: &mut [u8], src: &[u8]) {
+    if let (Some(d), Some(s)) = (dst.first_chunk_mut::<BW>(), src.first_chunk::<BW>()) {
+        *d = *s;
     }
 }
 
@@ -108,90 +128,90 @@ pub fn mc_luma(p: PlaneRef, x: i32, y: i32, fx: u32, fy: u32, bw: usize, bh: usi
 }
 
 /// Luma interpolation from a prepared window: `src[0]` is the sample at (x - 2, y - 2) and `ss` the
-/// window stride; the window covers (bw + 5) x (bh + 5) samples.
+/// window stride; the window covers (bw + 5) x (bh + 5) samples. `bw` is 4, 8 or 16.
 #[allow(clippy::too_many_arguments)]
 pub fn mc_luma_win(src: &[u8], ss: usize, fx: u32, fy: u32, bw: usize, bh: usize, out: &mut [u8], os: usize) {
+    match bw {
+        16 => luma_win::<16>(src, ss, fx, fy, bh, out, os),
+        8 => luma_win::<8>(src, ss, fx, fy, bh, out, os),
+        _ => luma_win::<4>(src, ss, fx, fy, bh, out, os),
+    }
+}
+
+#[inline(always)]
+fn luma_win<const BW: usize>(src: &[u8], ss: usize, fx: u32, fy: u32, bh: usize, out: &mut [u8], os: usize) {
     // window row r (0..bh+5) starts at src[r * ss]; sample G of block (r, c) is at window (r + 2, c + 2)
-    let wrow = |r: usize| &src[r * ss..r * ss + bw + 5];
-    let mut t = [0i32; 16];
+    let wrow = |r: usize| &src[r * ss..r * ss + BW + 5];
+    let rows6 = |r: usize, off: usize| [wrow(r), wrow(r + 1), wrow(r + 2), wrow(r + 3), wrow(r + 4), wrow(r + 5)].map(|x| &x[off..]);
+    let mut t = [0i16; 16];
     match (fx, fy) {
         (0, 0) => {
             for r in 0..bh {
-                copy_n(&mut out[r * os..], &wrow(r + 2)[2..], bw);
+                copy_fixed::<BW>(&mut out[r * os..], &wrow(r + 2)[2..]);
             }
         }
         (_, 0) => {
+            let g = if fx == 1 { 2 } else { 3 };
             for r in 0..bh {
                 let row = wrow(r + 2);
-                htap_row(row, &mut t, bw);
-                let o = &mut out[r * os..r * os + bw];
-                match fx {
-                    1 => {
-                        for c in 0..bw {
-                            o[c] = avg(row[c + 2], clip1((t[c] + 16) >> 5));
-                        }
-                    }
-                    2 => {
-                        for c in 0..bw {
-                            o[c] = clip1((t[c] + 16) >> 5);
-                        }
+                htap_row::<BW>(row, &mut t);
+                let o = &mut out[r * os..r * os + BW];
+                if fx == 2 {
+                    for c in 0..BW {
+                        o[c] = round5(t[c]);
                     }
-                    _ => {
-                        for c in 0..bw {
-                            o[c] = avg(row[c + 3], clip1((t[c] + 16) >> 5));
-                        }
+                } else {
+                    let g = &row[g..g + BW];
+                    for c in 0..BW {
+                        o[c] = avg(g[c], round5(t[c]));
                     }
                 }
             }
         }
         (0, _) => {
             for r in 0..bh {
-                let rows = [wrow(r), wrow(r + 1), wrow(r + 2), wrow(r + 3), wrow(r + 4), wrow(r + 5)].map(|x| &x[2..]);
-                vtap_row(rows, &mut t, bw);
-                let g = if fy == 1 { rows[2] } else { rows[3] };
-                let o = &mut out[r * os..r * os + bw];
+                let rows = rows6(r, 2);
+                vtap_row::<BW>(rows, &mut t);
+                let o = &mut out[r * os..r * os + BW];
                 if fy == 2 {
-                    for c in 0..bw {
-                        o[c] = clip1((t[c] + 16) >> 5);
+                    for c in 0..BW {
+                        o[c] = round5(t[c]);
                     }
                 } else {
-                    for c in 0..bw {
-                        o[c] = avg(g[c], clip1((t[c] + 16) >> 5));
+                    let g = &(if fy == 1 { rows[2] } else { rows[3] })[..BW];
+                    for c in 0..BW {
+                        o[c] = avg(g[c], round5(t[c]));
                     }
                 }
             }
         }
         (2, _) | (_, 2) => {
             // unclipped horizontal half samples b1 for window rows 0..bh+5
-            let mut b1 = [[0i32; 16]; WIN];
+            let mut b1 = [[0i16; 16]; WIN];
             for (r, bt) in b1.iter_mut().enumerate().take(bh + 5) {
-                htap_row(wrow(r), bt, bw);
+                htap_row::<BW>(wrow(r), bt);
             }
-            let mut v = [0i32; 16];
+            let mut j = [0u8; 16];
+            let mut v = [0i16; 16];
             for r in 0..bh {
-                let o = &mut out[r * os..r * os + bw];
-                let (b0, b1r, b2, b3, b4, b5) = (&b1[r], &b1[r + 1], &b1[r + 2], &b1[r + 3], &b1[r + 4], &b1[r + 5]);
-                for c in 0..bw {
-                    t[c] = tap6(b0[c], b1r[c], b2[c], b3[c], b4[c], b5[c]);
+                let o = &mut out[r * os..r * os + BW];
+                let [b0, b1r, b2, b3, b4, b5] = [&b1[r], &b1[r + 1], &b1[r + 2], &b1[r + 3], &b1[r + 4], &b1[r + 5]];
+                for c in 0..BW {
+                    let [a, b, cc, d, e, f] = [b0[c], b1r[c], b2[c], b3[c], b4[c], b5[c]].map(i32::from);
+                    j[c] = clip1((tap6(a, b, cc, d, e, f) + 512) >> 10);
                 }
                 match (fx, fy) {
-                    (2, 2) => {
-                        for c in 0..bw {
-                            o[c] = clip1((t[c] + 512) >> 10);
-                        }
-                    }
+                    (2, 2) => o.copy_from_slice(&j[..BW]),
                     (2, 1) | (2, 3) => {
                         let bh_ = if fy == 1 { b2 } else { b3 };
-                        for c in 0..bw {
-                            o[c] = avg(clip1((bh_[c] + 16) >> 5), clip1((t[c] + 512) >> 10));
+                        for c in 0..BW {
+                            o[c] = avg(round5(bh_[c]), j[c]);
                         }
                     }
                     _ => {
-                        let off = if fx == 1 { 2 } else { 3 };
-                        let rows = [wrow(r), wrow(r + 1), wrow(r + 2), wrow(r + 3), wrow(r + 4), wrow(r + 5)].map(|x| &x[off..]);
-                        vtap_row(rows, &mut v, bw);
-                        for c in 0..bw {
-                            o[c] = avg(clip1((v[c] + 16) >> 5), clip1((t[c] + 512) >> 10));
+                        vtap_row::<BW>(rows6(r, if fx == 1 { 2 } else { 3 }), &mut v);
+                        for c in 0..BW {
+                            o[c] = avg(round5(v[c]), j[c]);
                         }
                     }
                 }
@@ -201,14 +221,13 @@ pub fn mc_luma_win(src: &[u8], ss: usize, fx: u32, fy: u32, bw: usize, bh: usize
             // e, g, p, r: average of a horizontal half sample (row r or r + 1) and a vertical one (col c or c + 1)
             let hoff = if fy == 1 { 2 } else { 3 };
             let voff = if fx == 1 { 2 } else { 3 };
-            let mut v = [0i32; 16];
+            let mut v = [0i16; 16];
             for r in 0..bh {
-                htap_row(wrow(r + hoff), &mut t, bw);
-                let rows = [wrow(r), wrow(r + 1), wrow(r + 2), wrow(r + 3), wrow(r + 4), wrow(r + 5)].map(|x| &x[voff..]);
-                vtap_row(rows, &mut v, bw);
-                let o = &mut out[r * os..r * os + bw];
-                for c in 0..bw {
-                    o[c] = avg(clip1((t[c] + 16) >> 5), clip1((v[c] + 16) >> 5));
+                htap_row::<BW>(wrow(r + hoff), &mut t);
+                vtap_row::<BW>(rows6(r, voff), &mut v);
+                let o = &mut out[r * os..r * os + BW];
+                for c in 0..BW {
+                    o[c] = avg(round5(t[c]), round5(v[c]));
                 }
             }
         }
@@ -240,24 +259,33 @@ pub fn mc_chroma(p: PlaneRef, x: i32, y: i32, fx: u32, fy: u32, bw: usize, bh: u
 }
 
 /// Chroma interpolation from a prepared (bw + 1) x (bh + 1) window whose first sample is the integer
-/// position of the block.
+/// position of the block. `bw` is 2, 4 or 8.
 #[allow(clippy::too_many_arguments)]
 pub fn mc_chroma_win(src: &[u8], ss: usize, fx: u32, fy: u32, bw: usize, bh: usize, out: &mut [u8], os: usize) {
-    let (fx, fy) = (fx as u16, fy as u16);
-    let (w00, w10, w01, w11) = ((8 - fx) * (8 - fy), fx * (8 - fy), (8 - fx) * fy, fx * fy);
+    match bw {
+        8 => chroma_win::<8>(src, ss, fx, fy, bh, out, os),
+        4 => chroma_win::<4>(src, ss, fx, fy, bh, out, os),
+        _ => chroma_win::<2>(src, ss, fx, fy, bh, out, os),
+    }
+}
+
+#[inline(always)]
+fn chroma_win<const BW: usize>(src: &[u8], ss: usize, fx: u32, fy: u32, bh: usize, out: &mut [u8], os: usize) {
     if fx == 0 && fy == 0 {
         for r in 0..bh {
-            copy_n(&mut out[r * os..], &src[r * ss..], bw);
+            copy_fixed::<BW>(&mut out[r * os..], &src[r * ss..]);
         }
         return;
     }
+    let (fx, fy) = (fx as u16, fy as u16);
+    let (w00, w10, w01, w11) = ((8 - fx) * (8 - fy), fx * (8 - fy), (8 - fx) * fy, fx * fy);
     for r in 0..bh {
-        let r0 = &src[r * ss..r * ss + bw + 1];
-        let r1 = &src[(r + 1) * ss..(r + 1) * ss + bw + 1];
-        let o = &mut out[r * os..r * os + bw];
-        for (c, o) in o.iter_mut().enumerate() {
+        let r0 = &src[r * ss..r * ss + BW + 1];
+        let r1 = &src[(r + 1) * ss..(r + 1) * ss + BW + 1];
+        let o = &mut out[r * os..r * os + BW];
+        for c in 0..BW {
             let v = w00 * r0[c] as u16 + w10 * r0[c + 1] as u16 + w01 * r1[c] as u16 + w11 * r1[c + 1] as u16;
-            *o = ((v + 32) >> 6) as u8;
+            o[c] = ((v + 32) >> 6) as u8;
         }
     }
 }
@@ -500,6 +528,34 @@ mod tests {
         }
     }
 
+    #[test]
+    fn chroma_matches_formula() {
+        let mut seed = 11u32;
+        let src: Vec<u8> = (0..9 * 9)
+            .map(|_| {
+                seed = seed.wrapping_mul(1664525).wrapping_add(1013904223);
+                (seed >> 24) as u8
+            })
+            .collect();
+        for bw in [2, 4, 8] {
+            for bh in [2, 4, 8] {
+                for fx in 0..8 {
+                    for fy in 0..8 {
+                        let mut out = [0u8; 64];
+                        mc_chroma_win(&src, 9, fx, fy, bw, bh, &mut out, 8);
+                        for r in 0..bh {
+                            for c in 0..bw {
+                                let s = |dr: usize, dc: usize| src[(r + dr) * 9 + c + dc] as u32;
+                                let want = ((8 - fx) * (8 - fy) * s(0, 0) + fx * (8 - fy) * s(0, 1) + (8 - fx) * fy * s(1, 0) + fx * fy * s(1, 1) + 32) >> 6;
+                                assert_eq!(out[r * 8 + c] as u32, want, "{bw}x{bh} frac {fx},{fy} at {r},{c}");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     #[test]
     fn weighting() {
         let a = [100u8; 4];
diff --git a/crates/h264/src/picture.rs b/crates/h264/src/picture.rs
--- a/crates/h264/src/picture.rs
+++ b/crates/h264/src/picture.rs
@@ -302,7 +302,10 @@ fn copy_line<const N: usize>(line: &[u8], x0: i32, out: &mut [u8], w: usize) {
 }
 
 /// Copy `out.len()` samples of `line` starting at x0, replicating edge samples outside the line.
-#[inline(always)]
+/// Kept out of line so the fixed-size path of `copy_line` stays an inline move rather than being
+/// merged with this variable-length copy into a libc memcpy call.
+#[cold]
+#[inline(never)]
 fn copy_clamped(line: &[u8], x0: i32, out: &mut [u8]) {
     let w = out.len();
     if x0 >= 0 && x0 as usize + w <= line.len() {
