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 i in 0..num_lists {
109 let seq_scaling_list_present_flag = reader.read_flag()?;
110 if seq_scaling_list_present_flag {
111 let size = if i < 6 { 16 } else { 64 };
113 skip_scaling_list(&mut reader, size)?;
114 }
115 }
116 }
117 }
118
119 let log2_max_frame_num_minus4 = read_ue(&mut reader)? as u8;
120 if log2_max_frame_num_minus4 > 12 {
121 return Err(Error::MalformedSps("Invalid log2_max_frame_num".into()));
122 }
123
124 let pic_order_cnt_type = read_ue(&mut reader)? as u8;
125
126 let mut log2_max_pic_order_cnt_lsb_minus4 = 0;
127 let mut delta_pic_order_always_zero_flag = false;
128 let mut offset_for_non_ref_pic = 0;
129 let mut offset_for_top_to_bottom_field = 0;
130 let mut num_ref_frames_in_pic_order_cnt_cycle = 0;
131
132 match pic_order_cnt_type {
133 0 => {
134 log2_max_pic_order_cnt_lsb_minus4 = read_ue(&mut reader)? as u8;
135 if log2_max_pic_order_cnt_lsb_minus4 > 12 {
136 return Err(Error::MalformedSps(
137 "Invalid log2_max_pic_order_cnt_lsb".into(),
138 ));
139 }
140 }
141 1 => {
142 delta_pic_order_always_zero_flag = reader.read_flag()?;
143 offset_for_non_ref_pic = read_se(&mut reader)?;
144 offset_for_top_to_bottom_field = read_se(&mut reader)?;
145 num_ref_frames_in_pic_order_cnt_cycle = read_ue(&mut reader)? as u8;
146
147 for _ in 0..num_ref_frames_in_pic_order_cnt_cycle {
148 let _offset_for_ref_frame = read_se(&mut reader)?;
149 }
150 }
151 2 => {}
152 _ => return Err(Error::MalformedSps("Invalid pic_order_cnt_type".into())),
153 }
154
155 let max_num_ref_frames = read_ue(&mut reader)?;
156 let gaps_in_frame_num_value_allowed_flag = reader.read_flag()?;
157
158 let pic_width_in_mbs_minus1 = read_ue(&mut reader)?;
159 let pic_height_in_map_units_minus1 = read_ue(&mut reader)?;
160
161 let frame_mbs_only_flag = reader.read_flag()?;
162 let mut mb_adaptive_frame_field_flag = false;
163 if !frame_mbs_only_flag {
164 mb_adaptive_frame_field_flag = reader.read_flag()?;
165 }
166
167 let direct_8x8_inference_flag = reader.read_flag()?;
168
169 let frame_cropping_flag = reader.read_flag()?;
170 let mut frame_crop_left_offset = 0;
171 let mut frame_crop_right_offset = 0;
172 let mut frame_crop_top_offset = 0;
173 let mut frame_crop_bottom_offset = 0;
174
175 if frame_cropping_flag {
176 frame_crop_left_offset = read_ue(&mut reader)?;
177 frame_crop_right_offset = read_ue(&mut reader)?;
178 frame_crop_top_offset = read_ue(&mut reader)?;
179 frame_crop_bottom_offset = read_ue(&mut reader)?;
180 }
181
182 let vui_parameters_present_flag = reader.read_flag()?;
183
184 let width = (pic_width_in_mbs_minus1 + 1) * 16;
185 let height =
186 (pic_height_in_map_units_minus1 + 1) * 16 * if frame_mbs_only_flag { 1 } else { 2 };
187
188 let (sub_width_c, sub_height_c) = match chroma_format_idc {
189 0 => (0, 0),
190 1 => (2, 2),
191 2 => (2, 1),
192 3 => (1, 1),
193 _ => (0, 0),
194 };
195
196 let width = if frame_cropping_flag && sub_width_c > 0 {
197 width - sub_width_c * (frame_crop_left_offset + frame_crop_right_offset)
198 } else {
199 width
200 };
201
202 let height = if frame_cropping_flag && sub_height_c > 0 {
203 let mult = if frame_mbs_only_flag { 1 } else { 2 };
204 height - sub_height_c * mult * (frame_crop_top_offset + frame_crop_bottom_offset)
205 } else {
206 height
207 };
208
209 Ok(Sps {
210 profile_idc,
211 constraint_set0_flag,
212 constraint_set1_flag,
213 constraint_set2_flag,
214 constraint_set3_flag,
215 constraint_set4_flag,
216 constraint_set5_flag,
217 level_idc,
218 seq_parameter_set_id: seq_parameter_set_id as u8,
219 chroma_format_idc,
220 separate_colour_plane_flag,
221 bit_depth_luma_minus8,
222 bit_depth_chroma_minus8,
223 qpprime_y_zero_transform_bypass_flag,
224 seq_scaling_matrix_present_flag,
225 log2_max_frame_num_minus4,
226 pic_order_cnt_type,
227 log2_max_pic_order_cnt_lsb_minus4,
228 delta_pic_order_always_zero_flag,
229 offset_for_non_ref_pic,
230 offset_for_top_to_bottom_field,
231 num_ref_frames_in_pic_order_cnt_cycle,
232 max_num_ref_frames,
233 gaps_in_frame_num_value_allowed_flag,
234 pic_width_in_mbs_minus1,
235 pic_height_in_map_units_minus1,
236 frame_mbs_only_flag,
237 mb_adaptive_frame_field_flag,
238 direct_8x8_inference_flag,
239 frame_cropping_flag,
240 frame_crop_left_offset,
241 frame_crop_right_offset,
242 frame_crop_top_offset,
243 frame_crop_bottom_offset,
244 vui_parameters_present_flag,
245 width,
246 height,
247 })
248 }
249}
250
251fn skip_scaling_list(reader: &mut BitReader, size: usize) -> Result<()> {
252 let mut last_scale = 8;
253 let mut next_scale = 8;
254
255 for _ in 0..size {
256 if next_scale != 0 {
257 let delta_scale = read_se(reader)?;
258 next_scale = (last_scale + delta_scale + 256) % 256;
259 }
260 last_scale = if next_scale == 0 {
261 last_scale
262 } else {
263 next_scale
264 };
265 }
266
267 Ok(())
268}
269
270#[cfg(test)]
271mod tests {
272 use super::*;
273 use crate::nal::ebsp_to_rbsp;
274
275 #[test]
276 fn test_basic_sps_parse() {
277 let ebsp = vec![
278 0x42, 0x00, 0x1f, 0xac, 0x34, 0xc8, 0x14, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00,
279 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc6, 0x58,
280 ];
281
282 let rbsp = ebsp_to_rbsp(&ebsp);
283 let sps = Sps::parse(&rbsp).unwrap();
284
285 assert_eq!(sps.profile_idc, 66);
286 assert_eq!(sps.level_idc, 31);
287 assert!(sps.width > 0);
288 assert!(sps.height > 0);
289 }
290
291 #[test]
295 fn test_sps_with_8x8_scaling_list() {
296 let nal = vec![
298 0x27, 0x64, 0x00, 0x28, 0xad, 0x84, 0x05, 0x45, 0x62, 0xb8, 0xac, 0x54, 0x71, 0x08, 0x0a,
299 0x8a, 0xc5, 0x71, 0x58, 0xa8, 0xe2, 0x10, 0x24, 0x85, 0x21, 0x39, 0x3c, 0x9f, 0x27, 0xe4,
300 0xfe, 0x4f, 0xc9, 0xf2, 0x79, 0xb9, 0xb3, 0x4d, 0x08, 0x12, 0x42, 0x90, 0x9c, 0x9e, 0x4f,
301 0x93, 0xf2, 0x7f, 0x27, 0xe4, 0xf9, 0x3c, 0xdc, 0xd9, 0xa6, 0x1b, 0x2b, 0x01, 0xe0, 0x11,
302 0x1f, 0x78, 0x08, 0x80, 0x00, 0x01, 0xf4, 0x80, 0x00, 0x75, 0x30, 0x42,
303 ];
304
305 let rbsp = ebsp_to_rbsp(&nal[1..]);
306 let sps = Sps::parse(&rbsp).unwrap();
307
308 assert_eq!(sps.profile_idc, 100);
309 assert_eq!(sps.level_idc, 40);
310 assert_eq!(sps.width, 1920);
311 assert_eq!(sps.height, 1080);
312 }
313}