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