1use crate::nal::sps::{HrdParameters, SeqParameterSet, SpsError, TimingInfo};
12use crate::rbsp::BitRead;
13
14#[derive(Clone, Debug, PartialEq, Eq)]
16pub enum SubsetSpsExtension {
17 Svc(SvcSpsExtension),
18 Mvc {
19 ext: MvcSpsExtension,
20 mvc_vui_parameters: Option<MvcVuiParametersExtension>,
21 },
22 Mvcd,
24}
25
26#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct SvcSpsExtension {
29 pub inter_layer_deblocking_filter_control_present_flag: bool,
30 pub extended_spatial_scalability_idc: u8,
31 pub chroma_phase_x_plus1_flag: bool,
32 pub chroma_phase_y_plus1: u8,
33 pub seq_ref_layer_chroma_phase_x_plus1_flag: bool,
34 pub seq_ref_layer_chroma_phase_y_plus1: u8,
35 pub seq_scaled_ref_layer_left_offset: i32,
36 pub seq_scaled_ref_layer_top_offset: i32,
37 pub seq_scaled_ref_layer_right_offset: i32,
38 pub seq_scaled_ref_layer_bottom_offset: i32,
39 pub seq_tcoeff_level_prediction_flag: bool,
40 pub adaptive_tcoeff_level_prediction_flag: bool,
41 pub slice_header_restriction_flag: bool,
42 pub svc_vui_parameters_present_flag: bool,
43}
44
45#[derive(Clone, Debug, PartialEq, Eq)]
47pub struct MvcView {
48 pub view_id: u16,
49 pub anchor_refs_l0: Vec<u16>,
50 pub anchor_refs_l1: Vec<u16>,
51 pub non_anchor_refs_l0: Vec<u16>,
52 pub non_anchor_refs_l1: Vec<u16>,
53}
54
55#[derive(Clone, Debug, PartialEq, Eq)]
57pub struct MvcLevelValue {
58 pub level_idc: u8,
59 pub applicable_ops: Vec<MvcApplicableOp>,
60}
61
62#[derive(Clone, Debug, PartialEq, Eq)]
64pub struct MvcApplicableOp {
65 pub temporal_id: u8,
66 pub num_target_views_minus1: u16,
67 pub target_view_ids: Vec<u16>,
68 pub num_views_minus1: u16,
69}
70
71#[derive(Clone, Debug, PartialEq, Eq)]
73pub struct MvcSpsExtension {
74 pub views: Vec<MvcView>,
75 pub level_values: Vec<MvcLevelValue>,
76}
77
78#[derive(Clone, Debug, PartialEq, Eq)]
80pub struct MvcVuiOp {
81 pub temporal_id: u8,
82 pub target_output_view_ids: Vec<u16>,
83 pub timing_info: Option<TimingInfo>,
84 pub nal_hrd_parameters: Option<HrdParameters>,
85 pub vcl_hrd_parameters: Option<HrdParameters>,
86 pub low_delay_hrd_flag: Option<bool>,
87 pub pic_struct_present_flag: bool,
88}
89
90#[derive(Clone, Debug, PartialEq, Eq)]
92pub struct MvcVuiParametersExtension {
93 pub ops: Vec<MvcVuiOp>,
94}
95
96#[derive(Clone, Debug, PartialEq, Eq)]
98pub struct SubsetSps {
99 pub sps: SeqParameterSet,
100 pub extension: Option<SubsetSpsExtension>,
101 pub additional_extension2_flag: bool,
102}
103
104fn read_ue_bounded<R: BitRead>(r: &mut R, name: &'static str, max: u32) -> Result<u16, SpsError> {
106 let val = r.read_ue(name)?;
107 if val > max {
108 return Err(SpsError::FieldValueTooLarge { name, value: val });
109 }
110 Ok(val as u16)
111}
112
113impl SubsetSps {
114 pub fn from_bits<R: BitRead>(mut r: R) -> Result<SubsetSps, SpsError> {
115 let sps = SeqParameterSet::read_seq_parameter_set_data(&mut r)?;
116 let profile_idc: u8 = sps.profile_idc.into();
117
118 let (extension, has_unparsed_vui) = match profile_idc {
119 83 | 86 => {
120 let _bit_equal_to_one = r.read_bit("bit_equal_to_one")?;
122 let ext = read_svc_extension(&mut r, &sps)?;
123 let has_vui = ext.svc_vui_parameters_present_flag;
124 (Some(SubsetSpsExtension::Svc(ext)), has_vui)
125 }
126 118 | 128 | 134 => {
127 let _bit_equal_to_one = r.read_bit("bit_equal_to_one")?;
129 let ext = read_mvc_extension(&mut r)?;
130 let mvc_vui_parameters_present_flag =
131 r.read_bit("mvc_vui_parameters_present_flag")?;
132 let mvc_vui_parameters = if mvc_vui_parameters_present_flag {
133 Some(read_mvc_vui_parameters_extension(&mut r)?)
134 } else {
135 None
136 };
137 (
138 Some(SubsetSpsExtension::Mvc {
139 ext,
140 mvc_vui_parameters,
141 }),
142 false,
143 )
144 }
145 135 | 138 | 139 => {
146 let _bit_equal_to_one = r.read_bit("bit_equal_to_one")?;
148 (Some(SubsetSpsExtension::Mvcd), true)
150 }
151 _ => (None, false),
152 };
153
154 let additional_extension2_flag = if has_unparsed_vui {
155 false
157 } else {
158 let flag = r.read_bit("additional_extension2_flag")?;
159 r.finish_rbsp()?;
160 flag
161 };
162
163 Ok(SubsetSps {
164 sps,
165 extension,
166 additional_extension2_flag,
167 })
168 }
169}
170
171fn read_svc_extension<R: BitRead>(
172 r: &mut R,
173 sps: &SeqParameterSet,
174) -> Result<SvcSpsExtension, SpsError> {
175 let inter_layer_deblocking_filter_control_present_flag =
176 r.read_bit("inter_layer_deblocking_filter_control_present_flag")?;
177 let extended_spatial_scalability_idc: u8 =
178 r.read::<2, _>("extended_spatial_scalability_idc")?;
179
180 let chroma_array_type = sps.chroma_info.chroma_array_type();
181
182 let chroma_phase_x_plus1_flag = if chroma_array_type == 1 || chroma_array_type == 2 {
183 r.read_bit("chroma_phase_x_plus1_flag")?
184 } else {
185 false
186 };
187 let chroma_phase_y_plus1 = if chroma_array_type == 1 {
188 r.read::<2, _>("chroma_phase_y_plus1")?
189 } else {
190 if chroma_array_type == 0 {
192 0
193 } else {
194 1
195 }
196 };
197
198 let (
199 seq_ref_layer_chroma_phase_x_plus1_flag,
200 seq_ref_layer_chroma_phase_y_plus1,
201 seq_scaled_ref_layer_left_offset,
202 seq_scaled_ref_layer_top_offset,
203 seq_scaled_ref_layer_right_offset,
204 seq_scaled_ref_layer_bottom_offset,
205 ) = if extended_spatial_scalability_idc == 1 {
206 let ref_phase_x = if chroma_array_type == 1 || chroma_array_type == 2 {
207 r.read_bit("seq_ref_layer_chroma_phase_x_plus1_flag")?
208 } else {
209 false
210 };
211 let ref_phase_y = if chroma_array_type == 1 {
212 r.read::<2, _>("seq_ref_layer_chroma_phase_y_plus1")?
213 } else {
214 if chroma_array_type == 0 {
215 0
216 } else {
217 1
218 }
219 };
220 (
221 ref_phase_x,
222 ref_phase_y,
223 r.read_se("seq_scaled_ref_layer_left_offset")?,
224 r.read_se("seq_scaled_ref_layer_top_offset")?,
225 r.read_se("seq_scaled_ref_layer_right_offset")?,
226 r.read_se("seq_scaled_ref_layer_bottom_offset")?,
227 )
228 } else {
229 (
230 false,
231 if chroma_array_type == 0 { 0 } else { 1 },
232 0,
233 0,
234 0,
235 0,
236 )
237 };
238
239 let seq_tcoeff_level_prediction_flag = r.read_bit("seq_tcoeff_level_prediction_flag")?;
240 let adaptive_tcoeff_level_prediction_flag = if seq_tcoeff_level_prediction_flag {
241 r.read_bit("adaptive_tcoeff_level_prediction_flag")?
242 } else {
243 false
244 };
245 let slice_header_restriction_flag = r.read_bit("slice_header_restriction_flag")?;
246 let svc_vui_parameters_present_flag = r.read_bit("svc_vui_parameters_present_flag")?;
247
248 Ok(SvcSpsExtension {
249 inter_layer_deblocking_filter_control_present_flag,
250 extended_spatial_scalability_idc,
251 chroma_phase_x_plus1_flag,
252 chroma_phase_y_plus1,
253 seq_ref_layer_chroma_phase_x_plus1_flag,
254 seq_ref_layer_chroma_phase_y_plus1,
255 seq_scaled_ref_layer_left_offset,
256 seq_scaled_ref_layer_top_offset,
257 seq_scaled_ref_layer_right_offset,
258 seq_scaled_ref_layer_bottom_offset,
259 seq_tcoeff_level_prediction_flag,
260 adaptive_tcoeff_level_prediction_flag,
261 slice_header_restriction_flag,
262 svc_vui_parameters_present_flag,
263 })
264}
265
266fn read_mvc_extension<R: BitRead>(r: &mut R) -> Result<MvcSpsExtension, SpsError> {
267 let num_views_minus1 = r.read_ue("num_views_minus1")?;
268 if num_views_minus1 > 1023 {
269 return Err(SpsError::FieldValueTooLarge {
270 name: "num_views_minus1",
271 value: num_views_minus1,
272 });
273 }
274
275 let mut views = Vec::with_capacity(num_views_minus1 as usize + 1);
276 for _ in 0..=num_views_minus1 {
277 let view_id = read_ue_bounded(r, "view_id", 1023)?;
278 views.push(MvcView {
279 view_id,
280 anchor_refs_l0: Vec::new(),
281 anchor_refs_l1: Vec::new(),
282 non_anchor_refs_l0: Vec::new(),
283 non_anchor_refs_l1: Vec::new(),
284 });
285 }
286
287 for i in 1..=num_views_minus1 as usize {
289 let num_anchor_refs_l0 = r.read_ue("num_anchor_refs_l0")?;
290 if num_anchor_refs_l0 > 15 {
291 return Err(SpsError::FieldValueTooLarge {
292 name: "num_anchor_refs_l0",
293 value: num_anchor_refs_l0,
294 });
295 }
296 for _ in 0..num_anchor_refs_l0 {
297 views[i]
298 .anchor_refs_l0
299 .push(read_ue_bounded(r, "anchor_ref_l0", 1023)?);
300 }
301 let num_anchor_refs_l1 = r.read_ue("num_anchor_refs_l1")?;
302 if num_anchor_refs_l1 > 15 {
303 return Err(SpsError::FieldValueTooLarge {
304 name: "num_anchor_refs_l1",
305 value: num_anchor_refs_l1,
306 });
307 }
308 for _ in 0..num_anchor_refs_l1 {
309 views[i]
310 .anchor_refs_l1
311 .push(read_ue_bounded(r, "anchor_ref_l1", 1023)?);
312 }
313 }
314
315 for i in 1..=num_views_minus1 as usize {
317 let num_non_anchor_refs_l0 = r.read_ue("num_non_anchor_refs_l0")?;
318 if num_non_anchor_refs_l0 > 15 {
319 return Err(SpsError::FieldValueTooLarge {
320 name: "num_non_anchor_refs_l0",
321 value: num_non_anchor_refs_l0,
322 });
323 }
324 for _ in 0..num_non_anchor_refs_l0 {
325 views[i]
326 .non_anchor_refs_l0
327 .push(read_ue_bounded(r, "non_anchor_ref_l0", 1023)?);
328 }
329 let num_non_anchor_refs_l1 = r.read_ue("num_non_anchor_refs_l1")?;
330 if num_non_anchor_refs_l1 > 15 {
331 return Err(SpsError::FieldValueTooLarge {
332 name: "num_non_anchor_refs_l1",
333 value: num_non_anchor_refs_l1,
334 });
335 }
336 for _ in 0..num_non_anchor_refs_l1 {
337 views[i]
338 .non_anchor_refs_l1
339 .push(read_ue_bounded(r, "non_anchor_ref_l1", 1023)?);
340 }
341 }
342
343 let num_level_values_signalled_minus1 = r.read_ue("num_level_values_signalled_minus1")?;
345 if num_level_values_signalled_minus1 > 63 {
346 return Err(SpsError::FieldValueTooLarge {
347 name: "num_level_values_signalled_minus1",
348 value: num_level_values_signalled_minus1,
349 });
350 }
351
352 let mut level_values = Vec::with_capacity(num_level_values_signalled_minus1 as usize + 1);
353 for _ in 0..=num_level_values_signalled_minus1 {
354 let level_idc: u8 = r.read::<8, _>("level_idc")?;
355 let num_applicable_ops_minus1 = r.read_ue("num_applicable_ops_minus1")?;
356 if num_applicable_ops_minus1 > 1023 {
357 return Err(SpsError::FieldValueTooLarge {
358 name: "num_applicable_ops_minus1",
359 value: num_applicable_ops_minus1,
360 });
361 }
362 let mut applicable_ops = Vec::with_capacity(num_applicable_ops_minus1 as usize + 1);
363 for _ in 0..=num_applicable_ops_minus1 {
364 let temporal_id: u8 = r.read::<3, _>("applicable_op_temporal_id")?;
365 let num_target_views_minus1 =
366 read_ue_bounded(r, "applicable_op_num_target_views_minus1", 1023)?;
367 let mut target_view_ids = Vec::with_capacity(num_target_views_minus1 as usize + 1);
368 for _ in 0..=num_target_views_minus1 {
369 target_view_ids.push(read_ue_bounded(r, "applicable_op_target_view_id", 1023)?);
370 }
371 let num_views_minus1 = read_ue_bounded(r, "applicable_op_num_views_minus1", 1023)?;
372 applicable_ops.push(MvcApplicableOp {
373 temporal_id,
374 num_target_views_minus1,
375 target_view_ids,
376 num_views_minus1,
377 });
378 }
379 level_values.push(MvcLevelValue {
380 level_idc,
381 applicable_ops,
382 });
383 }
384
385 Ok(MvcSpsExtension {
386 views,
387 level_values,
388 })
389}
390
391fn read_mvc_vui_parameters_extension<R: BitRead>(
392 r: &mut R,
393) -> Result<MvcVuiParametersExtension, SpsError> {
394 let vui_mvc_num_ops_minus1 = r.read_ue("vui_mvc_num_ops_minus1")?;
395 if vui_mvc_num_ops_minus1 > 1023 {
396 return Err(SpsError::FieldValueTooLarge {
397 name: "vui_mvc_num_ops_minus1",
398 value: vui_mvc_num_ops_minus1,
399 });
400 }
401 let mut ops = Vec::with_capacity(vui_mvc_num_ops_minus1 as usize + 1);
402 for _ in 0..=vui_mvc_num_ops_minus1 {
403 let temporal_id: u8 = r.read::<3, _>("vui_mvc_temporal_id")?;
404 let vui_mvc_num_target_output_views_minus1 =
405 r.read_ue("vui_mvc_num_target_output_views_minus1")?;
406 if vui_mvc_num_target_output_views_minus1 > 1023 {
407 return Err(SpsError::FieldValueTooLarge {
408 name: "vui_mvc_num_target_output_views_minus1",
409 value: vui_mvc_num_target_output_views_minus1,
410 });
411 }
412 let mut target_output_view_ids =
413 Vec::with_capacity(vui_mvc_num_target_output_views_minus1 as usize + 1);
414 for _ in 0..=vui_mvc_num_target_output_views_minus1 {
415 target_output_view_ids.push(read_ue_bounded(r, "vui_mvc_view_id", 1023)?);
416 }
417 let timing_info = TimingInfo::read(r)?;
418 let mut hrd_parameters_present = false;
419 let nal_hrd_parameters = HrdParameters::read(r, &mut hrd_parameters_present)?;
420 let vcl_hrd_parameters = HrdParameters::read(r, &mut hrd_parameters_present)?;
421 let low_delay_hrd_flag = if hrd_parameters_present {
422 Some(r.read_bit("vui_mvc_low_delay_hrd_flag")?)
423 } else {
424 None
425 };
426 let pic_struct_present_flag = r.read_bit("vui_mvc_pic_struct_present_flag")?;
427 ops.push(MvcVuiOp {
428 temporal_id,
429 target_output_view_ids,
430 timing_info,
431 nal_hrd_parameters,
432 vcl_hrd_parameters,
433 low_delay_hrd_flag,
434 pic_struct_present_flag,
435 });
436 }
437 Ok(MvcVuiParametersExtension { ops })
438}
439
440#[cfg(test)]
441mod test {
442 use super::*;
443 use crate::rbsp::BitReader;
444
445 #[test]
446 fn parse_subset_sps_unknown_profile() {
447 #[rustfmt::skip]
465 let data = [
466 0x42, 0xC0, 0x1E, 0xFB,
474 0x84,
483 ];
484 let subset = SubsetSps::from_bits(BitReader::new(&data[..])).unwrap();
485 assert_eq!(u8::from(subset.sps.profile_idc), 66);
486 assert!(subset.extension.is_none());
487 assert!(!subset.additional_extension2_flag);
488 }
489}