otf-pixels-codec-avif 0.1.0

AVIF codec for otf-pixels, implemented from scratch.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
//! The deblocking loop filter (spec §7.14).
//!
//! After a frame is reconstructed, the loop filter smooths the block and
//! transform boundaries that the semi-independent coding of super-blocks leaves
//! behind. It runs in two passes over the whole frame — every vertical boundary
//! first, then every horizontal boundary — and at each 4x4 edge decides, from
//! the transform sizes on either side and an adaptive strength derived from the
//! frame's `loop_filter` parameters, whether to apply a narrow (4-tap) or one of
//! the wide (8-/14-tap luma, 6-/8-tap chroma) low-pass filters.
//!
//! This is the still-picture intra subset: every block is intra, so the
//! `applyFilter` test reduces to "there is a transform edge here", the segment
//! id and per-block loop-filter delta are always zero, and the mode type is
//! always the intra type 0. Edges are walked in luma mode-info units; a
//! subsampled chroma plane visits every second row/column and filters at the
//! shifted plane position. The `LoopfilterTxSizes` grid is filled per plane,
//! in that plane's 4x4 units, as each transform block is reconstructed.

use super::frame::LoopFilter;
use super::plane::Plane;
use super::tile::{FRAME_LF_COUNT, MAX_SEGMENTS};
use super::transform::TxSize;

/// `MI_SIZE` (§3): the side of the smallest coded block, in samples.
const MI_SIZE: usize = 4;
/// `MAX_LOOP_FILTER` (§3).
const MAX_LOOP_FILTER: i32 = 63;

/// Everything the loop filter reads: the reconstructed planes it filters in
/// place, the frame's `loop_filter` parameters, and the per-4x4 mode-info grids
/// gathered during reconstruction. Grids are row-major, `mi_cols` wide.
pub struct Deblock<'a> {
    /// The reconstructed planes, filtered in place.
    pub planes: &'a mut [Plane],
    /// The frame's loop-filter parameters.
    pub loop_filter: &'a LoopFilter,
    /// Sample bit depth (8/10/12).
    pub bit_depth: u8,
    /// Number of planes (1 monochrome, 3 otherwise).
    pub num_planes: usize,
    /// Horizontal chroma subsampling (0 or 1).
    pub subsampling_x: usize,
    /// Vertical chroma subsampling (0 or 1).
    pub subsampling_y: usize,
    /// Frame dimensions in 4x4 units.
    pub mi_rows: usize,
    pub mi_cols: usize,
    /// Visible frame dimensions in luma samples (`FrameWidth`/`FrameHeight`).
    pub frame_width: usize,
    pub frame_height: usize,
    /// `LoopfilterTxSizes[plane][row][col]`: the transform size (a `TxSize`
    /// index) reconstructed at each 4x4 unit of the plane, one grid per plane,
    /// each `mi_cols` wide.
    pub lf_tx_sizes: &'a [Vec<u8>],
    /// `DeltaLFs[row][col]`: the per-block loop-filter deltas, all zero unless
    /// `delta_lf_present`.
    pub delta_lfs: &'a [[i8; FRAME_LF_COUNT]],
    /// `delta_lf_multi`: one delta per filter level rather than one shared.
    pub delta_lf_multi: bool,
    /// `SegmentIds[row][col]`; empty when segmentation is off.
    pub segment_ids: &'a [u8],
    /// `FeatureData[segment][SEG_LVL_ALT_LF_Y_V + i]` for active features, 0
    /// otherwise, in `loop_filter_level` order.
    pub segment_lf: [[i32; FRAME_LF_COUNT]; MAX_SEGMENTS],
}

// A full inter-capable filter would also read `Skips`, `MiSizes` (for the block
// edge test) and `YModes`/`RefFrames`/`SegmentIds` (for the strength
// derivation). In this all-intra subset those collapse to constants:
// `applyFilter` is just the transform-edge test and the strength comes from the
// frame `loop_filter` level, the block's `DeltaLFs` and the intra reference
// delta, so they are omitted.

impl Deblock<'_> {
    /// Apply the loop filter to every plane (§7.14.1): all vertical boundaries,
    /// then all horizontal, per plane. A plane with a zero filter level (which a
    /// coded-lossless frame always has) is left untouched.
    pub fn run(&mut self) {
        // Frame-level guard (libaom `av1_loop_filter_frame_init`): if both luma
        // levels are zero the whole loop filter is skipped — even though the
        // per-block intra reference delta could otherwise raise the strength
        // above zero. A coded-lossless or filters-off frame always lands here.
        let luma_vert = self.loop_filter.level.first().copied().unwrap_or(0);
        let luma_horz = self.loop_filter.level.get(1).copied().unwrap_or(0);
        if luma_vert == 0 && luma_horz == 0 {
            return;
        }
        for plane in 0..self.num_planes {
            // Y is always filtered; a chroma plane only if its level is nonzero.
            if plane != 0 && self.level_for(plane) == 0 {
                continue;
            }
            let (sub_x, sub_y) = self.plane_subsampling(plane);
            for pass in 0..2 {
                let mut row = 0;
                while row < self.mi_rows {
                    let mut col = 0;
                    while col < self.mi_cols {
                        self.filter_edge(plane, pass, row, col);
                        col += 1 << sub_x;
                    }
                    row += 1 << sub_y;
                }
            }
        }
    }

    /// `(subsampling_x, subsampling_y)` for `plane`: zero for luma.
    fn plane_subsampling(&self, plane: usize) -> (usize, usize) {
        if plane == 0 {
            (0, 0)
        } else {
            (self.subsampling_x, self.subsampling_y)
        }
    }

    /// `loop_filter_level[1 + plane]` for the chroma-plane gate.
    fn level_for(&self, plane: usize) -> u8 {
        self.loop_filter.level.get(1 + plane).copied().unwrap_or(0)
    }

    /// The transform size stored for `plane` at the plane's 4x4 unit
    /// `(row, col)`.
    fn tx_size(&self, plane: usize, row: usize, col: usize) -> TxSize {
        let idx = row * self.mi_cols + col;
        let raw = self
            .lf_tx_sizes
            .get(plane)
            .and_then(|g| g.get(idx))
            .copied()
            .unwrap_or(0);
        TxSize::from_index(usize::from(raw))
    }

    /// Edge loop filter process (§7.14.2) for the boundary at luma mode-info
    /// unit `(row, col)`.
    fn filter_edge(&mut self, plane: usize, pass: usize, row: usize, col: usize) {
        let (dx, dy) = if pass == 0 { (1_usize, 0) } else { (0, 1) };
        let (sub_x, sub_y) = self.plane_subsampling(plane);
        // x/y are luma coordinates, taken before row/col move to the unit that
        // owns the plane's samples (the odd one of a subsampled pair).
        let x = col * MI_SIZE;
        let y = row * MI_SIZE;
        let row = row | sub_y;
        let col = col | sub_x;

        // onScreen: both sides of the boundary must lie in the visible area, and
        // the frame's own top/left edge is never an interior boundary.
        if x >= self.frame_width || y >= self.frame_height {
            return;
        }
        if pass == 0 && x == 0 {
            return;
        }
        if pass == 1 && y == 0 {
            return;
        }

        // The boundary's position in the plane.
        let xp = x >> sub_x;
        let yp = y >> sub_y;
        let tx_sz = self.tx_size(plane, row >> sub_y, col >> sub_x);
        let tx_w = tx_sz.width();
        let tx_h = tx_sz.height();

        // The mode-info block on the other side of the boundary.
        let (prev_row, prev_col) = if pass == 0 {
            (row, col.wrapping_sub(1 << sub_x))
        } else {
            (row.wrapping_sub(1 << sub_y), col)
        };
        let prev_tx_sz = self.tx_size(plane, prev_row >> sub_y, prev_col >> sub_x);

        // applyFilter (§7.14.2) is `isTxEdge && (isBlockEdge || !skip || isIntra)`.
        // Every block in this subset is intra, so the parenthesis is always true
        // and the test reduces to "this is a transform edge".
        let is_tx_edge = if pass == 0 {
            xp % tx_w == 0
        } else {
            yp % tx_h == 0
        };
        if !is_tx_edge {
            return;
        }

        let filter_size = filter_size(tx_sz, prev_tx_sz, pass, plane);

        // Adaptive strength for this block; fall back to the neighbour's when the
        // current block's level is zero (§7.14.2).
        let (mut lvl, mut limit, mut blimit, mut thresh) =
            self.filter_strength(row, col, plane, pass);
        if lvl == 0 {
            let (l2, li2, bl2, th2) = self.filter_strength(prev_row, prev_col, plane, pass);
            lvl = l2;
            limit = li2;
            blimit = bl2;
            thresh = th2;
        }
        if lvl == 0 {
            return;
        }

        let Some(plane_buf) = self.planes.get_mut(plane) else {
            return;
        };
        for i in 0..MI_SIZE {
            let fx = xp + dy * i;
            let fy = yp + dx * i;
            sample_filter(
                plane_buf,
                fx,
                fy,
                plane,
                limit,
                blimit,
                thresh,
                dx,
                dy,
                filter_size,
                self.bit_depth,
            );
        }
    }

    /// Adaptive filter strength process (§7.14.4/§7.14.5). Segment id is
    /// always zero in this subset and every block is intra, so the strength
    /// comes from `loop_filter_level`, the block's `DeltaLFs` entry and the
    /// intra reference delta.
    fn filter_strength(
        &self,
        row: usize,
        col: usize,
        plane: usize,
        pass: usize,
    ) -> (i32, i32, i32, i32) {
        let i = if plane == 0 { pass } else { plane + 1 };
        let base = self.loop_filter.level.get(i).copied().unwrap_or(0);
        let deltas = row
            .checked_mul(self.mi_cols)
            .and_then(|at| at.checked_add(col))
            .and_then(|at| self.delta_lfs.get(at))
            .copied()
            .unwrap_or_default();
        let delta = if self.delta_lf_multi {
            deltas.get(i).copied().unwrap_or(0)
        } else {
            deltas.first().copied().unwrap_or(0)
        };
        let mut lvl = (i32::from(base) + i32::from(delta)).clamp(0, MAX_LOOP_FILTER);
        // The segment's offset (step 3); an inactive feature contributes 0,
        // and a clamp of an already clamped level changes nothing.
        let segment = row
            .checked_mul(self.mi_cols)
            .and_then(|at| at.checked_add(col))
            .and_then(|at| self.segment_ids.get(at))
            .map_or(0, |&s| usize::from(s));
        let offset = self
            .segment_lf
            .get(segment)
            .and_then(|lf| lf.get(i))
            .copied()
            .unwrap_or(0);
        lvl = (lvl + offset).clamp(0, MAX_LOOP_FILTER);
        if self.loop_filter.delta_enabled {
            // ref == INTRA_FRAME (0) for every block; the mode delta applies only
            // to inter modes, so it never contributes here.
            let n_shift = lvl >> 5;
            let intra_delta = self.loop_filter.ref_deltas.first().copied().unwrap_or(0);
            lvl = (lvl + (intra_delta << n_shift)).clamp(0, MAX_LOOP_FILTER);
        }

        let sharpness = i32::from(self.loop_filter.sharpness);
        let shift = if sharpness > 4 {
            2
        } else if sharpness > 0 {
            1
        } else {
            0
        };
        let limit = if sharpness > 0 {
            (lvl >> shift).clamp(1, 9 - sharpness)
        } else {
            (lvl >> shift).max(1)
        };
        let blimit = 2 * (lvl + 2) + limit;
        let thresh = lvl >> 4;
        (lvl, limit, blimit, thresh)
    }
}

/// Filter size process (§7.14.3): the maximum filter width the boundary allows.
fn filter_size(tx_sz: TxSize, prev_tx_sz: TxSize, pass: usize, plane: usize) -> usize {
    let base = if pass == 0 {
        prev_tx_sz.width().min(tx_sz.width())
    } else {
        prev_tx_sz.height().min(tx_sz.height())
    };
    if plane == 0 {
        base.min(16)
    } else {
        base.min(8)
    }
}

/// Read a sample as a signed value, replicating the nearest edge off-frame.
fn get(plane: &Plane, x: usize, y: usize, dx: usize, dy: usize, k: isize) -> i32 {
    let sx = x as isize + dx as isize * k;
    let sy = y as isize + dy as isize * k;
    i32::from(plane.sample_clamped(sx, sy))
}

/// Sample filtering process (§7.14.6): choose and apply the filter for the
/// boundary sample at `(x, y)` running perpendicular to `(dx, dy)`.
#[allow(clippy::too_many_arguments, reason = "mirrors the spec's input list")]
fn sample_filter(
    plane_buf: &mut Plane,
    x: usize,
    y: usize,
    plane: usize,
    limit: i32,
    blimit: i32,
    thresh: i32,
    dx: usize,
    dy: usize,
    filter_size: usize,
    bit_depth: u8,
) {
    let bd = u32::from(bit_depth);
    // q0..q6 on the near side, p0..p6 on the far side of the boundary.
    let q = |k: isize| get(plane_buf, x, y, dx, dy, k);
    let p = |k: isize| get(plane_buf, x, y, dx, dy, -1 - k);
    let (q0, q1, q2, q3) = (q(0), q(1), q(2), q(3));
    let (p0, p1, p2, p3) = (p(0), p(1), p(2), p(3));

    // filterLen: taps each side used by the masks.
    let filter_len = if filter_size == 4 {
        4
    } else if plane != 0 {
        6
    } else if filter_size == 8 {
        8
    } else {
        16
    };

    let shift = bd - 8;
    let thresh_bd = thresh << shift;
    let hev_mask = ((p1 - p0).abs() > thresh_bd) || ((q1 - q0).abs() > thresh_bd);

    let limit_bd = limit << shift;
    let blimit_bd = blimit << shift;
    let mut mask = false;
    mask |= (p1 - p0).abs() > limit_bd;
    mask |= (q1 - q0).abs() > limit_bd;
    mask |= (p0 - q0).abs() * 2 + (p1 - q1).abs() / 2 > blimit_bd;
    if filter_len >= 6 {
        mask |= (p2 - p1).abs() > limit_bd;
        mask |= (q2 - q1).abs() > limit_bd;
    }
    if filter_len >= 8 {
        mask |= (p3 - p2).abs() > limit_bd;
        mask |= (q3 - q2).abs() > limit_bd;
    }
    let filter_mask = !mask;
    if !filter_mask {
        return;
    }

    // flatMask (filterSize >= 8) and flatMask2 (filterSize >= 16).
    let threshold_bd = 1_i32 << shift;
    let flat_mask = if filter_size >= 8 {
        let mut m = false;
        m |= (p1 - p0).abs() > threshold_bd;
        m |= (q1 - q0).abs() > threshold_bd;
        m |= (p2 - p0).abs() > threshold_bd;
        m |= (q2 - q0).abs() > threshold_bd;
        if filter_len >= 8 {
            m |= (p3 - p0).abs() > threshold_bd;
            m |= (q3 - q0).abs() > threshold_bd;
        }
        !m
    } else {
        false
    };
    let flat_mask2 = if filter_size >= 16 {
        let (q4, q5, q6) = (q(4), q(5), q(6));
        let (p4, p5, p6) = (p(4), p(5), p(6));
        let mut m = false;
        m |= (p6 - p0).abs() > threshold_bd;
        m |= (q6 - q0).abs() > threshold_bd;
        m |= (p5 - p0).abs() > threshold_bd;
        m |= (q5 - q0).abs() > threshold_bd;
        m |= (p4 - p0).abs() > threshold_bd;
        m |= (q4 - q0).abs() > threshold_bd;
        !m
    } else {
        false
    };

    if filter_size == 4 || !flat_mask {
        narrow_filter(plane_buf, x, y, dx, dy, hev_mask, bd);
    } else if filter_size == 8 || !flat_mask2 {
        wide_filter(plane_buf, x, y, plane, dx, dy, 3);
    } else {
        wide_filter(plane_buf, x, y, plane, dx, dy, 4);
    }
}

/// `filter4_clamp`: clamp to the signed `BitDepth` range.
fn filter4_clamp(value: i32, bd: u32) -> i32 {
    let lo = -(1_i32 << (bd - 1));
    let hi = (1_i32 << (bd - 1)) - 1;
    value.clamp(lo, hi)
}

/// `Round2(x, n)`.
fn round2(x: i32, n: u32) -> i32 {
    if n == 0 { x } else { (x + (1 << (n - 1))) >> n }
}

/// Narrow filter process (§7.14.6.3): modifies up to two samples each side.
fn narrow_filter(
    plane_buf: &mut Plane,
    x: usize,
    y: usize,
    dx: usize,
    dy: usize,
    hev_mask: bool,
    bd: u32,
) {
    let bias = 0x80 << (bd - 8);
    let read = |buf: &Plane, k: isize| get(buf, x, y, dx, dy, k);
    let q0 = read(plane_buf, 0);
    let q1 = read(plane_buf, 1);
    let p0 = read(plane_buf, -1);
    let p1 = read(plane_buf, -2);
    let ps1 = p1 - bias;
    let ps0 = p0 - bias;
    let qs0 = q0 - bias;
    let qs1 = q1 - bias;
    let mut filter = if hev_mask {
        filter4_clamp(ps1 - qs1, bd)
    } else {
        0
    };
    filter = filter4_clamp(filter + 3 * (qs0 - ps0), bd);
    let filter1 = filter4_clamp(filter + 4, bd) >> 3;
    let filter2 = filter4_clamp(filter + 3, bd) >> 3;
    let oq0 = filter4_clamp(qs0 - filter1, bd) + bias;
    let op0 = filter4_clamp(ps0 + filter2, bd) + bias;
    put(plane_buf, x, y, dx, dy, 0, oq0);
    put(plane_buf, x, y, dx, dy, -1, op0);
    if !hev_mask {
        let f = round2(filter1, 1);
        let oq1 = filter4_clamp(qs1 - f, bd) + bias;
        let op1 = filter4_clamp(ps1 + f, bd) + bias;
        put(plane_buf, x, y, dx, dy, 1, oq1);
        put(plane_buf, x, y, dx, dy, -2, op1);
    }
}

/// Wide filter process (§7.14.6.4): a symmetric low-pass over `2n` samples.
fn wide_filter(
    plane_buf: &mut Plane,
    x: usize,
    y: usize,
    plane: usize,
    dx: usize,
    dy: usize,
    log2_size: u32,
) {
    let n: isize = if log2_size == 4 {
        6
    } else if plane == 0 {
        3
    } else {
        2
    };
    let n2: isize = if log2_size == 3 && plane == 0 { 0 } else { 1 };
    let mut filtered = [0_i32; 12]; // indices i = -n..n-1, offset by n (n <= 6)
    for i in -n..n {
        let mut t = 0;
        for j in -n..=n {
            let pos = (i + j).clamp(-(n + 1), n);
            let tap = if j.abs() <= n2 { 2 } else { 1 };
            t += get(plane_buf, x, y, dx, dy, pos) * tap;
        }
        if let Some(cell) = filtered.get_mut((i + n) as usize) {
            *cell = round2(t, log2_size);
        }
    }
    for i in -n..n {
        let v = filtered.get((i + n) as usize).copied().unwrap_or(0);
        put(plane_buf, x, y, dx, dy, i, v);
    }
}

/// Write a sample at `(x, y) + k * (dx, dy)`, dropping out-of-range writes.
fn put(plane_buf: &mut Plane, x: usize, y: usize, dx: usize, dy: usize, k: isize, value: i32) {
    let sx = x as isize + dx as isize * k;
    let sy = y as isize + dy as isize * k;
    if sx < 0 || sy < 0 {
        return;
    }
    plane_buf.set(sx as usize, sy as usize, value.max(0) as u16);
}

#[cfg(test)]
#[allow(
    clippy::unwrap_used,
    clippy::indexing_slicing,
    clippy::panic,
    reason = "tests operate on known-good values and assert shapes directly"
)]
mod tests {
    use super::super::frame::LoopFilter;
    use super::*;

    fn lf(level: [u8; 4]) -> LoopFilter {
        LoopFilter {
            level,
            sharpness: 0,
            delta_enabled: true,
            // Default intra ref delta of 1: exercises the strength derivation.
            ref_deltas: [1, 0, 0, 0, -1, -1, -1, -1],
            mode_deltas: [0, 0],
        }
    }

    /// A perfectly flat region has no edges, so every filter is a no-op (the
    /// wide filter has unity DC gain and reproduces a constant exactly).
    #[test]
    fn a_flat_region_is_left_unchanged() {
        let (w, h) = (16, 16);
        let mut plane = Plane::new(w, h);
        for y in 0..h {
            for x in 0..w {
                plane.set(x, y, 137);
            }
        }
        let before = plane.clone();
        // One 8x8 transform grid (index 1) everywhere, so tx edges exist at 8.
        let grid = vec![1_u8; (w / MI_SIZE) * (h / MI_SIZE)];
        let mut planes = [plane];
        Deblock {
            planes: &mut planes,
            loop_filter: &lf([20, 20, 20, 20]),
            bit_depth: 8,
            num_planes: 1,
            subsampling_x: 0,
            subsampling_y: 0,
            mi_rows: h / MI_SIZE,
            mi_cols: w / MI_SIZE,
            frame_width: w,
            frame_height: h,
            lf_tx_sizes: std::slice::from_ref(&grid),
            delta_lfs: &[],
            delta_lf_multi: false,
            segment_ids: &[],
            segment_lf: [[0; FRAME_LF_COUNT]; MAX_SEGMENTS],
        }
        .run();
        assert_eq!(planes[0].row(0), before.row(0));
        assert_eq!(planes[0].row(7), before.row(7));
        assert_eq!(planes[0].row(8), before.row(8));
    }

    /// With both luma levels zero the whole filter is skipped, even though the
    /// intra reference delta would otherwise raise the strength above zero.
    #[test]
    fn zero_luma_level_skips_filtering() {
        let (w, h) = (16, 16);
        let mut plane = Plane::new(w, h);
        // A hard vertical step at the 8-sample transform edge that the filter
        // would smooth if it ran.
        for y in 0..h {
            for x in 0..w {
                plane.set(x, y, if x < 8 { 40 } else { 200 });
            }
        }
        let before = plane.clone();
        let grid = vec![1_u8; (w / MI_SIZE) * (h / MI_SIZE)];
        let mut planes = [plane];
        Deblock {
            planes: &mut planes,
            loop_filter: &lf([0, 0, 0, 0]),
            bit_depth: 8,
            num_planes: 1,
            subsampling_x: 0,
            subsampling_y: 0,
            mi_rows: h / MI_SIZE,
            mi_cols: w / MI_SIZE,
            frame_width: w,
            frame_height: h,
            lf_tx_sizes: std::slice::from_ref(&grid),
            delta_lfs: &[],
            delta_lf_multi: false,
            segment_ids: &[],
            segment_lf: [[0; FRAME_LF_COUNT]; MAX_SEGMENTS],
        }
        .run();
        assert_eq!(planes[0].row(0), before.row(0));
    }

    /// A nonzero level does smooth a hard transform-edge step: the samples
    /// either side of the boundary move toward each other.
    #[test]
    fn subsampled_chroma_is_filtered_on_its_own_transform_grid() {
        // 4:2:0, 32x32 luma, so each chroma plane is 16x16 and every chroma
        // transform is 8x8. A chroma step at x = 8 sits on a transform edge and
        // is smoothed; one at x = 4 lies inside an 8x8 transform and is not —
        // which only holds if edges are tested in the plane's own coordinates.
        let (w, h) = (32, 32);
        let step_at = |edge: usize| {
            let mut p = Plane::new(w / 2, h / 2);
            for y in 0..h / 2 {
                for x in 0..w / 2 {
                    p.set(x, y, if x < edge { 100 } else { 140 });
                }
            }
            p
        };
        let luma = Plane::new(w, h);
        let mut planes = [luma, step_at(8), step_at(4)];
        // TX_8X8 everywhere, each plane's grid in its own 4x4 units.
        let grid = vec![1_u8; (w / MI_SIZE) * (h / MI_SIZE)];
        let grids = [grid.clone(), grid.clone(), grid];
        Deblock {
            planes: &mut planes,
            loop_filter: &lf([32, 32, 32, 32]),
            bit_depth: 8,
            num_planes: 3,
            subsampling_x: 1,
            subsampling_y: 1,
            mi_rows: h / MI_SIZE,
            mi_cols: w / MI_SIZE,
            frame_width: w,
            frame_height: h,
            lf_tx_sizes: &grids,
            delta_lfs: &[],
            delta_lf_multi: false,
            segment_ids: &[],
            segment_lf: [[0; FRAME_LF_COUNT]; MAX_SEGMENTS],
        }
        .run();
        let u = planes[1].row(5).unwrap();
        assert!(u[7] > 100 && u[8] < 140, "edge on the tx grid: {u:?}");
        let v = planes[2].row(5).unwrap();
        assert_eq!((v[3], v[4]), (100, 140), "edge inside a transform: {v:?}");
    }

    /// Filter a vertical step edge at x = 8 with every 4x4 unit carrying
    /// `deltas`, and report whether the edge moved.
    fn step_edge_filtered(deltas: [i8; FRAME_LF_COUNT], multi: bool) -> bool {
        step_edge_filtered_in_segment(deltas, multi, [0; FRAME_LF_COUNT])
    }

    /// As [`step_edge_filtered`], with every unit in segment 1, whose
    /// loop-filter offsets are `segment_lf`.
    fn step_edge_filtered_in_segment(
        deltas: [i8; FRAME_LF_COUNT],
        multi: bool,
        segment_lf: [i32; FRAME_LF_COUNT],
    ) -> bool {
        let (w, h) = (16, 16);
        let mut plane = Plane::new(w, h);
        for y in 0..h {
            for x in 0..w {
                plane.set(x, y, if x < 8 { 100 } else { 140 });
            }
        }
        let grid = vec![1_u8; (w / MI_SIZE) * (h / MI_SIZE)];
        let delta_lfs = vec![deltas; (w / MI_SIZE) * (h / MI_SIZE)];
        let segment_ids = vec![1_u8; (w / MI_SIZE) * (h / MI_SIZE)];
        let mut offsets = [[0; FRAME_LF_COUNT]; MAX_SEGMENTS];
        offsets[1] = segment_lf;
        // No reference delta, so a level the block delta zeroes stays zero.
        let loop_filter = LoopFilter {
            delta_enabled: false,
            ..lf([32, 32, 0, 0])
        };
        let mut planes = [plane];
        Deblock {
            planes: &mut planes,
            loop_filter: &loop_filter,
            bit_depth: 8,
            num_planes: 1,
            subsampling_x: 0,
            subsampling_y: 0,
            mi_rows: h / MI_SIZE,
            mi_cols: w / MI_SIZE,
            frame_width: w,
            frame_height: h,
            lf_tx_sizes: std::slice::from_ref(&grid),
            delta_lfs: &delta_lfs,
            delta_lf_multi: multi,
            segment_ids: &segment_ids,
            segment_lf: offsets,
        }
        .run();
        let row = planes[0].row(4).unwrap();
        (row[7], row[8]) != (100, 140)
    }

    #[test]
    fn a_block_delta_moves_the_filter_level() {
        assert!(step_edge_filtered([0; FRAME_LF_COUNT], false));
        // -32 cancels the frame level of 32 exactly.
        assert!(!step_edge_filtered([-32, 0, 0, 0], false));
        // A positive delta past the maximum is clipped, not wrapped.
        assert!(step_edge_filtered([63, 0, 0, 0], false));
    }

    #[test]
    fn a_segment_offset_moves_the_filter_level_for_its_direction() {
        // SEG_LVL_ALT_LF_Y_V (index 0 here) reaches the vertical edge.
        assert!(!step_edge_filtered_in_segment(
            [0; FRAME_LF_COUNT],
            false,
            [-32, 0, 0, 0]
        ));
        // SEG_LVL_ALT_LF_Y_H does not.
        assert!(step_edge_filtered_in_segment(
            [0; FRAME_LF_COUNT],
            false,
            [0, -32, 0, 0]
        ));
        // The block delta and the segment offset add: +16 then -48 is zero.
        assert!(!step_edge_filtered_in_segment(
            [16, 0, 0, 0],
            false,
            [-48, 0, 0, 0]
        ));
    }

    #[test]
    fn delta_lf_multi_picks_the_delta_for_the_edge_direction() {
        // A vertical edge is filtered in the first (vertical) pass, so with
        // `delta_lf_multi` only DeltaLF[0] reaches it.
        assert!(!step_edge_filtered([-32, 0, 0, 0], true));
        assert!(step_edge_filtered([0, -32, 0, 0], true));
        // Without it, DeltaLF[0] is shared and the others are never read.
        assert!(step_edge_filtered([0, -32, -32, -32], false));
    }

    #[test]
    fn a_step_edge_is_smoothed() {
        let (w, h) = (16, 16);
        let mut plane = Plane::new(w, h);
        for y in 0..h {
            for x in 0..w {
                plane.set(x, y, if x < 8 { 100 } else { 140 });
            }
        }
        let grid = vec![1_u8; (w / MI_SIZE) * (h / MI_SIZE)];
        let mut planes = [plane];
        Deblock {
            planes: &mut planes,
            loop_filter: &lf([32, 32, 0, 0]),
            bit_depth: 8,
            num_planes: 1,
            subsampling_x: 0,
            subsampling_y: 0,
            mi_rows: h / MI_SIZE,
            mi_cols: w / MI_SIZE,
            frame_width: w,
            frame_height: h,
            lf_tx_sizes: std::slice::from_ref(&grid),
            delta_lfs: &[],
            delta_lf_multi: false,
            segment_ids: &[],
            segment_lf: [[0; FRAME_LF_COUNT]; MAX_SEGMENTS],
        }
        .run();
        // The last "left" sample rose and the first "right" sample fell.
        let row = planes[0].row(4).unwrap();
        assert!(row[7] > 100, "left edge sample should rise, got {}", row[7]);
        assert!(
            row[8] < 140,
            "right edge sample should fall, got {}",
            row[8]
        );
    }
}