• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::cell::Ref;
6 use std::cell::RefCell;
7 use std::cell::RefMut;
8 use std::rc::Rc;
9 
10 use anyhow::anyhow;
11 use anyhow::Result;
12 use log::debug;
13 
14 use crate::decoders::h264::picture::Field;
15 use crate::decoders::h264::picture::IsIdr;
16 use crate::decoders::h264::picture::PictureData;
17 use crate::decoders::h264::picture::Reference;
18 use crate::decoders::DecodedHandle;
19 
20 // Shortcut to refer to a DPB entry.
21 //
22 // The first member of the tuple is the `PictureData` for the frame.
23 //
24 // The second member is the backend handle of the frame. It can be `None` if the inserted picture
25 // is non-existing (i.e. `nonexisting` is true on the `PictureData`).
26 #[derive(Clone)]
27 pub struct DpbEntry<T: DecodedHandle>(pub Rc<RefCell<PictureData>>, pub Option<T>);
28 
29 pub struct Dpb<T: DecodedHandle> {
30     /// List of `PictureData` and backend handles to decoded pictures.
31     entries: Vec<DpbEntry<T>>,
32     /// The maximum number of pictures that can be stored.
33     max_num_pics: usize,
34     /// Whether we're decoding in interlaced mode. Interlaced support is
35     /// inspired by the GStreamer implementation, in which frames are split if
36     /// interlaced=1. This makes reference marking easier. We also decode both
37     /// fields to the same surface, and this surface with both fields is
38     /// outputted only once.
39     interlaced: bool,
40 }
41 
42 impl<T: DecodedHandle> Dpb<T> {
43     /// Returns an iterator over the underlying H264 pictures stored in the
44     /// DPB.
pictures(&self) -> impl Iterator<Item = Ref<'_, PictureData>>45     pub fn pictures(&self) -> impl Iterator<Item = Ref<'_, PictureData>> {
46         self.entries.iter().map(|h| h.0.borrow())
47     }
48 
49     /// Returns a mutable iterator over the underlying H264 pictures stored in
50     /// the DPB.
pictures_mut(&mut self) -> impl Iterator<Item = RefMut<'_, PictureData>>51     pub fn pictures_mut(&mut self) -> impl Iterator<Item = RefMut<'_, PictureData>> {
52         self.entries.iter().map(|h| h.0.borrow_mut())
53     }
54 
55     /// Returns the length of the DPB.
len(&self) -> usize56     pub fn len(&self) -> usize {
57         self.entries.len()
58     }
59 
60     /// Get a reference to the whole DPB entries.
entries(&self) -> &Vec<DpbEntry<T>>61     pub fn entries(&self) -> &Vec<DpbEntry<T>> {
62         &self.entries
63     }
64 
65     /// Set the dpb's max num pics.
set_max_num_pics(&mut self, max_num_pics: usize)66     pub fn set_max_num_pics(&mut self, max_num_pics: usize) {
67         self.max_num_pics = max_num_pics;
68     }
69 
70     /// Get a reference to the dpb's max num pics.
max_num_pics(&self) -> usize71     pub fn max_num_pics(&self) -> usize {
72         self.max_num_pics
73     }
74 
75     // Returns the number of reference frames, counting the first field only if
76     // dealing with interlaced content.
num_ref_frames(&self) -> usize77     pub fn num_ref_frames(&self) -> usize {
78         self.pictures()
79             .filter(|p| p.is_ref() && !p.is_second_field())
80             .count()
81     }
82 
83     /// Get a reference to the dpb's interlaced mode.
interlaced(&self) -> bool84     pub fn interlaced(&self) -> bool {
85         self.interlaced
86     }
87 
88     /// Set the dpb's interlaced mode.
set_interlaced(&mut self, interlaced: bool)89     pub fn set_interlaced(&mut self, interlaced: bool) {
90         self.interlaced = interlaced;
91     }
92 
93     /// Find the short term reference picture with the lowest `frame_num_wrap`
94     /// value.
find_short_term_lowest_frame_num_wrap(&self) -> Option<Rc<RefCell<PictureData>>>95     pub fn find_short_term_lowest_frame_num_wrap(&self) -> Option<Rc<RefCell<PictureData>>> {
96         let lowest = self
97             .entries
98             .iter()
99             .filter(|h| {
100                 let p = h.0.borrow();
101                 matches!(p.reference(), Reference::ShortTerm)
102             })
103             .cloned()
104             .map(|h| h.0)
105             .min_by_key(|h| {
106                 let p = h.borrow();
107                 p.frame_num_wrap
108             });
109 
110         lowest
111     }
112 
113     /// Mark all pictures in the DPB as unused for reference.
mark_all_as_unused_for_ref(&mut self)114     pub fn mark_all_as_unused_for_ref(&mut self) {
115         for mut picture in self.pictures_mut() {
116             picture.set_reference(Reference::None, false);
117         }
118     }
119 
120     /// Remove unused pictures from the DPB. A picture is not going to be used
121     /// anymore if it's a) not a reference and b) not needed for output
remove_unused(&mut self)122     pub fn remove_unused(&mut self) {
123         self.entries.retain(|handle| {
124             let pic = handle.0.borrow();
125             let discard = !pic.is_ref() && !pic.needed_for_output;
126 
127             if discard {
128                 log::debug!("Removing unused picture {:#?}", pic);
129             }
130 
131             !discard
132         });
133     }
134 
135     /// Find a short term reference picture with the given `pic_num` value.
find_short_term_with_pic_num(&self, pic_num: i32) -> Option<DpbEntry<T>>136     pub fn find_short_term_with_pic_num(&self, pic_num: i32) -> Option<DpbEntry<T>> {
137         let position = self
138             .pictures()
139             .position(|p| matches!(p.reference(), Reference::ShortTerm) && p.pic_num == pic_num);
140 
141         log::debug!(
142             "find_short_term_with_pic_num: {}, found position {:?}",
143             pic_num,
144             position
145         );
146 
147         Some(self.entries[position?].clone())
148     }
149 
150     /// Find a long term reference picture with the given `long_term_pic_num`
151     /// value.
find_long_term_with_long_term_pic_num( &self, long_term_pic_num: i32, ) -> Option<DpbEntry<T>>152     pub fn find_long_term_with_long_term_pic_num(
153         &self,
154         long_term_pic_num: i32,
155     ) -> Option<DpbEntry<T>> {
156         let position = self.pictures().position(|p| {
157             matches!(p.reference(), Reference::LongTerm) && p.long_term_pic_num == long_term_pic_num
158         });
159 
160         log::debug!(
161             "find_long_term_with_long_term_pic_num: {}, found position {:?}",
162             long_term_pic_num,
163             position
164         );
165 
166         Some(self.entries[position?].clone())
167     }
168 
169     /// Store a picture and its backend handle in the DPB.
store_picture( &mut self, picture: Rc<RefCell<PictureData>>, handle: Option<T>, ) -> Result<()>170     pub fn store_picture(
171         &mut self,
172         picture: Rc<RefCell<PictureData>>,
173         handle: Option<T>,
174     ) -> Result<()> {
175         let max_pics = if self.interlaced {
176             self.max_num_pics * 2
177         } else {
178             self.max_num_pics
179         };
180 
181         if self.entries.len() >= max_pics {
182             return Err(anyhow!("Can't add a picture to the DPB: DPB is full."));
183         }
184 
185         let mut pic_mut = picture.borrow_mut();
186 
187         // C.4.2. Decoding of gaps in frame_num and storage of "non-existing"
188         // pictures
189         if !pic_mut.nonexisting {
190             pic_mut.needed_for_output = true;
191         } else {
192             pic_mut.needed_for_output = false;
193         }
194 
195         if pic_mut.is_second_field() {
196             let first_field_rc = pic_mut.other_field_unchecked();
197             drop(pic_mut);
198             let mut first_field = first_field_rc.borrow_mut();
199             first_field.set_second_field_to(&picture);
200         } else {
201             drop(pic_mut);
202         }
203 
204         let pic = picture.borrow();
205         debug!(
206             "Stored picture POC {:?}, field {:?}, the DPB length is {:?}",
207             pic.pic_order_cnt,
208             pic.field,
209             self.entries.len()
210         );
211         drop(pic);
212 
213         self.entries.push(DpbEntry(picture, handle));
214 
215         Ok(())
216     }
217 
218     /// Whether the DPB has an empty slot for a new picture.
has_empty_frame_buffer(&self) -> bool219     pub fn has_empty_frame_buffer(&self) -> bool {
220         if !self.interlaced {
221             self.entries.len() < self.max_num_pics
222         } else {
223             let count = self
224                 .pictures()
225                 .filter(|pic| {
226                     !pic.is_second_field()
227                         && (matches!(pic.field, Field::Frame) || pic.other_field().is_some())
228                 })
229                 .count();
230 
231             count < self.max_num_pics
232         }
233     }
234 
235     /// Whether the DPB needs bumping, as described by clauses 1, 4, 5, 6 of
236     /// C.4.5.3 "Bumping" process.
needs_bumping(&self, to_insert: &PictureData) -> bool237     pub fn needs_bumping(&self, to_insert: &PictureData) -> bool {
238         // In C.4.5.3 we handle clauses 2 and 3 separately. All other clauses
239         // check for an empty frame buffer first. Here we handle:
240         //    - There is no empty frame buffer and a empty frame buffer is
241         //    needed for storage of an inferred "non-existing" frame.
242         //
243         //    - There is no empty frame buffer and an empty frame buffer is
244         //    needed for storage of a decoded (non-IDR) reference picture.
245         //
246         //    - There is no empty frame buffer and the current picture is a non-
247         //    reference picture that is not the second field of a complementary
248         //    non-reference field pair and there are pictures in the DPB that
249         //    are marked as "needed for output" that precede the current
250         //    non-reference picture in output order.
251         //
252         // Clauses 2 and 3 are handled by H264Codec::handle_picture and
253         // H264Codec::finish_picture, respectively.
254         if self.has_empty_frame_buffer() {
255             return false;
256         }
257 
258         if to_insert.nonexisting {
259             return true;
260         }
261 
262         let is_ref = !matches!(to_insert.reference(), Reference::None);
263         let non_idr_ref = is_ref && matches!(to_insert.is_idr, IsIdr::No);
264 
265         if non_idr_ref {
266             return true;
267         }
268 
269         let lowest_poc = match self.find_lowest_poc_for_bumping() {
270             Some(handle) => handle.0.borrow().pic_order_cnt,
271             None => return false,
272         };
273 
274         !to_insert.is_second_field_of_complementary_ref_pair()
275             && to_insert.pic_order_cnt > lowest_poc
276     }
277 
278     /// Find the lowest POC in the DPB that can be bumped.
find_lowest_poc_for_bumping(&self) -> Option<DpbEntry<T>>279     fn find_lowest_poc_for_bumping(&self) -> Option<DpbEntry<T>> {
280         let lowest = self
281             .pictures()
282             .filter(|pic| {
283                 if !pic.needed_for_output {
284                     return false;
285                 }
286 
287                 let skip = !matches!(pic.field, Field::Frame)
288                     && (pic.other_field().is_none() || pic.is_second_field());
289 
290                 !skip
291             })
292             .min_by_key(|pic| pic.pic_order_cnt)?;
293 
294         let position = self
295             .entries
296             .iter()
297             .position(|handle| handle.0.borrow().pic_order_cnt == lowest.pic_order_cnt)
298             .unwrap();
299 
300         Some(self.entries[position].clone())
301     }
302 
303     /// Gets the position of `needle` in the DPB, if any.
get_position(&self, needle: &Rc<RefCell<PictureData>>) -> Option<usize>304     fn get_position(&self, needle: &Rc<RefCell<PictureData>>) -> Option<usize> {
305         self.entries
306             .iter()
307             .position(|handle| Rc::ptr_eq(&handle.0, needle))
308     }
309 
310     /// Bump the dpb, returning a picture as per the bumping process described in C.4.5.3.
311     /// Note that this picture will still be referenced by its pair, if any.
bump(&mut self, flush: bool) -> Option<DpbEntry<T>>312     pub fn bump(&mut self, flush: bool) -> Option<DpbEntry<T>> {
313         let handle = self.find_lowest_poc_for_bumping()?;
314         let mut pic = handle.0.borrow_mut();
315 
316         debug!("Bumping picture {:#?} from the dpb", pic);
317 
318         pic.needed_for_output = false;
319 
320         if !pic.is_ref() || flush {
321             let index = self.get_position(&handle.0).unwrap();
322             log::debug!("removed picture {:#?} from dpb", pic);
323             self.entries.remove(index);
324         }
325 
326         if pic.other_field().is_some() {
327             let other_field_rc = pic.other_field_unchecked();
328             let mut other_field = other_field_rc.borrow_mut();
329             other_field.needed_for_output = false;
330 
331             if !other_field.is_ref() {
332                 log::debug!("other_field: removed picture {:#?} from dpb", other_field);
333                 let index = self.get_position(&other_field_rc).unwrap();
334                 self.entries.remove(index);
335             }
336         }
337 
338         drop(pic);
339         Some(handle)
340     }
341 
342     /// Drains the DPB by continuously invoking the bumping process.
drain(&mut self) -> Vec<DpbEntry<T>>343     pub fn drain(&mut self) -> Vec<DpbEntry<T>> {
344         debug!("Draining the DPB.");
345 
346         let mut pics = vec![];
347 
348         while let Some(pic) = self.bump(true) {
349             pics.push(pic);
350         }
351 
352         pics
353     }
354 
355     /// Clears the DPB, dropping all the pictures.
clear(&mut self)356     pub fn clear(&mut self) {
357         debug!("Clearing the DPB");
358 
359         let max_num_pics = self.max_num_pics;
360         let interlaced = self.interlaced;
361 
362         *self = Default::default();
363 
364         self.max_num_pics = max_num_pics;
365         self.interlaced = interlaced;
366     }
367 
368     /// Gets a Vec<ContainedPicture> of short term refs into `out`
get_short_term_refs(&self, out: &mut Vec<DpbEntry<T>>)369     pub fn get_short_term_refs(&self, out: &mut Vec<DpbEntry<T>>) {
370         out.extend(
371             self.entries
372                 .iter()
373                 .filter(|&handle| matches!(handle.0.borrow().reference(), Reference::ShortTerm))
374                 .cloned(),
375         )
376     }
377 
378     /// Gets a Vec<ContainedPicture> of long term refs into `out`
get_long_term_refs(&self, out: &mut Vec<DpbEntry<T>>)379     pub fn get_long_term_refs(&self, out: &mut Vec<DpbEntry<T>>) {
380         out.extend(
381             self.entries
382                 .iter()
383                 .filter(|&handle| matches!(handle.0.borrow().reference(), Reference::LongTerm))
384                 .cloned(),
385         )
386     }
387 }
388 
389 impl<T: DecodedHandle> Default for Dpb<T> {
default() -> Self390     fn default() -> Self {
391         // See https://github.com/rust-lang/rust/issues/26925 on why this can't
392         // be derived.
393         Self {
394             entries: Default::default(),
395             max_num_pics: Default::default(),
396             interlaced: Default::default(),
397         }
398     }
399 }
400 
401 impl<T: DecodedHandle> std::fmt::Debug for Dpb<T> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result402     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
403         let pics = self
404             .entries
405             .iter()
406             .map(|h| &h.0)
407             .enumerate()
408             .collect::<Vec<_>>();
409         f.debug_struct("Dpb")
410             .field("pictures", &pics)
411             .field("max_num_pics", &self.max_num_pics)
412             .field("interlaced", &self.interlaced)
413             .finish()
414     }
415 }
416