Skip to main content

h264_reader/nal/slice/
mod.rs

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    /// All slices in the picture have the same type
25    Exclusive,
26    /// Other slices in the picture may have a different type than the current slice
27    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    /// `slice_alpha_c0_offset_div2` was outside the expected range of `-6` to `+6`
96    InvalidSliceAlphaC0OffsetDiv2(i32),
97    /// `slice_beta_offset_div2` was outside the expected range of `-6` to `+6`
98    InvalidSliceBetaOffsetDiv2(i32),
99    /// `num_ref_idx_l0_default_active_minus1` or num_ref_idx_l1_default_active_minus1` is
100    /// greater than allowed 32.
101    InvalidNumRefIdx(&'static str, u32),
102    /// The header contained syntax elements that the parser isn't able to handle yet
103    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    /// Indicates the _chroma_ colour plane
124    Y,
125    /// Indicates the _blue-difference_ colour plane
126    Cb,
127    /// Indicates the _red-difference_ colour plane
128    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    /// MVC: `modification_of_pic_nums_idc` value `4`, reads `abs_diff_view_idx_minus1`
206    SubtractViewIdx(u32),
207    /// MVC: `modification_of_pic_nums_idc` value `5`, reads `abs_diff_view_idx_minus1`
208    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        // either ref_pic_list_modification_flag_l0 or ref_pic_list_modification_flag_l1 depending
245        // on call-site,
246        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            // Per spec section 6.2: when separate_colour_plane_flag is 1,
298            // ChromaArrayType is set to 0 (i.e. Monochrome).
299            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    /// `memory_management_control_operation` value of `1`
383    ShortTermUnusedForRef { difference_of_pic_nums_minus1: u32 },
384    /// `memory_management_control_operation` value of `2`
385    LongTermUnusedForRef { long_term_pic_num: u32 },
386    /// `memory_management_control_operation` value of `3`
387    ShortTermUsedForLongTerm {
388        difference_of_pic_nums_minus1: u32,
389        long_term_frame_idx: u32,
390    },
391    /// `memory_management_control_operation` value of `4`
392    MaxUsedLongTermFrameRef { max_long_term_frame_idx_plus1: u32 },
393    /// `memory_management_control_operation` value of `5`
394    AllRefPicturesUnused,
395    /// `memory_management_control_operation` value of `6`
396    CurrentUsedForLongTerm { long_term_frame_idx: u32 },
397}
398
399/// Decoded reference picture marking
400#[derive(Debug)]
401pub enum DecRefPicMarking {
402    Idr {
403        no_output_of_prior_pics_flag: bool,
404        long_term_reference_flag: bool,
405    },
406    /// `adaptive_ref_pic_marking_mode_flag` equal to `0`
407    SlidingWindow,
408    /// `adaptive_ref_pic_marking_mode_flag` equal to `1`
409    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        // Examples from fuzz testing.
782        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}