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::RefMut; 7 use std::fmt; 8 use std::rc::Rc; 9 10 use log::debug; 11 12 use crate::codec::h264::parser::MaxLongTermFrameIdx; 13 use crate::codec::h264::parser::RefPicMarkingInner; 14 use crate::codec::h264::parser::Sps; 15 use crate::codec::h264::picture::Field; 16 use crate::codec::h264::picture::FieldRank; 17 use crate::codec::h264::picture::IsIdr; 18 use crate::codec::h264::picture::PictureData; 19 use crate::codec::h264::picture::RcPictureData; 20 use crate::codec::h264::picture::Reference; 21 22 pub type DpbPicRefList<'a, H> = Vec<&'a DpbEntry<H>>; 23 24 /// All the reference picture lists used to decode a picture. 25 #[derive(Default)] 26 pub struct ReferencePicLists { 27 /// Reference picture list for P slices. Retains the same meaning as in the 28 /// specification. Points into the pictures stored in the DPB. Derived once 29 /// per picture. 30 pub ref_pic_list_p0: Vec<usize>, 31 /// Reference picture list 0 for B slices. Retains the same meaning as in 32 /// the specification. Points into the pictures stored in the DPB. Derived 33 /// once per picture. 34 pub ref_pic_list_b0: Vec<usize>, 35 /// Reference picture list 1 for B slices. Retains the same meaning as in 36 /// the specification. Points into the pictures stored in the DPB. Derived 37 /// once per picture. 38 pub ref_pic_list_b1: Vec<usize>, 39 } 40 41 /// A single entry in the DPB. 42 #[derive(Clone)] 43 pub struct DpbEntry<T> { 44 /// `PictureData` of the frame in this entry. 45 pub pic: RcPictureData, 46 /// Reference to the decoded frame, ensuring that it doesn't get reused while in the DPB. 47 pub reference: Option<T>, 48 /// Decoded frame promise. It will be set when the frame enters the DPB, and taken during the 49 /// bump process. 50 pub decoded_frame: Option<T>, 51 /// Whether the picture is still waiting to be bumped and displayed. 52 needed_for_output: bool, 53 } 54 55 impl<T> DpbEntry<T> { 56 /// Returns `true` is the entry is eligible to be bumped. 57 /// 58 /// An entry can be bumped if its `needed_for_output` flag is true and it is the first field of 59 /// a frame which fields are all decoded. is_bumpable(&self) -> bool60 fn is_bumpable(&self) -> bool { 61 if !self.needed_for_output { 62 return false; 63 } 64 65 let pic = self.pic.borrow(); 66 match pic.field { 67 // Progressive frames in the DPB are fully decoded. 68 Field::Frame => true, 69 // Only return the first field of fully decoded interlaced frames. 70 Field::Top | Field::Bottom => matches!(pic.field_rank(), FieldRank::First(..)), 71 } 72 } 73 } 74 75 pub struct Dpb<T> { 76 /// List of `PictureData` and backend handles to decoded pictures. 77 entries: Vec<DpbEntry<T>>, 78 /// The maximum number of pictures that can be stored. 79 max_num_pics: usize, 80 /// Indicates an upper bound for the number of frames buffers, in the 81 /// decoded picture buffer (DPB), that are required for storing frames, 82 /// complementary field pairs, and non-paired fields before output. It is a 83 /// requirement of bitstream conformance that the maximum number of frames, 84 /// complementary field pairs, or non-paired fields that precede any frame, 85 /// complementary field pair, or non-paired field in the coded video 86 /// sequence in decoding order and follow it in output order shall be less 87 /// than or equal to max_num_reorder_frames. 88 max_num_reorder_frames: usize, 89 /// Whether we're decoding in interlaced mode. Interlaced support is 90 /// inspired by the GStreamer implementation, in which frames are split if 91 /// interlaced=1. This makes reference marking easier. We also decode both 92 /// fields to the same frame, and this frame with both fields is outputted 93 /// only once. 94 interlaced: bool, 95 } 96 97 #[derive(Debug)] 98 pub enum StorePictureError { 99 DpbIsFull, 100 } 101 102 impl fmt::Display for StorePictureError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 104 write!(f, "DPB is full") 105 } 106 } 107 108 impl std::error::Error for StorePictureError {} 109 110 #[derive(Debug)] 111 pub enum MmcoError { 112 NoShortTermPic, 113 ExpectedMarked, 114 ExpectedExisting, 115 UnknownMmco(u8), 116 } 117 118 impl fmt::Display for MmcoError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 120 match self { 121 MmcoError::NoShortTermPic => { 122 write!(f, "could not find ShortTerm picture to mark in the DPB") 123 } 124 MmcoError::ExpectedMarked => { 125 write!(f, "a ShortTerm picture was expected to be marked for MMCO=3") 126 } 127 MmcoError::ExpectedExisting => { 128 write!(f, "picture cannot be marked as nonexisting for MMCO=3") 129 } 130 MmcoError::UnknownMmco(x) => write!(f, "unknown MMCO: {}", x), 131 } 132 } 133 } 134 135 impl std::error::Error for MmcoError {} 136 137 impl<T: Clone> Dpb<T> { 138 /// Returns an iterator over the underlying H264 pictures stored in the 139 /// DPB. pictures(&self) -> impl Iterator<Item = Ref<'_, PictureData>>140 fn pictures(&self) -> impl Iterator<Item = Ref<'_, PictureData>> { 141 self.entries.iter().map(|h| h.pic.borrow()) 142 } 143 144 /// Returns a mutable iterator over the underlying H264 pictures stored in 145 /// the DPB. pictures_mut(&mut self) -> impl Iterator<Item = RefMut<'_, PictureData>>146 fn pictures_mut(&mut self) -> impl Iterator<Item = RefMut<'_, PictureData>> { 147 self.entries.iter().map(|h| h.pic.borrow_mut()) 148 } 149 150 /// Returns the length of the DPB. len(&self) -> usize151 pub fn len(&self) -> usize { 152 self.entries.len() 153 } 154 is_empty(&self) -> bool155 pub fn is_empty(&self) -> bool { 156 self.len() == 0 157 } 158 159 /// Get a reference to the whole DPB entries. entries(&self) -> &Vec<DpbEntry<T>>160 pub fn entries(&self) -> &Vec<DpbEntry<T>> { 161 &self.entries 162 } 163 164 /// Set the DPB's limits in terms of maximum number or pictures. set_limits(&mut self, max_num_pics: usize, max_num_reorder_frames: usize)165 pub fn set_limits(&mut self, max_num_pics: usize, max_num_reorder_frames: usize) { 166 self.max_num_pics = max_num_pics; 167 self.max_num_reorder_frames = max_num_reorder_frames; 168 } 169 170 /// Get a reference to the dpb's max num pics. max_num_pics(&self) -> usize171 pub fn max_num_pics(&self) -> usize { 172 self.max_num_pics 173 } 174 175 // Returns the number of reference frames, counting the first field only if 176 // dealing with interlaced content. num_ref_frames(&self) -> usize177 pub fn num_ref_frames(&self) -> usize { 178 self.pictures().filter(|p| p.is_ref() && !p.is_second_field()).count() 179 } 180 181 /// Get a reference to the dpb's interlaced mode. interlaced(&self) -> bool182 pub fn interlaced(&self) -> bool { 183 self.interlaced 184 } 185 186 /// Set the dpb's interlaced mode. set_interlaced(&mut self, interlaced: bool)187 pub fn set_interlaced(&mut self, interlaced: bool) { 188 self.interlaced = interlaced; 189 } 190 191 /// Find the short term reference picture with the lowest `frame_num_wrap` 192 /// value. find_short_term_lowest_frame_num_wrap(&self) -> Option<&DpbEntry<T>>193 pub fn find_short_term_lowest_frame_num_wrap(&self) -> Option<&DpbEntry<T>> { 194 let lowest = self 195 .entries 196 .iter() 197 .filter(|h| { 198 let p = h.pic.borrow(); 199 matches!(p.reference(), Reference::ShortTerm) 200 }) 201 .min_by_key(|h| { 202 let p = h.pic.borrow(); 203 p.frame_num_wrap 204 }); 205 206 lowest 207 } 208 209 /// Mark all pictures in the DPB as unused for reference. mark_all_as_unused_for_ref(&mut self)210 pub fn mark_all_as_unused_for_ref(&mut self) { 211 for mut picture in self.pictures_mut() { 212 picture.set_reference(Reference::None, false); 213 } 214 } 215 216 /// Remove unused pictures from the DPB. A picture is not going to be used 217 /// anymore if it's a) not a reference and b) not needed for output remove_unused(&mut self)218 fn remove_unused(&mut self) { 219 self.entries.retain(|entry| { 220 let pic = entry.pic.borrow(); 221 let discard = !pic.is_ref() && !entry.needed_for_output; 222 223 if discard { 224 log::debug!("Removing unused picture {:#?}", pic); 225 } 226 227 !discard 228 }); 229 } 230 231 /// Find a short term reference picture with the given `pic_num` value. find_short_term_with_pic_num_pos(&self, pic_num: i32) -> Option<usize>232 fn find_short_term_with_pic_num_pos(&self, pic_num: i32) -> Option<usize> { 233 let position = self 234 .pictures() 235 .position(|p| matches!(p.reference(), Reference::ShortTerm) && p.pic_num == pic_num); 236 237 log::debug!("find_short_term_with_pic_num: {}, found position {:?}", pic_num, position); 238 239 position 240 } 241 242 /// 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>>243 pub fn find_short_term_with_pic_num(&self, pic_num: i32) -> Option<&DpbEntry<T>> { 244 let position = self.find_short_term_with_pic_num_pos(pic_num)?; 245 Some(&self.entries[position]) 246 } 247 248 /// Find a long term reference picture with the given `long_term_pic_num` 249 /// value. find_long_term_with_long_term_pic_num_pos(&self, long_term_pic_num: u32) -> Option<usize>250 fn find_long_term_with_long_term_pic_num_pos(&self, long_term_pic_num: u32) -> Option<usize> { 251 let position = self.pictures().position(|p| { 252 matches!(p.reference(), Reference::LongTerm) && p.long_term_pic_num == long_term_pic_num 253 }); 254 255 log::debug!( 256 "find_long_term_with_long_term_pic_num: {}, found position {:?}", 257 long_term_pic_num, 258 position 259 ); 260 261 position 262 } 263 264 /// Find a long term reference picture with the given `long_term_pic_num` 265 /// value. find_long_term_with_long_term_pic_num( &self, long_term_pic_num: u32, ) -> Option<&DpbEntry<T>>266 pub fn find_long_term_with_long_term_pic_num( 267 &self, 268 long_term_pic_num: u32, 269 ) -> Option<&DpbEntry<T>> { 270 let position = self.find_long_term_with_long_term_pic_num_pos(long_term_pic_num)?; 271 Some(&self.entries[position]) 272 } 273 274 /// Store `picture` and its backend handle in the DPB. store_picture( &mut self, picture: RcPictureData, handle: Option<T>, ) -> Result<(), StorePictureError>275 pub fn store_picture( 276 &mut self, 277 picture: RcPictureData, 278 handle: Option<T>, 279 ) -> Result<(), StorePictureError> { 280 let max_pics = if self.interlaced { self.max_num_pics * 2 } else { self.max_num_pics }; 281 282 if self.entries.len() >= max_pics { 283 return Err(StorePictureError::DpbIsFull); 284 } 285 286 let pic = picture.borrow(); 287 288 // C.4.2. Decoding of gaps in frame_num and storage of "non-existing" 289 // pictures 290 let needed_for_output = !pic.nonexisting; 291 292 debug!( 293 "Stored picture POC {:?}, field {:?}, the DPB length is {:?}", 294 pic.pic_order_cnt, 295 pic.field, 296 self.entries.len() 297 ); 298 drop(pic); 299 300 self.entries.push(DpbEntry { 301 pic: picture, 302 reference: handle.clone(), 303 decoded_frame: handle, 304 needed_for_output, 305 }); 306 307 Ok(()) 308 } 309 310 /// Whether the DPB has an empty slot for a new picture. has_empty_frame_buffer(&self) -> bool311 pub fn has_empty_frame_buffer(&self) -> bool { 312 let count = if !self.interlaced { 313 self.entries.len() 314 } else { 315 self.pictures() 316 .filter(|pic| { 317 matches!(pic.field_rank(), FieldRank::First(..)) 318 || (matches!(pic.field_rank(), FieldRank::Single) 319 && pic.field == Field::Frame) 320 }) 321 .count() 322 }; 323 324 count < self.max_num_pics 325 } 326 327 /// Whether the DPB needs bumping, as described by clauses 1, 4, 5, 6 of 328 /// C.4.5.3 "Bumping" process. needs_bumping(&self, to_insert: &PictureData) -> bool329 pub fn needs_bumping(&self, to_insert: &PictureData) -> bool { 330 // In C.4.5.3 we handle clauses 2 and 3 separately. All other clauses 331 // check for an empty frame buffer first. Here we handle: 332 // - There is no empty frame buffer and a empty frame buffer is 333 // needed for storage of an inferred "non-existing" frame. 334 // 335 // - There is no empty frame buffer and an empty frame buffer is 336 // needed for storage of a decoded (non-IDR) reference picture. 337 // 338 // - There is no empty frame buffer and the current picture is a non- 339 // reference picture that is not the second field of a complementary 340 // non-reference field pair and there are pictures in the DPB that 341 // are marked as "needed for output" that precede the current 342 // non-reference picture in output order. 343 // 344 // Clauses 2 and 3 are handled by H264Codec::handle_picture and 345 // H264Codec::finish_picture, respectively. 346 if self.has_empty_frame_buffer() { 347 return false; 348 } 349 350 if to_insert.nonexisting { 351 return true; 352 } 353 354 let non_idr_ref = to_insert.is_ref() && matches!(to_insert.is_idr, IsIdr::No); 355 if non_idr_ref { 356 return true; 357 } 358 359 let lowest_poc = match self.find_lowest_poc_for_bumping() { 360 Some(handle) => handle.pic.borrow().pic_order_cnt, 361 None => return false, 362 }; 363 364 !to_insert.is_second_field_of_complementary_ref_pair() 365 && to_insert.pic_order_cnt > lowest_poc 366 } 367 368 /// Find the lowest POC in the DPB that can be bumped. find_lowest_poc_for_bumping(&self) -> Option<&DpbEntry<T>>369 fn find_lowest_poc_for_bumping(&self) -> Option<&DpbEntry<T>> { 370 self.entries 371 .iter() 372 .filter(|entry| entry.is_bumpable()) 373 .min_by_key(|handle| handle.pic.borrow().pic_order_cnt) 374 } 375 376 /// Find the lowest POC in the DPB that can be bumped and return a mutable reference. find_lowest_poc_for_bumping_mut(&mut self) -> Option<&mut DpbEntry<T>>377 fn find_lowest_poc_for_bumping_mut(&mut self) -> Option<&mut DpbEntry<T>> { 378 self.entries 379 .iter_mut() 380 .filter(|entry| entry.is_bumpable()) 381 .min_by_key(|handle| handle.pic.borrow().pic_order_cnt) 382 } 383 384 /// Bump the dpb, returning a picture as per the bumping process described in C.4.5.3. 385 /// Note that this picture will still be referenced by its pair, if any. bump(&mut self) -> Option<Option<T>>386 fn bump(&mut self) -> Option<Option<T>> { 387 let dpb_entry = self.find_lowest_poc_for_bumping_mut()?; 388 let handle = dpb_entry.decoded_frame.take(); 389 let pic = dpb_entry.pic.borrow(); 390 391 debug!("Bumping picture {:#?} from the dpb", pic); 392 393 dpb_entry.needed_for_output = false; 394 // Lookup the second field entry and flip as well. 395 // `find_lowest_poc_for_bumping_mut` always returns the first field, never the second. 396 if let FieldRank::First(second_field) = pic.field_rank() { 397 let second_field = second_field.upgrade(); 398 drop(pic); 399 if let Some(second_field) = 400 second_field.and_then(|f| self.entries.iter_mut().find(|e| Rc::ptr_eq(&f, &e.pic))) 401 { 402 second_field.needed_for_output = false; 403 } 404 } 405 406 Some(handle) 407 } 408 409 /// Drains the DPB by continuously invoking the bumping process. drain(&mut self) -> Vec<Option<T>>410 pub fn drain(&mut self) -> Vec<Option<T>> { 411 debug!("Draining the DPB."); 412 413 let mut pics = vec![]; 414 415 while let Some(pic) = self.bump() { 416 pics.push(pic); 417 } 418 419 self.clear(); 420 421 pics 422 } 423 424 /// Clears the DPB, dropping all the pictures. clear(&mut self)425 pub fn clear(&mut self) { 426 debug!("Clearing the DPB"); 427 428 let max_num_pics = self.max_num_pics; 429 let max_num_reorder_frames = self.max_num_reorder_frames; 430 let interlaced = self.interlaced; 431 432 *self = Default::default(); 433 434 self.max_num_pics = max_num_pics; 435 self.max_num_reorder_frames = max_num_reorder_frames; 436 self.interlaced = interlaced; 437 } 438 439 /// Returns an iterator of short term refs. short_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>>440 pub fn short_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>> { 441 self.entries 442 .iter() 443 .filter(|&handle| matches!(handle.pic.borrow().reference(), Reference::ShortTerm)) 444 } 445 446 /// Returns an iterator of long term refs. long_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>>447 pub fn long_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>> { 448 self.entries 449 .iter() 450 .filter(|&handle| matches!(handle.pic.borrow().reference(), Reference::LongTerm)) 451 } 452 update_pic_nums( &mut self, frame_num: u32, max_frame_num: u32, current_pic: &PictureData, )453 pub fn update_pic_nums( 454 &mut self, 455 frame_num: u32, 456 max_frame_num: u32, 457 current_pic: &PictureData, 458 ) { 459 for mut pic in self.pictures_mut() { 460 if !pic.is_ref() { 461 continue; 462 } 463 464 if *pic.reference() == Reference::LongTerm { 465 pic.long_term_pic_num = if current_pic.field == Field::Frame { 466 pic.long_term_frame_idx 467 } else if current_pic.field == pic.field { 468 2 * pic.long_term_frame_idx + 1 469 } else { 470 2 * pic.long_term_frame_idx 471 }; 472 } else { 473 pic.frame_num_wrap = if pic.frame_num > frame_num { 474 pic.frame_num as i32 - max_frame_num as i32 475 } else { 476 pic.frame_num as i32 477 }; 478 479 pic.pic_num = if current_pic.field == Field::Frame { 480 pic.frame_num_wrap 481 } else if pic.field == current_pic.field { 482 2 * pic.frame_num_wrap + 1 483 } else { 484 2 * pic.frame_num_wrap 485 }; 486 } 487 } 488 } 489 490 /// Gets the number of frames that could potentially be output. num_not_outputted(&self) -> usize491 pub fn num_not_outputted(&self) -> usize { 492 self.entries.iter().filter(|e| e.needed_for_output).count() 493 } 494 495 /// Bumps the DPB if needed. DPB bumping is described on C.4.5.3. bump_as_needed(&mut self, current_pic: &PictureData) -> Vec<Option<T>>496 pub fn bump_as_needed(&mut self, current_pic: &PictureData) -> Vec<Option<T>> { 497 let mut pics = vec![]; 498 // We bump proactively, even though the spec only says we need to bump if the DPB is full. 499 // This cuts down on decode latency and seems to be in line with Codec2's expectations. 500 // Also, there is precedence for this in Chrome's H264 decoder. 501 while self.needs_bumping(current_pic) 502 || self.num_not_outputted() >= self.max_num_reorder_frames 503 { 504 match self.bump() { 505 Some(pic) => pics.push(pic), 506 None => return pics, 507 } 508 self.remove_unused(); 509 } 510 511 pics 512 } 513 514 // 8.2.5.3 sliding_window_marking(&mut self, pic: &mut PictureData, sps: &Sps)515 pub fn sliding_window_marking(&mut self, pic: &mut PictureData, sps: &Sps) { 516 // If the current picture is a coded field that is the second field in 517 // decoding order of a complementary reference field pair, and the first 518 // field has been marked as "used for short-term reference", the current 519 // picture and the complementary reference field pair are also marked as 520 // "used for short-term reference". 521 if let FieldRank::Second(other_field) = pic.field_rank() { 522 if matches!(other_field.borrow().reference(), Reference::ShortTerm) { 523 pic.set_reference(Reference::ShortTerm, false); 524 return; 525 } 526 } 527 528 let mut num_ref_pics = self.num_ref_frames(); 529 let max_num_ref_frames = std::cmp::max(1, sps.max_num_ref_frames as usize); 530 531 if num_ref_pics < max_num_ref_frames { 532 return; 533 } 534 535 while num_ref_pics >= max_num_ref_frames { 536 if let Some(to_unmark) = self.find_short_term_lowest_frame_num_wrap() { 537 to_unmark.pic.borrow_mut().set_reference(Reference::None, true); 538 num_ref_pics -= 1; 539 } else { 540 log::warn!("could not find a ShortTerm picture to unmark in the DPB"); 541 break; 542 } 543 } 544 545 self.remove_unused(); 546 } 547 mmco_op_1( &mut self, pic: &PictureData, marking: &RefPicMarkingInner, ) -> Result<(), MmcoError>548 pub fn mmco_op_1( 549 &mut self, 550 pic: &PictureData, 551 marking: &RefPicMarkingInner, 552 ) -> Result<(), MmcoError> { 553 let pic_num_x = pic.pic_num - (marking.difference_of_pic_nums_minus1 as i32 + 1); 554 555 log::debug!("MMCO op 1 for pic_num_x {}", pic_num_x); 556 log::trace!("Dpb state before MMCO=1: {:#?}", self); 557 558 let to_mark = 559 self.find_short_term_with_pic_num(pic_num_x).ok_or(MmcoError::NoShortTermPic)?; 560 561 to_mark.pic.borrow_mut().set_reference(Reference::None, matches!(pic.field, Field::Frame)); 562 563 Ok(()) 564 } 565 mmco_op_2( &mut self, pic: &PictureData, marking: &RefPicMarkingInner, ) -> Result<(), MmcoError>566 pub fn mmco_op_2( 567 &mut self, 568 pic: &PictureData, 569 marking: &RefPicMarkingInner, 570 ) -> Result<(), MmcoError> { 571 log::debug!("MMCO op 2 for long_term_pic_num {}", marking.long_term_pic_num); 572 573 log::trace!("Dpb state before MMCO=2: {:#?}", self); 574 575 let to_mark = self 576 .find_long_term_with_long_term_pic_num(marking.long_term_pic_num) 577 .ok_or(MmcoError::NoShortTermPic)?; 578 579 to_mark.pic.borrow_mut().set_reference(Reference::None, matches!(pic.field, Field::Frame)); 580 581 Ok(()) 582 } 583 mmco_op_3( &mut self, pic: &PictureData, marking: &RefPicMarkingInner, ) -> Result<(), MmcoError>584 pub fn mmco_op_3( 585 &mut self, 586 pic: &PictureData, 587 marking: &RefPicMarkingInner, 588 ) -> Result<(), MmcoError> { 589 let pic_num_x = pic.pic_num - (marking.difference_of_pic_nums_minus1 as i32 + 1); 590 591 log::debug!("MMCO op 3 for pic_num_x {}", pic_num_x); 592 log::trace!("Dpb state before MMCO=3: {:#?}", self); 593 594 let to_mark_as_long_pos = 595 self.find_short_term_with_pic_num_pos(pic_num_x).ok_or(MmcoError::NoShortTermPic)?; 596 let to_mark_as_long = &self.entries[to_mark_as_long_pos].pic; 597 598 if !matches!(to_mark_as_long.borrow().reference(), Reference::ShortTerm) { 599 return Err(MmcoError::ExpectedMarked); 600 } 601 602 if to_mark_as_long.borrow().nonexisting { 603 return Err(MmcoError::ExpectedExisting); 604 } 605 606 let to_mark_as_long_ptr = to_mark_as_long.as_ptr(); 607 let to_mark_as_long_other_field_ptr = 608 to_mark_as_long.borrow().other_field().map(|f| f.as_ptr()); 609 610 let long_term_frame_idx = marking.long_term_frame_idx; 611 612 for mut picture in self.pictures_mut() { 613 let long_already_assigned = matches!(picture.reference(), Reference::LongTerm) 614 && picture.long_term_frame_idx == long_term_frame_idx; 615 616 if long_already_assigned { 617 let is_frame = matches!(picture.field, Field::Frame); 618 619 let is_complementary_field_pair = picture 620 .other_field() 621 .map(|f| { 622 let pic = f.borrow(); 623 matches!(pic.reference(), Reference::LongTerm) 624 && pic.long_term_frame_idx == long_term_frame_idx 625 }) 626 .unwrap_or(false); 627 628 // When LongTermFrameIdx equal to 629 // long_term_frame_idx is already assigned to a 630 // long-term reference frame or a long-term 631 // complementary reference field pair, that frame or 632 // complementary field pair and both of its fields 633 // are marked as "unused for reference" 634 if is_frame || is_complementary_field_pair { 635 picture.set_reference(Reference::None, true); 636 break; 637 } 638 639 // When LongTermFrameIdx is already assigned to a 640 // reference field, and that reference field is not 641 // part of a complementary field pair that includes 642 // the picture specified by picNumX, that field is 643 // marked as "unused for reference". 644 let reference_field_is_not_part_of_pic_x = match picture.other_field() { 645 None => true, 646 Some(other_field) => { 647 // Check that the fields do not reference one another. 648 !std::ptr::eq(other_field.as_ptr(), to_mark_as_long_ptr) 649 && to_mark_as_long_other_field_ptr 650 .map(|p| !std::ptr::eq(p, &(*picture))) 651 .unwrap_or(true) 652 } 653 }; 654 655 if reference_field_is_not_part_of_pic_x { 656 picture.set_reference(Reference::None, false); 657 break; 658 } 659 } 660 } 661 662 let is_frame = matches!(pic.field, Field::Frame); 663 let to_mark_as_long = &self.entries[to_mark_as_long_pos].pic; 664 to_mark_as_long.borrow_mut().set_reference(Reference::LongTerm, is_frame); 665 to_mark_as_long.borrow_mut().long_term_frame_idx = long_term_frame_idx; 666 667 if let Some(other_field) = to_mark_as_long.borrow().other_field() { 668 let mut other_field = other_field.borrow_mut(); 669 if matches!(other_field.reference(), Reference::LongTerm) { 670 other_field.long_term_frame_idx = long_term_frame_idx; 671 672 log::debug!( 673 "Assigned long_term_frame_idx {} to other_field {:#?}", 674 long_term_frame_idx, 675 &other_field 676 ); 677 } 678 } 679 680 Ok(()) 681 } 682 683 /// Returns the new `max_long_term_frame_idx`. mmco_op_4(&mut self, marking: &RefPicMarkingInner) -> MaxLongTermFrameIdx684 pub fn mmco_op_4(&mut self, marking: &RefPicMarkingInner) -> MaxLongTermFrameIdx { 685 log::debug!("MMCO op 4, max_long_term_frame_idx: {:?}", marking.max_long_term_frame_idx); 686 687 log::trace!("Dpb state before MMCO=4: {:#?}", self); 688 689 for mut dpb_pic in self 690 .pictures_mut() 691 .filter(|pic| matches!(pic.reference(), Reference::LongTerm)) 692 .filter(|pic| marking.max_long_term_frame_idx < pic.long_term_frame_idx) 693 { 694 dpb_pic.set_reference(Reference::None, false); 695 } 696 697 marking.max_long_term_frame_idx 698 } 699 700 /// Returns the new `max_long_term_frame_idx`. mmco_op_5(&mut self, pic: &mut PictureData) -> MaxLongTermFrameIdx701 pub fn mmco_op_5(&mut self, pic: &mut PictureData) -> MaxLongTermFrameIdx { 702 log::debug!("MMCO op 5, marking all pictures in the DPB as unused for reference"); 703 log::trace!("Dpb state before MMCO=5: {:#?}", self); 704 705 self.mark_all_as_unused_for_ref(); 706 707 pic.has_mmco_5 = true; 708 709 // A picture including a memory_management_control_operation equal to 5 710 // shall have frame_num constraints as described above and, after the 711 // decoding of the current picture and the processing of the memory 712 // management control operations, the picture shall be inferred to have 713 // had frame_num equal to 0 for all subsequent use in the decoding 714 // process, except as specified in clause 7.4.1.2.4. 715 pic.frame_num = 0; 716 717 // When the current picture includes a 718 // memory_management_control_operation equal to 5, after the decoding of 719 // the current picture, tempPicOrderCnt is set equal to PicOrderCnt( 720 // CurrPic ), TopFieldOrderCnt of the current picture (if any) is set 721 // equal to TopFieldOrderCnt − tempPicOrderCnt, and BottomFieldOrderCnt 722 // of the current picture (if any) is set equal to BottomFieldOrderCnt − 723 // tempPicOrderCnt 724 match pic.field { 725 Field::Top => { 726 pic.top_field_order_cnt = 0; 727 pic.pic_order_cnt = 0; 728 } 729 Field::Bottom => { 730 pic.bottom_field_order_cnt = 0; 731 pic.pic_order_cnt = 0; 732 } 733 Field::Frame => { 734 pic.top_field_order_cnt -= pic.pic_order_cnt; 735 pic.bottom_field_order_cnt -= pic.pic_order_cnt; 736 pic.pic_order_cnt = 737 std::cmp::min(pic.top_field_order_cnt, pic.bottom_field_order_cnt); 738 } 739 } 740 741 MaxLongTermFrameIdx::NoLongTermFrameIndices 742 } 743 mmco_op_6(&mut self, pic: &mut PictureData, marking: &RefPicMarkingInner)744 pub fn mmco_op_6(&mut self, pic: &mut PictureData, marking: &RefPicMarkingInner) { 745 let long_term_frame_idx = marking.long_term_frame_idx; 746 747 log::debug!("MMCO op 6, long_term_frame_idx: {}", long_term_frame_idx); 748 log::trace!("Dpb state before MMCO=6: {:#?}", self); 749 750 for mut dpb_pic in self.pictures_mut() { 751 // When a variable LongTermFrameIdx equal to long_term_frame_idx is 752 // already assigned to a long-term reference frame or a long-term 753 // complementary reference field pair, that frame or complementary 754 // field pair and both of its fields are marked as "unused for 755 // reference". When LongTermFrameIdx is already assigned to a 756 // reference field, and that reference field is not part of a 757 // complementary field pair that includes the current picture, that 758 // field is marked as "unused for reference". 759 if matches!(dpb_pic.reference(), Reference::LongTerm) 760 && dpb_pic.long_term_frame_idx == long_term_frame_idx 761 { 762 let is_frame = matches!(dpb_pic.field, Field::Frame); 763 764 let is_complementary_ref_field_pair = dpb_pic 765 .other_field() 766 .map(|f| { 767 let pic = f.borrow(); 768 matches!(pic.reference(), Reference::LongTerm) 769 && pic.long_term_frame_idx == long_term_frame_idx 770 }) 771 .unwrap_or(false); 772 773 dpb_pic.set_reference(Reference::None, is_frame || is_complementary_ref_field_pair); 774 775 break; 776 } 777 } 778 779 let is_frame = matches!(pic.field, Field::Frame); 780 781 let is_second_ref_field = match pic.field_rank() { 782 FieldRank::Second(first_field) 783 if *first_field.borrow().reference() == Reference::LongTerm => 784 { 785 first_field.borrow_mut().long_term_frame_idx = long_term_frame_idx; 786 true 787 } 788 _ => false, 789 }; 790 791 pic.set_reference(Reference::LongTerm, is_frame || is_second_ref_field); 792 pic.long_term_frame_idx = long_term_frame_idx; 793 } 794 795 #[cfg(debug_assertions)] debug_ref_list_p(ref_pic_list: &[&DpbEntry<T>], field_pic: bool)796 fn debug_ref_list_p(ref_pic_list: &[&DpbEntry<T>], field_pic: bool) { 797 debug!( 798 "ref_list_p0: (ShortTerm|LongTerm, pic_num) {:?}", 799 ref_pic_list 800 .iter() 801 .map(|h| { 802 let p = h.pic.borrow(); 803 let reference = match p.reference() { 804 Reference::None => panic!("Not a reference."), 805 Reference::ShortTerm => "ShortTerm", 806 Reference::LongTerm => "LongTerm", 807 }; 808 809 let field = if !p.is_second_field() { "First field" } else { "Second field" }; 810 811 let field = format!("{}, {:?}", field, p.field); 812 813 let inner = match (field_pic, p.reference()) { 814 (false, _) => ("pic_num", p.pic_num, field), 815 (true, Reference::ShortTerm) => ("frame_num_wrap", p.frame_num_wrap, field), 816 (true, Reference::LongTerm) => { 817 ("long_term_frame_idx", p.long_term_frame_idx as i32, field) 818 } 819 820 _ => panic!("Not a reference."), 821 }; 822 (reference, inner) 823 }) 824 .collect::<Vec<_>>() 825 ); 826 } 827 828 #[cfg(debug_assertions)] debug_ref_list_b(ref_pic_list: &[&DpbEntry<T>], ref_pic_list_name: &str)829 fn debug_ref_list_b(ref_pic_list: &[&DpbEntry<T>], ref_pic_list_name: &str) { 830 debug!( 831 "{:?}: (ShortTerm|LongTerm, (POC|LongTermPicNum)) {:?}", 832 ref_pic_list_name, 833 ref_pic_list 834 .iter() 835 .map(|h| { 836 let p = h.pic.borrow(); 837 let reference = match p.reference() { 838 Reference::None => panic!("Not a reference."), 839 Reference::ShortTerm => "ShortTerm", 840 Reference::LongTerm => "LongTerm", 841 }; 842 843 let field = if !p.is_second_field() { "First field" } else { "Second field" }; 844 845 let field = format!("{}, {:?}", field, p.field); 846 847 let inner = match p.reference() { 848 Reference::ShortTerm => ("POC", p.pic_order_cnt, field), 849 Reference::LongTerm => { 850 ("LongTermPicNum", p.long_term_pic_num as i32, field) 851 } 852 _ => panic!("Not a reference!"), 853 }; 854 (reference, inner) 855 }) 856 .collect::<Vec<_>>() 857 ); 858 } 859 sort_pic_num_descending(pics: &mut [&DpbEntry<T>])860 fn sort_pic_num_descending(pics: &mut [&DpbEntry<T>]) { 861 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().pic_num)); 862 } 863 sort_frame_num_wrap_descending(pics: &mut [&DpbEntry<T>])864 fn sort_frame_num_wrap_descending(pics: &mut [&DpbEntry<T>]) { 865 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().frame_num_wrap)); 866 } 867 sort_long_term_pic_num_ascending(pics: &mut [&DpbEntry<T>])868 fn sort_long_term_pic_num_ascending(pics: &mut [&DpbEntry<T>]) { 869 pics.sort_by_key(|h| h.pic.borrow().long_term_pic_num); 870 } 871 sort_long_term_frame_idx_ascending(pics: &mut [&DpbEntry<T>])872 fn sort_long_term_frame_idx_ascending(pics: &mut [&DpbEntry<T>]) { 873 pics.sort_by_key(|h| h.pic.borrow().long_term_frame_idx); 874 } 875 sort_poc_descending(pics: &mut [&DpbEntry<T>])876 fn sort_poc_descending(pics: &mut [&DpbEntry<T>]) { 877 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().pic_order_cnt)); 878 } 879 sort_poc_ascending(pics: &mut [&DpbEntry<T>])880 fn sort_poc_ascending(pics: &mut [&DpbEntry<T>]) { 881 pics.sort_by_key(|h| h.pic.borrow().pic_order_cnt); 882 } 883 884 // When the reference picture list RefPicList1 has more than one entry 885 // and RefPicList1 is identical to the reference picture list 886 // RefPicList0, the first two entries RefPicList1[0] and RefPicList1[1] 887 // are switched. swap_b1_if_needed(b0: &DpbPicRefList<T>, b1: &mut DpbPicRefList<T>)888 fn swap_b1_if_needed(b0: &DpbPicRefList<T>, b1: &mut DpbPicRefList<T>) { 889 if b1.len() > 1 && b0.len() == b1.len() { 890 let mut equals = true; 891 for (x1, x2) in b0.iter().zip(b1.iter()) { 892 if !Rc::ptr_eq(&x1.pic, &x2.pic) { 893 equals = false; 894 break; 895 } 896 } 897 898 if equals { 899 b1.swap(0, 1); 900 } 901 } 902 } 903 904 /// Copies from refFrameList(XShort|Long)Term into RefPicListX as per 8.2.4.2.5. Used when 905 /// building the reference list for fields in interlaced decoding. init_ref_field_pic_list<'a>( mut field: Field, reference_type: Reference, ref_frame_list: &mut DpbPicRefList<'a, T>, ref_pic_list: &mut DpbPicRefList<'a, T>, )906 fn init_ref_field_pic_list<'a>( 907 mut field: Field, 908 reference_type: Reference, 909 ref_frame_list: &mut DpbPicRefList<'a, T>, 910 ref_pic_list: &mut DpbPicRefList<'a, T>, 911 ) { 912 // When one field of a reference frame was not decoded or is not marked as "used for 913 // (short|long)-term reference", the missing field is ignored and instead the next 914 // available stored reference field of the chosen parity from the ordered list of frames 915 // refFrameListX(Short|Long)Term is inserted into RefPicListX. 916 ref_frame_list.retain(|h| { 917 let p = h.pic.borrow(); 918 let skip = p.nonexisting || *p.reference() != reference_type; 919 !skip 920 }); 921 922 while let Some(position) = ref_frame_list.iter().position(|h| { 923 let p = h.pic.borrow(); 924 let found = p.field == field; 925 926 if found { 927 field = field.opposite(); 928 } 929 930 found 931 }) { 932 let pic = ref_frame_list.remove(position); 933 ref_pic_list.push(pic); 934 } 935 936 ref_pic_list.append(ref_frame_list); 937 } 938 939 /// 8.2.4.2.1 Initialization process for the reference picture list for P 940 /// and SP slices in frames build_ref_pic_list_p(&self) -> DpbPicRefList<T>941 fn build_ref_pic_list_p(&self) -> DpbPicRefList<T> { 942 let mut ref_pic_list_p0: Vec<_> = 943 self.short_term_refs_iter().filter(|h| !h.pic.borrow().is_second_field()).collect(); 944 945 Self::sort_pic_num_descending(&mut ref_pic_list_p0); 946 947 let num_short_term_refs = ref_pic_list_p0.len(); 948 949 ref_pic_list_p0 950 .extend(self.long_term_refs_iter().filter(|h| !h.pic.borrow().is_second_field())); 951 Self::sort_long_term_pic_num_ascending(&mut ref_pic_list_p0[num_short_term_refs..]); 952 953 #[cfg(debug_assertions)] 954 Self::debug_ref_list_p(&ref_pic_list_p0, false); 955 956 ref_pic_list_p0 957 } 958 959 /// 8.2.4.2.2 Initialization process for the reference picture list for P 960 /// and SP slices in fields build_ref_field_pic_list_p(&self, cur_pic: &PictureData) -> DpbPicRefList<T>961 fn build_ref_field_pic_list_p(&self, cur_pic: &PictureData) -> DpbPicRefList<T> { 962 let mut ref_pic_list_p0 = vec![]; 963 964 let mut ref_frame_list_0_short_term: Vec<_> = self.short_term_refs_iter().collect(); 965 Self::sort_frame_num_wrap_descending(&mut ref_frame_list_0_short_term); 966 967 let mut ref_frame_list_long_term: Vec<_> = self.long_term_refs_iter().collect(); 968 Self::sort_long_term_pic_num_ascending(&mut ref_frame_list_long_term); 969 970 // 8.2.4.2.5 971 Self::init_ref_field_pic_list( 972 cur_pic.field, 973 Reference::ShortTerm, 974 &mut ref_frame_list_0_short_term, 975 &mut ref_pic_list_p0, 976 ); 977 Self::init_ref_field_pic_list( 978 cur_pic.field, 979 Reference::LongTerm, 980 &mut ref_frame_list_long_term, 981 &mut ref_pic_list_p0, 982 ); 983 984 #[cfg(debug_assertions)] 985 Self::debug_ref_list_p(&ref_pic_list_p0, true); 986 987 ref_pic_list_p0 988 } 989 990 // 8.2.4.2.3 Initialization process for reference picture lists for B slices 991 // in frames build_ref_pic_list_b(&self, cur_pic: &PictureData) -> (DpbPicRefList<T>, DpbPicRefList<T>)992 fn build_ref_pic_list_b(&self, cur_pic: &PictureData) -> (DpbPicRefList<T>, DpbPicRefList<T>) { 993 let mut short_term_refs: Vec<_> = 994 self.short_term_refs_iter().filter(|h| !h.pic.borrow().is_second_field()).collect(); 995 996 // When pic_order_cnt_type is equal to 0, reference pictures that are 997 // marked as "non-existing" as specified in clause 8.2.5.2 are not 998 // included in either RefPicList0 or RefPicList1. 999 if cur_pic.pic_order_cnt_type == 0 { 1000 short_term_refs.retain(|h| !h.pic.borrow().nonexisting); 1001 } 1002 1003 let mut ref_pic_list_b0 = vec![]; 1004 let mut ref_pic_list_b1 = vec![]; 1005 let mut remaining = vec![]; 1006 // b0 contains three inner lists of pictures, i.e. [[0] [1] [2]] 1007 // [0]: short term pictures with POC < current, sorted by descending POC. 1008 // [1]: short term pictures with POC > current, sorted by ascending POC. 1009 // [2]: long term pictures sorted by ascending long_term_pic_num 1010 for &handle in &short_term_refs { 1011 let pic = handle.pic.borrow(); 1012 1013 if pic.pic_order_cnt < cur_pic.pic_order_cnt { 1014 ref_pic_list_b0.push(handle); 1015 } else { 1016 remaining.push(handle); 1017 } 1018 } 1019 1020 Self::sort_poc_descending(&mut ref_pic_list_b0); 1021 Self::sort_poc_ascending(&mut remaining); 1022 ref_pic_list_b0.append(&mut remaining); 1023 1024 let mut long_term_refs: Vec<_> = self 1025 .long_term_refs_iter() 1026 .filter(|h| !h.pic.borrow().nonexisting) 1027 .filter(|h| !h.pic.borrow().is_second_field()) 1028 .collect(); 1029 Self::sort_long_term_pic_num_ascending(&mut long_term_refs); 1030 1031 ref_pic_list_b0.extend(long_term_refs.clone()); 1032 1033 // b1 contains three inner lists of pictures, i.e. [[0] [1] [2]] 1034 // [0]: short term pictures with POC > current, sorted by ascending POC. 1035 // [1]: short term pictures with POC < current, sorted by descending POC. 1036 // [2]: long term pictures sorted by ascending long_term_pic_num 1037 for &handle in &short_term_refs { 1038 let pic = handle.pic.borrow(); 1039 1040 if pic.pic_order_cnt > cur_pic.pic_order_cnt { 1041 ref_pic_list_b1.push(handle); 1042 } else { 1043 remaining.push(handle); 1044 } 1045 } 1046 1047 Self::sort_poc_ascending(&mut ref_pic_list_b1); 1048 Self::sort_poc_descending(&mut remaining); 1049 1050 ref_pic_list_b1.extend(remaining); 1051 ref_pic_list_b1.extend(long_term_refs); 1052 1053 // When the reference picture list RefPicList1 has more than one entry 1054 // and RefPicList1 is identical to the reference picture list 1055 // RefPicList0, the first two entries RefPicList1[0] and RefPicList1[1] 1056 // are switched. 1057 Self::swap_b1_if_needed(&ref_pic_list_b0, &mut ref_pic_list_b1); 1058 1059 #[cfg(debug_assertions)] 1060 Self::debug_ref_list_b(&ref_pic_list_b0, "ref_pic_list_b0"); 1061 #[cfg(debug_assertions)] 1062 Self::debug_ref_list_b(&ref_pic_list_b1, "ref_pic_list_b1"); 1063 1064 (ref_pic_list_b0, ref_pic_list_b1) 1065 } 1066 1067 /// 8.2.4.2.4 Initialization process for reference picture lists for B 1068 /// slices in fields build_ref_field_pic_list_b( &self, cur_pic: &PictureData, ) -> (DpbPicRefList<T>, DpbPicRefList<T>)1069 fn build_ref_field_pic_list_b( 1070 &self, 1071 cur_pic: &PictureData, 1072 ) -> (DpbPicRefList<T>, DpbPicRefList<T>) { 1073 let mut ref_pic_list_b0 = vec![]; 1074 let mut ref_pic_list_b1 = vec![]; 1075 let mut ref_frame_list_0_short_term = vec![]; 1076 let mut ref_frame_list_1_short_term = vec![]; 1077 1078 let mut remaining = vec![]; 1079 1080 let mut short_term_refs: Vec<_> = self.short_term_refs_iter().collect(); 1081 1082 // When pic_order_cnt_type is equal to 0, reference pictures that are 1083 // marked as "non-existing" as specified in clause 8.2.5.2 are not 1084 // included in either RefPicList0 or RefPicList1. 1085 if cur_pic.pic_order_cnt_type == 0 { 1086 short_term_refs.retain(|h| !h.pic.borrow().nonexisting); 1087 } 1088 1089 // refFrameList0ShortTerm is comprised of two inner lists, [[0] [1]] 1090 // [0]: short term pictures with POC <= current, sorted by descending POC 1091 // [1]: short term pictures with POC > current, sorted by ascending POC 1092 // NOTE 3 – When the current field follows in decoding order a coded 1093 // field fldPrev with which together it forms a complementary reference 1094 // field pair, fldPrev is included into the list refFrameList0ShortTerm 1095 // using PicOrderCnt( fldPrev ) and the ordering method described in the 1096 // previous sentence is applied. 1097 for &handle in &short_term_refs { 1098 let pic = handle.pic.borrow(); 1099 1100 if pic.pic_order_cnt <= cur_pic.pic_order_cnt { 1101 ref_frame_list_0_short_term.push(handle); 1102 } else { 1103 remaining.push(handle); 1104 } 1105 } 1106 1107 Self::sort_poc_descending(&mut ref_frame_list_0_short_term); 1108 Self::sort_poc_ascending(&mut remaining); 1109 ref_frame_list_0_short_term.append(&mut remaining); 1110 1111 // refFrameList1ShortTerm is comprised of two inner lists, [[0] [1]] 1112 // [0]: short term pictures with POC > current, sorted by ascending POC 1113 // [1]: short term pictures with POC <= current, sorted by descending POC 1114 // NOTE 4 – When the current field follows in decoding order a coded 1115 // field fldPrev with which together it forms a complementary reference 1116 // field pair, fldPrev is included into the list refFrameList1ShortTerm 1117 // using PicOrderCnt( fldPrev ) and the ordering method described in the 1118 // previous sentence is applied. 1119 1120 for &handle in &short_term_refs { 1121 let pic = handle.pic.borrow(); 1122 1123 if pic.pic_order_cnt > cur_pic.pic_order_cnt { 1124 ref_frame_list_1_short_term.push(handle); 1125 } else { 1126 remaining.push(handle); 1127 } 1128 } 1129 1130 Self::sort_poc_ascending(&mut ref_frame_list_1_short_term); 1131 Self::sort_poc_descending(&mut remaining); 1132 ref_frame_list_1_short_term.append(&mut remaining); 1133 1134 // refFrameListLongTerm: long term pictures sorted by ascending 1135 // LongTermFrameIdx. 1136 // NOTE 5 – When the current picture is the second field of a 1137 // complementary field pair and the first field of the complementary 1138 // field pair is marked as "used for long-term reference", the first 1139 // field is included into the list refFrameListLongTerm. A reference 1140 // entry in which only one field is marked as "used for long-term 1141 // reference" is included into the list refFrameListLongTerm 1142 let mut ref_frame_list_long_term: Vec<_> = 1143 self.long_term_refs_iter().filter(|h| !h.pic.borrow().nonexisting).collect(); 1144 1145 Self::sort_long_term_frame_idx_ascending(&mut ref_frame_list_long_term); 1146 1147 #[cfg(debug_assertions)] 1148 Self::debug_ref_list_b(&ref_frame_list_0_short_term, "ref_frame_list_0_short_term"); 1149 #[cfg(debug_assertions)] 1150 Self::debug_ref_list_b(&ref_frame_list_1_short_term, "ref_frame_list_1_short_term"); 1151 #[cfg(debug_assertions)] 1152 Self::debug_ref_list_b(&ref_frame_list_long_term, "ref_frame_list_long_term"); 1153 1154 // 8.2.4.2.5 1155 let field = cur_pic.field; 1156 Self::init_ref_field_pic_list( 1157 field, 1158 Reference::ShortTerm, 1159 &mut ref_frame_list_0_short_term, 1160 &mut ref_pic_list_b0, 1161 ); 1162 Self::init_ref_field_pic_list( 1163 field, 1164 Reference::LongTerm, 1165 &mut ref_frame_list_long_term, 1166 &mut ref_pic_list_b0, 1167 ); 1168 1169 Self::init_ref_field_pic_list( 1170 field, 1171 Reference::ShortTerm, 1172 &mut ref_frame_list_1_short_term, 1173 &mut ref_pic_list_b1, 1174 ); 1175 Self::init_ref_field_pic_list( 1176 field, 1177 Reference::LongTerm, 1178 &mut ref_frame_list_long_term, 1179 &mut ref_pic_list_b1, 1180 ); 1181 1182 // When the reference picture list RefPicList1 has more than one entry 1183 // and RefPicList1 is identical to the reference picture list 1184 // RefPicList0, the first two entries RefPicList1[0] and RefPicList1[1] 1185 // are switched. 1186 Self::swap_b1_if_needed(&ref_pic_list_b0, &mut ref_pic_list_b1); 1187 1188 #[cfg(debug_assertions)] 1189 Self::debug_ref_list_b(&ref_pic_list_b0, "ref_pic_list_b0"); 1190 #[cfg(debug_assertions)] 1191 Self::debug_ref_list_b(&ref_pic_list_b1, "ref_pic_list_b1"); 1192 1193 (ref_pic_list_b0, ref_pic_list_b1) 1194 } 1195 1196 /// Returns the lists of reference pictures for `pic`. build_ref_pic_lists(&self, pic: &PictureData) -> ReferencePicLists1197 pub fn build_ref_pic_lists(&self, pic: &PictureData) -> ReferencePicLists { 1198 let num_refs = self.pictures().filter(|p| p.is_ref() && !p.nonexisting).count(); 1199 1200 // 8.2.4.2.1 ~ 8.2.4.2.4: When this process is invoked, there shall be 1201 // at least one reference frame or complementary reference field pair 1202 // that is currently marked as "used for reference" (i.e., as "used for 1203 // short-term reference" or "used for long-term reference") and is not 1204 // marked as "non-existing". 1205 if num_refs == 0 { 1206 return Default::default(); 1207 } 1208 1209 let (ref_pic_list_p0, (ref_pic_list_b0, ref_pic_list_b1)) = 1210 if matches!(pic.field, Field::Frame) { 1211 (self.build_ref_pic_list_p(), self.build_ref_pic_list_b(pic)) 1212 } else { 1213 (self.build_ref_field_pic_list_p(pic), self.build_ref_field_pic_list_b(pic)) 1214 }; 1215 1216 let dpb_start = self.entries.as_ptr(); 1217 let refs_to_index = |refs: Vec<_>| { 1218 refs.into_iter() 1219 .map(|r| r as *const DpbEntry<T>) 1220 .map(|r| unsafe { r.offset_from(dpb_start) }) 1221 .map(|i| i as usize) 1222 .collect() 1223 }; 1224 1225 ReferencePicLists { 1226 ref_pic_list_p0: refs_to_index(ref_pic_list_p0), 1227 ref_pic_list_b0: refs_to_index(ref_pic_list_b0), 1228 ref_pic_list_b1: refs_to_index(ref_pic_list_b1), 1229 } 1230 } 1231 } 1232 1233 impl<T> Default for Dpb<T> { default() -> Self1234 fn default() -> Self { 1235 // See https://github.com/rust-lang/rust/issues/26925 on why this can't 1236 // be derived. 1237 Self { 1238 entries: Default::default(), 1239 max_num_pics: Default::default(), 1240 max_num_reorder_frames: Default::default(), 1241 interlaced: Default::default(), 1242 } 1243 } 1244 } 1245 1246 impl<T> std::fmt::Debug for Dpb<T> { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1247 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 1248 let pics = self.entries.iter().map(|h| &h.pic).enumerate().collect::<Vec<_>>(); 1249 f.debug_struct("Dpb") 1250 .field("pictures", &pics) 1251 .field("max_num_pics", &self.max_num_pics) 1252 .field("interlaced", &self.interlaced) 1253 .finish() 1254 } 1255 } 1256