1use crate::bitreader::BitReader;
2use crate::eg::{read_se, read_ue};
3use crate::{Error, Result};
4
5#[derive(Debug, Clone)]
6pub struct Sps {
7 pub profile_idc: u8,
8 pub constraint_set0_flag: bool,
9 pub constraint_set1_flag: bool,
10 pub constraint_set2_flag: bool,
11 pub constraint_set3_flag: bool,
12 pub constraint_set4_flag: bool,
13 pub constraint_set5_flag: bool,
14 pub level_idc: u8,
15 pub seq_parameter_set_id: u8,
16
17 pub chroma_format_idc: u8,
18 pub separate_colour_plane_flag: bool,
19 pub bit_depth_luma_minus8: u8,
20 pub bit_depth_chroma_minus8: u8,
21 pub qpprime_y_zero_transform_bypass_flag: bool,
22 pub seq_scaling_matrix_present_flag: bool,
23
24 pub log2_max_frame_num_minus4: u8,
25 pub pic_order_cnt_type: u8,
26 pub log2_max_pic_order_cnt_lsb_minus4: u8,
27 pub delta_pic_order_always_zero_flag: bool,
28 pub offset_for_non_ref_pic: i32,
29 pub offset_for_top_to_bottom_field: i32,
30 pub num_ref_frames_in_pic_order_cnt_cycle: u8,
31
32 pub max_num_ref_frames: u32,
33 pub gaps_in_frame_num_value_allowed_flag: bool,
34 pub pic_width_in_mbs_minus1: u32,
35 pub pic_height_in_map_units_minus1: u32,
36 pub frame_mbs_only_flag: bool,
37 pub mb_adaptive_frame_field_flag: bool,
38 pub direct_8x8_inference_flag: bool,
39
40 pub frame_cropping_flag: bool,
41 pub frame_crop_left_offset: u32,
42 pub frame_crop_right_offset: u32,
43 pub frame_crop_top_offset: u32,
44 pub frame_crop_bottom_offset: u32,
45
46 pub vui_parameters_present_flag: bool,
47
48 pub width: u32,
49 pub height: u32,
50}
51
52impl Sps {
53 pub fn parse(rbsp: &[u8]) -> Result<Self> {
54 let mut reader = BitReader::new(rbsp);
55
56 let profile_idc = reader.read_u8()?;
57 let constraint_set0_flag = reader.read_flag()?;
58 let constraint_set1_flag = reader.read_flag()?;
59 let constraint_set2_flag = reader.read_flag()?;
60 let constraint_set3_flag = reader.read_flag()?;
61 let constraint_set4_flag = reader.read_flag()?;
62 let constraint_set5_flag = reader.read_flag()?;
63 let _reserved_zero_2bits = reader.read_bits(2)?;
64 let level_idc = reader.read_u8()?;
65
66 let seq_parameter_set_id = read_ue(&mut reader)?;
67 if seq_parameter_set_id > 31 {
68 return Err(Error::MalformedSps("Invalid SPS ID".into()));
69 }
70
71 let mut chroma_format_idc = 1;
72 let mut separate_colour_plane_flag = false;
73 let mut bit_depth_luma_minus8 = 0;
74 let mut bit_depth_chroma_minus8 = 0;
75 let mut qpprime_y_zero_transform_bypass_flag = false;
76 let mut seq_scaling_matrix_present_flag = false;
77
78 if profile_idc == 100
79 || profile_idc == 110
80 || profile_idc == 122
81 || profile_idc == 244
82 || profile_idc == 44
83 || profile_idc == 83
84 || profile_idc == 86
85 || profile_idc == 118
86 || profile_idc == 128
87 || profile_idc == 138
88 || profile_idc == 139
89 || profile_idc == 134
90 || profile_idc == 135
91 {
92 chroma_format_idc = read_ue(&mut reader)? as u8;
93 if chroma_format_idc > 3 {
94 return Err(Error::MalformedSps("Invalid chroma format".into()));
95 }
96
97 if chroma_format_idc == 3 {
98 separate_colour_plane_flag = reader.read_flag()?;
99 }
100
101 bit_depth_luma_minus8 = read_ue(&mut reader)? as u8;
102 bit_depth_chroma_minus8 = read_ue(&mut reader)? as u8;
103 qpprime_y_zero_transform_bypass_flag = reader.read_flag()?;
104 seq_scaling_matrix_present_flag = reader.read_flag()?;
105
106 if seq_scaling_matrix_present_flag {
107 let num_lists = if chroma_format_idc != 3 { 8 } else { 12 };
108 for _ in 0..num_lists {
109 let seq_scaling_list_present_flag = reader.read_flag()?;
110 if seq_scaling_list_present_flag {
111 skip_scaling_list(&mut reader)?;
112 }
113 }
114 }
115 }
116
117 let log2_max_frame_num_minus4 = read_ue(&mut reader)? as u8;
118 if log2_max_frame_num_minus4 > 12 {
119 return Err(Error::MalformedSps("Invalid log2_max_frame_num".into()));
120 }
121
122 let pic_order_cnt_type = read_ue(&mut reader)? as u8;
123
124 let mut log2_max_pic_order_cnt_lsb_minus4 = 0;
125 let mut delta_pic_order_always_zero_flag = false;
126 let mut offset_for_non_ref_pic = 0;
127 let mut offset_for_top_to_bottom_field = 0;
128 let mut num_ref_frames_in_pic_order_cnt_cycle = 0;
129
130 match pic_order_cnt_type {
131 0 => {
132 log2_max_pic_order_cnt_lsb_minus4 = read_ue(&mut reader)? as u8;
133 if log2_max_pic_order_cnt_lsb_minus4 > 12 {
134 return Err(Error::MalformedSps(
135 "Invalid log2_max_pic_order_cnt_lsb".into(),
136 ));
137 }
138 }
139 1 => {
140 delta_pic_order_always_zero_flag = reader.read_flag()?;
141 offset_for_non_ref_pic = read_se(&mut reader)?;
142 offset_for_top_to_bottom_field = read_se(&mut reader)?;
143 num_ref_frames_in_pic_order_cnt_cycle = read_ue(&mut reader)? as u8;
144
145 for _ in 0..num_ref_frames_in_pic_order_cnt_cycle {
146 let _offset_for_ref_frame = read_se(&mut reader)?;
147 }
148 }
149 2 => {}
150 _ => return Err(Error::MalformedSps("Invalid pic_order_cnt_type".into())),
151 }
152
153 let max_num_ref_frames = read_ue(&mut reader)?;
154 let gaps_in_frame_num_value_allowed_flag = reader.read_flag()?;
155
156 let pic_width_in_mbs_minus1 = read_ue(&mut reader)?;
157 let pic_height_in_map_units_minus1 = read_ue(&mut reader)?;
158
159 let frame_mbs_only_flag = reader.read_flag()?;
160 let mut mb_adaptive_frame_field_flag = false;
161 if !frame_mbs_only_flag {
162 mb_adaptive_frame_field_flag = reader.read_flag()?;
163 }
164
165 let direct_8x8_inference_flag = reader.read_flag()?;
166
167 let frame_cropping_flag = reader.read_flag()?;
168 let mut frame_crop_left_offset = 0;
169 let mut frame_crop_right_offset = 0;
170 let mut frame_crop_top_offset = 0;
171 let mut frame_crop_bottom_offset = 0;
172
173 if frame_cropping_flag {
174 frame_crop_left_offset = read_ue(&mut reader)?;
175 frame_crop_right_offset = read_ue(&mut reader)?;
176 frame_crop_top_offset = read_ue(&mut reader)?;
177 frame_crop_bottom_offset = read_ue(&mut reader)?;
178 }
179
180 let vui_parameters_present_flag = reader.read_flag()?;
181
182 let width = (pic_width_in_mbs_minus1 + 1) * 16;
183 let height =
184 (pic_height_in_map_units_minus1 + 1) * 16 * if frame_mbs_only_flag { 1 } else { 2 };
185
186 let (sub_width_c, sub_height_c) = match chroma_format_idc {
187 0 => (0, 0),
188 1 => (2, 2),
189 2 => (2, 1),
190 3 => (1, 1),
191 _ => (0, 0),
192 };
193
194 let width = if frame_cropping_flag && sub_width_c > 0 {
195 width - sub_width_c * (frame_crop_left_offset + frame_crop_right_offset)
196 } else {
197 width
198 };
199
200 let height = if frame_cropping_flag && sub_height_c > 0 {
201 let mult = if frame_mbs_only_flag { 1 } else { 2 };
202 height - sub_height_c * mult * (frame_crop_top_offset + frame_crop_bottom_offset)
203 } else {
204 height
205 };
206
207 Ok(Sps {
208 profile_idc,
209 constraint_set0_flag,
210 constraint_set1_flag,
211 constraint_set2_flag,
212 constraint_set3_flag,
213 constraint_set4_flag,
214 constraint_set5_flag,
215 level_idc,
216 seq_parameter_set_id: seq_parameter_set_id as u8,
217 chroma_format_idc,
218 separate_colour_plane_flag,
219 bit_depth_luma_minus8,
220 bit_depth_chroma_minus8,
221 qpprime_y_zero_transform_bypass_flag,
222 seq_scaling_matrix_present_flag,
223 log2_max_frame_num_minus4,
224 pic_order_cnt_type,
225 log2_max_pic_order_cnt_lsb_minus4,
226 delta_pic_order_always_zero_flag,
227 offset_for_non_ref_pic,
228 offset_for_top_to_bottom_field,
229 num_ref_frames_in_pic_order_cnt_cycle,
230 max_num_ref_frames,
231 gaps_in_frame_num_value_allowed_flag,
232 pic_width_in_mbs_minus1,
233 pic_height_in_map_units_minus1,
234 frame_mbs_only_flag,
235 mb_adaptive_frame_field_flag,
236 direct_8x8_inference_flag,
237 frame_cropping_flag,
238 frame_crop_left_offset,
239 frame_crop_right_offset,
240 frame_crop_top_offset,
241 frame_crop_bottom_offset,
242 vui_parameters_present_flag,
243 width,
244 height,
245 })
246 }
247}
248
249fn skip_scaling_list(reader: &mut BitReader) -> Result<()> {
250 let mut last_scale = 8;
251 let mut next_scale = 8;
252
253 for _ in 0..16 {
254 if next_scale != 0 {
255 let delta_scale = read_se(reader)?;
256 next_scale = (last_scale + delta_scale + 256) % 256;
257 }
258 last_scale = if next_scale == 0 {
259 last_scale
260 } else {
261 next_scale
262 };
263 }
264
265 Ok(())
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271 use crate::nal::ebsp_to_rbsp;
272
273 #[test]
274 fn test_basic_sps_parse() {
275 let ebsp = vec![
276 0x42, 0x00, 0x1f, 0xac, 0x34, 0xc8, 0x14, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00,
277 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc6, 0x58,
278 ];
279
280 let rbsp = ebsp_to_rbsp(&ebsp);
281 let sps = Sps::parse(&rbsp).unwrap();
282
283 assert_eq!(sps.profile_idc, 66);
284 assert_eq!(sps.level_idc, 31);
285 assert!(sps.width > 0);
286 assert!(sps.height > 0);
287 }
288}