scuffle_h265/sps/
sub_layer_ordering_info.rs1use std::io;
2
3use scuffle_bytes_util::BitReader;
4use scuffle_expgolomb::BitReaderExpGolombExt;
5
6use crate::range_check::range_check;
7
8#[derive(Debug, Clone, PartialEq)]
12pub struct SubLayerOrderingInfo {
13 pub sps_max_dec_pic_buffering_minus1: Vec<u64>,
16 pub sps_max_num_reorder_pics: Vec<u64>,
20 pub sps_max_latency_increase_plus1: Vec<u32>,
26}
27
28impl SubLayerOrderingInfo {
29 pub(crate) fn parse<R: io::Read>(
30 bit_reader: &mut BitReader<R>,
31 sps_sub_layer_ordering_info_present_flag: bool,
32 sps_max_sub_layers_minus1: u8,
33 ) -> io::Result<Self> {
34 let mut sps_max_dec_pic_buffering_minus1 = vec![0; sps_max_sub_layers_minus1 as usize + 1];
35 let mut sps_max_num_reorder_pics = vec![0; sps_max_sub_layers_minus1 as usize + 1];
36 let mut sps_max_latency_increase_plus1 = vec![0; sps_max_sub_layers_minus1 as usize + 1];
37
38 if sps_sub_layer_ordering_info_present_flag {
39 for i in 0..=sps_max_sub_layers_minus1 as usize {
40 sps_max_dec_pic_buffering_minus1[i] = bit_reader.read_exp_golomb()?;
41 range_check!(sps_max_dec_pic_buffering_minus1[i], 0, 16)?;
43 if i > 0 && sps_max_dec_pic_buffering_minus1[i] < sps_max_dec_pic_buffering_minus1[i - 1] {
44 return Err(io::Error::new(
45 io::ErrorKind::InvalidData,
46 "sps_max_dec_pic_buffering_minus1[i] must be greater than or equal to sps_max_dec_pic_buffering_minus1[i-1]",
47 ));
48 }
49
50 sps_max_num_reorder_pics[i] = bit_reader.read_exp_golomb()?;
51 range_check!(sps_max_num_reorder_pics[i], 0, sps_max_dec_pic_buffering_minus1[i])?;
52 if i > 0 && sps_max_num_reorder_pics[i] < sps_max_num_reorder_pics[i - 1] {
53 return Err(io::Error::new(
54 io::ErrorKind::InvalidData,
55 "sps_max_num_reorder_pics[i] must be greater than or equal to sps_max_num_reorder_pics[i-1]",
56 ));
57 }
58
59 let sps_max_latency_increase_plus1_i = bit_reader.read_exp_golomb()?;
60 range_check!(sps_max_latency_increase_plus1_i, 0, 2u64.pow(32) - 2)?;
61 sps_max_latency_increase_plus1[i] = sps_max_latency_increase_plus1_i as u32;
62 }
63 } else {
64 let sps_max_dec_pic_buffering_minus1_i = bit_reader.read_exp_golomb()?;
70 range_check!(sps_max_dec_pic_buffering_minus1_i, 0, 16)?;
72 sps_max_dec_pic_buffering_minus1.fill(sps_max_dec_pic_buffering_minus1_i);
73
74 let sps_max_num_reorder_pics_i = bit_reader.read_exp_golomb()?;
75 range_check!(sps_max_num_reorder_pics_i, 0, sps_max_dec_pic_buffering_minus1_i)?;
76 sps_max_num_reorder_pics.fill(sps_max_num_reorder_pics_i);
77
78 let sps_max_latency_increase_plus1_i = bit_reader.read_exp_golomb()?;
79 range_check!(sps_max_latency_increase_plus1_i, 0, 2u64.pow(32) - 2)?;
80 sps_max_latency_increase_plus1.fill(sps_max_latency_increase_plus1_i as u32);
81 }
82
83 Ok(SubLayerOrderingInfo {
84 sps_max_dec_pic_buffering_minus1,
85 sps_max_num_reorder_pics,
86 sps_max_latency_increase_plus1,
87 })
88 }
89
90 pub fn sps_max_latency_pictures(&self) -> Vec<Option<u64>> {
102 self.sps_max_num_reorder_pics
103 .iter()
104 .zip(self.sps_max_latency_increase_plus1.iter())
105 .map(|(reorder, latency)| Some(reorder + latency.checked_sub(1)? as u64))
106 .collect()
107 }
108
109 pub fn sps_max_latency_pictures_at(&self, i: usize) -> Option<u64> {
117 Some(self.sps_max_num_reorder_pics.get(i)? + self.sps_max_latency_increase_plus1.get(i)?.checked_sub(1)? as u64)
118 }
119}