#![allow(dead_code)]
use crate::cabac::{CabacDecoder, CabacError, CabacResult, CtxState};
#[inline]
fn dbg_enabled() -> bool {
use std::sync::OnceLock;
static CACHED: OnceLock<bool> = OnceLock::new();
*CACHED.get_or_init(|| std::env::var("OXIDEAV_H264_CABAC_DEBUG").is_ok())
}
#[inline]
fn ctx17_trace_enabled() -> bool {
use std::sync::OnceLock;
static CACHED: OnceLock<bool> = OnceLock::new();
*CACHED.get_or_init(|| std::env::var_os("OXIDEAV_H264_CTX17_TRACE").is_some())
}
#[inline]
fn dbg_emit(syntax: &str, bins_used: u64, extra: &str) {
if dbg_enabled() {
eprintln!("[CABAC] {syntax} bins={bins_used} {extra}");
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SliceKind {
I,
P,
B,
SI,
SP,
}
impl SliceKind {
fn is_i_like(self) -> bool {
matches!(self, SliceKind::I | SliceKind::SI)
}
fn is_p_like(self) -> bool {
matches!(self, SliceKind::P | SliceKind::SP)
}
}
type MN = (i32, i32);
const NA: Option<MN> = None;
#[derive(Debug, Copy, Clone)]
struct InitCell {
i_si: Option<MN>,
p0: Option<MN>,
p1: Option<MN>,
p2: Option<MN>,
}
impl InitCell {
const fn all(i_si: MN, p0: MN, p1: MN, p2: MN) -> Self {
Self {
i_si: Some(i_si),
p0: Some(p0),
p1: Some(p1),
p2: Some(p2),
}
}
const fn p(p0: MN, p1: MN, p2: MN) -> Self {
Self {
i_si: None,
p0: Some(p0),
p1: Some(p1),
p2: Some(p2),
}
}
const fn i(i_si: MN) -> Self {
Self {
i_si: Some(i_si),
p0: NA,
p1: NA,
p2: NA,
}
}
const fn same(mn: MN) -> Self {
Self {
i_si: Some(mn),
p0: Some(mn),
p1: Some(mn),
p2: Some(mn),
}
}
const fn none() -> Self {
Self {
i_si: NA,
p0: NA,
p1: NA,
p2: NA,
}
}
fn pick(&self, slice_kind: SliceKind, init_idc: Option<u32>) -> Option<MN> {
if slice_kind.is_i_like() {
return self.i_si;
}
match init_idc? {
0 => self.p0,
1 => self.p1,
2 => self.p2,
_ => None,
}
}
}
pub const NUM_CTX_IDX: usize = 1024;
const TBL_9_12: &[(usize, InitCell)] = &[
(0, InitCell::all((20, -15), (20, -15), (20, -15), (20, -15))),
(1, InitCell::all((2, 54), (2, 54), (2, 54), (2, 54))),
(2, InitCell::all((3, 74), (3, 74), (3, 74), (3, 74))),
(3, InitCell::all((20, -15), (20, -15), (20, -15), (20, -15))),
(4, InitCell::all((2, 54), (2, 54), (2, 54), (2, 54))),
(5, InitCell::all((3, 74), (3, 74), (3, 74), (3, 74))),
(
6,
InitCell::all((-28, 127), (-28, 127), (-28, 127), (-28, 127)),
),
(
7,
InitCell::all((-23, 104), (-23, 104), (-23, 104), (-23, 104)),
),
(8, InitCell::all((-6, 53), (-6, 53), (-6, 53), (-6, 53))),
(9, InitCell::all((-1, 54), (-1, 54), (-1, 54), (-1, 54))),
(10, InitCell::all((7, 51), (7, 51), (7, 51), (7, 51))),
];
const TBL_9_13: &[(usize, InitCell)] = &[
(11, InitCell::p((23, 33), (22, 25), (29, 16))),
(12, InitCell::p((23, 2), (34, 0), (25, 0))),
(13, InitCell::p((21, 0), (16, 0), (14, 0))),
(14, InitCell::p((1, 9), (-2, 9), (-10, 51))),
(15, InitCell::p((0, 49), (4, 41), (-3, 62))),
(16, InitCell::p((-37, 118), (-29, 118), (-27, 99))),
(17, InitCell::p((5, 57), (2, 65), (26, 16))),
(18, InitCell::p((-13, 78), (-6, 71), (-4, 85))),
(19, InitCell::p((-11, 65), (-13, 79), (-24, 102))),
(20, InitCell::p((1, 62), (5, 52), (5, 57))),
(21, InitCell::p((12, 49), (9, 50), (6, 57))),
(22, InitCell::p((-4, 73), (-3, 70), (-17, 73))),
(23, InitCell::p((17, 50), (10, 54), (14, 57))),
];
const TBL_9_14: &[(usize, InitCell)] = &[
(24, InitCell::p((18, 64), (26, 34), (20, 40))),
(25, InitCell::p((9, 43), (19, 22), (20, 10))),
(26, InitCell::p((29, 0), (40, 0), (29, 0))),
(27, InitCell::p((26, 67), (57, 2), (54, 0))),
(28, InitCell::p((16, 90), (41, 36), (37, 42))),
(29, InitCell::p((9, 104), (26, 69), (12, 97))),
(30, InitCell::p((-46, 127), (-45, 127), (-32, 127))),
(31, InitCell::p((-20, 104), (-15, 101), (-22, 117))),
(32, InitCell::p((1, 67), (-4, 76), (-2, 74))),
(33, InitCell::p((-13, 78), (-6, 71), (-4, 85))),
(34, InitCell::p((-11, 65), (-13, 79), (-24, 102))),
(35, InitCell::p((1, 62), (5, 52), (5, 57))),
(36, InitCell::p((-6, 86), (6, 69), (-6, 93))),
(37, InitCell::p((-17, 95), (-13, 90), (-14, 88))),
(38, InitCell::p((-6, 61), (0, 52), (-6, 44))),
(39, InitCell::p((9, 45), (8, 43), (4, 55))),
];
const TBL_9_15: &[(usize, InitCell)] = &[
(40, InitCell::p((-3, 69), (-2, 69), (-11, 89))),
(41, InitCell::p((-6, 81), (-5, 82), (-15, 103))),
(42, InitCell::p((-11, 96), (-10, 96), (-21, 116))),
(43, InitCell::p((6, 55), (2, 59), (19, 57))),
(44, InitCell::p((7, 67), (2, 75), (20, 58))),
(45, InitCell::p((-5, 86), (-3, 87), (4, 84))),
(46, InitCell::p((2, 88), (-3, 100), (6, 96))),
(47, InitCell::p((0, 58), (1, 56), (1, 63))),
(48, InitCell::p((-3, 76), (-3, 74), (-5, 85))),
(49, InitCell::p((-10, 94), (-6, 85), (-13, 106))),
(50, InitCell::p((5, 54), (0, 59), (5, 63))),
(51, InitCell::p((4, 69), (-3, 81), (6, 75))),
(52, InitCell::p((-3, 81), (-7, 86), (-3, 90))),
(53, InitCell::p((0, 88), (-5, 95), (-1, 101))),
];
const TBL_9_16: &[(usize, InitCell)] = &[
(54, InitCell::p((-7, 67), (-1, 66), (3, 55))),
(55, InitCell::p((-5, 74), (-1, 77), (-4, 79))),
(56, InitCell::p((-4, 74), (1, 70), (-2, 75))),
(57, InitCell::p((-5, 80), (-2, 86), (-12, 97))),
(58, InitCell::p((-7, 72), (-5, 72), (-7, 50))),
(59, InitCell::p((1, 58), (0, 61), (1, 60))),
(399, InitCell::all((31, 21), (12, 40), (25, 32), (21, 33))),
(400, InitCell::all((31, 31), (11, 51), (21, 49), (19, 50))),
(401, InitCell::all((25, 50), (14, 59), (21, 54), (17, 61))),
];
const TBL_9_17: &[(usize, InitCell)] = &[
(60, InitCell::same((0, 41))),
(61, InitCell::same((0, 63))),
(62, InitCell::same((0, 63))),
(63, InitCell::same((0, 63))),
(64, InitCell::same((-9, 83))),
(65, InitCell::same((4, 86))),
(66, InitCell::same((0, 97))),
(67, InitCell::same((-7, 72))),
(68, InitCell::same((13, 41))),
(69, InitCell::same((3, 62))),
];
const TBL_9_18: &[(usize, InitCell)] = &[
(70, InitCell::all((0, 11), (0, 45), (13, 15), (7, 34))),
(71, InitCell::all((1, 55), (-4, 78), (7, 51), (-9, 88))),
(72, InitCell::all((0, 69), (-3, 96), (2, 80), (-20, 127))),
(
73,
InitCell::all((-17, 127), (-27, 126), (-39, 127), (-36, 127)),
),
(
74,
InitCell::all((-13, 102), (-28, 98), (-18, 91), (-17, 91)),
),
(75, InitCell::all((0, 82), (-25, 101), (-17, 96), (-14, 95))),
(76, InitCell::all((-7, 74), (-23, 67), (-26, 81), (-25, 84))),
(
77,
InitCell::all((-21, 107), (-28, 82), (-35, 98), (-25, 86)),
),
(
78,
InitCell::all((-27, 127), (-20, 94), (-24, 102), (-12, 89)),
),
(
79,
InitCell::all((-31, 127), (-16, 83), (-23, 97), (-17, 91)),
),
(
80,
InitCell::all((-24, 127), (-22, 110), (-27, 119), (-31, 127)),
),
(
81,
InitCell::all((-18, 95), (-21, 91), (-24, 99), (-14, 76)),
),
(
82,
InitCell::all((-27, 127), (-18, 102), (-21, 110), (-18, 103)),
),
(
83,
InitCell::all((-21, 114), (-13, 93), (-18, 102), (-13, 90)),
),
(
84,
InitCell::all((-30, 127), (-29, 127), (-36, 127), (-37, 127)),
),
(85, InitCell::all((-17, 123), (-7, 92), (0, 80), (11, 80))),
(86, InitCell::all((-12, 115), (-5, 89), (-5, 89), (5, 76))),
(87, InitCell::all((-16, 122), (-7, 96), (-7, 94), (2, 84))),
(88, InitCell::all((-11, 115), (-13, 108), (-4, 92), (5, 78))),
(89, InitCell::all((-12, 63), (-3, 46), (0, 39), (-6, 55))),
(90, InitCell::all((-2, 68), (-1, 65), (0, 65), (4, 61))),
(91, InitCell::all((-15, 84), (-1, 57), (-15, 84), (-14, 83))),
(
92,
InitCell::all((-13, 104), (-9, 93), (-35, 127), (-37, 127)),
),
(93, InitCell::all((-3, 70), (-3, 74), (-2, 73), (-5, 79))),
(
94,
InitCell::all((-8, 93), (-9, 92), (-12, 104), (-11, 104)),
),
(95, InitCell::all((-10, 90), (-8, 87), (-9, 91), (-11, 91))),
(
96,
InitCell::all((-30, 127), (-23, 126), (-31, 127), (-30, 127)),
),
(97, InitCell::all((-1, 74), (5, 54), (3, 55), (0, 65))),
(98, InitCell::all((-6, 97), (6, 60), (7, 56), (-2, 79))),
(99, InitCell::all((-7, 91), (6, 59), (7, 55), (0, 72))),
(100, InitCell::all((-20, 127), (6, 69), (8, 61), (-4, 92))),
(101, InitCell::all((-4, 56), (-1, 48), (-3, 53), (-6, 56))),
(102, InitCell::all((-5, 82), (0, 68), (0, 68), (3, 68))),
(103, InitCell::all((-7, 76), (-4, 69), (-7, 74), (-8, 71))),
(
104,
InitCell::all((-22, 125), (-8, 88), (-9, 88), (-13, 98)),
),
];
const TBL_9_19: &[(usize, InitCell)] = &[
(105, InitCell::all((-7, 93), (-2, 85), (-13, 103), (-4, 86))),
(
106,
InitCell::all((-11, 87), (-6, 78), (-13, 91), (-12, 88)),
),
(107, InitCell::all((-3, 77), (-1, 75), (-9, 89), (-5, 82))),
(108, InitCell::all((-5, 71), (-7, 77), (-14, 92), (-3, 72))),
(109, InitCell::all((-4, 63), (2, 54), (-8, 76), (-4, 67))),
(110, InitCell::all((-4, 68), (5, 50), (-12, 87), (-8, 72))),
(
111,
InitCell::all((-12, 84), (-3, 68), (-23, 110), (-16, 89)),
),
(112, InitCell::all((-7, 62), (1, 50), (-24, 105), (-9, 69))),
(113, InitCell::all((-7, 65), (6, 42), (-10, 78), (-1, 59))),
(114, InitCell::all((8, 61), (-4, 81), (-20, 112), (5, 66))),
(115, InitCell::all((5, 56), (1, 63), (-17, 99), (4, 57))),
(116, InitCell::all((-2, 66), (-4, 70), (-78, 127), (-4, 71))),
(117, InitCell::all((1, 64), (0, 67), (-70, 127), (-2, 71))),
(118, InitCell::all((0, 61), (2, 57), (-50, 127), (2, 58))),
(119, InitCell::all((-2, 78), (-2, 76), (-46, 127), (-1, 74))),
(120, InitCell::all((1, 50), (11, 35), (-4, 66), (-4, 44))),
(121, InitCell::all((7, 52), (4, 64), (-5, 78), (-1, 69))),
(122, InitCell::all((10, 35), (1, 61), (-4, 71), (0, 62))),
(123, InitCell::all((0, 44), (11, 35), (-8, 72), (-7, 51))),
(124, InitCell::all((11, 38), (18, 25), (2, 59), (-4, 47))),
(125, InitCell::all((1, 45), (12, 24), (-1, 55), (-6, 42))),
(126, InitCell::all((0, 46), (13, 29), (-7, 70), (-3, 41))),
(127, InitCell::all((5, 44), (13, 36), (-6, 75), (-6, 53))),
(128, InitCell::all((31, 17), (-10, 93), (-8, 89), (8, 76))),
(129, InitCell::all((1, 51), (-7, 73), (-34, 119), (-9, 78))),
(130, InitCell::all((7, 50), (-2, 73), (-3, 75), (-11, 83))),
(131, InitCell::all((28, 19), (13, 46), (32, 20), (9, 52))),
(132, InitCell::all((16, 33), (9, 49), (30, 22), (0, 67))),
(
133,
InitCell::all((14, 62), (-7, 100), (-44, 127), (-5, 90)),
),
(134, InitCell::all((-13, 108), (9, 53), (0, 54), (1, 67))),
(135, InitCell::all((-15, 100), (2, 53), (-5, 61), (-15, 72))),
(136, InitCell::all((-13, 101), (5, 53), (0, 58), (-5, 75))),
(137, InitCell::all((-13, 91), (-2, 61), (-1, 60), (-8, 80))),
(138, InitCell::all((-12, 94), (0, 56), (-3, 61), (-21, 83))),
(139, InitCell::all((-10, 88), (0, 56), (-8, 67), (-21, 64))),
(
140,
InitCell::all((-16, 84), (-13, 63), (-25, 84), (-13, 31)),
),
(
141,
InitCell::all((-10, 86), (-5, 60), (-14, 74), (-25, 64)),
),
(142, InitCell::all((-7, 83), (-1, 62), (-5, 65), (-29, 94))),
(143, InitCell::all((-13, 87), (4, 57), (5, 52), (9, 75))),
(144, InitCell::all((-19, 94), (-6, 69), (2, 57), (17, 63))),
(145, InitCell::all((1, 70), (4, 57), (0, 61), (-8, 74))),
(146, InitCell::all((0, 72), (14, 39), (-9, 69), (-5, 35))),
(147, InitCell::all((-5, 74), (4, 51), (-11, 70), (-2, 27))),
(148, InitCell::all((18, 59), (13, 68), (18, 55), (13, 91))),
(149, InitCell::all((-8, 102), (3, 64), (-4, 71), (3, 65))),
(150, InitCell::all((-15, 100), (1, 61), (0, 58), (-7, 69))),
(151, InitCell::all((0, 95), (9, 63), (7, 61), (8, 77))),
(152, InitCell::all((-4, 75), (7, 50), (9, 41), (-10, 66))),
(153, InitCell::all((2, 72), (16, 39), (18, 25), (3, 62))),
(154, InitCell::all((-11, 75), (5, 44), (9, 32), (-3, 68))),
(155, InitCell::all((-3, 71), (4, 52), (5, 43), (-20, 81))),
(156, InitCell::all((15, 46), (11, 48), (9, 47), (0, 30))),
(157, InitCell::all((-13, 69), (-5, 60), (0, 44), (1, 7))),
(158, InitCell::all((0, 62), (-1, 59), (0, 51), (-3, 23))),
(159, InitCell::all((0, 65), (0, 59), (2, 46), (-21, 74))),
(160, InitCell::all((21, 37), (22, 33), (19, 38), (16, 66))),
(161, InitCell::all((-15, 72), (5, 44), (-4, 66), (-23, 124))),
(162, InitCell::all((9, 57), (14, 43), (15, 38), (17, 37))),
(163, InitCell::all((16, 54), (-1, 78), (12, 42), (44, -18))),
(164, InitCell::all((0, 62), (0, 60), (9, 34), (50, -34))),
(165, InitCell::all((12, 72), (9, 69), (0, 89), (-22, 127))),
];
const TBL_9_20: &[(usize, InitCell)] = &[
(166, InitCell::all((24, 0), (11, 28), (4, 45), (4, 39))),
(167, InitCell::all((15, 9), (2, 40), (10, 28), (0, 42))),
(168, InitCell::all((8, 25), (3, 44), (10, 31), (7, 34))),
(169, InitCell::all((13, 18), (0, 49), (33, -11), (11, 29))),
(170, InitCell::all((15, 9), (0, 46), (52, -43), (8, 31))),
(171, InitCell::all((13, 19), (2, 44), (18, 15), (6, 37))),
(172, InitCell::all((10, 37), (2, 51), (28, 0), (7, 42))),
(173, InitCell::all((12, 18), (0, 47), (35, -22), (3, 40))),
(174, InitCell::all((6, 29), (4, 39), (38, -25), (8, 33))),
(175, InitCell::all((20, 33), (2, 62), (34, 0), (13, 43))),
(176, InitCell::all((15, 30), (6, 46), (39, -18), (13, 36))),
(177, InitCell::all((4, 45), (0, 54), (32, -12), (4, 47))),
(178, InitCell::all((1, 58), (3, 54), (102, -94), (3, 55))),
(179, InitCell::all((0, 62), (2, 58), (0, 0), (2, 58))),
(180, InitCell::all((7, 61), (4, 63), (56, -15), (6, 60))),
(181, InitCell::all((12, 38), (6, 51), (33, -4), (8, 44))),
(182, InitCell::all((11, 45), (6, 57), (29, 10), (11, 44))),
(183, InitCell::all((15, 39), (7, 53), (37, -5), (14, 42))),
(184, InitCell::all((11, 42), (6, 52), (51, -29), (7, 48))),
(185, InitCell::all((13, 44), (6, 55), (39, -9), (4, 56))),
(186, InitCell::all((16, 45), (11, 45), (52, -34), (4, 52))),
(187, InitCell::all((12, 41), (14, 36), (69, -58), (13, 37))),
(188, InitCell::all((10, 49), (8, 53), (67, -63), (9, 49))),
(189, InitCell::all((30, 34), (-1, 82), (44, -5), (19, 58))),
(190, InitCell::all((18, 42), (7, 55), (32, 7), (10, 48))),
(191, InitCell::all((10, 55), (-3, 78), (55, -29), (12, 45))),
(192, InitCell::all((17, 51), (15, 46), (32, 1), (0, 69))),
(193, InitCell::all((17, 46), (22, 31), (0, 0), (20, 33))),
(194, InitCell::all((0, 89), (-1, 84), (27, 36), (8, 63))),
(195, InitCell::all((26, -19), (25, 7), (33, -25), (35, -18))),
(
196,
InitCell::all((22, -17), (30, -7), (34, -30), (33, -25)),
),
(197, InitCell::all((26, -17), (28, 3), (36, -28), (28, -3))),
(198, InitCell::all((30, -25), (28, 4), (38, -28), (24, 10))),
(199, InitCell::all((28, -20), (32, 0), (38, -27), (27, 0))),
(
200,
InitCell::all((33, -23), (34, -1), (34, -18), (34, -14)),
),
(201, InitCell::all((37, -27), (30, 6), (35, -16), (52, -44))),
(202, InitCell::all((33, -23), (30, 6), (34, -14), (39, -24))),
(203, InitCell::all((40, -28), (32, 9), (32, -8), (19, 17))),
(204, InitCell::all((38, -17), (31, 19), (37, -6), (31, 25))),
(205, InitCell::all((33, -11), (26, 27), (35, 0), (36, 29))),
(206, InitCell::all((40, -15), (26, 30), (30, 10), (24, 33))),
(207, InitCell::all((41, -6), (37, 20), (28, 18), (34, 15))),
(208, InitCell::all((38, 1), (28, 34), (26, 25), (30, 20))),
(209, InitCell::all((41, 17), (17, 70), (29, 41), (22, 73))),
(210, InitCell::all((30, -6), (1, 67), (0, 75), (20, 34))),
(211, InitCell::all((27, 3), (5, 59), (2, 72), (19, 31))),
(212, InitCell::all((26, 22), (9, 67), (8, 77), (27, 44))),
(213, InitCell::all((37, -16), (16, 30), (14, 35), (19, 16))),
(214, InitCell::all((35, -4), (18, 32), (18, 31), (15, 36))),
(215, InitCell::all((38, -8), (18, 35), (17, 35), (15, 36))),
(216, InitCell::all((38, -3), (22, 29), (21, 30), (21, 28))),
(217, InitCell::all((37, 3), (24, 31), (17, 45), (25, 21))),
(218, InitCell::all((38, 5), (23, 38), (20, 42), (30, 20))),
(219, InitCell::all((42, 0), (18, 43), (18, 45), (31, 12))),
(220, InitCell::all((35, 16), (20, 41), (27, 26), (27, 16))),
(221, InitCell::all((39, 22), (11, 63), (16, 54), (24, 42))),
(222, InitCell::all((14, 48), (9, 59), (7, 66), (0, 93))),
(223, InitCell::all((27, 37), (9, 64), (16, 56), (14, 56))),
(224, InitCell::all((21, 60), (-1, 94), (11, 73), (15, 57))),
(225, InitCell::all((12, 68), (-2, 89), (10, 67), (26, 38))),
(
226,
InitCell::all((2, 97), (-9, 108), (-10, 116), (-24, 127)),
),
];
const TBL_9_21: &[(usize, InitCell)] = &[
(
227,
InitCell::all((-3, 71), (-6, 76), (-23, 112), (-24, 115)),
),
(228, InitCell::all((-6, 42), (-2, 44), (-15, 71), (-22, 82))),
(229, InitCell::all((-5, 50), (0, 45), (-7, 61), (-9, 62))),
(230, InitCell::all((-3, 54), (0, 52), (0, 53), (0, 53))),
(231, InitCell::all((-2, 62), (-3, 64), (-5, 66), (0, 59))),
(232, InitCell::all((0, 58), (-2, 59), (-11, 77), (-14, 85))),
(233, InitCell::all((1, 63), (-4, 70), (-9, 80), (-13, 89))),
(234, InitCell::all((-2, 72), (-4, 75), (-9, 84), (-13, 94))),
(235, InitCell::all((-1, 74), (-8, 82), (-10, 87), (-11, 92))),
(
236,
InitCell::all((-9, 91), (-17, 102), (-34, 127), (-29, 127)),
),
(
237,
InitCell::all((-5, 67), (-9, 77), (-21, 101), (-21, 100)),
),
(238, InitCell::all((-5, 27), (3, 24), (-3, 39), (-14, 57))),
(239, InitCell::all((-3, 39), (0, 42), (-5, 53), (-12, 67))),
(240, InitCell::all((-2, 44), (0, 48), (-7, 61), (-11, 71))),
(241, InitCell::all((0, 46), (0, 55), (-11, 75), (-10, 77))),
(
242,
InitCell::all((-16, 64), (-6, 59), (-15, 77), (-21, 85)),
),
(243, InitCell::all((-8, 68), (-7, 71), (-17, 91), (-16, 88))),
(
244,
InitCell::all((-10, 78), (-12, 83), (-25, 107), (-23, 104)),
),
(
245,
InitCell::all((-6, 77), (-11, 87), (-25, 111), (-15, 98)),
),
(
246,
InitCell::all((-10, 86), (-30, 119), (-28, 122), (-37, 127)),
),
(247, InitCell::all((-12, 92), (1, 58), (-11, 76), (-10, 82))),
(248, InitCell::all((-15, 55), (-3, 29), (-10, 44), (-8, 48))),
(249, InitCell::all((-10, 60), (-1, 36), (-10, 52), (-8, 61))),
(250, InitCell::all((-6, 62), (1, 38), (-10, 57), (-8, 66))),
(251, InitCell::all((-4, 65), (2, 43), (-9, 58), (-7, 70))),
(
252,
InitCell::all((-12, 73), (-6, 55), (-16, 72), (-14, 75)),
),
(253, InitCell::all((-8, 76), (0, 58), (-7, 69), (-10, 79))),
(254, InitCell::all((-7, 80), (0, 64), (-4, 69), (-9, 83))),
(255, InitCell::all((-9, 88), (-3, 74), (-5, 74), (-12, 92))),
(
256,
InitCell::all((-17, 110), (-10, 90), (-9, 86), (-18, 108)),
),
(257, InitCell::all((-11, 97), (0, 70), (2, 66), (-4, 79))),
(258, InitCell::all((-20, 84), (-4, 29), (-9, 34), (-22, 69))),
(259, InitCell::all((-11, 79), (5, 31), (1, 32), (-16, 75))),
(260, InitCell::all((-6, 73), (7, 42), (11, 31), (-2, 58))),
(261, InitCell::all((-4, 74), (1, 59), (5, 52), (1, 58))),
(262, InitCell::all((-13, 86), (-2, 58), (-2, 55), (-13, 78))),
(263, InitCell::all((-13, 96), (-3, 72), (-2, 67), (-9, 83))),
(264, InitCell::all((-11, 97), (-3, 81), (0, 73), (-4, 81))),
(
265,
InitCell::all((-19, 117), (-11, 97), (-8, 89), (-13, 99)),
),
(266, InitCell::all((-8, 78), (0, 58), (3, 52), (-13, 81))),
(267, InitCell::all((-5, 33), (8, 5), (7, 4), (-6, 38))),
(268, InitCell::all((-4, 48), (10, 14), (10, 8), (-13, 62))),
(269, InitCell::all((-2, 53), (14, 18), (17, 8), (-6, 58))),
(270, InitCell::all((-3, 62), (13, 27), (16, 19), (-2, 59))),
(271, InitCell::all((-13, 71), (2, 40), (3, 37), (-16, 73))),
(272, InitCell::all((-10, 79), (0, 58), (-1, 61), (-10, 76))),
(273, InitCell::all((-12, 86), (-3, 70), (-5, 73), (-13, 86))),
(274, InitCell::all((-13, 90), (-6, 79), (-1, 70), (-9, 83))),
(275, InitCell::all((-14, 97), (-8, 85), (-4, 78), (-10, 87))),
];
const TBL_9_22: &[(usize, InitCell)] = &[
(
277,
InitCell::all((-6, 93), (-13, 106), (-21, 126), (-22, 127)),
),
(
278,
InitCell::all((-6, 84), (-16, 106), (-23, 124), (-25, 127)),
),
(
279,
InitCell::all((-8, 79), (-10, 87), (-20, 110), (-25, 120)),
),
(
280,
InitCell::all((0, 66), (-21, 114), (-26, 126), (-27, 127)),
),
(
281,
InitCell::all((-1, 71), (-18, 110), (-25, 124), (-19, 114)),
),
(
282,
InitCell::all((0, 62), (-14, 98), (-17, 105), (-23, 117)),
),
(
283,
InitCell::all((-2, 60), (-22, 110), (-27, 121), (-25, 118)),
),
(
284,
InitCell::all((-2, 59), (-21, 106), (-27, 117), (-26, 117)),
),
(
285,
InitCell::all((-5, 75), (-18, 103), (-17, 102), (-24, 113)),
),
(
286,
InitCell::all((-3, 62), (-21, 107), (-26, 117), (-28, 118)),
),
(
287,
InitCell::all((-4, 58), (-23, 108), (-27, 116), (-31, 120)),
),
(
288,
InitCell::all((-9, 66), (-26, 112), (-33, 122), (-37, 124)),
),
(
289,
InitCell::all((-1, 79), (-10, 96), (-10, 95), (-10, 94)),
),
(
290,
InitCell::all((0, 71), (-12, 95), (-14, 100), (-15, 102)),
),
(291, InitCell::all((3, 68), (-5, 91), (-8, 95), (-10, 99))),
(
292,
InitCell::all((10, 44), (-9, 93), (-17, 111), (-13, 106)),
),
(
293,
InitCell::all((-7, 62), (-22, 94), (-28, 114), (-50, 127)),
),
(294, InitCell::all((15, 36), (-5, 86), (-6, 89), (-5, 92))),
(295, InitCell::all((14, 40), (9, 67), (-2, 80), (17, 57))),
(296, InitCell::all((16, 27), (-4, 80), (-4, 82), (-5, 86))),
(297, InitCell::all((12, 29), (-10, 85), (-9, 85), (-13, 94))),
(298, InitCell::all((1, 44), (-1, 70), (-8, 81), (-12, 91))),
(299, InitCell::all((20, 36), (7, 60), (-1, 72), (-2, 77))),
(300, InitCell::all((18, 32), (9, 58), (5, 64), (0, 71))),
(301, InitCell::all((5, 42), (5, 61), (1, 67), (-1, 73))),
(302, InitCell::all((1, 48), (12, 50), (9, 56), (4, 64))),
(303, InitCell::all((10, 62), (15, 50), (0, 69), (-7, 81))),
(304, InitCell::all((17, 46), (18, 49), (1, 69), (5, 64))),
(305, InitCell::all((9, 64), (17, 54), (7, 69), (15, 57))),
(306, InitCell::all((-12, 104), (10, 41), (-7, 69), (1, 67))),
(307, InitCell::all((-11, 97), (7, 46), (-6, 67), (0, 68))),
(
308,
InitCell::all((-16, 96), (-1, 51), (-16, 77), (-10, 67)),
),
(309, InitCell::all((-7, 88), (7, 49), (-2, 64), (1, 68))),
(310, InitCell::all((-8, 85), (8, 52), (2, 61), (0, 77))),
(311, InitCell::all((-7, 85), (9, 41), (-6, 67), (2, 64))),
(312, InitCell::all((-9, 85), (6, 47), (-3, 64), (0, 68))),
(313, InitCell::all((-13, 88), (2, 55), (2, 57), (-5, 78))),
(314, InitCell::all((4, 66), (13, 41), (-3, 65), (7, 55))),
(315, InitCell::all((-3, 77), (10, 44), (-3, 66), (5, 59))),
(316, InitCell::all((-3, 76), (6, 50), (0, 62), (2, 65))),
(317, InitCell::all((-6, 76), (5, 53), (9, 51), (14, 54))),
(318, InitCell::all((10, 58), (13, 49), (-1, 66), (15, 44))),
(319, InitCell::all((-1, 76), (4, 63), (-2, 71), (5, 60))),
(320, InitCell::all((-1, 83), (6, 64), (-2, 75), (2, 70))),
(321, InitCell::all((-7, 99), (-2, 69), (-1, 70), (-2, 76))),
(322, InitCell::all((-14, 95), (-2, 59), (-9, 72), (-18, 86))),
(323, InitCell::all((2, 95), (6, 70), (14, 60), (12, 70))),
(324, InitCell::all((0, 76), (10, 44), (16, 37), (5, 64))),
(325, InitCell::all((-5, 74), (9, 31), (0, 47), (-12, 70))),
(326, InitCell::all((0, 70), (12, 43), (18, 35), (11, 55))),
(327, InitCell::all((-11, 75), (3, 53), (11, 37), (5, 56))),
(328, InitCell::all((1, 68), (14, 34), (12, 41), (0, 69))),
(329, InitCell::all((0, 65), (10, 38), (10, 41), (2, 65))),
(330, InitCell::all((-14, 73), (-3, 52), (2, 48), (-6, 74))),
(331, InitCell::all((3, 62), (13, 40), (12, 41), (5, 54))),
(332, InitCell::all((4, 62), (17, 32), (13, 41), (7, 54))),
(333, InitCell::all((-1, 68), (7, 44), (0, 59), (-6, 76))),
(334, InitCell::all((-13, 75), (7, 38), (3, 50), (-11, 82))),
(335, InitCell::all((11, 55), (13, 50), (19, 40), (-2, 77))),
(336, InitCell::all((5, 64), (10, 57), (3, 66), (-2, 77))),
(337, InitCell::all((12, 70), (26, 43), (18, 50), (25, 42))),
];
const TBL_9_23: &[(usize, InitCell)] = &[
(338, InitCell::all((15, 6), (14, 11), (19, -6), (17, -13))),
(339, InitCell::all((6, 19), (11, 14), (18, -6), (16, -9))),
(340, InitCell::all((7, 16), (9, 11), (14, 0), (17, -12))),
(341, InitCell::all((12, 14), (18, 11), (26, -12), (27, -21))),
(342, InitCell::all((18, 13), (21, 9), (31, -16), (37, -30))),
(343, InitCell::all((13, 11), (23, -2), (33, -25), (41, -40))),
(
344,
InitCell::all((13, 15), (32, -15), (33, -22), (42, -41)),
),
(
345,
InitCell::all((15, 16), (32, -15), (37, -28), (48, -47)),
),
(
346,
InitCell::all((12, 23), (34, -21), (39, -30), (39, -32)),
),
(
347,
InitCell::all((13, 23), (39, -23), (42, -30), (46, -40)),
),
(
348,
InitCell::all((15, 20), (42, -33), (47, -42), (52, -51)),
),
(
349,
InitCell::all((14, 26), (41, -31), (45, -36), (46, -41)),
),
(
350,
InitCell::all((14, 44), (46, -28), (49, -34), (52, -39)),
),
(
351,
InitCell::all((17, 40), (38, -12), (41, -17), (43, -19)),
),
(352, InitCell::all((17, 47), (21, 29), (32, 9), (32, 11))),
(
353,
InitCell::all((24, 17), (45, -24), (69, -71), (61, -55)),
),
(
354,
InitCell::all((21, 21), (53, -45), (63, -63), (56, -46)),
),
(
355,
InitCell::all((25, 22), (48, -26), (66, -64), (62, -50)),
),
(
356,
InitCell::all((31, 27), (65, -43), (77, -74), (81, -67)),
),
(
357,
InitCell::all((22, 29), (43, -19), (54, -39), (45, -20)),
),
(358, InitCell::all((19, 35), (39, -10), (52, -35), (35, -2))),
(359, InitCell::all((14, 50), (30, 9), (41, -10), (28, 15))),
(360, InitCell::all((10, 57), (18, 26), (36, 0), (34, 1))),
(361, InitCell::all((7, 63), (20, 27), (40, -1), (39, 1))),
(362, InitCell::all((-2, 77), (0, 57), (30, 14), (30, 17))),
(363, InitCell::all((-4, 82), (-14, 82), (28, 26), (20, 38))),
(364, InitCell::all((-3, 94), (-5, 75), (23, 37), (18, 45))),
(365, InitCell::all((9, 69), (-19, 97), (12, 55), (15, 54))),
(
366,
InitCell::all((-12, 109), (-35, 125), (11, 65), (0, 79)),
),
(367, InitCell::all((36, -35), (27, 0), (37, -33), (36, -16))),
(368, InitCell::all((36, -34), (28, 0), (39, -36), (37, -14))),
(
369,
InitCell::all((32, -26), (31, -4), (40, -37), (37, -17)),
),
(370, InitCell::all((37, -30), (27, 6), (38, -30), (32, 1))),
(371, InitCell::all((44, -32), (34, 8), (46, -33), (34, 15))),
(372, InitCell::all((34, -18), (30, 10), (42, -30), (29, 15))),
(373, InitCell::all((34, -15), (24, 22), (40, -24), (24, 25))),
(374, InitCell::all((40, -15), (33, 19), (49, -29), (34, 22))),
(375, InitCell::all((33, -7), (22, 32), (38, -12), (31, 16))),
(376, InitCell::all((35, -5), (26, 31), (40, -10), (35, 18))),
(377, InitCell::all((33, 0), (21, 41), (38, -3), (31, 28))),
(378, InitCell::all((38, 2), (26, 44), (46, -5), (33, 41))),
(379, InitCell::all((33, 13), (23, 47), (31, 20), (36, 28))),
(380, InitCell::all((23, 35), (16, 65), (29, 30), (27, 47))),
(381, InitCell::all((13, 58), (14, 71), (25, 44), (21, 62))),
(382, InitCell::all((29, -3), (8, 60), (12, 48), (18, 31))),
(383, InitCell::all((26, 0), (6, 63), (11, 49), (19, 26))),
(384, InitCell::all((22, 30), (17, 65), (26, 45), (36, 24))),
(385, InitCell::all((31, -7), (21, 24), (22, 22), (24, 23))),
(386, InitCell::all((35, -15), (23, 20), (23, 22), (27, 16))),
(387, InitCell::all((34, -3), (26, 23), (27, 21), (24, 30))),
(388, InitCell::all((34, 3), (27, 32), (33, 20), (31, 29))),
(389, InitCell::all((36, -1), (28, 23), (26, 28), (22, 41))),
(390, InitCell::all((34, 5), (28, 24), (30, 24), (22, 42))),
(391, InitCell::all((32, 11), (23, 40), (27, 34), (16, 60))),
(392, InitCell::all((35, 5), (24, 32), (18, 42), (15, 52))),
(393, InitCell::all((34, 12), (28, 29), (25, 39), (14, 60))),
(394, InitCell::all((39, 11), (23, 42), (18, 50), (3, 78))),
(395, InitCell::all((30, 29), (19, 57), (12, 70), (-16, 123))),
(396, InitCell::all((34, 26), (22, 53), (21, 54), (21, 53))),
(397, InitCell::all((29, 39), (22, 61), (14, 71), (22, 56))),
(398, InitCell::all((19, 66), (11, 86), (11, 83), (25, 61))),
];
const TBL_9_24: &[(usize, InitCell)] = &[
(402, InitCell::all((-17, 120), (-4, 79), (-5, 85), (-3, 78))),
(403, InitCell::all((-20, 112), (-7, 71), (-6, 81), (-8, 74))),
(
404,
InitCell::all((-18, 114), (-5, 69), (-10, 77), (-9, 72)),
),
(405, InitCell::all((-11, 85), (-9, 70), (-7, 81), (-10, 72))),
(
406,
InitCell::all((-15, 92), (-8, 66), (-17, 80), (-18, 75)),
),
(
407,
InitCell::all((-14, 89), (-10, 68), (-18, 73), (-12, 71)),
),
(
408,
InitCell::all((-26, 71), (-19, 73), (-4, 74), (-11, 63)),
),
(
409,
InitCell::all((-15, 81), (-12, 69), (-10, 83), (-5, 70)),
),
(
410,
InitCell::all((-14, 80), (-16, 70), (-9, 71), (-17, 75)),
),
(411, InitCell::all((0, 68), (-15, 67), (-9, 67), (-14, 72))),
(
412,
InitCell::all((-14, 70), (-20, 62), (-1, 61), (-16, 67)),
),
(413, InitCell::all((-24, 56), (-19, 70), (-8, 66), (-8, 53))),
(
414,
InitCell::all((-23, 68), (-16, 66), (-14, 66), (-14, 59)),
),
(415, InitCell::all((-24, 50), (-22, 65), (0, 59), (-9, 52))),
(416, InitCell::all((-11, 74), (-20, 63), (2, 59), (-11, 68))),
(417, InitCell::all((23, -13), (9, -2), (17, -10), (9, -2))),
(
418,
InitCell::all((26, -13), (26, -9), (32, -13), (30, -10)),
),
(419, InitCell::all((40, -15), (33, -9), (42, -9), (31, -4))),
(420, InitCell::all((49, -14), (39, -7), (49, -5), (33, -1))),
(421, InitCell::all((44, 3), (41, -2), (53, 0), (33, 7))),
(422, InitCell::all((45, 6), (45, 3), (64, 3), (31, 12))),
(423, InitCell::all((44, 34), (49, 9), (68, 10), (37, 23))),
(424, InitCell::all((33, 54), (45, 27), (66, 27), (31, 38))),
(425, InitCell::all((19, 82), (36, 59), (47, 57), (20, 64))),
(426, InitCell::all((-3, 75), (-6, 66), (-5, 71), (-9, 71))),
(427, InitCell::all((-1, 23), (-7, 35), (0, 24), (-7, 37))),
(428, InitCell::all((1, 34), (-7, 42), (-1, 36), (-8, 44))),
(429, InitCell::all((1, 43), (-8, 45), (-2, 42), (-11, 49))),
(430, InitCell::all((0, 54), (-5, 48), (-2, 52), (-10, 56))),
(431, InitCell::all((-2, 55), (-12, 56), (-9, 57), (-12, 59))),
(432, InitCell::all((0, 61), (-6, 60), (-6, 63), (-8, 63))),
(433, InitCell::all((1, 64), (-5, 62), (-4, 65), (-9, 67))),
(434, InitCell::all((0, 68), (-8, 66), (-4, 67), (-6, 68))),
(435, InitCell::all((-9, 92), (-8, 76), (-7, 82), (-10, 79))),
(436, InitCell::all((-14, 106), (-5, 85), (-3, 81), (-3, 78))),
(437, InitCell::all((-13, 97), (-6, 81), (-3, 76), (-8, 74))),
(438, InitCell::all((-15, 90), (-10, 77), (-7, 72), (-9, 72))),
(439, InitCell::all((-12, 90), (-7, 81), (-6, 78), (-10, 72))),
(
440,
InitCell::all((-18, 88), (-17, 80), (-12, 72), (-18, 75)),
),
(
441,
InitCell::all((-10, 73), (-18, 73), (-14, 68), (-12, 71)),
),
(442, InitCell::all((-9, 79), (-4, 74), (-3, 70), (-11, 63))),
(443, InitCell::all((-14, 86), (-10, 83), (-6, 76), (-5, 70))),
(444, InitCell::all((-10, 73), (-9, 71), (-5, 66), (-17, 75))),
(445, InitCell::all((-10, 70), (-9, 67), (-5, 62), (-14, 72))),
(446, InitCell::all((-10, 69), (-1, 61), (0, 57), (-16, 67))),
(447, InitCell::all((-5, 66), (-8, 66), (-4, 61), (-8, 53))),
(448, InitCell::all((-9, 64), (-14, 66), (-9, 60), (-14, 59))),
(449, InitCell::all((-5, 58), (0, 59), (1, 54), (-9, 52))),
(450, InitCell::all((2, 59), (2, 59), (2, 58), (-11, 68))),
(451, InitCell::all((21, -10), (21, -13), (17, -10), (9, -2))),
(
452,
InitCell::all((24, -11), (33, -14), (32, -13), (30, -10)),
),
(453, InitCell::all((28, -8), (39, -7), (42, -9), (31, -4))),
(454, InitCell::all((28, -1), (46, -2), (49, -5), (33, -1))),
(455, InitCell::all((29, 3), (51, 2), (53, 0), (33, 7))),
(456, InitCell::all((29, 9), (60, 6), (64, 3), (31, 12))),
(457, InitCell::all((35, 20), (61, 17), (68, 10), (37, 23))),
(458, InitCell::all((29, 36), (55, 34), (66, 27), (31, 38))),
(459, InitCell::all((14, 67), (42, 62), (47, 57), (20, 64))),
];
const TBL_9_25: &[(usize, InitCell)] = &[
(460, InitCell::all((-17, 123), (-7, 92), (0, 80), (11, 80))),
(461, InitCell::all((-12, 115), (-5, 89), (-5, 89), (5, 76))),
(462, InitCell::all((-16, 122), (-7, 96), (-7, 94), (2, 84))),
(
463,
InitCell::all((-11, 115), (-13, 108), (-4, 92), (5, 78)),
),
(464, InitCell::all((-12, 63), (-3, 46), (0, 39), (-6, 55))),
(465, InitCell::all((-2, 68), (-1, 65), (0, 65), (4, 61))),
(
466,
InitCell::all((-15, 84), (-1, 57), (-15, 84), (-14, 83)),
),
(
467,
InitCell::all((-13, 104), (-9, 93), (-35, 127), (-37, 127)),
),
(468, InitCell::all((-3, 70), (-3, 74), (-2, 73), (-5, 79))),
(
469,
InitCell::all((-8, 93), (-9, 92), (-12, 104), (-11, 104)),
),
(470, InitCell::all((-10, 90), (-8, 87), (-9, 91), (-11, 91))),
(
471,
InitCell::all((-30, 127), (-23, 126), (-31, 127), (-30, 127)),
),
(472, InitCell::all((-17, 123), (-7, 92), (0, 80), (11, 80))),
(473, InitCell::all((-12, 115), (-5, 89), (-5, 89), (5, 76))),
(474, InitCell::all((-16, 122), (-7, 96), (-7, 94), (2, 84))),
(
475,
InitCell::all((-11, 115), (-13, 108), (-4, 92), (5, 78)),
),
(476, InitCell::all((-12, 63), (-3, 46), (0, 39), (-6, 55))),
(477, InitCell::all((-2, 68), (-1, 65), (0, 65), (4, 61))),
(
478,
InitCell::all((-15, 84), (-1, 57), (-15, 84), (-14, 83)),
),
(
479,
InitCell::all((-13, 104), (-9, 93), (-35, 127), (-37, 127)),
),
(480, InitCell::all((-3, 70), (-3, 74), (-2, 73), (-5, 79))),
(
481,
InitCell::all((-8, 93), (-9, 92), (-12, 104), (-11, 104)),
),
(482, InitCell::all((-10, 90), (-8, 87), (-9, 91), (-11, 91))),
(
483,
InitCell::all((-30, 127), (-23, 126), (-31, 127), (-30, 127)),
),
];
const TBL_9_26: &[(usize, InitCell)] = &[
(484, InitCell::all((-7, 93), (-2, 85), (-13, 103), (-4, 86))),
(
485,
InitCell::all((-11, 87), (-6, 78), (-13, 91), (-12, 88)),
),
(486, InitCell::all((-3, 77), (-1, 75), (-9, 89), (-5, 82))),
(487, InitCell::all((-5, 71), (-7, 77), (-14, 92), (-3, 72))),
(488, InitCell::all((-4, 63), (2, 54), (-8, 76), (-4, 67))),
(489, InitCell::all((-4, 68), (5, 50), (-12, 87), (-8, 72))),
(
490,
InitCell::all((-12, 84), (-3, 68), (-23, 110), (-16, 89)),
),
(491, InitCell::all((-7, 62), (1, 50), (-24, 105), (-9, 69))),
(492, InitCell::all((-7, 65), (6, 42), (-10, 78), (-1, 59))),
(493, InitCell::all((8, 61), (-4, 81), (-20, 112), (5, 66))),
(494, InitCell::all((5, 56), (1, 63), (-17, 99), (4, 57))),
(495, InitCell::all((-2, 66), (-4, 70), (-78, 127), (-4, 71))),
(496, InitCell::all((1, 64), (0, 67), (-70, 127), (-2, 71))),
(497, InitCell::all((0, 61), (2, 57), (-50, 127), (2, 58))),
(498, InitCell::all((-2, 78), (-2, 76), (-46, 127), (-1, 74))),
(499, InitCell::all((1, 50), (11, 35), (-4, 66), (-4, 44))),
(500, InitCell::all((7, 52), (4, 64), (-5, 78), (-1, 69))),
(501, InitCell::all((10, 35), (1, 61), (-4, 71), (0, 62))),
(502, InitCell::all((0, 44), (11, 35), (-8, 72), (-7, 51))),
(503, InitCell::all((11, 38), (18, 25), (2, 59), (-4, 47))),
(504, InitCell::all((1, 45), (12, 24), (-1, 55), (-6, 42))),
(505, InitCell::all((0, 46), (13, 29), (-7, 70), (-3, 41))),
(506, InitCell::all((5, 44), (13, 36), (-6, 75), (-6, 53))),
(507, InitCell::all((31, 17), (-10, 93), (-8, 89), (8, 76))),
(508, InitCell::all((1, 51), (-7, 73), (-34, 119), (-9, 78))),
(509, InitCell::all((7, 50), (-2, 73), (-3, 75), (-11, 83))),
(510, InitCell::all((28, 19), (13, 46), (32, 20), (9, 52))),
(511, InitCell::all((16, 33), (9, 49), (30, 22), (0, 67))),
(
512,
InitCell::all((14, 62), (-7, 100), (-44, 127), (-5, 90)),
),
(513, InitCell::all((-13, 108), (9, 53), (0, 54), (1, 67))),
(514, InitCell::all((-15, 100), (2, 53), (-5, 61), (-15, 72))),
(515, InitCell::all((-13, 101), (5, 53), (0, 58), (-5, 75))),
(516, InitCell::all((-13, 91), (-2, 61), (-1, 60), (-8, 80))),
(517, InitCell::all((-12, 94), (0, 56), (-3, 61), (-21, 83))),
(518, InitCell::all((-10, 88), (0, 56), (-8, 67), (-21, 64))),
(
519,
InitCell::all((-16, 84), (-13, 63), (-25, 84), (-13, 31)),
),
(
520,
InitCell::all((-10, 86), (-5, 60), (-14, 74), (-25, 64)),
),
(521, InitCell::all((-7, 83), (-1, 62), (-5, 65), (-29, 94))),
(522, InitCell::all((-13, 87), (4, 57), (5, 52), (9, 75))),
(523, InitCell::all((-19, 94), (-6, 69), (2, 57), (17, 63))),
(524, InitCell::all((1, 70), (4, 57), (0, 61), (-8, 74))),
(525, InitCell::all((0, 72), (14, 39), (-9, 69), (-5, 35))),
(526, InitCell::all((-5, 74), (4, 51), (-11, 70), (-2, 27))),
(527, InitCell::all((18, 59), (13, 68), (18, 55), (13, 91))),
(528, InitCell::all((-7, 93), (-2, 85), (-13, 103), (-4, 86))),
(
529,
InitCell::all((-11, 87), (-6, 78), (-13, 91), (-12, 88)),
),
(530, InitCell::all((-3, 77), (-1, 75), (-9, 89), (-5, 82))),
(531, InitCell::all((-5, 71), (-7, 77), (-14, 92), (-3, 72))),
(532, InitCell::all((-4, 63), (2, 54), (-8, 76), (-4, 67))),
(533, InitCell::all((-4, 68), (5, 50), (-12, 87), (-8, 72))),
(
534,
InitCell::all((-12, 84), (-3, 68), (-23, 110), (-16, 89)),
),
(535, InitCell::all((-7, 62), (1, 50), (-24, 105), (-9, 69))),
(536, InitCell::all((-7, 65), (6, 42), (-10, 78), (-1, 59))),
(537, InitCell::all((8, 61), (-4, 81), (-20, 112), (5, 66))),
(538, InitCell::all((5, 56), (1, 63), (-17, 99), (4, 57))),
(539, InitCell::all((-2, 66), (-4, 70), (-78, 127), (-4, 71))),
(540, InitCell::all((1, 64), (0, 67), (-70, 127), (-2, 71))),
(541, InitCell::all((0, 61), (2, 57), (-50, 127), (2, 58))),
(542, InitCell::all((-2, 78), (-2, 76), (-46, 127), (-1, 74))),
(543, InitCell::all((1, 50), (11, 35), (-4, 66), (-4, 44))),
(544, InitCell::all((7, 52), (4, 64), (-5, 78), (-1, 69))),
(545, InitCell::all((10, 35), (1, 61), (-4, 71), (0, 62))),
(546, InitCell::all((0, 44), (11, 35), (-8, 72), (-7, 51))),
(547, InitCell::all((11, 38), (18, 25), (2, 59), (-4, 47))),
(548, InitCell::all((1, 45), (12, 24), (-1, 55), (-6, 42))),
(549, InitCell::all((0, 46), (13, 29), (-7, 70), (-3, 41))),
(550, InitCell::all((5, 44), (13, 36), (-6, 75), (-6, 53))),
(551, InitCell::all((31, 17), (-10, 93), (-8, 89), (8, 76))),
(552, InitCell::all((1, 51), (-7, 73), (-34, 119), (-9, 78))),
(553, InitCell::all((7, 50), (-2, 73), (-3, 75), (-11, 83))),
(554, InitCell::all((28, 19), (13, 46), (32, 20), (9, 52))),
(555, InitCell::all((16, 33), (9, 49), (30, 22), (0, 67))),
(
556,
InitCell::all((14, 62), (-7, 100), (-44, 127), (-5, 90)),
),
(557, InitCell::all((-13, 108), (9, 53), (0, 54), (1, 67))),
(558, InitCell::all((-15, 100), (2, 53), (-5, 61), (-15, 72))),
(559, InitCell::all((-13, 101), (5, 53), (0, 58), (-5, 75))),
(560, InitCell::all((-13, 91), (-2, 61), (-1, 60), (-8, 80))),
(561, InitCell::all((-12, 94), (0, 56), (-3, 61), (-21, 83))),
(562, InitCell::all((-10, 88), (0, 56), (-8, 67), (-21, 64))),
(
563,
InitCell::all((-16, 84), (-13, 63), (-25, 84), (-13, 31)),
),
(
564,
InitCell::all((-10, 86), (-5, 60), (-14, 74), (-25, 64)),
),
(565, InitCell::all((-7, 83), (-1, 62), (-5, 65), (-29, 94))),
(566, InitCell::all((-13, 87), (4, 57), (5, 52), (9, 75))),
(567, InitCell::all((-19, 94), (-6, 69), (2, 57), (17, 63))),
(568, InitCell::all((1, 70), (4, 57), (0, 61), (-8, 74))),
(569, InitCell::all((0, 72), (14, 39), (-9, 69), (-5, 35))),
(570, InitCell::all((-5, 74), (4, 51), (-11, 70), (-2, 27))),
(571, InitCell::all((18, 59), (13, 68), (18, 55), (13, 91))),
];
const TBL_9_27: &[(usize, InitCell)] = &[
(572, InitCell::all((24, 0), (11, 28), (4, 45), (4, 39))),
(573, InitCell::all((15, 9), (2, 40), (10, 28), (0, 42))),
(574, InitCell::all((8, 25), (3, 44), (10, 31), (7, 34))),
(575, InitCell::all((13, 18), (0, 49), (33, -11), (11, 29))),
(576, InitCell::all((15, 9), (0, 46), (52, -43), (8, 31))),
(577, InitCell::all((13, 19), (2, 44), (18, 15), (6, 37))),
(578, InitCell::all((10, 37), (2, 51), (28, 0), (7, 42))),
(579, InitCell::all((12, 18), (0, 47), (35, -22), (3, 40))),
(580, InitCell::all((6, 29), (4, 39), (38, -25), (8, 33))),
(581, InitCell::all((20, 33), (2, 62), (34, 0), (13, 43))),
(582, InitCell::all((15, 30), (6, 46), (39, -18), (13, 36))),
(583, InitCell::all((4, 45), (0, 54), (32, -12), (4, 47))),
(584, InitCell::all((1, 58), (3, 54), (102, -94), (3, 55))),
(585, InitCell::all((0, 62), (2, 58), (0, 0), (2, 58))),
(586, InitCell::all((7, 61), (4, 63), (56, -15), (6, 60))),
(587, InitCell::all((12, 38), (6, 51), (33, -4), (8, 44))),
(588, InitCell::all((11, 45), (6, 57), (29, 10), (11, 44))),
(589, InitCell::all((15, 39), (7, 53), (37, -5), (14, 42))),
(590, InitCell::all((11, 42), (6, 52), (51, -29), (7, 48))),
(591, InitCell::all((13, 44), (6, 55), (39, -9), (4, 56))),
(592, InitCell::all((16, 45), (11, 45), (52, -34), (4, 52))),
(593, InitCell::all((12, 41), (14, 36), (69, -58), (13, 37))),
(594, InitCell::all((10, 49), (8, 53), (67, -63), (9, 49))),
(595, InitCell::all((30, 34), (-1, 82), (44, -5), (19, 58))),
(596, InitCell::all((18, 42), (7, 55), (32, 7), (10, 48))),
(597, InitCell::all((10, 55), (-3, 78), (55, -29), (12, 45))),
(598, InitCell::all((17, 51), (15, 46), (32, 1), (0, 69))),
(599, InitCell::all((17, 46), (22, 31), (0, 0), (20, 33))),
(600, InitCell::all((0, 89), (-1, 84), (27, 36), (8, 63))),
(601, InitCell::all((26, -19), (25, 7), (33, -25), (35, -18))),
(
602,
InitCell::all((22, -17), (30, -7), (34, -30), (33, -25)),
),
(603, InitCell::all((26, -17), (28, 3), (36, -28), (28, -3))),
(604, InitCell::all((30, -25), (28, 4), (38, -28), (24, 10))),
(605, InitCell::all((28, -20), (32, 0), (38, -27), (27, 0))),
(
606,
InitCell::all((33, -23), (34, -1), (34, -18), (34, -14)),
),
(607, InitCell::all((37, -27), (30, 6), (35, -16), (52, -44))),
(608, InitCell::all((33, -23), (30, 6), (34, -14), (39, -24))),
(609, InitCell::all((40, -28), (32, 9), (32, -8), (19, 17))),
(610, InitCell::all((38, -17), (31, 19), (37, -6), (31, 25))),
(611, InitCell::all((33, -11), (26, 27), (35, 0), (36, 29))),
(612, InitCell::all((40, -15), (26, 30), (30, 10), (24, 33))),
(613, InitCell::all((41, -6), (37, 20), (28, 18), (34, 15))),
(614, InitCell::all((38, 1), (28, 34), (26, 25), (30, 20))),
(615, InitCell::all((41, 17), (17, 70), (29, 41), (22, 73))),
(616, InitCell::all((24, 0), (11, 28), (4, 45), (4, 39))),
(617, InitCell::all((15, 9), (2, 40), (10, 28), (0, 42))),
(618, InitCell::all((8, 25), (3, 44), (10, 31), (7, 34))),
(619, InitCell::all((13, 18), (0, 49), (33, -11), (11, 29))),
(620, InitCell::all((15, 9), (0, 46), (52, -43), (8, 31))),
(621, InitCell::all((13, 19), (2, 44), (18, 15), (6, 37))),
(622, InitCell::all((10, 37), (2, 51), (28, 0), (7, 42))),
(623, InitCell::all((12, 18), (0, 47), (35, -22), (3, 40))),
(624, InitCell::all((6, 29), (4, 39), (38, -25), (8, 33))),
(625, InitCell::all((20, 33), (2, 62), (34, 0), (13, 43))),
(626, InitCell::all((15, 30), (6, 46), (39, -18), (13, 36))),
(627, InitCell::all((4, 45), (0, 54), (32, -12), (4, 47))),
(628, InitCell::all((1, 58), (3, 54), (102, -94), (3, 55))),
(629, InitCell::all((0, 62), (2, 58), (0, 0), (2, 58))),
(630, InitCell::all((7, 61), (4, 63), (56, -15), (6, 60))),
(631, InitCell::all((12, 38), (6, 51), (33, -4), (8, 44))),
(632, InitCell::all((11, 45), (6, 57), (29, 10), (11, 44))),
(633, InitCell::all((15, 39), (7, 53), (37, -5), (14, 42))),
(634, InitCell::all((11, 42), (6, 52), (51, -29), (7, 48))),
(635, InitCell::all((13, 44), (6, 55), (39, -9), (4, 56))),
(636, InitCell::all((16, 45), (11, 45), (52, -34), (4, 52))),
(637, InitCell::all((12, 41), (14, 36), (69, -58), (13, 37))),
(638, InitCell::all((10, 49), (8, 53), (67, -63), (9, 49))),
(639, InitCell::all((30, 34), (-1, 82), (44, -5), (19, 58))),
(640, InitCell::all((18, 42), (7, 55), (32, 7), (10, 48))),
(641, InitCell::all((10, 55), (-3, 78), (55, -29), (12, 45))),
(642, InitCell::all((17, 51), (15, 46), (32, 1), (0, 69))),
(643, InitCell::all((17, 46), (22, 31), (0, 0), (20, 33))),
(644, InitCell::all((0, 89), (-1, 84), (27, 36), (8, 63))),
(645, InitCell::all((26, -19), (25, 7), (33, -25), (35, -18))),
(
646,
InitCell::all((22, -17), (30, -7), (34, -30), (33, -25)),
),
(647, InitCell::all((26, -17), (28, 3), (36, -28), (28, -3))),
(648, InitCell::all((30, -25), (28, 4), (38, -28), (24, 10))),
(649, InitCell::all((28, -20), (32, 0), (38, -27), (27, 0))),
(
650,
InitCell::all((33, -23), (34, -1), (34, -18), (34, -14)),
),
(651, InitCell::all((37, -27), (30, 6), (35, -16), (52, -44))),
(652, InitCell::all((33, -23), (30, 6), (34, -14), (39, -24))),
(653, InitCell::all((40, -28), (32, 9), (32, -8), (19, 17))),
(654, InitCell::all((38, -17), (31, 19), (37, -6), (31, 25))),
(655, InitCell::all((33, -11), (26, 27), (35, 0), (36, 29))),
(656, InitCell::all((40, -15), (26, 30), (30, 10), (24, 33))),
(657, InitCell::all((41, -6), (37, 20), (28, 18), (34, 15))),
(658, InitCell::all((38, 1), (28, 34), (26, 25), (30, 20))),
(659, InitCell::all((41, 17), (17, 70), (29, 41), (22, 73))),
];
const TBL_9_28: &[(usize, InitCell)] = &[
(660, InitCell::all((-17, 120), (-4, 79), (-5, 85), (-3, 78))),
(661, InitCell::all((-20, 112), (-7, 71), (-6, 81), (-8, 74))),
(
662,
InitCell::all((-18, 114), (-5, 69), (-10, 77), (-9, 72)),
),
(663, InitCell::all((-11, 85), (-9, 70), (-7, 81), (-10, 72))),
(
664,
InitCell::all((-15, 92), (-8, 66), (-17, 80), (-18, 75)),
),
(
665,
InitCell::all((-14, 89), (-10, 68), (-18, 73), (-12, 71)),
),
(
666,
InitCell::all((-26, 71), (-19, 73), (-4, 74), (-11, 63)),
),
(
667,
InitCell::all((-15, 81), (-12, 69), (-10, 83), (-5, 70)),
),
(
668,
InitCell::all((-14, 80), (-16, 70), (-9, 71), (-17, 75)),
),
(669, InitCell::all((0, 68), (-15, 67), (-9, 67), (-14, 72))),
(
670,
InitCell::all((-14, 70), (-20, 62), (-1, 61), (-16, 67)),
),
(671, InitCell::all((-24, 56), (-19, 70), (-8, 66), (-8, 53))),
(
672,
InitCell::all((-23, 68), (-16, 66), (-14, 66), (-14, 59)),
),
(673, InitCell::all((-24, 50), (-22, 65), (0, 59), (-9, 52))),
(674, InitCell::all((-11, 74), (-20, 63), (2, 59), (-11, 68))),
(675, InitCell::all((-14, 106), (-5, 85), (-3, 81), (-3, 78))),
(676, InitCell::all((-13, 97), (-6, 81), (-3, 76), (-8, 74))),
(677, InitCell::all((-15, 90), (-10, 77), (-7, 72), (-9, 72))),
(678, InitCell::all((-12, 90), (-7, 81), (-6, 78), (-10, 72))),
(
679,
InitCell::all((-18, 88), (-17, 80), (-12, 72), (-18, 75)),
),
(
680,
InitCell::all((-10, 73), (-18, 73), (-14, 68), (-12, 71)),
),
(681, InitCell::all((-9, 79), (-4, 74), (-3, 70), (-11, 63))),
(682, InitCell::all((-14, 86), (-10, 83), (-6, 76), (-5, 70))),
(683, InitCell::all((-10, 73), (-9, 71), (-5, 66), (-17, 75))),
(684, InitCell::all((-10, 70), (-9, 67), (-5, 62), (-14, 72))),
(685, InitCell::all((-10, 69), (-1, 61), (0, 57), (-16, 67))),
(686, InitCell::all((-5, 66), (-8, 66), (-4, 61), (-8, 53))),
(687, InitCell::all((-9, 64), (-14, 66), (-9, 60), (-14, 59))),
(688, InitCell::all((-5, 58), (0, 59), (1, 54), (-9, 52))),
(689, InitCell::all((2, 59), (2, 59), (2, 58), (-11, 68))),
(690, InitCell::all((23, -13), (9, -2), (17, -10), (9, -2))),
(
691,
InitCell::all((26, -13), (26, -9), (32, -13), (30, -10)),
),
(692, InitCell::all((40, -15), (33, -9), (42, -9), (31, -4))),
(693, InitCell::all((49, -14), (39, -7), (49, -5), (33, -1))),
(694, InitCell::all((44, 3), (41, -2), (53, 0), (33, 7))),
(695, InitCell::all((45, 6), (45, 3), (64, 3), (31, 12))),
(696, InitCell::all((44, 34), (49, 9), (68, 10), (37, 23))),
(697, InitCell::all((33, 54), (45, 27), (66, 27), (31, 38))),
(698, InitCell::all((19, 82), (36, 59), (47, 57), (20, 64))),
(699, InitCell::all((21, -10), (21, -13), (17, -10), (9, -2))),
(
700,
InitCell::all((24, -11), (33, -14), (32, -13), (30, -10)),
),
(701, InitCell::all((28, -8), (39, -7), (42, -9), (31, -4))),
(702, InitCell::all((28, -1), (46, -2), (49, -5), (33, -1))),
(703, InitCell::all((29, 3), (51, 2), (53, 0), (33, 7))),
(704, InitCell::all((29, 9), (60, 6), (64, 3), (31, 12))),
(705, InitCell::all((35, 20), (61, 17), (68, 10), (37, 23))),
(706, InitCell::all((29, 36), (55, 34), (66, 27), (31, 38))),
(707, InitCell::all((14, 67), (42, 62), (47, 57), (20, 64))),
(708, InitCell::all((-3, 75), (-6, 66), (-5, 71), (-9, 71))),
(709, InitCell::all((-1, 23), (-7, 35), (0, 24), (-7, 37))),
(710, InitCell::all((1, 34), (-7, 42), (-1, 36), (-8, 44))),
(711, InitCell::all((1, 43), (-8, 45), (-2, 42), (-11, 49))),
(712, InitCell::all((0, 54), (-5, 48), (-2, 52), (-10, 56))),
(713, InitCell::all((-2, 55), (-12, 56), (-9, 57), (-12, 59))),
(714, InitCell::all((0, 61), (-6, 60), (-6, 63), (-8, 63))),
(715, InitCell::all((1, 64), (-5, 62), (-4, 65), (-9, 67))),
(716, InitCell::all((0, 68), (-8, 66), (-4, 67), (-6, 68))),
(717, InitCell::all((-9, 92), (-8, 76), (-7, 82), (-10, 79))),
];
const TBL_9_29: &[(usize, InitCell)] = &[
(718, InitCell::all((-17, 120), (-4, 79), (-5, 85), (-3, 78))),
(719, InitCell::all((-20, 112), (-7, 71), (-6, 81), (-8, 74))),
(
720,
InitCell::all((-18, 114), (-5, 69), (-10, 77), (-9, 72)),
),
(721, InitCell::all((-11, 85), (-9, 70), (-7, 81), (-10, 72))),
(
722,
InitCell::all((-15, 92), (-8, 66), (-17, 80), (-18, 75)),
),
(
723,
InitCell::all((-14, 89), (-10, 68), (-18, 73), (-12, 71)),
),
(
724,
InitCell::all((-26, 71), (-19, 73), (-4, 74), (-11, 63)),
),
(
725,
InitCell::all((-15, 81), (-12, 69), (-10, 83), (-5, 70)),
),
(
726,
InitCell::all((-14, 80), (-16, 70), (-9, 71), (-17, 75)),
),
(727, InitCell::all((0, 68), (-15, 67), (-9, 67), (-14, 72))),
(
728,
InitCell::all((-14, 70), (-20, 62), (-1, 61), (-16, 67)),
),
(729, InitCell::all((-24, 56), (-19, 70), (-8, 66), (-8, 53))),
(
730,
InitCell::all((-23, 68), (-16, 66), (-14, 66), (-14, 59)),
),
(731, InitCell::all((-24, 50), (-22, 65), (0, 59), (-9, 52))),
(732, InitCell::all((-11, 74), (-20, 63), (2, 59), (-11, 68))),
(733, InitCell::all((-14, 106), (-5, 85), (-3, 81), (-3, 78))),
(734, InitCell::all((-13, 97), (-6, 81), (-3, 76), (-8, 74))),
(735, InitCell::all((-15, 90), (-10, 77), (-7, 72), (-9, 72))),
(736, InitCell::all((-12, 90), (-7, 81), (-6, 78), (-10, 72))),
(
737,
InitCell::all((-18, 88), (-17, 80), (-12, 72), (-18, 75)),
),
(
738,
InitCell::all((-10, 73), (-18, 73), (-14, 68), (-12, 71)),
),
(739, InitCell::all((-9, 79), (-4, 74), (-3, 70), (-11, 63))),
(740, InitCell::all((-14, 86), (-10, 83), (-6, 76), (-5, 70))),
(741, InitCell::all((-10, 73), (-9, 71), (-5, 66), (-17, 75))),
(742, InitCell::all((-10, 70), (-9, 67), (-5, 62), (-14, 72))),
(743, InitCell::all((-10, 69), (-1, 61), (0, 57), (-16, 67))),
(744, InitCell::all((-5, 66), (-8, 66), (-4, 61), (-8, 53))),
(745, InitCell::all((-9, 64), (-14, 66), (-9, 60), (-14, 59))),
(746, InitCell::all((-5, 58), (0, 59), (1, 54), (-9, 52))),
(747, InitCell::all((2, 59), (2, 59), (2, 58), (-11, 68))),
(748, InitCell::all((23, -13), (9, -2), (17, -10), (9, -2))),
(
749,
InitCell::all((26, -13), (26, -9), (32, -13), (30, -10)),
),
(750, InitCell::all((40, -15), (33, -9), (42, -9), (31, -4))),
(751, InitCell::all((49, -14), (39, -7), (49, -5), (33, -1))),
(752, InitCell::all((44, 3), (41, -2), (53, 0), (33, 7))),
(753, InitCell::all((45, 6), (45, 3), (64, 3), (31, 12))),
(754, InitCell::all((44, 34), (49, 9), (68, 10), (37, 23))),
(755, InitCell::all((33, 54), (45, 27), (66, 27), (31, 38))),
(756, InitCell::all((19, 82), (36, 59), (47, 57), (20, 64))),
(757, InitCell::all((21, -10), (21, -13), (17, -10), (9, -2))),
(
758,
InitCell::all((24, -11), (33, -14), (32, -13), (30, -10)),
),
(759, InitCell::all((28, -8), (39, -7), (42, -9), (31, -4))),
(760, InitCell::all((28, -1), (46, -2), (49, -5), (33, -1))),
(761, InitCell::all((29, 3), (51, 2), (53, 0), (33, 7))),
(762, InitCell::all((29, 9), (60, 6), (64, 3), (31, 12))),
(763, InitCell::all((35, 20), (61, 17), (68, 10), (37, 23))),
(764, InitCell::all((29, 36), (55, 34), (66, 27), (31, 38))),
(765, InitCell::all((14, 67), (42, 62), (47, 57), (20, 64))),
(766, InitCell::all((-3, 75), (-6, 66), (-5, 71), (-9, 71))),
(767, InitCell::all((-1, 23), (-7, 35), (0, 24), (-7, 37))),
(768, InitCell::all((1, 34), (-7, 42), (-1, 36), (-8, 44))),
(769, InitCell::all((1, 43), (-8, 45), (-2, 42), (-11, 49))),
(770, InitCell::all((0, 54), (-5, 48), (-2, 52), (-10, 56))),
(771, InitCell::all((-2, 55), (-12, 56), (-9, 57), (-12, 59))),
(772, InitCell::all((0, 61), (-6, 60), (-6, 63), (-8, 63))),
(773, InitCell::all((1, 64), (-5, 62), (-4, 65), (-9, 67))),
(774, InitCell::all((0, 68), (-8, 66), (-4, 67), (-6, 68))),
(775, InitCell::all((-9, 92), (-8, 76), (-7, 82), (-10, 79))),
];
const TBL_9_30: &[(usize, InitCell)] = &[
(
776,
InitCell::all((-6, 93), (-13, 106), (-21, 126), (-22, 127)),
),
(
777,
InitCell::all((-6, 84), (-16, 106), (-23, 124), (-25, 127)),
),
(
778,
InitCell::all((-8, 79), (-10, 87), (-20, 110), (-25, 120)),
),
(
779,
InitCell::all((0, 66), (-21, 114), (-26, 126), (-27, 127)),
),
(
780,
InitCell::all((-1, 71), (-18, 110), (-25, 124), (-19, 114)),
),
(
781,
InitCell::all((0, 62), (-14, 98), (-17, 105), (-23, 117)),
),
(
782,
InitCell::all((-2, 60), (-22, 110), (-27, 121), (-25, 118)),
),
(
783,
InitCell::all((-2, 59), (-21, 106), (-27, 117), (-26, 117)),
),
(
784,
InitCell::all((-5, 75), (-18, 103), (-17, 102), (-24, 113)),
),
(
785,
InitCell::all((-3, 62), (-21, 107), (-26, 117), (-28, 118)),
),
(
786,
InitCell::all((-4, 58), (-23, 108), (-27, 116), (-31, 120)),
),
(
787,
InitCell::all((-9, 66), (-26, 112), (-33, 122), (-37, 124)),
),
(
788,
InitCell::all((-1, 79), (-10, 96), (-10, 95), (-10, 94)),
),
(
789,
InitCell::all((0, 71), (-12, 95), (-14, 100), (-15, 102)),
),
(790, InitCell::all((3, 68), (-5, 91), (-8, 95), (-10, 99))),
(
791,
InitCell::all((10, 44), (-9, 93), (-17, 111), (-13, 106)),
),
(
792,
InitCell::all((-7, 62), (-22, 94), (-28, 114), (-50, 127)),
),
(793, InitCell::all((15, 36), (-5, 86), (-6, 89), (-5, 92))),
(794, InitCell::all((14, 40), (9, 67), (-2, 80), (17, 57))),
(795, InitCell::all((16, 27), (-4, 80), (-4, 82), (-5, 86))),
(796, InitCell::all((12, 29), (-10, 85), (-9, 85), (-13, 94))),
(797, InitCell::all((1, 44), (-1, 70), (-8, 81), (-12, 91))),
(798, InitCell::all((20, 36), (7, 60), (-1, 72), (-2, 77))),
(799, InitCell::all((18, 32), (9, 58), (5, 64), (0, 71))),
(800, InitCell::all((5, 42), (5, 61), (1, 67), (-1, 73))),
(801, InitCell::all((1, 48), (12, 50), (9, 56), (4, 64))),
(802, InitCell::all((10, 62), (15, 50), (0, 69), (-7, 81))),
(803, InitCell::all((17, 46), (18, 49), (1, 69), (5, 64))),
(804, InitCell::all((9, 64), (17, 54), (7, 69), (15, 57))),
(805, InitCell::all((-12, 104), (10, 41), (-7, 69), (1, 67))),
(806, InitCell::all((-11, 97), (7, 46), (-6, 67), (0, 68))),
(
807,
InitCell::all((-16, 96), (-1, 51), (-16, 77), (-10, 67)),
),
(808, InitCell::all((-7, 88), (7, 49), (-2, 64), (1, 68))),
(809, InitCell::all((-8, 85), (8, 52), (2, 61), (0, 77))),
(810, InitCell::all((-7, 85), (9, 41), (-6, 67), (2, 64))),
(811, InitCell::all((-9, 85), (6, 47), (-3, 64), (0, 68))),
(812, InitCell::all((-13, 88), (2, 55), (2, 57), (-5, 78))),
(813, InitCell::all((4, 66), (13, 41), (-3, 65), (7, 55))),
(814, InitCell::all((-3, 77), (10, 44), (-3, 66), (5, 59))),
(815, InitCell::all((-3, 76), (6, 50), (0, 62), (2, 65))),
(816, InitCell::all((-6, 76), (5, 53), (9, 51), (14, 54))),
(817, InitCell::all((10, 58), (13, 49), (-1, 66), (15, 44))),
(818, InitCell::all((-1, 76), (4, 63), (-2, 71), (5, 60))),
(819, InitCell::all((-1, 83), (6, 64), (-2, 75), (2, 70))),
(
820,
InitCell::all((-6, 93), (-13, 106), (-21, 126), (-22, 127)),
),
(
821,
InitCell::all((-6, 84), (-16, 106), (-23, 124), (-25, 127)),
),
(
822,
InitCell::all((-8, 79), (-10, 87), (-20, 110), (-25, 120)),
),
(
823,
InitCell::all((0, 66), (-21, 114), (-26, 126), (-27, 127)),
),
(
824,
InitCell::all((-1, 71), (-18, 110), (-25, 124), (-19, 114)),
),
(
825,
InitCell::all((0, 62), (-14, 98), (-17, 105), (-23, 117)),
),
(
826,
InitCell::all((-2, 60), (-22, 110), (-27, 121), (-25, 118)),
),
(
827,
InitCell::all((-2, 59), (-21, 106), (-27, 117), (-26, 117)),
),
(
828,
InitCell::all((-5, 75), (-18, 103), (-17, 102), (-24, 113)),
),
(
829,
InitCell::all((-3, 62), (-21, 107), (-26, 117), (-28, 118)),
),
(
830,
InitCell::all((-4, 58), (-23, 108), (-27, 116), (-31, 120)),
),
(
831,
InitCell::all((-9, 66), (-26, 112), (-33, 122), (-37, 124)),
),
(
832,
InitCell::all((-1, 79), (-10, 96), (-10, 95), (-10, 94)),
),
(
833,
InitCell::all((0, 71), (-12, 95), (-14, 100), (-15, 102)),
),
(834, InitCell::all((3, 68), (-5, 91), (-8, 95), (-10, 99))),
(
835,
InitCell::all((10, 44), (-9, 93), (-17, 111), (-13, 106)),
),
(
836,
InitCell::all((-7, 62), (-22, 94), (-28, 114), (-50, 127)),
),
(837, InitCell::all((15, 36), (-5, 86), (-6, 89), (-5, 92))),
(838, InitCell::all((14, 40), (9, 67), (-2, 80), (17, 57))),
(839, InitCell::all((16, 27), (-4, 80), (-4, 82), (-5, 86))),
(840, InitCell::all((12, 29), (-10, 85), (-9, 85), (-13, 94))),
(841, InitCell::all((1, 44), (-1, 70), (-8, 81), (-12, 91))),
(842, InitCell::all((20, 36), (7, 60), (-1, 72), (-2, 77))),
(843, InitCell::all((18, 32), (9, 58), (5, 64), (0, 71))),
(844, InitCell::all((5, 42), (5, 61), (1, 67), (-1, 73))),
(845, InitCell::all((1, 48), (12, 50), (9, 56), (4, 64))),
(846, InitCell::all((10, 62), (15, 50), (0, 69), (-7, 81))),
(847, InitCell::all((17, 46), (18, 49), (1, 69), (5, 64))),
(848, InitCell::all((9, 64), (17, 54), (7, 69), (15, 57))),
(849, InitCell::all((-12, 104), (10, 41), (-7, 69), (1, 67))),
(850, InitCell::all((-11, 97), (7, 46), (-6, 67), (0, 68))),
(
851,
InitCell::all((-16, 96), (-1, 51), (-16, 77), (-10, 67)),
),
(852, InitCell::all((-7, 88), (7, 49), (-2, 64), (1, 68))),
(853, InitCell::all((-8, 85), (8, 52), (2, 61), (0, 77))),
(854, InitCell::all((-7, 85), (9, 41), (-6, 67), (2, 64))),
(855, InitCell::all((-9, 85), (6, 47), (-3, 64), (0, 68))),
(856, InitCell::all((-13, 88), (2, 55), (2, 57), (-5, 78))),
(857, InitCell::all((4, 66), (13, 41), (-3, 65), (7, 55))),
(858, InitCell::all((-3, 77), (10, 44), (-3, 66), (5, 59))),
(859, InitCell::all((-3, 76), (6, 50), (0, 62), (2, 65))),
(860, InitCell::all((-6, 76), (5, 53), (9, 51), (14, 54))),
(861, InitCell::all((10, 58), (13, 49), (-1, 66), (15, 44))),
(862, InitCell::all((-1, 76), (4, 63), (-2, 71), (5, 60))),
(863, InitCell::all((-1, 83), (6, 64), (-2, 75), (2, 70))),
];
const TBL_9_31: &[(usize, InitCell)] = &[
(864, InitCell::all((15, 6), (14, 11), (19, -6), (17, -13))),
(865, InitCell::all((6, 19), (11, 14), (18, -6), (16, -9))),
(866, InitCell::all((7, 16), (9, 11), (14, 0), (17, -12))),
(867, InitCell::all((12, 14), (18, 11), (26, -12), (27, -21))),
(868, InitCell::all((18, 13), (21, 9), (31, -16), (37, -30))),
(869, InitCell::all((13, 11), (23, -2), (33, -25), (41, -40))),
(
870,
InitCell::all((13, 15), (32, -15), (33, -22), (42, -41)),
),
(
871,
InitCell::all((15, 16), (32, -15), (37, -28), (48, -47)),
),
(
872,
InitCell::all((12, 23), (34, -21), (39, -30), (39, -32)),
),
(
873,
InitCell::all((13, 23), (39, -23), (42, -30), (46, -40)),
),
(
874,
InitCell::all((15, 20), (42, -33), (47, -42), (52, -51)),
),
(
875,
InitCell::all((14, 26), (41, -31), (45, -36), (46, -41)),
),
(
876,
InitCell::all((14, 44), (46, -28), (49, -34), (52, -39)),
),
(
877,
InitCell::all((17, 40), (38, -12), (41, -17), (43, -19)),
),
(878, InitCell::all((17, 47), (21, 29), (32, 9), (32, 11))),
(
879,
InitCell::all((24, 17), (45, -24), (69, -71), (61, -55)),
),
(
880,
InitCell::all((21, 21), (53, -45), (63, -63), (56, -46)),
),
(
881,
InitCell::all((25, 22), (48, -26), (66, -64), (62, -50)),
),
(
882,
InitCell::all((31, 27), (65, -43), (77, -74), (81, -67)),
),
(
883,
InitCell::all((22, 29), (43, -19), (54, -39), (45, -20)),
),
(884, InitCell::all((19, 35), (39, -10), (52, -35), (35, -2))),
(885, InitCell::all((14, 50), (30, 9), (41, -10), (28, 15))),
(886, InitCell::all((10, 57), (18, 26), (36, 0), (34, 1))),
(887, InitCell::all((7, 63), (20, 27), (40, -1), (39, 1))),
(888, InitCell::all((-2, 77), (0, 57), (30, 14), (30, 17))),
(889, InitCell::all((-4, 82), (-14, 82), (28, 26), (20, 38))),
(890, InitCell::all((-3, 94), (-5, 75), (23, 37), (18, 45))),
(891, InitCell::all((9, 69), (-19, 97), (12, 55), (15, 54))),
(
892,
InitCell::all((-12, 109), (-35, 125), (11, 65), (0, 79)),
),
(893, InitCell::all((36, -35), (27, 0), (37, -33), (36, -16))),
(894, InitCell::all((36, -34), (28, 0), (39, -36), (37, -14))),
(
895,
InitCell::all((32, -26), (31, -4), (40, -37), (37, -17)),
),
(896, InitCell::all((37, -30), (27, 6), (38, -30), (32, 1))),
(897, InitCell::all((44, -32), (34, 8), (46, -33), (34, 15))),
(898, InitCell::all((34, -18), (30, 10), (42, -30), (29, 15))),
(899, InitCell::all((34, -15), (24, 22), (40, -24), (24, 25))),
(900, InitCell::all((40, -15), (33, 19), (49, -29), (34, 22))),
(901, InitCell::all((33, -7), (22, 32), (38, -12), (31, 16))),
(902, InitCell::all((35, -5), (26, 31), (40, -10), (35, 18))),
(903, InitCell::all((33, 0), (21, 41), (38, -3), (31, 28))),
(904, InitCell::all((38, 2), (26, 44), (46, -5), (33, 41))),
(905, InitCell::all((33, 13), (23, 47), (31, 20), (36, 28))),
(906, InitCell::all((23, 35), (16, 65), (29, 30), (27, 47))),
(907, InitCell::all((13, 58), (14, 71), (25, 44), (21, 62))),
(908, InitCell::all((15, 6), (14, 11), (19, -6), (17, -13))),
(909, InitCell::all((6, 19), (11, 14), (18, -6), (16, -9))),
(910, InitCell::all((7, 16), (9, 11), (14, 0), (17, -12))),
(911, InitCell::all((12, 14), (18, 11), (26, -12), (27, -21))),
(912, InitCell::all((18, 13), (21, 9), (31, -16), (37, -30))),
(913, InitCell::all((13, 11), (23, -2), (33, -25), (41, -40))),
(
914,
InitCell::all((13, 15), (32, -15), (33, -22), (42, -41)),
),
(
915,
InitCell::all((15, 16), (32, -15), (37, -28), (48, -47)),
),
(
916,
InitCell::all((12, 23), (34, -21), (39, -30), (39, -32)),
),
(
917,
InitCell::all((13, 23), (39, -23), (42, -30), (46, -40)),
),
(
918,
InitCell::all((15, 20), (42, -33), (47, -42), (52, -51)),
),
(
919,
InitCell::all((14, 26), (41, -31), (45, -36), (46, -41)),
),
(
920,
InitCell::all((14, 44), (46, -28), (49, -34), (52, -39)),
),
(
921,
InitCell::all((17, 40), (38, -12), (41, -17), (43, -19)),
),
(922, InitCell::all((17, 47), (21, 29), (32, 9), (32, 11))),
(
923,
InitCell::all((24, 17), (45, -24), (69, -71), (61, -55)),
),
(
924,
InitCell::all((21, 21), (53, -45), (63, -63), (56, -46)),
),
(
925,
InitCell::all((25, 22), (48, -26), (66, -64), (62, -50)),
),
(
926,
InitCell::all((31, 27), (65, -43), (77, -74), (81, -67)),
),
(
927,
InitCell::all((22, 29), (43, -19), (54, -39), (45, -20)),
),
(928, InitCell::all((19, 35), (39, -10), (52, -35), (35, -2))),
(929, InitCell::all((14, 50), (30, 9), (41, -10), (28, 15))),
(930, InitCell::all((10, 57), (18, 26), (36, 0), (34, 1))),
(931, InitCell::all((7, 63), (20, 27), (40, -1), (39, 1))),
(932, InitCell::all((-2, 77), (0, 57), (30, 14), (30, 17))),
(933, InitCell::all((-4, 82), (-14, 82), (28, 26), (20, 38))),
(934, InitCell::all((-3, 94), (-5, 75), (23, 37), (18, 45))),
(935, InitCell::all((9, 69), (-19, 97), (12, 55), (15, 54))),
(
936,
InitCell::all((-12, 109), (-35, 125), (11, 65), (0, 79)),
),
(937, InitCell::all((36, -35), (27, 0), (37, -33), (36, -16))),
(938, InitCell::all((36, -34), (28, 0), (39, -36), (37, -14))),
(
939,
InitCell::all((32, -26), (31, -4), (40, -37), (37, -17)),
),
(940, InitCell::all((37, -30), (27, 6), (38, -30), (32, 1))),
(941, InitCell::all((44, -32), (34, 8), (46, -33), (34, 15))),
(942, InitCell::all((34, -18), (30, 10), (42, -30), (29, 15))),
(943, InitCell::all((34, -15), (24, 22), (40, -24), (24, 25))),
(944, InitCell::all((40, -15), (33, 19), (49, -29), (34, 22))),
(945, InitCell::all((33, -7), (22, 32), (38, -12), (31, 16))),
(946, InitCell::all((35, -5), (26, 31), (40, -10), (35, 18))),
(947, InitCell::all((33, 0), (21, 41), (38, -3), (31, 28))),
(948, InitCell::all((38, 2), (26, 44), (46, -5), (33, 41))),
(949, InitCell::all((33, 13), (23, 47), (31, 20), (36, 28))),
(950, InitCell::all((23, 35), (16, 65), (29, 30), (27, 47))),
(951, InitCell::all((13, 58), (14, 71), (25, 44), (21, 62))),
];
const TBL_9_32: &[(usize, InitCell)] = &[
(
952,
InitCell::all((-3, 71), (-6, 76), (-23, 112), (-24, 115)),
),
(953, InitCell::all((-6, 42), (-2, 44), (-15, 71), (-22, 82))),
(954, InitCell::all((-5, 50), (0, 45), (-7, 61), (-9, 62))),
(955, InitCell::all((-3, 54), (0, 52), (0, 53), (0, 53))),
(956, InitCell::all((-2, 62), (-3, 64), (-5, 66), (0, 59))),
(957, InitCell::all((0, 58), (-2, 59), (-11, 77), (-14, 85))),
(958, InitCell::all((1, 63), (-4, 70), (-9, 80), (-13, 89))),
(959, InitCell::all((-2, 72), (-4, 75), (-9, 84), (-13, 94))),
(960, InitCell::all((-1, 74), (-8, 82), (-10, 87), (-11, 92))),
(
961,
InitCell::all((-9, 91), (-17, 102), (-34, 127), (-29, 127)),
),
(
962,
InitCell::all((-5, 67), (-9, 77), (-21, 101), (-21, 100)),
),
(963, InitCell::all((-5, 27), (3, 24), (-3, 39), (-14, 57))),
(964, InitCell::all((-3, 39), (0, 42), (-5, 53), (-12, 67))),
(965, InitCell::all((-2, 44), (0, 48), (-7, 61), (-11, 71))),
(966, InitCell::all((0, 46), (0, 55), (-11, 75), (-10, 77))),
(
967,
InitCell::all((-16, 64), (-6, 59), (-15, 77), (-21, 85)),
),
(968, InitCell::all((-8, 68), (-7, 71), (-17, 91), (-16, 88))),
(
969,
InitCell::all((-10, 78), (-12, 83), (-25, 107), (-23, 104)),
),
(
970,
InitCell::all((-6, 77), (-11, 87), (-25, 111), (-15, 98)),
),
(
971,
InitCell::all((-10, 86), (-30, 119), (-28, 122), (-37, 127)),
),
(972, InitCell::all((-12, 92), (1, 58), (-11, 76), (-10, 82))),
(973, InitCell::all((-15, 55), (-3, 29), (-10, 44), (-8, 48))),
(974, InitCell::all((-10, 60), (-1, 36), (-10, 52), (-8, 61))),
(975, InitCell::all((-6, 62), (1, 38), (-10, 57), (-8, 66))),
(976, InitCell::all((-4, 65), (2, 43), (-9, 58), (-7, 70))),
(
977,
InitCell::all((-12, 73), (-6, 55), (-16, 72), (-14, 75)),
),
(978, InitCell::all((-8, 76), (0, 58), (-7, 69), (-10, 79))),
(979, InitCell::all((-7, 80), (0, 64), (-4, 69), (-9, 83))),
(980, InitCell::all((-9, 88), (-3, 74), (-5, 74), (-12, 92))),
(
981,
InitCell::all((-17, 110), (-10, 90), (-9, 86), (-18, 108)),
),
(
982,
InitCell::all((-3, 71), (-6, 76), (-23, 112), (-24, 115)),
),
(983, InitCell::all((-6, 42), (-2, 44), (-15, 71), (-22, 82))),
(984, InitCell::all((-5, 50), (0, 45), (-7, 61), (-9, 62))),
(985, InitCell::all((-3, 54), (0, 52), (0, 53), (0, 53))),
(986, InitCell::all((-2, 62), (-3, 64), (-5, 66), (0, 59))),
(987, InitCell::all((0, 58), (-2, 59), (-11, 77), (-14, 85))),
(988, InitCell::all((1, 63), (-4, 70), (-9, 80), (-13, 89))),
(989, InitCell::all((-2, 72), (-4, 75), (-9, 84), (-13, 94))),
(990, InitCell::all((-1, 74), (-8, 82), (-10, 87), (-11, 92))),
(
991,
InitCell::all((-9, 91), (-17, 102), (-34, 127), (-29, 127)),
),
(
992,
InitCell::all((-5, 67), (-9, 77), (-21, 101), (-21, 100)),
),
(993, InitCell::all((-5, 27), (3, 24), (-3, 39), (-14, 57))),
(994, InitCell::all((-3, 39), (0, 42), (-5, 53), (-12, 67))),
(995, InitCell::all((-2, 44), (0, 48), (-7, 61), (-11, 71))),
(996, InitCell::all((0, 46), (0, 55), (-11, 75), (-10, 77))),
(
997,
InitCell::all((-16, 64), (-6, 59), (-15, 77), (-21, 85)),
),
(998, InitCell::all((-8, 68), (-7, 71), (-17, 91), (-16, 88))),
(
999,
InitCell::all((-10, 78), (-12, 83), (-25, 107), (-23, 104)),
),
(
1000,
InitCell::all((-6, 77), (-11, 87), (-25, 111), (-15, 98)),
),
(
1001,
InitCell::all((-10, 86), (-30, 119), (-28, 122), (-37, 127)),
),
(
1002,
InitCell::all((-12, 92), (1, 58), (-11, 76), (-10, 82)),
),
(
1003,
InitCell::all((-15, 55), (-3, 29), (-10, 44), (-8, 48)),
),
(
1004,
InitCell::all((-10, 60), (-1, 36), (-10, 52), (-8, 61)),
),
(1005, InitCell::all((-6, 62), (1, 38), (-10, 57), (-8, 66))),
(1006, InitCell::all((-4, 65), (2, 43), (-9, 58), (-7, 70))),
(
1007,
InitCell::all((-12, 73), (-6, 55), (-16, 72), (-14, 75)),
),
(1008, InitCell::all((-8, 76), (0, 58), (-7, 69), (-10, 79))),
(1009, InitCell::all((-7, 80), (0, 64), (-4, 69), (-9, 83))),
(1010, InitCell::all((-9, 88), (-3, 74), (-5, 74), (-12, 92))),
(
1011,
InitCell::all((-17, 110), (-10, 90), (-9, 86), (-18, 108)),
),
];
const TBL_9_33: &[(usize, InitCell)] = &[
(1012, InitCell::all((-3, 70), (-3, 74), (-2, 73), (-5, 79))),
(
1013,
InitCell::all((-8, 93), (-9, 92), (-12, 104), (-11, 104)),
),
(
1014,
InitCell::all((-10, 90), (-8, 87), (-9, 91), (-11, 91)),
),
(
1015,
InitCell::all((-30, 127), (-23, 126), (-31, 127), (-30, 127)),
),
(1016, InitCell::all((-3, 70), (-3, 74), (-2, 73), (-5, 79))),
(
1017,
InitCell::all((-8, 93), (-9, 92), (-12, 104), (-11, 104)),
),
(
1018,
InitCell::all((-10, 90), (-8, 87), (-9, 91), (-11, 91)),
),
(
1019,
InitCell::all((-30, 127), (-23, 126), (-31, 127), (-30, 127)),
),
(1020, InitCell::all((-3, 70), (-3, 74), (-2, 73), (-5, 79))),
(
1021,
InitCell::all((-8, 93), (-9, 92), (-12, 104), (-11, 104)),
),
(
1022,
InitCell::all((-10, 90), (-8, 87), (-9, 91), (-11, 91)),
),
(
1023,
InitCell::all((-30, 127), (-23, 126), (-31, 127), (-30, 127)),
),
];
struct InitTable {
cells: [InitCell; NUM_CTX_IDX],
}
impl InitTable {
const fn empty() -> Self {
Self {
cells: [InitCell::none(); NUM_CTX_IDX],
}
}
}
fn init_table() -> &'static [InitCell; NUM_CTX_IDX] {
use std::sync::OnceLock;
static TABLE: OnceLock<[InitCell; NUM_CTX_IDX]> = OnceLock::new();
TABLE.get_or_init(|| {
let mut arr = [InitCell::none(); NUM_CTX_IDX];
for table in &[
TBL_9_12, TBL_9_13, TBL_9_14, TBL_9_15, TBL_9_16, TBL_9_17, TBL_9_18, TBL_9_19,
TBL_9_20, TBL_9_21, TBL_9_22, TBL_9_23, TBL_9_24, TBL_9_25, TBL_9_26, TBL_9_27,
TBL_9_28, TBL_9_29, TBL_9_30, TBL_9_31, TBL_9_32, TBL_9_33,
] {
for (idx, cell) in *table {
arr[*idx] = *cell;
}
}
arr
})
}
#[derive(Debug, Clone)]
pub struct CabacContexts {
pub contexts: Vec<CtxState>,
pub slice_kind: SliceKind,
}
impl CabacContexts {
pub fn init(
slice_kind: SliceKind,
cabac_init_idc: Option<u32>,
slice_qp_y: i32,
) -> CabacResult<Self> {
let table = init_table();
let mut ctx = vec![
CtxState {
state_idx: 0,
val_mps: 0
};
NUM_CTX_IDX
];
for (idx, cell) in table.iter().enumerate() {
if let Some((m, n)) = cell.pick(slice_kind, cabac_init_idc) {
ctx[idx] = CtxState::init(m, n, slice_qp_y)?;
}
}
ctx[276] = CtxState {
state_idx: 63,
val_mps: 0,
};
Ok(Self {
contexts: ctx,
slice_kind,
})
}
pub fn at(&self, idx: usize) -> &CtxState {
&self.contexts[idx]
}
pub fn at_mut(&mut self, idx: usize) -> &mut CtxState {
&mut self.contexts[idx]
}
}
#[derive(Debug, Copy, Clone, Default)]
pub struct NeighbourCtx {
pub available_left: bool,
pub available_above: bool,
pub mb_skip_flag_left: bool,
pub mb_skip_flag_above: bool,
pub left_is_si: bool,
pub above_is_si: bool,
pub left_is_i_nxn: bool,
pub above_is_i_nxn: bool,
pub left_is_b_skip_or_direct: bool,
pub above_is_b_skip_or_direct: bool,
pub left_inter: bool,
pub above_inter: bool,
pub left_is_i_pcm: bool,
pub above_is_i_pcm: bool,
pub left_intra_chroma_pred_mode_nonzero: bool,
pub above_intra_chroma_pred_mode_nonzero: bool,
pub left_transform_8x8: bool,
pub above_transform_8x8: bool,
pub left_cbp_luma: u8,
pub above_cbp_luma: u8,
pub left_cbp_chroma: u8,
pub above_cbp_chroma: u8,
pub left_is_p_or_b_skip: bool,
pub above_is_p_or_b_skip: bool,
pub cbp_luma_mbaff: Option<[[CbpMbaffProbe; 4]; 2]>,
}
#[derive(Debug, Copy, Clone, Default)]
pub struct CbpMbaffProbe {
pub available: bool,
pub is_i_pcm: bool,
pub is_skip: bool,
pub cbp_bit_set: bool,
}
fn mb_skip_flag_ctx_offset(slice_kind: SliceKind) -> Option<u32> {
match slice_kind {
SliceKind::P | SliceKind::SP => Some(11),
SliceKind::B => Some(24),
_ => None, }
}
pub fn decode_mb_skip_flag(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
slice_kind: SliceKind,
neighbours: &NeighbourCtx,
) -> CabacResult<bool> {
let offset = mb_skip_flag_ctx_offset(slice_kind)
.expect("mb_skip_flag is not decoded on I/SI slices; caller must gate");
let cond_a = u32::from(neighbours.available_left && !neighbours.mb_skip_flag_left);
let cond_b = u32::from(neighbours.available_above && !neighbours.mb_skip_flag_above);
let ctx_idx = (offset + cond_a + cond_b) as usize;
let bin = dec.decode_decision(ctxs.at_mut(ctx_idx))?;
Ok(bin == 1)
}
fn mb_type_cond_term_flag(offset: u32, neighbours: &NeighbourCtx, is_left: bool) -> u32 {
let available = if is_left {
neighbours.available_left
} else {
neighbours.available_above
};
if !available {
return 0;
}
let filtered = match offset {
0 => {
if is_left {
neighbours.left_is_si
} else {
neighbours.above_is_si
}
}
3 => {
if is_left {
neighbours.left_is_i_nxn
} else {
neighbours.above_is_i_nxn
}
}
27 => {
if is_left {
neighbours.left_is_b_skip_or_direct
} else {
neighbours.above_is_b_skip_or_direct
}
}
_ => false,
};
u32::from(!filtered)
}
fn mb_type_ctx_inc_first3(offset: u32, bin_idx: u32, neighbours: &NeighbourCtx) -> u32 {
if bin_idx == 0 {
mb_type_cond_term_flag(offset, neighbours, true)
+ mb_type_cond_term_flag(offset, neighbours, false)
} else {
bin_idx
}
}
fn decode_mb_type_i_suffix(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
offset: u32,
already_read_bin0: Option<u8>,
) -> CabacResult<u32> {
let b0 = match already_read_bin0 {
Some(v) => v,
None => dec.decode_decision(ctxs.at_mut(offset as usize))?,
};
if b0 == 0 {
return Ok(0);
}
let b1 = dec.decode_terminate()?;
if b1 == 1 {
return Ok(25);
}
let (inc_b2, inc_b3, inc_b4_b3ne0, inc_b4_b3eq0, inc_b5_b3ne0, inc_b5_b3eq0, inc_b6) =
if offset == 3 {
(3u32, 4u32, 5u32, 6u32, 6u32, 7u32, 7u32)
} else {
(1u32, 2u32, 2u32, 3u32, 3u32, 3u32, 3u32)
};
let b2 = dec.decode_decision(ctxs.at_mut((offset + inc_b2) as usize))?;
let b3 = dec.decode_decision(ctxs.at_mut((offset + inc_b3) as usize))?;
let b4_inc = if b3 != 0 { inc_b4_b3ne0 } else { inc_b4_b3eq0 };
let b4 = dec.decode_decision(ctxs.at_mut((offset + b4_inc) as usize))?;
let b5_inc = if b3 != 0 { inc_b5_b3ne0 } else { inc_b5_b3eq0 };
let b5 = dec.decode_decision(ctxs.at_mut((offset + b5_inc) as usize))?;
let b6 = if b3 != 0 {
dec.decode_decision(ctxs.at_mut((offset + inc_b6) as usize))?
} else {
0
};
Ok(mb_type_i_suffix_value(b2, b3, b4, b5, b6))
}
fn mb_type_i_suffix_value(b2: u8, b3: u8, b4: u8, b5: u8, b6: u8) -> u32 {
let base = 12u32 * (b2 as u32);
if b3 == 0 {
base + 1 + (((b4 as u32) << 1) | (b5 as u32))
} else {
base + 5 + 4 * (b4 as u32) + (((b5 as u32) << 1) | (b6 as u32))
}
}
pub fn decode_mb_type_i(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
neighbours: &NeighbourCtx,
) -> CabacResult<u32> {
const OFFSET: u32 = 3;
let inc0 = mb_type_ctx_inc_first3(OFFSET, 0, neighbours);
let b0 = dec.decode_decision(ctxs.at_mut((OFFSET + inc0) as usize))?;
if b0 == 0 {
return Ok(0); }
decode_mb_type_i_suffix(dec, ctxs, OFFSET, Some(b0))
}
pub fn decode_mb_type_p(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
_neighbours: &NeighbourCtx,
) -> CabacResult<u32> {
const OFFSET: u32 = 14;
if ctx17_trace_enabled() {
let c14 = ctxs.at(14);
let c15 = ctxs.at(15);
let c16 = ctxs.at(16);
let c17 = ctxs.at(17);
eprintln!(
"[CTX17] pre mb_type_p: c14=({},{}) c15=({},{}) c16=({},{}) c17=({},{})",
c14.state_idx,
c14.val_mps,
c15.state_idx,
c15.val_mps,
c16.state_idx,
c16.val_mps,
c17.state_idx,
c17.val_mps,
);
}
let b0 = dec.decode_decision(ctxs.at_mut(OFFSET as usize))?;
if b0 == 1 {
let suffix = decode_mb_type_i_suffix(dec, ctxs, 17, None)?;
return Ok(5 + suffix);
}
let b1 = dec.decode_decision(ctxs.at_mut((OFFSET + 1) as usize))?;
let inc_b2 = if b1 != 1 { 2 } else { 3 };
let b2 = dec.decode_decision(ctxs.at_mut((OFFSET + inc_b2) as usize))?;
let val = match (b1, b2) {
(0, 0) => 0,
(0, 1) => 3,
(1, 1) => 1,
(1, 0) => 2,
_ => unreachable!(),
};
Ok(val)
}
pub fn decode_mb_type_b(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
neighbours: &NeighbourCtx,
) -> CabacResult<u32> {
const OFFSET: u32 = 27;
let inc0 = mb_type_ctx_inc_first3(OFFSET, 0, neighbours);
let b0 = dec.decode_decision(ctxs.at_mut((OFFSET + inc0) as usize))?;
if b0 == 0 {
return Ok(0); }
let b1 = dec.decode_decision(ctxs.at_mut((OFFSET + 3) as usize))?;
let inc_b2 = if b1 != 0 { 4 } else { 5 };
let b2 = dec.decode_decision(ctxs.at_mut((OFFSET + inc_b2) as usize))?;
if b1 == 0 {
let val = if b2 == 0 { 1 } else { 2 };
return Ok(val);
}
let b3 = dec.decode_decision(ctxs.at_mut((OFFSET + 5) as usize))?;
let b4 = dec.decode_decision(ctxs.at_mut((OFFSET + 5) as usize))?;
let b5 = dec.decode_decision(ctxs.at_mut((OFFSET + 5) as usize))?;
if b2 == 0 {
return Ok(3 + ((b3 as u32) << 2) + ((b4 as u32) << 1) + (b5 as u32));
}
if b3 == 1 && b4 == 1 && b5 == 1 {
return Ok(22); }
if b3 == 1 && b4 == 1 && b5 == 0 {
return Ok(11); }
if b3 == 1 && b4 == 0 && b5 == 1 {
let suffix = decode_mb_type_i_suffix(dec, ctxs, 32, None)?;
return Ok(23 + suffix);
}
let b6 = dec.decode_decision(ctxs.at_mut((OFFSET + 5) as usize))?;
let val = 12 + ((b3 as u32) << 3) + ((b4 as u32) << 2) + ((b5 as u32) << 1) + (b6 as u32);
Ok(val)
}
pub fn decode_mb_qp_delta(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
prev_mb_qp_delta_nonzero: bool,
) -> CabacResult<i32> {
const OFFSET: u32 = 60;
let inc0 = u32::from(prev_mb_qp_delta_nonzero);
let b0 = dec.decode_decision(ctxs.at_mut((OFFSET + inc0) as usize))?;
if b0 == 0 {
return Ok(0);
}
let b1 = dec.decode_decision(ctxs.at_mut((OFFSET + 2) as usize))?;
if b1 == 0 {
return Ok(1);
}
let mut mapped: u32 = 2;
loop {
let bin = dec.decode_decision(ctxs.at_mut((OFFSET + 3) as usize))?;
if bin == 0 {
break;
}
mapped += 1;
if mapped > 100 {
break;
}
}
let val = if mapped & 1 == 1 {
((mapped as i32) + 1) / 2
} else {
-((mapped as i32) / 2)
};
Ok(val)
}
pub fn decode_ref_idx_lx(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
neighbour_ref_idx_gt_0_left: bool,
neighbour_ref_idx_gt_0_above: bool,
) -> CabacResult<u32> {
const OFFSET: u32 = 54;
let cond_a = u32::from(neighbour_ref_idx_gt_0_left);
let cond_b = u32::from(neighbour_ref_idx_gt_0_above);
let inc0 = cond_a + 2 * cond_b;
let b0 = dec.decode_decision(ctxs.at_mut((OFFSET + inc0) as usize))?;
if b0 == 0 {
return Ok(0);
}
let b1 = dec.decode_decision(ctxs.at_mut((OFFSET + 4) as usize))?;
if b1 == 0 {
return Ok(1);
}
let mut value: u32 = 2;
loop {
let bin = dec.decode_decision(ctxs.at_mut((OFFSET + 5) as usize))?;
if bin == 0 {
break;
}
value += 1;
if value > 32 {
break;
}
}
Ok(value)
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum MvdComponent {
X,
Y,
}
pub fn decode_mvd_lx(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
component: MvdComponent,
neighbour_abs_mvd_sum: u32,
) -> CabacResult<i32> {
let offset = match component {
MvdComponent::X => 40,
MvdComponent::Y => 47,
};
let inc0 = if neighbour_abs_mvd_sum > 32 {
2
} else if neighbour_abs_mvd_sum > 2 {
1
} else {
0
};
let mut prefix_val: u32 = 0;
let bins: [u32; 9] = [inc0, 3, 4, 5, 6, 6, 6, 6, 6];
for (i, inc) in bins.iter().enumerate() {
let ctx_idx = (offset + inc) as usize;
let bin = dec.decode_decision(ctxs.at_mut(ctx_idx))?;
if bin == 0 {
prefix_val = i as u32;
break;
}
if i == 8 {
prefix_val = 9;
}
}
let abs_val: u32 = if prefix_val < 9 {
prefix_val
} else {
let k0: u32 = 3;
let mut k = k0;
let mut suf_s: u32 = 0;
loop {
let b = dec.decode_bypass()? as u32;
if b == 1 {
if k >= 30 {
return Err(CabacError::EgEscapeSuffixOverflow);
}
suf_s += 1u32 << k;
k += 1;
} else {
break;
}
}
let mut tail: u32 = 0;
for _ in 0..k {
tail = (tail << 1) | (dec.decode_bypass()? as u32);
}
suf_s + tail + 9
};
if abs_val == 0 {
return Ok(0);
}
let sign = dec.decode_bypass()? as u32;
let v = abs_val as i32;
Ok(if sign == 1 { -v } else { v })
}
pub fn decode_intra_chroma_pred_mode(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
neighbours: &NeighbourCtx,
) -> CabacResult<u32> {
const OFFSET: u32 = 64;
let cond_a = u32::from(
neighbours.available_left
&& !neighbours.left_inter
&& !neighbours.left_is_i_pcm
&& neighbours.left_intra_chroma_pred_mode_nonzero,
);
let cond_b = u32::from(
neighbours.available_above
&& !neighbours.above_inter
&& !neighbours.above_is_i_pcm
&& neighbours.above_intra_chroma_pred_mode_nonzero,
);
let inc0 = cond_a + cond_b;
let b0 = dec.decode_decision(ctxs.at_mut((OFFSET + inc0) as usize))?;
if b0 == 0 {
return Ok(0);
}
let b1 = dec.decode_decision(ctxs.at_mut((OFFSET + 3) as usize))?;
if b1 == 0 {
return Ok(1);
}
let b2 = dec.decode_decision(ctxs.at_mut((OFFSET + 3) as usize))?;
Ok(if b2 == 0 { 2 } else { 3 })
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BlockType {
Luma16x16Dc = 0,
Luma16x16Ac = 1,
Luma4x4 = 2,
ChromaDc = 3,
ChromaAc = 4,
Luma8x8 = 5,
CbIntra16x16Dc = 6,
CbIntra16x16Ac = 7,
CbLuma4x4 = 8,
Cb8x8 = 9,
CrIntra16x16Dc = 10,
CrIntra16x16Ac = 11,
CrLuma4x4 = 12,
Cr8x8 = 13,
}
impl BlockType {
fn ctx_block_cat(self) -> u32 {
self as u32
}
fn cbf_block_cat_offset(self) -> u32 {
match self {
BlockType::Luma16x16Dc => 0,
BlockType::Luma16x16Ac => 4,
BlockType::Luma4x4 => 8,
BlockType::ChromaDc => 12,
BlockType::ChromaAc => 16,
BlockType::Luma8x8 => 0,
BlockType::CbIntra16x16Dc => 0,
BlockType::CbIntra16x16Ac => 4,
BlockType::CbLuma4x4 => 8,
BlockType::Cb8x8 => 4,
BlockType::CrIntra16x16Dc => 0,
BlockType::CrIntra16x16Ac => 4,
BlockType::CrLuma4x4 => 8,
BlockType::Cr8x8 => 8,
}
}
fn sig_block_cat_offset(self) -> u32 {
match self {
BlockType::Luma16x16Dc => 0,
BlockType::Luma16x16Ac => 15,
BlockType::Luma4x4 => 29,
BlockType::ChromaDc => 44,
BlockType::ChromaAc => 47,
BlockType::Luma8x8 => 0,
BlockType::CbIntra16x16Dc => 0,
BlockType::CbIntra16x16Ac => 15,
BlockType::CbLuma4x4 => 29,
BlockType::Cb8x8 => 0,
BlockType::CrIntra16x16Dc => 0,
BlockType::CrIntra16x16Ac => 15,
BlockType::CrLuma4x4 => 29,
BlockType::Cr8x8 => 0,
}
}
fn lvl_block_cat_offset(self) -> u32 {
match self {
BlockType::Luma16x16Dc => 0,
BlockType::Luma16x16Ac => 10,
BlockType::Luma4x4 => 20,
BlockType::ChromaDc => 30,
BlockType::ChromaAc => 39,
BlockType::Luma8x8 => 0,
BlockType::CbIntra16x16Dc => 0,
BlockType::CbIntra16x16Ac => 10,
BlockType::CbLuma4x4 => 20,
BlockType::Cb8x8 => 0,
BlockType::CrIntra16x16Dc => 0,
BlockType::CrIntra16x16Ac => 10,
BlockType::CrLuma4x4 => 20,
BlockType::Cr8x8 => 0,
}
}
fn cbf_ctx_offset(self) -> u32 {
match self.ctx_block_cat() {
0..=4 => 85,
6..=8 => 460,
10..=12 => 472,
5 | 9 | 13 => 1012,
_ => 85,
}
}
fn sig_coef_ctx_offset(self, field: bool) -> u32 {
if field {
match self.ctx_block_cat() {
0..=4 => 277,
5 => 436,
6..=8 => 776,
9 => 675,
10..=12 => 820,
13 => 733,
_ => 277,
}
} else {
match self.ctx_block_cat() {
0..=4 => 105,
5 => 402,
6..=8 => 484,
9 => 660,
10..=12 => 528,
13 => 718,
_ => 105,
}
}
}
fn last_coef_ctx_offset(self, field: bool) -> u32 {
if field {
match self.ctx_block_cat() {
0..=4 => 338,
5 => 451,
6..=8 => 864,
9 => 699,
10..=12 => 908,
13 => 757,
_ => 338,
}
} else {
match self.ctx_block_cat() {
0..=4 => 166,
5 => 417,
6..=8 => 572,
9 => 690,
10..=12 => 616,
13 => 748,
_ => 166,
}
}
}
fn abs_level_ctx_offset(self) -> u32 {
match self.ctx_block_cat() {
0..=4 => 227,
5 => 426,
6..=8 => 952,
9 => 708,
10..=12 => 982,
13 => 766,
_ => 227,
}
}
}
pub fn decode_coded_block_flag(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
block_type: BlockType,
neighbour_cbf_left: Option<bool>,
neighbour_cbf_above: Option<bool>,
) -> CabacResult<bool> {
let base = block_type.cbf_ctx_offset();
let cat_offset = block_type.cbf_block_cat_offset();
let cond_a = u32::from(neighbour_cbf_left.unwrap_or(false));
let cond_b = u32::from(neighbour_cbf_above.unwrap_or(false));
let inc = cond_a + 2 * cond_b;
let ctx_idx = (base + cat_offset + inc) as usize;
let bin = dec.decode_decision(ctxs.at_mut(ctx_idx))?;
if dbg_enabled() {
eprintln!(
"[CABAC] cbf bt={:?} base={} cat={} inc={} ctx={} -> {} cond_left={:?} cond_above={:?}",
block_type, base, cat_offset, inc, ctx_idx, bin,
neighbour_cbf_left, neighbour_cbf_above
);
}
Ok(bin == 1)
}
pub fn decode_coded_block_pattern(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
neighbours: &NeighbourCtx,
chroma_array_type: u32,
) -> CabacResult<u32> {
const LUMA_OFFSET: u32 = 73;
const CHROMA_OFFSET: u32 = 77;
let mut luma: u32 = 0;
let mut prev_bins = [0u32; 4];
let cond_ext =
|avail: bool, is_i_pcm: bool, is_skip: bool, cbp_luma: u8, bit_idx_n: u32| -> u32 {
if !avail {
return 0;
}
if is_i_pcm {
return 0;
}
if is_skip {
return 1;
}
let bit_set = ((cbp_luma >> bit_idx_n) & 1) != 0;
if bit_set {
0
} else {
1
}
};
let cond_probe = |p: &CbpMbaffProbe| -> u32 {
if !p.available {
return 0;
}
if p.is_i_pcm {
return 0;
}
if p.is_skip {
return 1;
}
if p.cbp_bit_set {
0
} else {
1
}
};
for bin_idx in 0..4u32 {
let cond_a = match bin_idx {
0 | 2 => {
if let Some(probes) = &neighbours.cbp_luma_mbaff {
cond_probe(&probes[0][bin_idx as usize])
} else {
cond_ext(
neighbours.available_left,
neighbours.left_is_i_pcm,
neighbours.left_is_p_or_b_skip,
neighbours.left_cbp_luma,
if bin_idx == 0 { 1 } else { 3 },
)
}
}
1 => {
let b_k = prev_bins[0];
if b_k != 0 {
0
} else {
1
}
}
3 => {
let b_k = prev_bins[2];
if b_k != 0 {
0
} else {
1
}
}
_ => 0,
};
let cond_b = match bin_idx {
0 | 1 => {
if let Some(probes) = &neighbours.cbp_luma_mbaff {
cond_probe(&probes[1][bin_idx as usize])
} else {
cond_ext(
neighbours.available_above,
neighbours.above_is_i_pcm,
neighbours.above_is_p_or_b_skip,
neighbours.above_cbp_luma,
if bin_idx == 0 { 2 } else { 3 },
)
}
}
2 => {
let b_k = prev_bins[0];
if b_k != 0 {
0
} else {
1
}
}
3 => {
let b_k = prev_bins[1];
if b_k != 0 {
0
} else {
1
}
}
_ => 0,
};
let inc = cond_a + 2 * cond_b;
let ctx_idx = (LUMA_OFFSET + inc) as usize;
let bin = dec.decode_decision(ctxs.at_mut(ctx_idx))?;
prev_bins[bin_idx as usize] = bin as u32;
luma |= (bin as u32) << bin_idx;
}
let chroma = if chroma_array_type == 1 || chroma_array_type == 2 {
let chroma_cond =
|avail: bool, is_i_pcm: bool, is_skip: bool, cbp_chroma: u8, bin_idx: u32| -> u32 {
if !avail {
return 0;
}
if is_i_pcm {
return 1;
}
if is_skip {
return 0;
}
let zero_branch = match bin_idx {
0 => cbp_chroma == 0,
1 => cbp_chroma != 2,
_ => false,
};
if zero_branch {
0
} else {
1
}
};
let cond_a0 = chroma_cond(
neighbours.available_left,
neighbours.left_is_i_pcm,
neighbours.left_is_p_or_b_skip,
neighbours.left_cbp_chroma,
0,
);
let cond_b0 = chroma_cond(
neighbours.available_above,
neighbours.above_is_i_pcm,
neighbours.above_is_p_or_b_skip,
neighbours.above_cbp_chroma,
0,
);
let inc0 = cond_a0 + 2 * cond_b0;
let b0 = dec.decode_decision(ctxs.at_mut((CHROMA_OFFSET + inc0) as usize))?;
if b0 == 0 {
0
} else {
let cond_a1 = chroma_cond(
neighbours.available_left,
neighbours.left_is_i_pcm,
neighbours.left_is_p_or_b_skip,
neighbours.left_cbp_chroma,
1,
);
let cond_b1 = chroma_cond(
neighbours.available_above,
neighbours.above_is_i_pcm,
neighbours.above_is_p_or_b_skip,
neighbours.above_cbp_chroma,
1,
);
let inc1 = cond_a1 + 2 * cond_b1 + 4;
let b1 = dec.decode_decision(ctxs.at_mut((CHROMA_OFFSET + inc1) as usize))?;
if b1 == 0 {
1
} else {
2
}
}
} else {
0
};
Ok(luma | (chroma << 4))
}
static TBL_9_43: [(u8, u8, u8); 63] = [
(0, 0, 0),
(1, 1, 1),
(2, 1, 1),
(3, 2, 1),
(4, 2, 1),
(5, 3, 1),
(5, 3, 1),
(4, 4, 1),
(4, 5, 1),
(3, 6, 1),
(3, 7, 1),
(4, 7, 1),
(4, 7, 1),
(4, 8, 1),
(5, 4, 1),
(5, 5, 1),
(4, 6, 2),
(4, 9, 2),
(4, 10, 2),
(4, 10, 2),
(3, 8, 2),
(3, 11, 2),
(6, 12, 2),
(7, 11, 2),
(7, 9, 2),
(7, 9, 2),
(8, 10, 2),
(9, 10, 2),
(10, 8, 2),
(9, 11, 2),
(8, 12, 2),
(7, 11, 2),
(7, 9, 3),
(6, 9, 3),
(11, 10, 3),
(12, 10, 3),
(13, 8, 3),
(11, 11, 3),
(6, 12, 3),
(7, 11, 3),
(8, 9, 4),
(9, 9, 4),
(14, 10, 4),
(10, 10, 4),
(9, 8, 4),
(8, 13, 4),
(6, 13, 4),
(11, 9, 4),
(12, 9, 5),
(13, 10, 5),
(11, 10, 5),
(6, 8, 5),
(9, 13, 6),
(14, 13, 6),
(10, 9, 6),
(9, 9, 6),
(11, 10, 7),
(12, 10, 7),
(13, 14, 7),
(11, 14, 7),
(14, 14, 8),
(10, 14, 8),
(12, 14, 8),
];
fn sig_coeff_inc(block_type: BlockType, level_list_idx: u32, field: bool, num_c8x8: u32) -> u32 {
match block_type.ctx_block_cat() {
3 => {
core::cmp::min(level_list_idx / num_c8x8.max(1), 2)
}
5 | 9 | 13 => {
let row = TBL_9_43[level_list_idx as usize];
if field {
row.1 as u32
} else {
row.0 as u32
}
}
_ => {
level_list_idx
}
}
}
fn last_coeff_inc(block_type: BlockType, level_list_idx: u32, num_c8x8: u32) -> u32 {
match block_type.ctx_block_cat() {
3 => core::cmp::min(level_list_idx / num_c8x8.max(1), 2),
5 | 9 | 13 => TBL_9_43[level_list_idx as usize].2 as u32,
_ => level_list_idx,
}
}
pub fn decode_significant_coeff_flag(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
block_type: BlockType,
coeff_idx: u32,
field: bool,
num_c8x8: u32,
) -> CabacResult<bool> {
let base = block_type.sig_coef_ctx_offset(field);
let cat_offset = block_type.sig_block_cat_offset();
let inc = sig_coeff_inc(block_type, coeff_idx, field, num_c8x8);
let ctx_idx = (base + cat_offset + inc) as usize;
let bin = dec.decode_decision(ctxs.at_mut(ctx_idx))?;
Ok(bin == 1)
}
pub fn decode_last_significant_coeff_flag(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
block_type: BlockType,
coeff_idx: u32,
field: bool,
num_c8x8: u32,
) -> CabacResult<bool> {
let base = block_type.last_coef_ctx_offset(field);
let cat_offset = block_type.sig_block_cat_offset();
let inc = last_coeff_inc(block_type, coeff_idx, num_c8x8);
let ctx_idx = (base + cat_offset + inc) as usize;
let bin = dec.decode_decision(ctxs.at_mut(ctx_idx))?;
Ok(bin == 1)
}
pub fn decode_coeff_abs_level_minus1(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
block_type: BlockType,
num_decoded_eq_1: u32,
num_decoded_gt_1: u32,
) -> CabacResult<u32> {
let start_bins = dec.bin_count();
let base = block_type.abs_level_ctx_offset();
let cat_offset = block_type.lvl_block_cat_offset();
let u_coff: u32 = 14;
let inc0 = if num_decoded_gt_1 != 0 {
0
} else {
core::cmp::min(4, 1 + num_decoded_eq_1)
};
let ctx0 = (base + cat_offset + inc0) as usize;
let b0 = dec.decode_decision(ctxs.at_mut(ctx0))?;
if b0 == 0 {
dbg_emit(
"coeff_abs_level_minus1",
dec.bin_count() - start_bins,
&format!("eq1={num_decoded_eq_1} gt1={num_decoded_gt_1} val=0"),
);
return Ok(0);
}
let cat_minus = if block_type.ctx_block_cat() == 3 {
1
} else {
0
};
let inc_rest = 5 + core::cmp::min(4u32 - cat_minus, num_decoded_gt_1);
let ctx_rest = (base + cat_offset + inc_rest) as usize;
let mut prefix_val: u32 = 1;
while prefix_val < u_coff {
let bin = dec.decode_decision(ctxs.at_mut(ctx_rest))?;
if bin == 0 {
dbg_emit(
"coeff_abs_level_minus1",
dec.bin_count() - start_bins,
&format!("eq1={num_decoded_eq_1} gt1={num_decoded_gt_1} val={prefix_val}"),
);
return Ok(prefix_val);
}
prefix_val += 1;
}
let mut k: u32 = 0;
let mut suf_s: u32 = 0;
loop {
let b = dec.decode_bypass()? as u32;
if b == 1 {
if k >= 21 {
return Err(CabacError::EgEscapeSuffixOverflow);
}
suf_s += 1u32 << k;
k += 1;
} else {
break;
}
}
let mut tail: u32 = 0;
for _ in 0..k {
tail = (tail << 1) | (dec.decode_bypass()? as u32);
}
let val = u_coff + suf_s + tail;
dbg_emit(
"coeff_abs_level_minus1",
dec.bin_count() - start_bins,
&format!("eq1={num_decoded_eq_1} gt1={num_decoded_gt_1} ESCAPE k={k} val={val}"),
);
Ok(val)
}
pub fn decode_coeff_sign_flag(dec: &mut CabacDecoder<'_>) -> CabacResult<bool> {
Ok(dec.decode_bypass()? == 1)
}
pub fn decode_end_of_slice_flag(dec: &mut CabacDecoder<'_>) -> CabacResult<bool> {
let before_bins = dec.bin_count();
let (b, bi) = dec.position();
let v = dec.decode_terminate()?;
if dbg_enabled() {
eprintln!(
"[CABAC] end_of_slice_flag pre_bins={} pre_pos=({},{}) -> {}",
before_bins, b, bi, v
);
}
Ok(v == 1)
}
pub fn decode_prev_intra_pred_mode_flag(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
) -> CabacResult<bool> {
let ctx_idx = 68usize;
Ok(dec.decode_decision(ctxs.at_mut(ctx_idx))? == 1)
}
pub fn decode_rem_intra_pred_mode(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
) -> CabacResult<u32> {
let ctx_idx = 69usize;
let mut v: u32 = 0;
for i in 0..3 {
let bin = dec.decode_decision(ctxs.at_mut(ctx_idx))? as u32;
v |= bin << i;
}
Ok(v)
}
pub fn decode_transform_size_8x8_flag(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
neighbours: &NeighbourCtx,
) -> CabacResult<bool> {
const OFFSET: u32 = 399;
let cond_a = u32::from(neighbours.available_left && neighbours.left_transform_8x8);
let cond_b = u32::from(neighbours.available_above && neighbours.above_transform_8x8);
let inc = cond_a + cond_b;
let ctx_idx = (OFFSET + inc) as usize;
Ok(dec.decode_decision(ctxs.at_mut(ctx_idx))? == 1)
}
pub fn decode_sub_mb_type_p(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
) -> CabacResult<u32> {
const OFFSET: u32 = 21;
let b0 = dec.decode_decision(ctxs.at_mut(OFFSET as usize))?;
if b0 == 1 {
return Ok(0);
}
let b1 = dec.decode_decision(ctxs.at_mut((OFFSET + 1) as usize))?;
if b1 == 0 {
return Ok(1);
}
let b2 = dec.decode_decision(ctxs.at_mut((OFFSET + 2) as usize))?;
Ok(if b2 == 1 { 2 } else { 3 })
}
pub fn decode_sub_mb_type_b(
dec: &mut CabacDecoder<'_>,
ctxs: &mut CabacContexts,
) -> CabacResult<u32> {
const OFFSET: u32 = 36;
let b0 = dec.decode_decision(ctxs.at_mut(OFFSET as usize))?;
if b0 == 0 {
return Ok(0);
}
let b1 = dec.decode_decision(ctxs.at_mut((OFFSET + 1) as usize))?;
let inc_b2 = if b1 != 0 { 2 } else { 3 };
let b2 = dec.decode_decision(ctxs.at_mut((OFFSET + inc_b2) as usize))?;
if b1 == 0 {
return Ok(if b2 == 0 { 1 } else { 2 });
}
let b3 = dec.decode_decision(ctxs.at_mut((OFFSET + 3) as usize))?;
let b4 = dec.decode_decision(ctxs.at_mut((OFFSET + 3) as usize))?;
if b2 == 0 {
return Ok(3 + ((b3 as u32) << 1) + (b4 as u32));
}
if b3 == 1 {
return Ok(if b4 == 0 { 11 } else { 12 });
}
let b5 = dec.decode_decision(ctxs.at_mut((OFFSET + 3) as usize))?;
Ok(7 + ((b4 as u32) << 1) + (b5 as u32))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bitstream::BitReader;
#[test]
fn ctx_init_picks_i_si_column_for_i_slice() {
let ctxs = CabacContexts::init(SliceKind::I, None, 26).unwrap();
assert_eq!(
ctxs.at(0),
&CtxState {
state_idx: 46,
val_mps: 0
}
);
}
#[test]
fn ctx_init_picks_p_column_by_init_idc() {
let ctxs = CabacContexts::init(SliceKind::P, Some(0), 30).unwrap();
assert_eq!(
ctxs.at(11),
&CtxState {
state_idx: 12,
val_mps: 1
}
);
}
#[test]
fn ctx_init_ctx_276_is_non_adapting() {
let ctxs = CabacContexts::init(SliceKind::I, None, 26).unwrap();
assert_eq!(
ctxs.at(276),
&CtxState {
state_idx: 63,
val_mps: 0
}
);
}
#[test]
fn ctx_init_b_slice_reads_b_column() {
let ctxs = CabacContexts::init(SliceKind::B, Some(2), 26).unwrap();
assert_eq!(
ctxs.at(11),
&CtxState {
state_idx: 0,
val_mps: 0
}
);
}
fn expect_ctx(m: i32, n: i32, qp: i32) -> CtxState {
let clipped_qp = qp.clamp(0, 51);
let pre = (((m * clipped_qp) >> 4) + n).clamp(1, 126);
if pre <= 63 {
CtxState {
state_idx: (63 - pre) as u8,
val_mps: 0,
}
} else {
CtxState {
state_idx: (pre - 64) as u8,
val_mps: 1,
}
}
}
#[test]
fn ctx_402_through_459_initialised_for_b_slice() {
let ctxs = CabacContexts::init(SliceKind::B, Some(0), 26).unwrap();
assert_eq!(ctxs.at(402), &expect_ctx(-4, 79, 26));
assert_eq!(ctxs.at(417), &expect_ctx(9, -2, 26));
assert_eq!(ctxs.at(426), &expect_ctx(-6, 66, 26));
assert_eq!(ctxs.at(435), &expect_ctx(-8, 76, 26));
assert_eq!(ctxs.at(459), &expect_ctx(42, 62, 26));
}
#[test]
fn ctx_402_through_459_initialised_for_p_slice() {
let ctxs = CabacContexts::init(SliceKind::P, Some(1), 30).unwrap();
assert_eq!(ctxs.at(402), &expect_ctx(-5, 85, 30));
assert_eq!(ctxs.at(426), &expect_ctx(-5, 71, 30));
}
#[test]
fn ctx_402_for_i_slice_uses_i_si_column() {
let ctxs = CabacContexts::init(SliceKind::I, None, 21).unwrap();
assert_eq!(ctxs.at(402), &expect_ctx(-17, 120, 21));
}
#[test]
fn ctx_402_through_459_not_default_neutral() {
let ctxs = CabacContexts::init(SliceKind::B, Some(0), 26).unwrap();
let neutral = CtxState {
state_idx: 62,
val_mps: 0,
};
let count_neutral = (402..=459).filter(|&i| ctxs.at(i) == &neutral).count();
assert!(
count_neutral < 5,
"ctxIdx 402..=459 came back as the neutral (62, 0) default \
{count_neutral} times — TBL_9_24 likely missing from the \
init dispatcher (see init_table())",
);
}
fn make_decoder(data: &[u8]) -> CabacDecoder<'_> {
CabacDecoder::new(BitReader::new(data)).unwrap()
}
#[test]
fn mb_skip_flag_offset_ranges() {
assert_eq!(mb_skip_flag_ctx_offset(SliceKind::P), Some(11));
assert_eq!(mb_skip_flag_ctx_offset(SliceKind::SP), Some(11));
assert_eq!(mb_skip_flag_ctx_offset(SliceKind::B), Some(24));
assert!(mb_skip_flag_ctx_offset(SliceKind::I).is_none());
}
#[test]
fn mb_skip_flag_decode_mps() {
let data = [0x00, 0x00, 0x00];
let mut dec = make_decoder(&data);
let mut ctxs = CabacContexts::init(SliceKind::P, Some(0), 26).unwrap();
let neighbours = NeighbourCtx::default();
let flag = decode_mb_skip_flag(&mut dec, &mut ctxs, SliceKind::P, &neighbours).unwrap();
let mut dec2 = make_decoder(&data);
let mut ctxs2 = CabacContexts::init(SliceKind::P, Some(0), 26).unwrap();
let flag2 = decode_mb_skip_flag(&mut dec2, &mut ctxs2, SliceKind::P, &neighbours).unwrap();
assert_eq!(flag, flag2);
}
#[test]
fn mb_type_i_i_nxn() {
let data = [0x00, 0x00, 0x00];
let mut dec = make_decoder(&data);
let mut ctxs = CabacContexts::init(SliceKind::I, None, 26).unwrap();
let neighbours = NeighbourCtx::default();
let mb_type = decode_mb_type_i(&mut dec, &mut ctxs, &neighbours).unwrap();
assert_eq!(mb_type, 0);
}
#[test]
fn mb_type_i_suffix_value_matches_table_9_36() {
let cases: &[(u32, u8, u8, u8, u8, u8)] = &[
(1, 0, 0, 0, 0, 0), (2, 0, 0, 0, 1, 0), (3, 0, 0, 1, 0, 0), (4, 0, 0, 1, 1, 0), (5, 0, 1, 0, 0, 0), (6, 0, 1, 0, 0, 1), (7, 0, 1, 0, 1, 0), (8, 0, 1, 0, 1, 1), (9, 0, 1, 1, 0, 0), (10, 0, 1, 1, 0, 1), (11, 0, 1, 1, 1, 0), (12, 0, 1, 1, 1, 1), (13, 1, 0, 0, 0, 0), (14, 1, 0, 0, 1, 0), (15, 1, 0, 1, 0, 0), (16, 1, 0, 1, 1, 0), (17, 1, 1, 0, 0, 0), (18, 1, 1, 0, 0, 1), (19, 1, 1, 0, 1, 0), (20, 1, 1, 0, 1, 1), (21, 1, 1, 1, 0, 0), (22, 1, 1, 1, 0, 1), (23, 1, 1, 1, 1, 0), (24, 1, 1, 1, 1, 1), ];
for &(expected, b2, b3, b4, b5, b6) in cases {
let got = mb_type_i_suffix_value(b2, b3, b4, b5, b6);
assert_eq!(
got, expected,
"mb_type_i_suffix_value({b2},{b3},{b4},{b5},{b6}) = {got}, want {expected}"
);
}
let mut seen = std::collections::BTreeSet::new();
for b2 in 0..=1u8 {
for b4 in 0..=1u8 {
for b5 in 0..=1u8 {
seen.insert(mb_type_i_suffix_value(b2, 0, b4, b5, 0));
for b6 in 0..=1u8 {
seen.insert(mb_type_i_suffix_value(b2, 1, b4, b5, b6));
}
}
}
}
let expected_set: std::collections::BTreeSet<u32> = (1u32..=24).collect();
assert_eq!(seen, expected_set);
}
#[test]
fn coeff_sign_flag_bypass_round_trip() {
let data = [0xFE, 0x80, 0x00]; let mut dec = make_decoder(&data);
let sign = decode_coeff_sign_flag(&mut dec).unwrap();
assert!(sign);
}
#[test]
fn end_of_slice_flag_not_yet() {
let data = [0x00, 0x00, 0x00];
let mut dec = make_decoder(&data);
let flag = decode_end_of_slice_flag(&mut dec).unwrap();
assert!(!flag);
}
#[test]
fn end_of_slice_flag_fires() {
let data = [0xFE, 0x80, 0x00];
let mut dec = make_decoder(&data);
let flag = decode_end_of_slice_flag(&mut dec).unwrap();
assert!(flag);
}
#[test]
fn block_type_cat_offsets() {
assert_eq!(BlockType::Luma16x16Dc.ctx_block_cat(), 0);
assert_eq!(BlockType::ChromaDc.ctx_block_cat(), 3);
assert_eq!(BlockType::Luma8x8.ctx_block_cat(), 5);
assert_eq!(BlockType::Cr8x8.ctx_block_cat(), 13);
}
#[test]
fn block_type_cbf_block_cat_offsets_match_table_9_40() {
assert_eq!(BlockType::Luma16x16Dc.cbf_block_cat_offset(), 0);
assert_eq!(BlockType::Luma16x16Ac.cbf_block_cat_offset(), 4);
assert_eq!(BlockType::Luma4x4.cbf_block_cat_offset(), 8);
assert_eq!(BlockType::ChromaDc.cbf_block_cat_offset(), 12);
assert_eq!(BlockType::ChromaAc.cbf_block_cat_offset(), 16);
assert_eq!(BlockType::Luma8x8.cbf_block_cat_offset(), 0);
assert_eq!(BlockType::CbIntra16x16Dc.cbf_block_cat_offset(), 0);
assert_eq!(BlockType::CbIntra16x16Ac.cbf_block_cat_offset(), 4);
assert_eq!(BlockType::CbLuma4x4.cbf_block_cat_offset(), 8);
assert_eq!(BlockType::Cb8x8.cbf_block_cat_offset(), 4);
assert_eq!(BlockType::CrIntra16x16Dc.cbf_block_cat_offset(), 0);
assert_eq!(BlockType::CrIntra16x16Ac.cbf_block_cat_offset(), 4);
assert_eq!(BlockType::CrLuma4x4.cbf_block_cat_offset(), 8);
assert_eq!(BlockType::Cr8x8.cbf_block_cat_offset(), 8);
}
#[test]
fn tbl_9_43_sentinel_cells() {
assert_eq!(TBL_9_43[0], (0, 0, 0));
assert_eq!(TBL_9_43[1], (1, 1, 1));
assert_eq!(TBL_9_43[15], (5, 5, 1));
assert_eq!(TBL_9_43[32], (7, 9, 3));
assert_eq!(TBL_9_43[62], (12, 14, 8));
}
#[test]
fn ref_idx_lx_decodes_zero_with_mps_stream() {
let data = [0x00, 0x00, 0x00, 0x00];
let mut dec = make_decoder(&data);
let mut ctxs = CabacContexts::init(SliceKind::P, Some(0), 26).unwrap();
let v = decode_ref_idx_lx(&mut dec, &mut ctxs, false, false).unwrap();
assert_eq!(v, 0);
}
#[test]
fn mb_qp_delta_zero_path() {
let data = [0x00, 0x00, 0x00, 0x00];
let mut dec = make_decoder(&data);
let mut ctxs = CabacContexts::init(SliceKind::P, Some(0), 26).unwrap();
let v = decode_mb_qp_delta(&mut dec, &mut ctxs, false).unwrap();
assert_eq!(v, 0);
}
#[test]
fn intra_chroma_pred_mode_zero_path() {
let data = [0x00, 0x00, 0x00, 0x00];
let mut dec = make_decoder(&data);
let mut ctxs = CabacContexts::init(SliceKind::I, None, 26).unwrap();
let neighbours = NeighbourCtx::default();
let v = decode_intra_chroma_pred_mode(&mut dec, &mut ctxs, &neighbours).unwrap();
assert!(v > 0);
}
#[test]
fn decoder_new_init_table_populated_ranges() {
let table = init_table();
assert!(table[0].i_si.is_some()); assert!(table[11].p0.is_some()); assert!(table[54].p0.is_some()); assert!(table[68].i_si.is_some()); assert!(table[104].p1.is_some()); assert!(table[105].p0.is_some()); assert!(table[226].p2.is_some()); assert!(table[275].i_si.is_some()); }
#[test]
fn p_slice_intra_suffix_reads_bin0_of_suffix() {
let data = [0x00, 0x00, 0x00, 0x00, 0x00];
let mut dec = make_decoder(&data);
let mut ctxs = CabacContexts::init(SliceKind::P, Some(0), 26).unwrap();
let before = dec.bin_count();
let _ = decode_mb_type_p(&mut dec, &mut ctxs, &NeighbourCtx::default()).unwrap();
let bins_used = dec.bin_count() - before;
assert_eq!(bins_used, 3, "inter P mb_type must read exactly 3 bins");
}
fn assert_bins_consumed(data: &[u8], expected: u64, body: impl FnOnce(&mut CabacDecoder<'_>)) {
let mut dec = make_decoder(data);
let before = dec.bin_count();
body(&mut dec);
let got = dec.bin_count() - before;
assert_eq!(got, expected, "bin count mismatch");
}
#[test]
fn i_suffix_helper_reads_binidx_1_through_6_when_b3_nonzero() {
let data = [0x00, 0x00, 0x00, 0x00, 0x00];
assert_bins_consumed(&data, 6, |dec| {
let mut ctxs = CabacContexts::init(SliceKind::I, None, 26).unwrap();
let _ = decode_mb_type_i_suffix(dec, &mut ctxs, 3, Some(1)).unwrap();
});
}
#[test]
fn p_suffix_helper_reads_binidx_0_through_5() {
let data = [0x00, 0x00, 0x00, 0x00, 0x00];
assert_bins_consumed(&data, 6, |dec| {
let mut ctxs = CabacContexts::init(SliceKind::P, Some(0), 26).unwrap();
let _ = decode_mb_type_i_suffix(dec, &mut ctxs, 17, None).unwrap();
});
}
#[test]
fn b_suffix_helper_reads_binidx_0_through_5() {
let data = [0x00, 0x00, 0x00, 0x00, 0x00];
assert_bins_consumed(&data, 6, |dec| {
let mut ctxs = CabacContexts::init(SliceKind::B, Some(0), 26).unwrap();
let _ = decode_mb_type_i_suffix(dec, &mut ctxs, 32, None).unwrap();
});
}
#[test]
fn p_suffix_helper_i_nxn_stops_after_one_bin() {
let data = [0x8D, 0x80, 0x00, 0x00];
let mut dec = make_decoder(&data);
let before = dec.bin_count();
let mut ctxs = CabacContexts::init(SliceKind::P, Some(0), 26).unwrap();
let v = decode_mb_type_i_suffix(&mut dec, &mut ctxs, 17, None).unwrap();
let bins = dec.bin_count() - before;
assert_eq!(v, 0, "I_NxN in P slice is Table 9-36 row 0");
assert_eq!(bins, 1, "I_NxN path reads exactly binIdx=0 of the suffix");
}
struct TestEncoder {
cod_i_low: u32,
cod_i_range: u32,
first_bit_flag: bool,
bits_outstanding: u64,
bits: Vec<u8>, bit_pos_in_byte: u8, }
impl TestEncoder {
fn new() -> Self {
Self {
cod_i_low: 0,
cod_i_range: 510,
first_bit_flag: true,
bits_outstanding: 0,
bits: Vec::new(),
bit_pos_in_byte: 0,
}
}
fn write_bit(&mut self, b: u8) {
if self.bit_pos_in_byte == 0 {
self.bits.push(0);
}
let idx = self.bits.len() - 1;
let shift = 7 - self.bit_pos_in_byte;
self.bits[idx] |= (b & 1) << shift;
self.bit_pos_in_byte = (self.bit_pos_in_byte + 1) % 8;
}
fn put_bit(&mut self, b: u8) {
if self.first_bit_flag {
self.first_bit_flag = false;
} else {
self.write_bit(b);
}
while self.bits_outstanding > 0 {
self.write_bit(1 - b);
self.bits_outstanding -= 1;
}
}
fn renorm_e(&mut self) {
while self.cod_i_range < 256 {
if self.cod_i_low < 256 {
self.put_bit(0);
} else if self.cod_i_low >= 512 {
self.cod_i_low -= 512;
self.put_bit(1);
} else {
self.cod_i_low -= 256;
self.bits_outstanding += 1;
}
self.cod_i_range <<= 1;
self.cod_i_low <<= 1;
}
}
fn encode_decision(&mut self, ctx: &mut crate::cabac::CtxState, bin: u8) {
let q_idx = ((self.cod_i_range >> 6) & 0b11) as usize;
let cod_i_range_lps = crate::cabac::RANGE_TAB_LPS[ctx.state_idx as usize][q_idx] as u32;
self.cod_i_range -= cod_i_range_lps;
if bin != ctx.val_mps {
self.cod_i_low += self.cod_i_range;
self.cod_i_range = cod_i_range_lps;
if ctx.state_idx == 0 {
ctx.val_mps = 1 - ctx.val_mps;
}
ctx.state_idx = crate::cabac::TRANS_IDX_LPS[ctx.state_idx as usize];
} else {
ctx.state_idx = crate::cabac::TRANS_IDX_MPS[ctx.state_idx as usize];
}
self.renorm_e();
}
fn finish(mut self) -> Vec<u8> {
self.cod_i_range = 2;
self.renorm_e();
self.put_bit(((self.cod_i_low >> 9) & 1) as u8);
let last2 = ((self.cod_i_low >> 7) & 3) | 1;
self.write_bit(((last2 >> 1) & 1) as u8);
self.write_bit((last2 & 1) as u8);
while self.bit_pos_in_byte != 0 {
self.write_bit(0);
}
for _ in 0..4 {
self.bits.push(0);
}
self.bits
}
}
fn round_trip_bins(
slice_kind: SliceKind,
init_idc: Option<u32>,
qp: i32,
bins: &[(usize, u8)],
) -> (Vec<u8>, CabacContexts) {
let mut enc = TestEncoder::new();
let mut enc_ctxs = CabacContexts::init(slice_kind, init_idc, qp).unwrap();
for &(ctx_idx, bin) in bins {
enc.encode_decision(enc_ctxs.at_mut(ctx_idx), bin);
}
let bytes = enc.finish();
let mut dec = make_decoder(&bytes);
let mut dec_ctxs = CabacContexts::init(slice_kind, init_idc, qp).unwrap();
let mut decoded = Vec::with_capacity(bins.len());
for &(ctx_idx, _) in bins {
let b = dec.decode_decision(dec_ctxs.at_mut(ctx_idx)).unwrap();
decoded.push(b);
}
(decoded, dec_ctxs)
}
#[test]
fn test_encoder_round_trips_simple_sequences() {
for bin in [0u8, 1] {
let (decoded, _) = round_trip_bins(SliceKind::P, Some(0), 26, &[(21, bin)]);
assert_eq!(decoded, vec![bin]);
}
let bins = [(21, 0u8), (22, 1), (23, 0)];
let (decoded, _) = round_trip_bins(SliceKind::P, Some(0), 26, &bins);
assert_eq!(
decoded,
vec![0, 1, 0],
"test encoder must round-trip a 3-bin P sub_mb_type sequence"
);
let bins: [(usize, u8); 6] = [(36, 1), (37, 1), (38, 1), (39, 0), (39, 0), (39, 0)];
let (decoded, _) = round_trip_bins(SliceKind::B, Some(2), 26, &bins);
let expected: Vec<u8> = bins.iter().map(|&(_, b)| b).collect();
assert_eq!(decoded, expected);
}
#[test]
fn sub_mb_type_p_round_trips_all_values() {
let cases: [(&[(usize, u8)], u32); 4] = [
(&[(21, 1)], 0),
(&[(21, 0), (22, 0)], 1),
(&[(21, 0), (22, 1), (23, 1)], 2),
(&[(21, 0), (22, 1), (23, 0)], 3),
];
for &(bins, expected) in &cases {
let mut enc = TestEncoder::new();
let mut enc_ctxs = CabacContexts::init(SliceKind::P, Some(0), 26).unwrap();
for &(ctx_idx, b) in bins {
enc.encode_decision(enc_ctxs.at_mut(ctx_idx), b);
}
let bytes = enc.finish();
let mut dec = make_decoder(&bytes);
let mut dec_ctxs = CabacContexts::init(SliceKind::P, Some(0), 26).unwrap();
let got = decode_sub_mb_type_p(&mut dec, &mut dec_ctxs).unwrap();
assert_eq!(
got, expected,
"P sub_mb_type round-trip: bins {bins:?} expected {expected}, got {got}"
);
}
}
#[test]
fn sub_mb_type_b_round_trips_all_values() {
fn build(bs: &[u8]) -> Vec<(usize, u8)> {
let mut out: Vec<(usize, u8)> = Vec::with_capacity(bs.len());
let mut b1: u8 = 0;
for (i, &bit) in bs.iter().enumerate() {
let ctx_idx: usize = match i {
0 => 36, 1 => 37, 2
if b1 != 0 => {
36 + 2
}
_ => 36 + 3, };
out.push((ctx_idx, bit));
if i == 1 {
b1 = bit;
}
}
out
}
let cases: [(&[u8], u32); 13] = [
(&[0], 0), (&[1, 0, 0], 1), (&[1, 0, 1], 2), (&[1, 1, 0, 0, 0], 3), (&[1, 1, 0, 0, 1], 4), (&[1, 1, 0, 1, 0], 5), (&[1, 1, 0, 1, 1], 6), (&[1, 1, 1, 0, 0, 0], 7), (&[1, 1, 1, 0, 0, 1], 8), (&[1, 1, 1, 0, 1, 0], 9), (&[1, 1, 1, 0, 1, 1], 10), (&[1, 1, 1, 1, 0], 11), (&[1, 1, 1, 1, 1], 12), ];
for &(bs, expected) in &cases {
let bins = build(bs);
let mut enc = TestEncoder::new();
let mut enc_ctxs = CabacContexts::init(SliceKind::B, Some(1), 26).unwrap();
for &(ctx_idx, b) in &bins {
enc.encode_decision(enc_ctxs.at_mut(ctx_idx), b);
}
let bytes = enc.finish();
let mut dec = make_decoder(&bytes);
let mut dec_ctxs = CabacContexts::init(SliceKind::B, Some(1), 26).unwrap();
let got = decode_sub_mb_type_b(&mut dec, &mut dec_ctxs).unwrap();
assert_eq!(
got, expected,
"B sub_mb_type round-trip: bin string {bs:?} expected {expected}, got {got}"
);
}
}
}