scuffle_h265/sps/sps_range_extension.rs
1use std::io;
2
3use scuffle_bytes_util::BitReader;
4
5/// Sequence parameter set range extension.
6///
7/// `sps_range_extension()`
8///
9/// - ISO/IEC 23008-2 - 7.3.2.2.2
10/// - ISO/IEC 23008-2 - 7.4.3.2.2
11#[derive(Debug, Clone, PartialEq)]
12pub struct SpsRangeExtension {
13 /// Equal to `true` specifies that a rotation is applied to the residual data
14 /// block for intra 4x4 blocks coded using a transform skip operation.
15 ///
16 /// Equal to `false` specifies that this rotation is not applied.
17 pub transform_skip_rotation_enabled_flag: bool,
18 /// Equal to `true` specifies that a particular context is used for the
19 /// parsing of the `sig_coeff_flag` for transform blocks with a skipped transform.
20 ///
21 /// Equal to `false` specifies that the presence or absence of transform
22 /// skipping or a transform bypass for transform blocks is not used in the context selection for this flag.
23 pub transform_skip_context_enabled_flag: bool,
24 /// Equal to `true` specifies that the residual modification process for blocks using
25 /// a transform bypass may be used for intra blocks in the CVS.
26 ///
27 /// Equal to `false` specifies that the residual modification process is not used for intra blocks in the CVS.
28 pub implicit_rdpcm_enabled_flag: bool,
29 /// Equal to `true` specifies that the residual modification process for blocks using
30 /// a transform bypass may be used for inter blocks in the CVS.
31 ///
32 /// Equal to `false` specifies that the residual modification process is not used for inter blocks in the CVS.
33 pub explicit_rdpcm_enabled_flag: bool,
34 /// Equal to `true` specifies that an extended dynamic range is used for
35 /// transform coefficients and transform processing.
36 ///
37 /// Equal to `false` specifies that the extended dynamic range is not used.
38 ///
39 /// Defines [`CoeffMinY`](SpsRangeExtension::coeff_min_y), [`CoeffMinC`](SpsRangeExtension::coeff_min_c),
40 /// [`CoeffMaxY`](SpsRangeExtension::coeff_max_y), and [`CoeffMaxC`](SpsRangeExtension::coeff_max_c).
41 pub extended_precision_processing_flag: bool,
42 /// Equal to `true` specifies that the filtering process of neighbouring samples is
43 /// unconditionally disabled for intra prediction.
44 ///
45 /// Equal to `false` specifies that the filtering process of neighbouring samples is not disabled.
46 pub intra_smoothing_disabled_flag: bool,
47 /// Equal to `true` specifies that weighted prediction offset values are
48 /// signalled using a bit-depth-dependent precision.
49 ///
50 /// Equal to `false` specifies that weighted prediction offset values are signalled with
51 /// a precision equivalent to eight bit processing.
52 ///
53 /// Defines [`WpOffsetBdShiftY`](SpsRangeExtension::wp_offset_bd_shift_y),
54 /// [`WpOffsetBdShiftC`](SpsRangeExtension::wp_offset_bd_shift_c),
55 /// [`WpOffsetHalfRangeY`](SpsRangeExtension::wp_offset_half_range_y), and
56 /// [`WpOffsetHalfRangeC`](SpsRangeExtension::wp_offset_half_range_c).
57 pub high_precision_offsets_enabled_flag: bool,
58 /// Equal to `true` specifies that the Rice parameter derivation for the
59 /// binarization of `coeff_abs_level_remaining[]` is initialized at the start of each sub-block using mode
60 /// dependent statistics accumulated from previous sub-blocks.
61 ///
62 /// Equal to `false` specifies that no previous sub-block state is used in Rice parameter derivation.
63 pub persistent_rice_adaptation_enabled_flag: bool,
64 /// Equal to `true` specifies that a CABAC alignment process is used
65 /// prior to bypass decoding of the syntax elements `coeff_sign_flag[]` and `coeff_abs_level_remaining[]`.
66 ///
67 /// Equal to `false` specifies that no CABAC alignment process is used prior to bypass decoding.
68 pub cabac_bypass_alignment_enabled_flag: bool,
69}
70
71impl SpsRangeExtension {
72 pub(crate) fn parse<R: io::Read>(bit_reader: &mut BitReader<R>) -> io::Result<Self> {
73 Ok(Self {
74 transform_skip_rotation_enabled_flag: bit_reader.read_bit()?,
75 transform_skip_context_enabled_flag: bit_reader.read_bit()?,
76 implicit_rdpcm_enabled_flag: bit_reader.read_bit()?,
77 explicit_rdpcm_enabled_flag: bit_reader.read_bit()?,
78 extended_precision_processing_flag: bit_reader.read_bit()?,
79 intra_smoothing_disabled_flag: bit_reader.read_bit()?,
80 high_precision_offsets_enabled_flag: bit_reader.read_bit()?,
81 persistent_rice_adaptation_enabled_flag: bit_reader.read_bit()?,
82 cabac_bypass_alignment_enabled_flag: bit_reader.read_bit()?,
83 })
84 }
85
86 /// `CoeffMinY = −(1 << (extended_precision_processing_flag ? Max(15, BitDepthY + 6) : 15))` (7-27)
87 ///
88 /// ISO/IEC 23008-2 - 7.4.3.2.2
89 pub fn coeff_min_y(&self, bit_depth_y: u8) -> i64 {
90 let n = if self.extended_precision_processing_flag {
91 15.max(bit_depth_y + 6)
92 } else {
93 15
94 };
95 -(1 << n)
96 }
97
98 /// `CoeffMinC = −(1 << (extended_precision_processing_flag ? Max(15, BitDepthC + 6) : 15))` (7-28)
99 ///
100 /// ISO/IEC 23008-2 - 7.4.3.2.2
101 pub fn coeff_min_c(&self, bit_depth_c: u8) -> i64 {
102 let n = if self.extended_precision_processing_flag {
103 15.max(bit_depth_c + 6)
104 } else {
105 15
106 };
107 -(1 << n)
108 }
109
110 /// `CoeffMaxY = (1 << (extended_precision_processing_flag ? Max(15, BitDepthY + 6) : 15)) - 1` (7-29)
111 ///
112 /// ISO/IEC 23008-2 - 7.4.3.2.2
113 pub fn coeff_max_y(&self, bit_depth_y: u8) -> i64 {
114 let n = if self.extended_precision_processing_flag {
115 15.max(bit_depth_y + 6)
116 } else {
117 15
118 };
119 (1 << n) - 1
120 }
121
122 /// `CoeffMaxC = (1 << (extended_precision_processing_flag ? Max(15, BitDepthC + 6) : 15)) − 1` (7-30)
123 ///
124 /// ISO/IEC 23008-2 - 7.4.3.2.2
125 pub fn coeff_max_c(&self, bit_depth_c: u8) -> i64 {
126 let n = if self.extended_precision_processing_flag {
127 15.max(bit_depth_c + 6)
128 } else {
129 15
130 };
131 (1 << n) - 1
132 }
133
134 /// `WpOffsetBdShiftY = high_precision_offsets_enabled_flag ? 0 : (BitDepthY − 8)` (7-31)
135 ///
136 /// ISO/IEC 23008-2 - 7.4.3.2.2
137 pub fn wp_offset_bd_shift_y(&self, bit_depth_y: u8) -> i8 {
138 if self.high_precision_offsets_enabled_flag {
139 0
140 } else {
141 bit_depth_y as i8 - 8
142 }
143 }
144
145 /// `WpOffsetBdShiftC = high_precision_offsets_enabled_flag ? 0 : (BitDepthC − 8)` (7-32)
146 ///
147 /// ISO/IEC 23008-2 - 7.4.3.2.2
148 pub fn wp_offset_bd_shift_c(&self, bit_depth_c: u8) -> i8 {
149 if self.high_precision_offsets_enabled_flag {
150 0
151 } else {
152 bit_depth_c as i8 - 8
153 }
154 }
155
156 /// `WpOffsetHalfRangeY = 1 << (high_precision_offsets_enabled_flag ? (BitDepthY − 1) : 7)` (7-33)
157 ///
158 /// ISO/IEC 23008-2 - 7.4.3.2.2
159 pub fn wp_offset_half_range_y(&self, bit_depth_y: u8) -> i8 {
160 let n = if self.high_precision_offsets_enabled_flag {
161 bit_depth_y.saturating_sub(1)
162 } else {
163 7
164 };
165 1 << n
166 }
167
168 /// `WpOffsetHalfRangeC = 1 << (high_precision_offsets_enabled_flag ? (BitDepthC − 1) : 7)` (7-34)
169 ///
170 /// ISO/IEC 23008-2 - 7.4.3.2.2
171 pub fn wp_offset_half_range_c(&self, bit_depth_c: u8) -> i8 {
172 let n = if self.high_precision_offsets_enabled_flag {
173 bit_depth_c.saturating_sub(1)
174 } else {
175 7
176 };
177 1 << n
178 }
179}