1 // Copyright 2023 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 crate::codec::h265::parser::Sps; 11 use crate::codec::h265::picture::PictureData; 12 use crate::codec::h265::picture::Reference; 13 14 // Shortcut to refer to a DPB entry. 15 // 16 // The first member of the tuple is the `PictureData` for the frame. 17 // 18 // The second member is the backend handle of the frame. 19 #[derive(Clone, Debug)] 20 pub struct DpbEntry<T>(pub Rc<RefCell<PictureData>>, pub T); 21 22 pub struct Dpb<T> { 23 /// List of `PictureData` and backend handles to decoded pictures. 24 entries: Vec<DpbEntry<T>>, 25 /// The maximum number of pictures that can be stored. 26 max_num_pics: usize, 27 } 28 29 impl<T: Clone> Dpb<T> { 30 /// Returns an iterator over the underlying H265 pictures stored in the 31 /// DPB. pictures(&self) -> impl Iterator<Item = Ref<'_, PictureData>>32 pub fn pictures(&self) -> impl Iterator<Item = Ref<'_, PictureData>> { 33 self.entries.iter().map(|h| h.0.borrow()) 34 } 35 36 /// Returns a mutable iterator over the underlying H265 pictures stored in 37 /// the DPB. pictures_mut(&mut self) -> impl Iterator<Item = RefMut<'_, PictureData>>38 pub fn pictures_mut(&mut self) -> impl Iterator<Item = RefMut<'_, PictureData>> { 39 self.entries.iter().map(|h| h.0.borrow_mut()) 40 } 41 42 /// Returns the length of the DPB. len(&self) -> usize43 pub fn len(&self) -> usize { 44 self.entries.len() 45 } 46 is_empty(&self) -> bool47 pub fn is_empty(&self) -> bool { 48 self.len() == 0 49 } 50 51 /// Get a reference to the whole DPB entries. entries(&self) -> &Vec<DpbEntry<T>>52 pub fn entries(&self) -> &Vec<DpbEntry<T>> { 53 &self.entries 54 } 55 56 /// Set the dpb's max num pics. set_max_num_pics(&mut self, max_num_pics: usize)57 pub fn set_max_num_pics(&mut self, max_num_pics: usize) { 58 self.max_num_pics = max_num_pics; 59 } 60 61 /// Get a reference to the dpb's max num pics. max_num_pics(&self) -> usize62 pub fn max_num_pics(&self) -> usize { 63 self.max_num_pics 64 } 65 66 /// Mark all pictures in the DPB as unused for reference. mark_all_as_unused_for_ref(&mut self)67 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 /// Gets the position of `needle` in the DPB, if any. get_position(&self, needle: &Rc<RefCell<PictureData>>) -> Option<usize>74 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 /// Finds a reference picture in the DPB using `poc`. find_ref_by_poc(&self, poc: i32) -> Option<DpbEntry<T>>79 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 /// Finds a reference picture in the DPB using `poc` and `mask`. find_ref_by_poc_masked(&self, poc: i32, mask: i32) -> Option<DpbEntry<T>>87 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 /// Finds a short term reference picture in the DPB using `poc`. find_short_term_ref_by_poc(&self, poc: i32) -> Option<DpbEntry<T>>96 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 /// Drains the DPB by continuously invoking the bumping process. drain(&mut self) -> Vec<DpbEntry<T>>106 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 /// Whether the DPB needs bumping. See C.5.2.2. needs_bumping(&mut self, sps: &Sps) -> bool118 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 /// Find the lowest POC in the DPB that can be bumped. find_lowest_poc_for_bumping(&self) -> Option<DpbEntry<T>>136 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 /// See C.5.2.4 "Bumping process". bump(&mut self, flush: bool) -> Option<DpbEntry<T>>152 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 /// See C.5.2.3. Happens when we are done decoding the picture. needs_additional_bumping(&mut self, sps: &Sps) -> bool178 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 /// Clears the DPB, dropping all the pictures. clear(&mut self)194 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 /// Removes all pictures which are marked as "not needed for output" and 204 /// "unused for reference". See C.5.2.2 remove_unused(&mut self)205 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 /// Store a picture and its backend handle in the DPB. store_picture( &mut self, picture: Rc<RefCell<PictureData>>, handle: T, ) -> Result<(), String>216 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 // C.3.4. 240 // After all the slices of the current picture have been decoded, this 241 // picture is marked as "used for short-term reference". 242 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 /// Returns all the references in the DPB. get_all_references(&self) -> Vec<DpbEntry<T>>255 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 260 impl<T: Clone> Default for Dpb<T> { default() -> Self261 fn default() -> Self { 262 // See https://github.com/rust-lang/rust/issues/26925 on why this can't 263 // be derived. 264 Self { entries: Default::default(), max_num_pics: Default::default() } 265 } 266 } 267 268 impl<T: Clone> std::fmt::Debug for Dpb<T> { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result269 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 } 277