1mod cavlc;
2pub mod data;
3pub mod macroblock;
4
5use crate::nal::pps;
6use crate::nal::pps::{PicParamSetId, PicParameterSet};
7use crate::nal::sps;
8use crate::nal::sps::SeqParameterSet;
9use crate::nal::{NalHeader, NalHeaderExtension};
10use crate::rbsp::BitRead;
11use crate::rbsp::BitReaderError;
12use crate::Context;
13
14#[derive(Debug, Clone, Copy, PartialEq)]
15pub enum SliceFamily {
16 P,
17 B,
18 I,
19 SP,
20 SI,
21}
22#[derive(Debug, PartialEq)]
23pub enum SliceExclusive {
24 Exclusive,
26 NonExclusive,
28}
29#[derive(Debug, PartialEq)]
30pub struct SliceType {
31 pub family: SliceFamily,
32 pub exclusive: SliceExclusive,
33}
34impl SliceType {
35 fn from_id(id: u32) -> Result<SliceType, SliceHeaderError> {
36 match id {
37 0 => Ok(SliceType {
38 family: SliceFamily::P,
39 exclusive: SliceExclusive::NonExclusive,
40 }),
41 1 => Ok(SliceType {
42 family: SliceFamily::B,
43 exclusive: SliceExclusive::NonExclusive,
44 }),
45 2 => Ok(SliceType {
46 family: SliceFamily::I,
47 exclusive: SliceExclusive::NonExclusive,
48 }),
49 3 => Ok(SliceType {
50 family: SliceFamily::SP,
51 exclusive: SliceExclusive::NonExclusive,
52 }),
53 4 => Ok(SliceType {
54 family: SliceFamily::SI,
55 exclusive: SliceExclusive::NonExclusive,
56 }),
57 5 => Ok(SliceType {
58 family: SliceFamily::P,
59 exclusive: SliceExclusive::Exclusive,
60 }),
61 6 => Ok(SliceType {
62 family: SliceFamily::B,
63 exclusive: SliceExclusive::Exclusive,
64 }),
65 7 => Ok(SliceType {
66 family: SliceFamily::I,
67 exclusive: SliceExclusive::Exclusive,
68 }),
69 8 => Ok(SliceType {
70 family: SliceFamily::SP,
71 exclusive: SliceExclusive::Exclusive,
72 }),
73 9 => Ok(SliceType {
74 family: SliceFamily::SI,
75 exclusive: SliceExclusive::Exclusive,
76 }),
77 _ => Err(SliceHeaderError::InvalidSliceType(id)),
78 }
79 }
80}
81
82#[derive(Debug)]
83pub enum SliceHeaderError {
84 RbspError(BitReaderError),
85 InvalidSliceType(u32),
86 InvalidSeqParamSetId(pps::PicParamSetIdError),
87 UndefinedPicParamSetId(pps::PicParamSetId),
88 UndefinedSeqParamSetId(sps::SeqParamSetId),
89 ColourPlaneError(ColourPlaneError),
90 InvalidModificationOfPicNumIdc(u32),
91 InvalidMemoryManagementControlOperation(u32),
92 InvalidSliceQpDelta(i32),
93 InvalidSliceQsDelta(i32),
94 InvalidDisableDeblockingFilterIdc(u32),
95 InvalidSliceAlphaC0OffsetDiv2(i32),
97 InvalidSliceBetaOffsetDiv2(i32),
99 InvalidNumRefIdx(&'static str, u32),
102 UnsupportedSyntax(&'static str),
104}
105impl From<BitReaderError> for SliceHeaderError {
106 fn from(e: BitReaderError) -> Self {
107 SliceHeaderError::RbspError(e)
108 }
109}
110impl From<pps::PicParamSetIdError> for SliceHeaderError {
111 fn from(e: pps::PicParamSetIdError) -> Self {
112 SliceHeaderError::InvalidSeqParamSetId(e)
113 }
114}
115impl From<ColourPlaneError> for SliceHeaderError {
116 fn from(e: ColourPlaneError) -> Self {
117 SliceHeaderError::ColourPlaneError(e)
118 }
119}
120
121#[derive(Debug)]
122pub enum ColourPlane {
123 Y,
125 Cb,
127 Cr,
129}
130#[derive(Debug)]
131pub enum ColourPlaneError {
132 InvalidId(u8),
133}
134impl ColourPlane {
135 fn from_id(id: u8) -> Result<ColourPlane, ColourPlaneError> {
136 match id {
137 0 => Ok(ColourPlane::Y),
138 1 => Ok(ColourPlane::Cb),
139 2 => Ok(ColourPlane::Cr),
140 _ => Err(ColourPlaneError::InvalidId(id)),
141 }
142 }
143}
144
145#[derive(Debug, PartialEq)]
146pub enum Field {
147 Top,
148 Bottom,
149}
150
151#[derive(Debug, PartialEq)]
152pub enum FieldPic {
153 Frame,
154 Field(Field),
155}
156
157#[derive(Debug, PartialEq)]
158pub enum PicOrderCountLsb {
159 Frame(u32),
160 FieldsAbsolute {
161 pic_order_cnt_lsb: u32,
162 delta_pic_order_cnt_bottom: i32,
163 },
164 FieldsDelta([i32; 2]),
165}
166
167#[derive(Debug)]
168pub enum NumRefIdxActive {
169 P {
170 num_ref_idx_l0_active_minus1: u32,
171 },
172 B {
173 num_ref_idx_l0_active_minus1: u32,
174 num_ref_idx_l1_active_minus1: u32,
175 },
176}
177impl NumRefIdxActive {
178 fn num_ref_idx_l0_active_minus1(&self) -> u32 {
179 match *self {
180 NumRefIdxActive::P {
181 num_ref_idx_l0_active_minus1,
182 } => num_ref_idx_l0_active_minus1,
183 NumRefIdxActive::B {
184 num_ref_idx_l0_active_minus1,
185 ..
186 } => num_ref_idx_l0_active_minus1,
187 }
188 }
189 fn num_ref_idx_l1_active_minus1(&self) -> Option<u32> {
190 match *self {
191 NumRefIdxActive::P { .. } => None,
192 NumRefIdxActive::B {
193 num_ref_idx_l1_active_minus1,
194 ..
195 } => Some(num_ref_idx_l1_active_minus1),
196 }
197 }
198}
199
200#[derive(Debug)]
201pub enum ModificationOfPicNums {
202 Subtract(u32),
203 Add(u32),
204 LongTermRef(u32),
205 SubtractViewIdx(u32),
207 AddViewIdx(u32),
209}
210#[derive(Debug)]
211pub enum RefPicListModifications {
212 I,
213 P {
214 ref_pic_list_modification_l0: Vec<ModificationOfPicNums>,
215 },
216 B {
217 ref_pic_list_modification_l0: Vec<ModificationOfPicNums>,
218 ref_pic_list_modification_l1: Vec<ModificationOfPicNums>,
219 },
220}
221impl RefPicListModifications {
222 fn read<R: BitRead>(
223 slice_family: &SliceFamily,
224 r: &mut R,
225 mvc: bool,
226 ) -> Result<RefPicListModifications, SliceHeaderError> {
227 Ok(match slice_family {
228 SliceFamily::I | SliceFamily::SI => RefPicListModifications::I,
229 SliceFamily::B => RefPicListModifications::B {
230 ref_pic_list_modification_l0: Self::read_list(r, mvc)?,
231 ref_pic_list_modification_l1: Self::read_list(r, mvc)?,
232 },
233 SliceFamily::P | SliceFamily::SP => RefPicListModifications::P {
234 ref_pic_list_modification_l0: Self::read_list(r, mvc)?,
235 },
236 })
237 }
238
239 fn read_list<R: BitRead>(
240 r: &mut R,
241 mvc: bool,
242 ) -> Result<Vec<ModificationOfPicNums>, SliceHeaderError> {
243 let mut result = vec![];
244 if !r.read_bit("ref_pic_list_modification_flag")? {
247 return Ok(result);
248 }
249 loop {
250 match r.read_ue("modification_of_pic_nums_idc")? {
251 0 => result.push(ModificationOfPicNums::Subtract(
252 r.read_ue("abs_diff_pic_num_minus1")?,
253 )),
254 1 => result.push(ModificationOfPicNums::Add(
255 r.read_ue("abs_diff_pic_num_minus1")?,
256 )),
257 2 => result.push(ModificationOfPicNums::LongTermRef(
258 r.read_ue("long_term_pic_num")?,
259 )),
260 3 => break,
261 4 if mvc => result.push(ModificationOfPicNums::SubtractViewIdx(
262 r.read_ue("abs_diff_view_idx_minus1")?,
263 )),
264 5 if mvc => result.push(ModificationOfPicNums::AddViewIdx(
265 r.read_ue("abs_diff_view_idx_minus1")?,
266 )),
267 v => return Err(SliceHeaderError::InvalidModificationOfPicNumIdc(v)),
268 }
269 }
270 Ok(result)
271 }
272}
273
274#[derive(Debug)]
275pub struct PredWeight {
276 pub weight: i32,
277 pub offset: i32,
278}
279#[derive(Debug)]
280pub struct PredWeightTable {
281 pub luma_log2_weight_denom: u32,
282 pub chroma_log2_weight_denom: Option<u32>,
283 pub luma_weights: Vec<Option<PredWeight>>,
284 pub chroma_weights: Vec<Vec<PredWeight>>,
285 pub luma_weights_l1: Vec<Option<PredWeight>>,
286 pub chroma_weights_l1: Vec<Vec<PredWeight>>,
287}
288impl PredWeightTable {
289 fn read<R: BitRead>(
290 r: &mut R,
291 slice_type: &SliceType,
292 pps: &pps::PicParameterSet,
293 sps: &sps::SeqParameterSet,
294 num_ref_active: &Option<NumRefIdxActive>,
295 ) -> Result<PredWeightTable, SliceHeaderError> {
296 let chroma_array_type = if sps.chroma_info.separate_colour_plane_flag {
297 sps::ChromaFormat::Monochrome
300 } else {
301 sps.chroma_info.chroma_format
302 };
303 let luma_log2_weight_denom = r.read_ue("luma_log2_weight_denom")?;
304 let chroma_log2_weight_denom = if chroma_array_type != sps::ChromaFormat::Monochrome {
305 Some(r.read_ue("chroma_log2_weight_denom")?)
306 } else {
307 None
308 };
309 let num_ref_idx_l0_active_minus1 = num_ref_active
310 .as_ref()
311 .map(|n| n.num_ref_idx_l0_active_minus1())
312 .unwrap_or_else(|| pps.num_ref_idx_l0_default_active_minus1);
313 let mut luma_weights = Vec::with_capacity((num_ref_idx_l0_active_minus1 + 1) as usize);
314 let mut chroma_weights = Vec::with_capacity((num_ref_idx_l0_active_minus1 + 1) as usize);
315 for _ in 0..=num_ref_idx_l0_active_minus1 {
316 if r.read_bit("luma_weight_l0_flag")? {
317 luma_weights.push(Some(PredWeight {
318 weight: r.read_se("luma_weight_l0")?,
319 offset: r.read_se("luma_offset_l0")?,
320 }));
321 } else {
322 luma_weights.push(None);
323 }
324 if chroma_array_type != sps::ChromaFormat::Monochrome {
325 let mut weights = Vec::with_capacity(2);
326 if r.read_bit("chroma_weight_l0_flag")? {
327 for _j in 0..2 {
328 weights.push(PredWeight {
329 weight: r.read_se("chroma_weight_l0")?,
330 offset: r.read_se("chroma_offset_l0")?,
331 });
332 }
333 }
334 chroma_weights.push(weights);
335 }
336 }
337 let mut luma_weights_l1 = vec![];
338 let mut chroma_weights_l1 = vec![];
339 if slice_type.family == SliceFamily::B {
340 let num_ref_idx_l1_active_minus1 = num_ref_active
341 .as_ref()
342 .and_then(|n| n.num_ref_idx_l1_active_minus1())
343 .unwrap_or_else(|| pps.num_ref_idx_l1_default_active_minus1);
344 luma_weights_l1.reserve((num_ref_idx_l1_active_minus1 + 1) as usize);
345 chroma_weights_l1.reserve((num_ref_idx_l1_active_minus1 + 1) as usize);
346 for _ in 0..=num_ref_idx_l1_active_minus1 {
347 if r.read_bit("luma_weight_l1_flag")? {
348 luma_weights_l1.push(Some(PredWeight {
349 weight: r.read_se("luma_weight_l1")?,
350 offset: r.read_se("luma_offset_l1")?,
351 }));
352 } else {
353 luma_weights_l1.push(None);
354 }
355 if chroma_array_type != sps::ChromaFormat::Monochrome {
356 let mut weights = Vec::with_capacity(2);
357 if r.read_bit("chroma_weight_l1_flag")? {
358 for _j in 0..2 {
359 weights.push(PredWeight {
360 weight: r.read_se("chroma_weight_l1")?,
361 offset: r.read_se("chroma_offset_l1")?,
362 });
363 }
364 }
365 chroma_weights_l1.push(weights);
366 }
367 }
368 }
369 Ok(PredWeightTable {
370 luma_log2_weight_denom,
371 chroma_log2_weight_denom,
372 luma_weights,
373 chroma_weights,
374 luma_weights_l1,
375 chroma_weights_l1,
376 })
377 }
378}
379
380#[derive(Debug)]
381pub enum MemoryManagementControlOperation {
382 ShortTermUnusedForRef { difference_of_pic_nums_minus1: u32 },
384 LongTermUnusedForRef { long_term_pic_num: u32 },
386 ShortTermUsedForLongTerm {
388 difference_of_pic_nums_minus1: u32,
389 long_term_frame_idx: u32,
390 },
391 MaxUsedLongTermFrameRef { max_long_term_frame_idx_plus1: u32 },
393 AllRefPicturesUnused,
395 CurrentUsedForLongTerm { long_term_frame_idx: u32 },
397}
398
399#[derive(Debug)]
401pub enum DecRefPicMarking {
402 Idr {
403 no_output_of_prior_pics_flag: bool,
404 long_term_reference_flag: bool,
405 },
406 SlidingWindow,
408 Adaptive(Vec<MemoryManagementControlOperation>),
410}
411impl DecRefPicMarking {
412 fn read<R: BitRead>(
413 r: &mut R,
414 idr_pic_flag: bool,
415 ) -> Result<DecRefPicMarking, SliceHeaderError> {
416 Ok(if idr_pic_flag {
417 DecRefPicMarking::Idr {
418 no_output_of_prior_pics_flag: r.read_bit("no_output_of_prior_pics_flag")?,
419 long_term_reference_flag: r.read_bit("long_term_reference_flag")?,
420 }
421 } else if r.read_bit("adaptive_ref_pic_marking_mode_flag")? {
422 let mut ctl = vec![];
423 loop {
424 let op = match r.read_ue("memory_management_control_operation")? {
425 0 => break,
426 1 => {
427 let difference_of_pic_nums_minus1 =
428 r.read_ue("difference_of_pic_nums_minus1")?;
429 MemoryManagementControlOperation::ShortTermUnusedForRef {
430 difference_of_pic_nums_minus1,
431 }
432 }
433 2 => {
434 let long_term_pic_num = r.read_ue("long_term_pic_num")?;
435 MemoryManagementControlOperation::LongTermUnusedForRef { long_term_pic_num }
436 }
437 3 => {
438 let difference_of_pic_nums_minus1 =
439 r.read_ue("difference_of_pic_nums_minus1")?;
440 let long_term_frame_idx = r.read_ue("long_term_frame_idx")?;
441 MemoryManagementControlOperation::ShortTermUsedForLongTerm {
442 difference_of_pic_nums_minus1,
443 long_term_frame_idx,
444 }
445 }
446 4 => {
447 let max_long_term_frame_idx_plus1 =
448 r.read_ue("max_long_term_frame_idx_plus1")?;
449 MemoryManagementControlOperation::MaxUsedLongTermFrameRef {
450 max_long_term_frame_idx_plus1,
451 }
452 }
453 5 => MemoryManagementControlOperation::AllRefPicturesUnused,
454 6 => {
455 let long_term_frame_idx = r.read_ue("long_term_frame_idx")?;
456 MemoryManagementControlOperation::CurrentUsedForLongTerm {
457 long_term_frame_idx,
458 }
459 }
460 other => {
461 return Err(SliceHeaderError::InvalidMemoryManagementControlOperation(
462 other,
463 ))
464 }
465 };
466 ctl.push(op);
467 }
468 DecRefPicMarking::Adaptive(ctl)
469 } else {
470 DecRefPicMarking::SlidingWindow
471 })
472 }
473}
474
475#[derive(Debug)]
476pub struct SliceHeader {
477 pub first_mb_in_slice: u32,
478 pub slice_type: SliceType,
479 pub colour_plane: Option<ColourPlane>,
480 pub frame_num: u16,
481 pub field_pic: FieldPic,
482 pub idr_pic_id: Option<u32>,
483 pub pic_order_cnt_lsb: Option<PicOrderCountLsb>,
484 pub redundant_pic_cnt: Option<u32>,
485 pub direct_spatial_mv_pred_flag: Option<bool>,
486 pub num_ref_idx_active: Option<NumRefIdxActive>,
487 pub ref_pic_list_modification: Option<RefPicListModifications>,
488 pub pred_weight_table: Option<PredWeightTable>,
489 pub dec_ref_pic_marking: Option<DecRefPicMarking>,
490 pub cabac_init_idc: Option<u32>,
491 pub slice_qp_delta: i32,
492 pub sp_for_switch_flag: Option<bool>,
493 pub slice_qs: Option<u32>,
494 pub disable_deblocking_filter_idc: u8,
495 pub slice_alpha_c0_offset_div2: Option<i32>,
496 pub slice_beta_offset_div2: Option<i32>,
497 pub slice_group_change_cycle: Option<u32>,
498}
499impl SliceHeader {
500 pub fn from_bits<'a, R: BitRead>(
501 ctx: &'a Context,
502 r: &mut R,
503 header: NalHeader,
504 header_extension: Option<&NalHeaderExtension>,
505 ) -> Result<(SliceHeader, &'a SeqParameterSet, &'a PicParameterSet), SliceHeaderError> {
506 let first_mb_in_slice = r.read_ue("first_mb_in_slice")?;
507 let slice_type = SliceType::from_id(r.read_ue("slice_type")?)?;
508 let pic_parameter_set_id = PicParamSetId::from_u32(r.read_ue("pic_parameter_set_id")?)?;
509 let pps =
510 ctx.pps_by_id(pic_parameter_set_id)
511 .ok_or(SliceHeaderError::UndefinedPicParamSetId(
512 pic_parameter_set_id,
513 ))?;
514 let sps = ctx.sps_by_id(pps.seq_parameter_set_id).ok_or(
515 SliceHeaderError::UndefinedSeqParamSetId(pps.seq_parameter_set_id),
516 )?;
517 let colour_plane = if sps.chroma_info.separate_colour_plane_flag {
518 Some(ColourPlane::from_id(r.read::<2, _>("colour_plane_id")?)?)
519 } else {
520 None
521 };
522 let frame_num = r.read_var(u32::from(sps.log2_max_frame_num()), "frame_num")?;
523 let field_pic = if let sps::FrameMbsFlags::Fields { .. } = sps.frame_mbs_flags {
524 if r.read_bit("field_pic_flag")? {
525 if r.read_bit("bottom_field_flag")? {
526 FieldPic::Field(Field::Bottom)
527 } else {
528 FieldPic::Field(Field::Top)
529 }
530 } else {
531 FieldPic::Frame
532 }
533 } else {
534 FieldPic::Frame
535 };
536 let idr_pic_flag = match header.nal_unit_type() {
537 crate::nal::UnitType::SliceLayerWithoutPartitioningIdr => true,
538 crate::nal::UnitType::SliceExtension
539 | crate::nal::UnitType::SliceExtensionViewComponent => {
540 matches!(
541 header_extension,
542 Some(NalHeaderExtension::Mvc(ext)) if !ext.non_idr_flag()
543 )
544 }
545 _ => false,
546 };
547 let idr_pic_id = if idr_pic_flag {
548 Some(r.read_ue("idr_pic_id")?)
549 } else {
550 None
551 };
552 let pic_order_cnt_lsb = match sps.pic_order_cnt {
553 sps::PicOrderCntType::TypeZero {
554 log2_max_pic_order_cnt_lsb_minus4,
555 } => {
556 let pic_order_cnt_lsb = r.read_var(
557 u32::from(log2_max_pic_order_cnt_lsb_minus4) + 4,
558 "pic_order_cnt_lsb",
559 )?;
560 Some(
561 if pps.bottom_field_pic_order_in_frame_present_flag
562 && field_pic == FieldPic::Frame
563 {
564 let delta_pic_order_cnt_bottom = r.read_se("delta_pic_order_cnt_bottom")?;
565 PicOrderCountLsb::FieldsAbsolute {
566 pic_order_cnt_lsb,
567 delta_pic_order_cnt_bottom,
568 }
569 } else {
570 PicOrderCountLsb::Frame(pic_order_cnt_lsb)
571 },
572 )
573 }
574 sps::PicOrderCntType::TypeOne {
575 delta_pic_order_always_zero_flag,
576 ..
577 } => {
578 if delta_pic_order_always_zero_flag {
579 Some(PicOrderCountLsb::FieldsDelta([0, 0]))
580 } else {
581 let delta0 = r.read_se("delta_pic_order_cnt[0]")?;
582 if pps.bottom_field_pic_order_in_frame_present_flag
583 && field_pic == FieldPic::Frame
584 {
585 let delta1 = r.read_se("delta_pic_order_cnt[1]")?;
586 Some(PicOrderCountLsb::FieldsDelta([delta0, delta1]))
587 } else {
588 Some(PicOrderCountLsb::FieldsDelta([delta0, 0]))
589 }
590 }
591 }
592 sps::PicOrderCntType::TypeTwo => None,
593 };
594 let redundant_pic_cnt = if pps.redundant_pic_cnt_present_flag {
595 Some(r.read_ue("redundant_pic_cnt")?)
596 } else {
597 None
598 };
599 let direct_spatial_mv_pred_flag = if slice_type.family == SliceFamily::B {
600 Some(r.read_bit("direct_spatial_mv_pred_flag")?)
601 } else {
602 None
603 };
604 let num_ref_idx_active = if slice_type.family == SliceFamily::P
605 || slice_type.family == SliceFamily::SP
606 || slice_type.family == SliceFamily::B
607 {
608 if r.read_bit("num_ref_idx_active_override_flag")? {
609 let num_ref_idx_l0_active_minus1 =
610 read_num_ref_idx(r, "num_ref_idx_l0_active_minus1")?;
611 Some(if slice_type.family == SliceFamily::B {
612 let num_ref_idx_l1_active_minus1 =
613 read_num_ref_idx(r, "num_ref_idx_l1_active_minus1")?;
614 NumRefIdxActive::B {
615 num_ref_idx_l0_active_minus1,
616 num_ref_idx_l1_active_minus1,
617 }
618 } else {
619 NumRefIdxActive::P {
620 num_ref_idx_l0_active_minus1,
621 }
622 })
623 } else {
624 None
625 }
626 } else {
627 None
628 };
629 let ref_pic_list_modification = match header.nal_unit_type() {
630 crate::nal::UnitType::SliceExtension
631 | crate::nal::UnitType::SliceExtensionViewComponent => match header_extension {
632 Some(NalHeaderExtension::Mvc(_)) => {
633 RefPicListModifications::read(&slice_type.family, r, true)?
634 }
635 _ => {
636 return Err(SliceHeaderError::UnsupportedSyntax(
637 "SVC slice_header not supported",
638 ));
639 }
640 },
641 _ => RefPicListModifications::read(&slice_type.family, r, false)?,
642 };
643 let pred_weight_table = if (pps.weighted_pred_flag
644 && (slice_type.family == SliceFamily::P || slice_type.family == SliceFamily::SP))
645 || (pps.weighted_bipred_idc == 1 && slice_type.family == SliceFamily::B)
646 {
647 Some(PredWeightTable::read(
648 r,
649 &slice_type,
650 pps,
651 sps,
652 &num_ref_idx_active,
653 )?)
654 } else {
655 None
656 };
657 let dec_ref_pic_marking = if header.nal_ref_idc() == 0 {
658 None
659 } else {
660 Some(DecRefPicMarking::read(r, idr_pic_flag)?)
661 };
662 let cabac_init_idc = if pps.entropy_coding_mode_flag
663 && slice_type.family != SliceFamily::I
664 && slice_type.family != SliceFamily::SI
665 {
666 Some(r.read_ue("cabac_init_idc")?)
667 } else {
668 None
669 };
670 let slice_qp_delta = r.read_se("slice_qp_delta")?;
671 let qp_bd_offset_y = 6 * i32::from(sps.chroma_info.bit_depth_luma_minus8);
672 let slice_qp_y = 26 + pps.pic_init_qp_minus26 + slice_qp_delta;
673 if slice_qp_y < -qp_bd_offset_y || slice_qp_y > 51 {
674 return Err(SliceHeaderError::InvalidSliceQpDelta(slice_qp_delta));
675 }
676 let mut sp_for_switch_flag = None;
677 let slice_qs =
678 if slice_type.family == SliceFamily::SP || slice_type.family == SliceFamily::SI {
679 if slice_type.family == SliceFamily::SP {
680 sp_for_switch_flag = Some(r.read_bit("sp_for_switch_flag")?);
681 }
682 let slice_qs_delta = r.read_se("slice_qs_delta")?;
683 let qs_y = 26 + pps.pic_init_qs_minus26 + slice_qs_delta;
684 if qs_y < 0 || 51 < qs_y {
685 return Err(SliceHeaderError::InvalidSliceQsDelta(slice_qs_delta));
686 }
687 Some(qs_y as u32)
688 } else {
689 None
690 };
691 let mut disable_deblocking_filter_idc = 0;
692 let mut slice_alpha_c0_offset_div2 = None;
693 let mut slice_beta_offset_div2 = None;
694 if pps.deblocking_filter_control_present_flag {
695 disable_deblocking_filter_idc = {
696 let v = r.read_ue("disable_deblocking_filter_idc")?;
697 if v > 6 {
698 return Err(SliceHeaderError::InvalidDisableDeblockingFilterIdc(v));
699 }
700 v as u8
701 };
702 if disable_deblocking_filter_idc != 1 {
703 let alpha = r.read_se("slice_alpha_c0_offset_div2")?;
704 if alpha < -6 || 6 < alpha {
705 return Err(SliceHeaderError::InvalidSliceAlphaC0OffsetDiv2(alpha));
706 }
707 slice_alpha_c0_offset_div2 = Some(alpha);
708 let beta = r.read_se("slice_beta_offset_div2")?;
709 if beta < -6 || 6 < beta {
710 return Err(SliceHeaderError::InvalidSliceBetaOffsetDiv2(beta));
711 }
712 slice_beta_offset_div2 = Some(beta);
713 }
714 }
715 let slice_group_change_cycle = if let Some(pps::SliceGroup::Changing {
716 slice_group_change_rate_minus1,
717 ..
718 }) = &pps.slice_groups
719 {
720 let pic_size = sps.pic_size_in_map_units();
721 let change_rate = slice_group_change_rate_minus1 + 1;
722 let bits = (f64::from(pic_size) / f64::from(change_rate) + 1.0)
723 .log2()
724 .ceil() as u32;
725 Some(r.read_var(bits, "slice_group_change_cycle")?)
726 } else {
727 None
728 };
729 if !r.has_more_rbsp_data("slice_header")? {
730 return Err(SliceHeaderError::RbspError(BitReaderError::ReaderError(
731 "slice_header",
732 std::io::Error::new(
733 std::io::ErrorKind::UnexpectedEof,
734 "slice header overran rbsp trailing bits",
735 ),
736 )));
737 }
738 let header = SliceHeader {
739 first_mb_in_slice,
740 slice_type,
741 colour_plane,
742 frame_num,
743 field_pic,
744 idr_pic_id,
745 pic_order_cnt_lsb,
746 redundant_pic_cnt,
747 direct_spatial_mv_pred_flag,
748 num_ref_idx_active,
749 ref_pic_list_modification: Some(ref_pic_list_modification),
750 pred_weight_table,
751 dec_ref_pic_marking,
752 cabac_init_idc,
753 slice_qp_delta,
754 sp_for_switch_flag,
755 slice_qs,
756 disable_deblocking_filter_idc,
757 slice_alpha_c0_offset_div2,
758 slice_beta_offset_div2,
759 slice_group_change_cycle,
760 };
761 Ok((header, sps, pps))
762 }
763}
764
765fn read_num_ref_idx<R: BitRead>(r: &mut R, name: &'static str) -> Result<u32, SliceHeaderError> {
766 let val = r.read_ue(name)?;
767 if val > 31 {
768 return Err(SliceHeaderError::InvalidNumRefIdx(name, val));
769 }
770 Ok(val)
771}
772
773#[cfg(test)]
774mod test {
775 use super::*;
776 use crate::nal::{Nal, RefNal};
777 use hex_literal::hex;
778
779 #[test]
780 fn invalid_num_ref_idx() {
781 let mut ctx = crate::Context::default();
783 let sps = RefNal::new(
784 &hex!("27 d2 d2 d6 d2 27 50 aa 27 01 56 56 08 41 c5")[..],
785 &[],
786 true,
787 );
788 let sps = SeqParameterSet::from_bits(sps.rbsp_bits()).unwrap();
789 ctx.put_seq_param_set(sps);
790 let pps = RefNal::new(&hex!("28 c5 56 6a 08 41 00 fd")[..], &[], true);
791 let pps = PicParameterSet::from_bits(&ctx, pps.rbsp_bits()).unwrap();
792 ctx.put_pic_param_set(pps);
793 let nal = RefNal::new(&hex!("41 26 25 03 00")[..], &[], true);
794 let r = SliceHeader::from_bits(&ctx, &mut nal.rbsp_bits(), nal.header().unwrap(), None);
795 assert!(
796 matches!(r, Err(SliceHeaderError::InvalidNumRefIdx(_, _))),
797 "r={:#?}",
798 r
799 );
800 }
801}