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