1use std::io;
2
3use scuffle_bytes_util::BitReader;
4use scuffle_expgolomb::BitReaderExpGolombExt;
5
6const TABLE_7_5: [i64; 16] = [16; 16];
10
11#[rustfmt::skip]
15const TABLE_7_6_02: [i64; 64] = [
16 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 16, 17, 16, 17, 18,
18 17, 18, 18, 17, 18, 21, 19, 20, 21, 20, 19, 21, 24, 22, 22, 24,
19 24, 22, 22, 24, 25, 25, 27, 30, 27, 25, 25, 29, 31, 35, 35, 31,
20 29, 36, 41, 44, 41, 36, 47, 54, 54, 47, 65, 70, 65, 88, 88, 115,
21];
22
23#[rustfmt::skip]
27const TABLE_7_6_35: [i64; 64] = [
28 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18,
30 18, 18, 18, 18, 18, 20, 20, 20, 20, 20, 20, 20, 24, 24, 24, 24,
31 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 28, 28, 28, 28, 28,
32 28, 33, 33, 33, 33, 33, 41, 41, 41, 41, 54, 54, 54, 71, 71, 91,
33];
34
35const TABLE_7_6: [[i64; 64]; 6] = [
39 TABLE_7_6_02,
40 TABLE_7_6_02,
41 TABLE_7_6_02,
42 TABLE_7_6_35,
43 TABLE_7_6_35,
44 TABLE_7_6_35,
45];
46
47#[derive(Debug, Clone, PartialEq)]
54pub struct ScalingListData {
55 pub scaling_list: [[[i64; 64]; 6]; 4],
59}
60
61impl ScalingListData {
62 pub(crate) fn parse<R: io::Read>(bit_reader: &mut BitReader<R>) -> io::Result<Self> {
63 let mut scaling_list = [[[0; 64]; 6]; 4];
64
65 for (size_id, scaling_column) in scaling_list.iter_mut().enumerate() {
66 let mut matrix_id = 0;
67
68 while matrix_id < 6 {
69 let scaling_list_pred_mode_flag = bit_reader.read_bit()?;
70
71 if !scaling_list_pred_mode_flag {
72 let scaling_list_pred_matrix_id_delta = bit_reader.read_exp_golomb()? as usize;
75
76 if scaling_list_pred_matrix_id_delta == 0 {
77 if size_id == 0 {
79 scaling_column[matrix_id][0..16].copy_from_slice(&TABLE_7_5);
80 } else {
81 let end = usize::min(63, (1 << (4 + (size_id << 1))) - 1);
82 scaling_column[matrix_id][0..end].copy_from_slice(&TABLE_7_6[matrix_id][0..end]);
83 }
84 } else {
85 if size_id == 0 {
87 scaling_column[matrix_id][0..16].copy_from_slice(&TABLE_7_5);
88 } else {
89 let ref_matrix_id =
90 matrix_id - scaling_list_pred_matrix_id_delta * (if size_id == 3 { 3 } else { 1 });
91 let end = usize::min(63, (1 << (4 + (size_id << 1))) - 1);
92 scaling_column[matrix_id][0..end].copy_from_slice(&TABLE_7_6[ref_matrix_id][0..end]);
93 }
94 }
95 } else {
96 let mut next_coef = 8;
99 let coef_num = usize::min(64, 1 << (4 + (size_id << 1)));
100
101 if size_id > 1 {
102 let scaling_list_dc_coef_minus8 = bit_reader.read_signed_exp_golomb()?;
103 next_coef = scaling_list_dc_coef_minus8 + 8;
104 }
105
106 for i in 0..coef_num {
107 let scaling_list_delta_coef = bit_reader.read_signed_exp_golomb()?;
108 next_coef = (next_coef + scaling_list_delta_coef + 256) % 256;
109 scaling_column[matrix_id][i] = next_coef;
110 }
111 }
112
113 matrix_id += if size_id == 3 { 3 } else { 1 };
114 }
115 }
116
117 Ok(Self { scaling_list })
118 }
119}