scuffle_h265/sps/
st_ref_pic_set.rs1use std::fmt::Debug;
2use std::io;
3
4use scuffle_bytes_util::{BitReader, range_check};
5use scuffle_expgolomb::BitReaderExpGolombExt;
6
7#[derive(Debug, Clone, PartialEq)]
14pub struct ShortTermRefPicSets {
15 pub num_delta_pocs: Vec<u64>,
17 pub num_positive_pics: Vec<u64>,
19 pub num_negative_pics: Vec<u64>,
21 pub delta_poc_s1: Vec<Vec<i64>>,
23 pub delta_poc_s0: Vec<Vec<i64>>,
25 pub used_by_curr_pic_s0: Vec<Vec<bool>>,
27 pub used_by_curr_pic_s1: Vec<Vec<bool>>,
29}
30
31impl ShortTermRefPicSets {
32 pub(crate) fn parse<R: io::Read>(
33 bit_reader: &mut BitReader<R>,
34 num_short_term_ref_pic_sets: usize,
35 nuh_layer_id: u8,
36 sps_max_dec_pic_buffering_minus1_at_sps_max_sub_layers_minus1: u64,
37 ) -> io::Result<Self> {
38 let mut num_delta_pocs = Vec::with_capacity(num_short_term_ref_pic_sets);
39
40 let mut num_positive_pics = vec![0u64; num_short_term_ref_pic_sets];
42 let mut num_negative_pics = vec![0u64; num_short_term_ref_pic_sets];
43 let mut delta_poc_s1 = Vec::with_capacity(num_short_term_ref_pic_sets);
44 let mut delta_poc_s0 = Vec::with_capacity(num_short_term_ref_pic_sets);
45 let mut used_by_curr_pic_s0 = Vec::with_capacity(num_short_term_ref_pic_sets);
46 let mut used_by_curr_pic_s1 = Vec::with_capacity(num_short_term_ref_pic_sets);
47
48 for st_rps_idx in 0..num_short_term_ref_pic_sets {
49 let mut inter_ref_pic_set_prediction_flag = false;
50 if st_rps_idx != 0 {
51 inter_ref_pic_set_prediction_flag = bit_reader.read_bit()?;
52 }
53
54 if inter_ref_pic_set_prediction_flag {
55 let mut delta_idx_minus1 = 0;
56 if st_rps_idx == num_short_term_ref_pic_sets {
57 delta_idx_minus1 = bit_reader.read_exp_golomb()? as usize;
58 range_check!(delta_idx_minus1, 0, st_rps_idx - 1)?;
59 }
60
61 let ref_rps_idx = st_rps_idx - (delta_idx_minus1 + 1);
63
64 let delta_rps_sign = bit_reader.read_bit()?;
65 let abs_delta_rps_minus1 = bit_reader.read_exp_golomb()?;
66 range_check!(abs_delta_rps_minus1, 0, 2u64.pow(15) - 1)?;
67 let delta_rps = (1 - 2 * delta_rps_sign as i64) * (abs_delta_rps_minus1 + 1) as i64;
69
70 let len = num_delta_pocs[ref_rps_idx] as usize + 1;
72 let mut used_by_curr_pic_flag = vec![false; len];
73 let mut use_delta_flag = vec![true; len];
74 for j in 0..len {
75 used_by_curr_pic_flag[j] = bit_reader.read_bit()?;
76 if !used_by_curr_pic_flag[j] {
77 use_delta_flag[j] = bit_reader.read_bit()?;
78 }
79 }
80
81 delta_poc_s0.push(vec![0; len]);
82 delta_poc_s1.push(vec![0; len]);
83 used_by_curr_pic_s0.push(vec![false; len]);
84 used_by_curr_pic_s1.push(vec![false; len]);
85
86 let mut i = 0;
88 if let Some(start) = num_positive_pics[ref_rps_idx].checked_sub(1).map(|s| s as usize) {
89 for j in (0..=start).rev() {
90 let d_poc = delta_poc_s1[ref_rps_idx][j] + delta_rps;
91 if d_poc < 0 && use_delta_flag[num_negative_pics[ref_rps_idx] as usize + j] {
92 delta_poc_s0[st_rps_idx][i] = d_poc;
93 used_by_curr_pic_s0[st_rps_idx][i] =
94 used_by_curr_pic_flag[num_negative_pics[ref_rps_idx] as usize + j];
95 i += 1;
96 }
97 }
98 }
99
100 if delta_rps < 0 && use_delta_flag[num_delta_pocs[ref_rps_idx] as usize] {
101 delta_poc_s0[st_rps_idx][i] = delta_rps;
102 used_by_curr_pic_s0[st_rps_idx][i] = used_by_curr_pic_flag[num_delta_pocs[ref_rps_idx] as usize];
103 i += 1;
104 }
105
106 for j in 0..num_negative_pics[ref_rps_idx] as usize {
107 let d_poc = delta_poc_s0[ref_rps_idx][j] + delta_rps;
108 if d_poc < 0 && use_delta_flag[j] {
109 delta_poc_s0[st_rps_idx][i] = d_poc;
110 used_by_curr_pic_s0[st_rps_idx][i] = used_by_curr_pic_flag[j];
111 i += 1;
112 }
113 }
114
115 num_negative_pics[st_rps_idx] = i as u64;
116 range_check!(num_negative_pics[st_rps_idx], 0, 16)?;
121
122 i = 0;
123 if let Some(start) = num_negative_pics[ref_rps_idx].checked_sub(1).map(|s| s as usize) {
124 for j in (0..=start).rev() {
125 let d_poc = delta_poc_s0[ref_rps_idx][j] + delta_rps;
126 if d_poc > 0 && use_delta_flag[j] {
127 delta_poc_s1[st_rps_idx][i] = d_poc;
128 used_by_curr_pic_s1[st_rps_idx][i] = used_by_curr_pic_flag[j];
129 i += 1;
130 }
131 }
132 }
133
134 if delta_rps > 0 && use_delta_flag[num_delta_pocs[ref_rps_idx] as usize] {
135 delta_poc_s1[st_rps_idx][i] = delta_rps;
136 used_by_curr_pic_s1[st_rps_idx][i] = used_by_curr_pic_flag[num_delta_pocs[ref_rps_idx] as usize];
137 i += 1;
138 }
139
140 for j in 0..num_positive_pics[ref_rps_idx] as usize {
141 let d_poc = delta_poc_s1[ref_rps_idx][j] + delta_rps;
142 if d_poc > 0 && use_delta_flag[num_negative_pics[ref_rps_idx] as usize + j] {
143 delta_poc_s1[st_rps_idx][i] = d_poc;
144 used_by_curr_pic_s1[st_rps_idx][i] =
145 used_by_curr_pic_flag[num_negative_pics[ref_rps_idx] as usize + j];
146 i += 1;
147 }
148 }
149
150 num_positive_pics[st_rps_idx] = i as u64;
151 range_check!(num_negative_pics[st_rps_idx], 0, 16)?;
156 } else {
157 num_negative_pics[st_rps_idx] = bit_reader.read_exp_golomb()?;
158 num_positive_pics[st_rps_idx] = bit_reader.read_exp_golomb()?;
159
160 let upper_bound = if nuh_layer_id == 0 {
161 sps_max_dec_pic_buffering_minus1_at_sps_max_sub_layers_minus1
163 } else {
164 16
165 };
166 range_check!(num_negative_pics[st_rps_idx], 0, upper_bound)?;
167
168 let upper_bound = if nuh_layer_id == 0 {
169 sps_max_dec_pic_buffering_minus1_at_sps_max_sub_layers_minus1
171 .saturating_sub(num_negative_pics[st_rps_idx])
172 } else {
173 16
174 };
175 range_check!(num_positive_pics[st_rps_idx], 0, upper_bound)?;
176
177 delta_poc_s0.push(vec![0; num_negative_pics[st_rps_idx] as usize]);
178 used_by_curr_pic_s0.push(vec![false; num_negative_pics[st_rps_idx] as usize]);
179
180 for i in 0..num_negative_pics[st_rps_idx] as usize {
181 let delta_poc_s0_minus1 = bit_reader.read_exp_golomb()?;
182 range_check!(delta_poc_s0_minus1, 0, 2u64.pow(15) - 1)?;
183 if i == 0 {
184 delta_poc_s0[st_rps_idx][i] = -(delta_poc_s0_minus1 as i64 + 1);
186 } else {
187 delta_poc_s0[st_rps_idx][i] = delta_poc_s0[st_rps_idx][i - 1] - (delta_poc_s0_minus1 as i64 + 1);
189 }
190
191 let used_by_curr_pic_s0_flag = bit_reader.read_bit()?;
192 used_by_curr_pic_s0[st_rps_idx][i] = used_by_curr_pic_s0_flag;
193 }
194
195 delta_poc_s1.push(vec![0; num_positive_pics[st_rps_idx] as usize]);
196 used_by_curr_pic_s1.push(vec![false; num_positive_pics[st_rps_idx] as usize]);
197
198 for i in 0..num_positive_pics[st_rps_idx] as usize {
199 let delta_poc_s1_minus1 = bit_reader.read_exp_golomb()?;
200 range_check!(delta_poc_s1_minus1, 0, 2u64.pow(15) - 1)?;
201 if i == 0 {
202 delta_poc_s1[st_rps_idx][i] = delta_poc_s1_minus1 as i64 + 1;
204 } else {
205 delta_poc_s1[st_rps_idx][i] = delta_poc_s1[st_rps_idx][i - 1] + delta_poc_s1_minus1 as i64 + 1;
207 }
208
209 let used_by_curr_pic_s1_flag = bit_reader.read_bit()?;
210 used_by_curr_pic_s1[st_rps_idx][i] = used_by_curr_pic_s1_flag;
211 }
212 }
213
214 num_delta_pocs.push(num_negative_pics[st_rps_idx] + num_positive_pics[st_rps_idx]);
216 }
219
220 Ok(Self {
221 num_delta_pocs,
222 num_positive_pics,
223 num_negative_pics,
224 delta_poc_s1,
225 delta_poc_s0,
226 used_by_curr_pic_s0,
227 used_by_curr_pic_s1,
228 })
229 }
230}