cros_codecs/codec/h265/
dpb.rs1use std::cell::Ref;
6use std::cell::RefCell;
7use std::cell::RefMut;
8use std::rc::Rc;
9
10use anyhow::anyhow;
11
12use crate::codec::h265::parser::Sps;
13use crate::codec::h265::picture::PictureData;
14use crate::codec::h265::picture::Reference;
15
16#[derive(Clone, Debug)]
22pub struct DpbEntry<T>(pub Rc<RefCell<PictureData>>, pub T);
23
24pub struct Dpb<T> {
25 entries: Vec<DpbEntry<T>>,
27 max_num_pics: usize,
29}
30
31impl<T: Clone> Dpb<T> {
32 pub fn pictures(&self) -> impl Iterator<Item = Ref<'_, PictureData>> {
35 self.entries.iter().map(|h| h.0.borrow())
36 }
37
38 pub fn pictures_mut(&mut self) -> impl Iterator<Item = RefMut<'_, PictureData>> {
41 self.entries.iter().map(|h| h.0.borrow_mut())
42 }
43
44 pub fn len(&self) -> usize {
46 self.entries.len()
47 }
48
49 pub fn is_empty(&self) -> bool {
50 self.len() == 0
51 }
52
53 pub fn entries(&self) -> &Vec<DpbEntry<T>> {
55 &self.entries
56 }
57
58 pub fn set_max_num_pics(&mut self, max_num_pics: usize) {
60 self.max_num_pics = max_num_pics;
61 }
62
63 pub fn max_num_pics(&self) -> usize {
65 self.max_num_pics
66 }
67
68 pub fn mark_all_as_unused_for_ref(&mut self) {
70 for mut picture in self.pictures_mut() {
71 picture.set_reference(Reference::None);
72 }
73 }
74
75 fn get_position(&self, needle: &Rc<RefCell<PictureData>>) -> Option<usize> {
77 self.entries
78 .iter()
79 .position(|handle| Rc::ptr_eq(&handle.0, needle))
80 }
81
82 pub fn find_ref_by_poc(&self, poc: i32) -> Option<DpbEntry<T>> {
84 let position = self
85 .pictures()
86 .position(|p| p.is_ref() && p.pic_order_cnt_val == poc);
87
88 log::debug!("find_ref_by_poc: {}, found position {:?}", poc, position);
89 Some(self.entries[position?].clone())
90 }
91
92 pub fn find_ref_by_poc_masked(&self, poc: i32, mask: i32) -> Option<DpbEntry<T>> {
94 let position = self
95 .pictures()
96 .position(|p| p.is_ref() && p.pic_order_cnt_val & mask == poc);
97
98 log::debug!("find_ref_by_poc: {}, found position {:?}", poc, position);
99 Some(self.entries[position?].clone())
100 }
101
102 pub fn find_short_term_ref_by_poc(&self, poc: i32) -> Option<DpbEntry<T>> {
104 let position = self.pictures().position(|p| {
105 matches!(p.reference(), Reference::ShortTerm) && p.pic_order_cnt_val == poc
106 });
107
108 log::debug!(
109 "find_short_term_ref_by_poc: {}, found position {:?}",
110 poc,
111 position
112 );
113 Some(self.entries[position?].clone())
114 }
115
116 pub fn drain(&mut self) -> Vec<DpbEntry<T>> {
118 log::debug!("Draining the DPB.");
119
120 let mut pics = vec![];
121 while let Some(pic) = self.bump(true) {
122 pics.push(pic);
123 }
124
125 pics
126 }
127
128 pub fn needs_bumping(&mut self, sps: &Sps) -> bool {
130 let num_needed_for_output = self.pictures().filter(|pic| pic.needed_for_output).count();
131
132 let highest_tid = sps.max_sub_layers_minus1;
133 let max_num_reorder_pics = sps.max_num_reorder_pics[usize::from(highest_tid)];
134 let max_latency_increase_plus1 = sps.max_latency_increase_plus1[usize::from(highest_tid)];
135 let pic_over_max_latency = self.pictures().find(|pic| {
136 pic.needed_for_output && pic.pic_latency_cnt >= i32::from(max_latency_increase_plus1)
137 });
138 let max_dec_pic_buffering =
139 usize::from(sps.max_dec_pic_buffering_minus1[usize::from(highest_tid)]) + 1;
140
141 num_needed_for_output > max_num_reorder_pics.into()
142 || (max_latency_increase_plus1 != 0 && pic_over_max_latency.is_some())
143 || self.entries().len() >= max_dec_pic_buffering
144 }
145
146 fn find_lowest_poc_for_bumping(&self) -> Option<DpbEntry<T>> {
148 let lowest = self
149 .pictures()
150 .filter(|pic| pic.needed_for_output)
151 .min_by_key(|pic| pic.pic_order_cnt_val)?;
152
153 let position = self
154 .entries
155 .iter()
156 .position(|handle| handle.0.borrow().pic_order_cnt_val == lowest.pic_order_cnt_val)
157 .unwrap();
158
159 Some(self.entries[position].clone())
160 }
161
162 pub fn bump(&mut self, flush: bool) -> Option<DpbEntry<T>> {
164 let handle = self.find_lowest_poc_for_bumping()?;
165 let mut pic = handle.0.borrow_mut();
166
167 pic.needed_for_output = false;
168 log::debug!("Bumping POC {} from the dpb", pic.pic_order_cnt_val);
169 log::trace!("{:#?}", pic);
170
171 if !pic.is_ref() || flush {
172 let index = self.get_position(&handle.0).unwrap();
173
174 log::debug!(
175 "Removed POC {} from the dpb: reference: {}, flush: {}",
176 pic.pic_order_cnt_val,
177 pic.is_ref(),
178 flush
179 );
180 log::trace!("{:#?}", pic);
181
182 self.entries.remove(index);
183 }
184
185 Some(handle.clone())
186 }
187
188 pub fn needs_additional_bumping(&mut self, sps: &Sps) -> bool {
190 let num_needed_for_output = self.pictures().filter(|pic| pic.needed_for_output).count();
191 let highest_tid = sps.max_sub_layers_minus1;
192
193 let max_num_reorder_pics = sps.max_num_reorder_pics[usize::from(highest_tid)];
194 let max_latency_increase_plus1 = sps.max_latency_increase_plus1[usize::from(highest_tid)];
195
196 let pic_over_max_latency = self.pictures().find(|pic| {
197 pic.needed_for_output && pic.pic_latency_cnt >= i32::from(max_latency_increase_plus1)
198 });
199
200 num_needed_for_output > max_num_reorder_pics.into()
201 || (max_latency_increase_plus1 != 0 && pic_over_max_latency.is_some())
202 }
203
204 pub fn clear(&mut self) {
206 log::debug!("Clearing the DPB");
207
208 let max_num_pics = self.max_num_pics;
209
210 *self = Default::default();
211 self.max_num_pics = max_num_pics;
212 }
213
214 pub fn remove_unused(&mut self) {
217 log::debug!("Removing unused pictures from DPB.");
218 self.entries.retain(|e| {
219 let pic = e.0.borrow();
220 let retain = pic.needed_for_output || pic.is_ref();
221 log::debug!("Retaining pic POC: {}: {}", pic.pic_order_cnt_val, retain);
222 retain
223 })
224 }
225
226 pub fn store_picture(
228 &mut self,
229 picture: Rc<RefCell<PictureData>>,
230 handle: T,
231 ) -> anyhow::Result<()> {
232 if self.entries.len() >= self.max_num_pics {
233 return Err(anyhow!("Can't add a picture to the DPB: DPB is full."));
234 }
235
236 let mut pic = picture.borrow_mut();
237 log::debug!(
238 "Stored picture POC {:?}, the DPB length is {:?}",
239 pic.pic_order_cnt_val,
240 self.entries.len()
241 );
242
243 if pic.pic_output_flag {
244 pic.needed_for_output = true;
245 pic.pic_latency_cnt = 0;
246 } else {
247 pic.needed_for_output = false;
248 }
249
250 pic.set_reference(Reference::ShortTerm);
254 drop(pic);
255
256 for mut pic in self.pictures_mut() {
257 pic.pic_latency_cnt += 1;
258 }
259
260 self.entries.push(DpbEntry(picture, handle));
261
262 Ok(())
263 }
264
265 pub fn get_all_references(&self) -> Vec<DpbEntry<T>> {
267 self.entries
268 .iter()
269 .filter(|e| e.0.borrow().is_ref())
270 .cloned()
271 .collect()
272 }
273}
274
275impl<T: Clone> Default for Dpb<T> {
276 fn default() -> Self {
277 Self {
280 entries: Default::default(),
281 max_num_pics: Default::default(),
282 }
283 }
284}
285
286impl<T: Clone> std::fmt::Debug for Dpb<T> {
287 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
288 let pics = self
289 .entries
290 .iter()
291 .map(|h| &h.0)
292 .enumerate()
293 .collect::<Vec<_>>();
294 f.debug_struct("Dpb")
295 .field("pictures", &pics)
296 .field("max_num_pics", &self.max_num_pics)
297 .finish()
298 }
299}