///|
/// Bounded AV1 SPLIT tile decoder for a 64x64 reduced-still frame.
///
/// This path shares one MSAC reader and one mutable coefficient context across
/// the four 32x32 luma children. It is deliberately narrow (4:2:0, 8-bit,
/// DC intra prediction and all-zero chroma), but walks the real split syntax.
fn av1_split_luma_zero(q : Int) -> Array[Int] {
if q <= 20 {
[17920, 32768, 0]
} else if q <= 60 {
[26726, 32768, 0]
} else if q <= 120 {
[30669, 32768, 0]
} else {
[31671, 32768, 0]
}
}
///|
fn av1_split_chroma_zero(q : Int) -> Array[Int] {
if q <= 20 {
[3778, 32768, 0]
} else if q <= 60 {
[4215, 32768, 0]
} else if q <= 120 {
[3648, 32768, 0]
} else {
[3440, 32768, 0]
}
}
///|
fn av1_split_partition_cdf(use_128x128_superblock : Bool) -> Array[Int] {
if use_128x128_superblock {
[27899, 28219, 28529, 32484, 32539, 32619, 32639, 32768, 0]
} else {
[20137, 21547, 23078, 29566, 29837, 30261, 30524, 30892, 31724, 32768, 0]
}
}
///|
fn av1_split_skip_cdf() -> Array[Int] {
[31671, 32768, 0]
}
///|
fn av1_split_y_mode_cdf() -> Array[Int] {
[
15588, 17027, 19338, 20218, 20682, 21110, 21825, 23244, 24189, 28165, 29093,
30466, 32768, 0,
]
}
///|
fn av1_split_uv_mode_cdf() -> Array[Int] {
[
22631, 24152, 25378, 25661, 25986, 26520, 27055, 27923, 28244, 30059, 30941,
31961, 32768, 0,
]
}
///|
/// Decode a 64x64 root whose first partition symbol is SPLIT.
pub fn av1_decode_split_tile_64x64(
tile_payload : Array[Byte],
base_q_idx : Int,
disable_cdf_update? : Bool = false,
full_range? : Bool = false,
matrix_coefficients? : Int = 6,
use_128x128_superblock? : Bool = false,
allow_screen_content_tools? : Bool = false,
) -> Image? {
if tile_payload.length() == 0 ||
tile_payload.length() > 255 ||
base_q_idx < 0 ||
base_q_idx > 255 {
return None
}
let decoder = av1_msac_new(tile_payload, !disable_cdf_update)
if decoder.symbol(av1_split_partition_cdf(use_128x128_superblock)) != 3 {
return None
}
let y_context = av1_coeff_context(base_q_idx, 3, 0)
let y_zero = av1_split_luma_zero(base_q_idx)
let c_zero = av1_split_chroma_zero(base_q_idx)
let y_coeffs : Array[Array[Int]] = []
let y_modes : Array[Int] = []
let u_coeffs : Array[Array[Int]] = []
let v_coeffs : Array[Array[Int]] = []
let u_modes : Array[Int] = []
let v_modes : Array[Int] = []
for child in 0..<4 {
if decoder.symbol(av1_split_skip_cdf()) != 0 {
return None
}
let mode = decoder.symbol(av1_split_y_mode_cdf())
if allow_screen_content_tools &&
mode == 0 &&
decoder.symbol([32309, 32768, 0]) != 0 {
return None
}
if allow_screen_content_tools && decoder.symbol([32461, 32768, 0]) != 0 {
return None
}
let all_zero = decoder.symbol(y_zero)
if all_zero == 0 {
let blocks = match
av1_tx_decode_coeff_leaves(
decoder,
base_q_idx,
y_context,
{ row: child / 2 * 32, col: child % 2 * 32, width: 32, height: 32, },
[Av1TxNone],
8,
) {
Some(value) => value
None => return None
}
y_coeffs.push(blocks[0])
} else if all_zero == 1 {
y_coeffs.push(Array::make(32 * 32, 0))
} else {
return None
}
y_modes.push(mode)
let uv_mode = decoder.symbol(av1_split_uv_mode_cdf())
let u_zero = decoder.symbol(c_zero)
if u_zero == 1 {
u_coeffs.push(Array::make(16 * 16, 0))
} else if u_zero == 0 {
let blocks = match
av1_tx_decode_coeff_leaves(
decoder,
base_q_idx,
av1_coeff_context(base_q_idx, 3, 1),
{ row: 0, col: 0, width: 32, height: 32, },
[Av1TxNone],
8,
) {
Some(value) => value
None => return None
}
u_coeffs.push(blocks[0])
} else {
return None
}
let v_zero = decoder.symbol(c_zero)
if v_zero == 1 {
v_coeffs.push(Array::make(16 * 16, 0))
} else if v_zero == 0 {
let blocks = match
av1_tx_decode_coeff_leaves(
decoder,
base_q_idx,
av1_coeff_context(base_q_idx, 3, 2),
{ row: 0, col: 0, width: 32, height: 32, },
[Av1TxNone],
8,
) {
Some(value) => value
None => return None
}
v_coeffs.push(blocks[0])
} else {
return None
}
if uv_mode < 0 || uv_mode > AV1_INTRA_PAETH {
return None
}
u_modes.push(uv_mode)
v_modes.push(uv_mode)
}
av1_reconstruct_split_64x64(
y_coeffs,
u_coeffs,
v_coeffs,
y_modes,
u_modes,
v_modes,
full_range~,
matrix_coefficients~,
)
}
///|
test "split tile probe rejects a non-split root" {
assert_true(av1_decode_split_tile_64x64([b'\x2E'], 43) is None)
}