scuffle_h265/sps/
scaling_list.rs

1use std::io;
2
3use scuffle_bytes_util::BitReader;
4use scuffle_expgolomb::BitReaderExpGolombExt;
5
6/// `ScalingList[0][0..5][i]`
7///
8/// ISO/IEC 23008-2 - Table 7-5
9const TABLE_7_5: [i64; 16] = [16; 16];
10
11/// `ScalingList[1..3][0..2][i]`
12///
13/// /// ISO/IEC 23008-2 - Table 7-6
14#[rustfmt::skip]
15const TABLE_7_6_02: [i64; 64] = [
16    //0  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
17    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/// `ScalingList[1..3][3..5][i]`
24///
25/// ISO/IEC 23008-2 - Table 7-6
26#[rustfmt::skip]
27const TABLE_7_6_35: [i64; 64] = [
28    //0  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
29    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
35/// `ScalingList[1..3][i][j]`
36///
37/// ISO/IEC 23008-2 - 7.4.5
38const 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/// Scaling list data.
48///
49/// `scaling_list_data()`
50///
51/// - ISO/IEC 23008-2 - 7.3.4
52/// - ISO/IEC 23008-2 - 7.4.5
53#[derive(Debug, Clone, PartialEq)]
54pub struct ScalingListData {
55    /// The resulting scaling list.
56    ///
57    /// `ScalingList[0..3][0..5][0..63]`
58    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                    // the values of the scaling list are the same as the values of a reference scaling list.
73
74                    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                        // the scaling list is inferred from the default scaling list
78                        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                        // the scaling list is inferred from the reference scaling list
86                        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                    // the values of the scaling list are explicitly signalled.
97
98                    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}