scuffle_h265/sps/
sub_layer_ordering_info.rs

1use std::io;
2
3use scuffle_bytes_util::{BitReader, range_check};
4use scuffle_expgolomb::BitReaderExpGolombExt;
5
6/// Info for each sub-layer in the SPS.
7///
8/// Directly part of [SPS RBSP](crate::SpsRbsp).
9#[derive(Debug, Clone, PartialEq)]
10pub struct SubLayerOrderingInfo {
11    /// `sps_max_dec_pic_buffering_minus1[i]` plus 1 specifies the maximum required size of the decoded
12    /// picture buffer for the CVS in units of picture storage buffers when `HighestTid` is equal to `i`.
13    pub sps_max_dec_pic_buffering_minus1: Vec<u64>,
14    /// `sps_max_num_reorder_pics[i]` indicates the maximum allowed number of pictures with `PicOutputFlag`
15    /// equal to 1 that can precede any picture with `PicOutputFlag` equal to 1 in the CVS in decoding order and
16    /// follow that picture with `PicOutputFlag` equal to 1 in output order when `HighestTid` is equal to i.
17    pub sps_max_num_reorder_pics: Vec<u64>,
18    /// `sps_max_latency_increase_plus1[i]` not equal to 0 is used to compute the value of
19    /// [`SpsMaxLatencyPictures[i]`](SubLayerOrderingInfo::sps_max_latency_pictures_at),
20    /// which specifies the maximum number of pictures with `PicOutputFlag` equal
21    /// to 1 that can precede any picture with `PicOutputFlag` equal to 1 in the CVS in output order and follow that
22    /// picture with `PicOutputFlag` equal to 1 in decoding order when `HighestTid` is equal to i.
23    pub sps_max_latency_increase_plus1: Vec<u32>,
24}
25
26impl SubLayerOrderingInfo {
27    pub(crate) fn parse<R: io::Read>(
28        bit_reader: &mut BitReader<R>,
29        sps_sub_layer_ordering_info_present_flag: bool,
30        sps_max_sub_layers_minus1: u8,
31    ) -> io::Result<Self> {
32        let mut sps_max_dec_pic_buffering_minus1 = vec![0; sps_max_sub_layers_minus1 as usize + 1];
33        let mut sps_max_num_reorder_pics = vec![0; sps_max_sub_layers_minus1 as usize + 1];
34        let mut sps_max_latency_increase_plus1 = vec![0; sps_max_sub_layers_minus1 as usize + 1];
35
36        if sps_sub_layer_ordering_info_present_flag {
37            for i in 0..=sps_max_sub_layers_minus1 as usize {
38                sps_max_dec_pic_buffering_minus1[i] = bit_reader.read_exp_golomb()?;
39                // (A-2) defines MaxDpbSize which is always at most 16
40                range_check!(sps_max_dec_pic_buffering_minus1[i], 0, 16)?;
41                if i > 0 && sps_max_dec_pic_buffering_minus1[i] < sps_max_dec_pic_buffering_minus1[i - 1] {
42                    return Err(io::Error::new(
43                        io::ErrorKind::InvalidData,
44                        "sps_max_dec_pic_buffering_minus1[i] must be greater than or equal to sps_max_dec_pic_buffering_minus1[i-1]",
45                    ));
46                }
47
48                sps_max_num_reorder_pics[i] = bit_reader.read_exp_golomb()?;
49                range_check!(sps_max_num_reorder_pics[i], 0, sps_max_dec_pic_buffering_minus1[i])?;
50                if i > 0 && sps_max_num_reorder_pics[i] < sps_max_num_reorder_pics[i - 1] {
51                    return Err(io::Error::new(
52                        io::ErrorKind::InvalidData,
53                        "sps_max_num_reorder_pics[i] must be greater than or equal to sps_max_num_reorder_pics[i-1]",
54                    ));
55                }
56
57                let sps_max_latency_increase_plus1_i = bit_reader.read_exp_golomb()?;
58                range_check!(sps_max_latency_increase_plus1_i, 0, 2u64.pow(32) - 2)?;
59                sps_max_latency_increase_plus1[i] = sps_max_latency_increase_plus1_i as u32;
60            }
61        } else {
62            // From the spec, page 108 and 109:
63            // When sps_max_dec_pic_buffering_minus1[i] is not present (...) due to
64            // sps_sub_layer_ordering_info_present_flag being equal to 0, it is inferred to be equal to
65            // sps_max_dec_pic_buffering_minus1[sps_max_sub_layers_minus1].
66
67            let sps_max_dec_pic_buffering_minus1_i = bit_reader.read_exp_golomb()?;
68            // (A-2) defines MaxDpbSize which is always at most 16
69            range_check!(sps_max_dec_pic_buffering_minus1_i, 0, 16)?;
70            sps_max_dec_pic_buffering_minus1.fill(sps_max_dec_pic_buffering_minus1_i);
71
72            let sps_max_num_reorder_pics_i = bit_reader.read_exp_golomb()?;
73            range_check!(sps_max_num_reorder_pics_i, 0, sps_max_dec_pic_buffering_minus1_i)?;
74            sps_max_num_reorder_pics.fill(sps_max_num_reorder_pics_i);
75
76            let sps_max_latency_increase_plus1_i = bit_reader.read_exp_golomb()?;
77            range_check!(sps_max_latency_increase_plus1_i, 0, 2u64.pow(32) - 2)?;
78            sps_max_latency_increase_plus1.fill(sps_max_latency_increase_plus1_i as u32);
79        }
80
81        Ok(SubLayerOrderingInfo {
82            sps_max_dec_pic_buffering_minus1,
83            sps_max_num_reorder_pics,
84            sps_max_latency_increase_plus1,
85        })
86    }
87
88    /// Specifies the maximum number of pictures with `PicOutputFlag` equal
89    /// to 1 that can precede any picture with `PicOutputFlag` equal to 1 in the CVS in output order and follow that
90    /// picture with `PicOutputFlag` equal to 1 in decoding order when `HighestTid` is equal to i.
91    ///
92    /// Calculates the full `SpsMaxLatencyPictures` array.
93    ///
94    /// Use [`SubLayerOrderingInfo::sps_max_latency_pictures_at`] to only calculate one specific value `SpsMaxLatencyPictures[i]`.
95    ///
96    /// `SpsMaxLatencyPictures[i] = sps_max_num_reorder_pics[i] + sps_max_latency_increase_plus1[i] − 1` (7-9)
97    ///
98    /// ISO/IEC 23008-2 - 7.4.3.2
99    pub fn sps_max_latency_pictures(&self) -> Vec<Option<u64>> {
100        self.sps_max_num_reorder_pics
101            .iter()
102            .zip(self.sps_max_latency_increase_plus1.iter())
103            .map(|(reorder, latency)| Some(reorder + latency.checked_sub(1)? as u64))
104            .collect()
105    }
106
107    /// Calculates `SpsMaxLatencyPictures[i]`.
108    ///
109    /// See [`sps_max_latency_pictures`](SubLayerOrderingInfo::sps_max_latency_pictures) for details.
110    ///
111    /// `SpsMaxLatencyPictures[i] = sps_max_num_reorder_pics[i] + sps_max_latency_increase_plus1[i] − 1` (7-9)
112    ///
113    /// ISO/IEC 23008-2 - 7.4.3.2
114    pub fn sps_max_latency_pictures_at(&self, i: usize) -> Option<u64> {
115        Some(self.sps_max_num_reorder_pics.get(i)? + self.sps_max_latency_increase_plus1.get(i)?.checked_sub(1)? as u64)
116    }
117}