1use std::cell::Ref;
6use std::cell::RefMut;
7use std::fmt;
8use std::rc::Rc;
9
10use log::debug;
11
12use crate::codec::h264::parser::MaxLongTermFrameIdx;
13use crate::codec::h264::parser::RefPicMarkingInner;
14use crate::codec::h264::parser::Sps;
15use crate::codec::h264::picture::Field;
16use crate::codec::h264::picture::FieldRank;
17use crate::codec::h264::picture::IsIdr;
18use crate::codec::h264::picture::PictureData;
19use crate::codec::h264::picture::RcPictureData;
20use crate::codec::h264::picture::Reference;
21
22pub type DpbPicRefList<'a, H> = Vec<&'a DpbEntry<H>>;
23
24#[derive(Default)]
26pub struct ReferencePicLists {
27 pub ref_pic_list_p0: Vec<usize>,
31 pub ref_pic_list_b0: Vec<usize>,
35 pub ref_pic_list_b1: Vec<usize>,
39}
40
41#[derive(Clone)]
43pub struct DpbEntry<T> {
44 pub pic: RcPictureData,
46 pub reference: Option<T>,
48 pub decoded_frame: Option<T>,
51 needed_for_output: bool,
53}
54
55impl<T> DpbEntry<T> {
56 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 Field::Frame => true,
69 Field::Top | Field::Bottom => matches!(pic.field_rank(), FieldRank::First(..)),
71 }
72 }
73}
74
75pub struct Dpb<T> {
76 entries: Vec<DpbEntry<T>>,
78 max_num_pics: usize,
80 max_num_reorder_frames: usize,
89 interlaced: bool,
95}
96
97#[derive(Debug)]
98pub enum StorePictureError {
99 DpbIsFull,
100}
101
102impl fmt::Display for StorePictureError {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 write!(f, "DPB is full")
105 }
106}
107
108impl std::error::Error for StorePictureError {}
109
110#[derive(Debug)]
111pub enum MmcoError {
112 NoShortTermPic,
113 ExpectedMarked,
114 ExpectedExisting,
115 UnknownMmco(u8),
116}
117
118impl fmt::Display for MmcoError {
119 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
135impl std::error::Error for MmcoError {}
136
137impl<T: Clone> Dpb<T> {
138 fn pictures(&self) -> impl Iterator<Item = Ref<'_, PictureData>> {
141 self.entries.iter().map(|h| h.pic.borrow())
142 }
143
144 fn pictures_mut(&mut self) -> impl Iterator<Item = RefMut<'_, PictureData>> {
147 self.entries.iter().map(|h| h.pic.borrow_mut())
148 }
149
150 pub fn len(&self) -> usize {
152 self.entries.len()
153 }
154
155 pub fn is_empty(&self) -> bool {
156 self.len() == 0
157 }
158
159 pub fn entries(&self) -> &Vec<DpbEntry<T>> {
161 &self.entries
162 }
163
164 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 pub fn max_num_pics(&self) -> usize {
172 self.max_num_pics
173 }
174
175 pub fn num_ref_frames(&self) -> usize {
178 self.pictures().filter(|p| p.is_ref() && !p.is_second_field()).count()
179 }
180
181 pub fn interlaced(&self) -> bool {
183 self.interlaced
184 }
185
186 pub fn set_interlaced(&mut self, interlaced: bool) {
188 self.interlaced = interlaced;
189 }
190
191 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 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 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 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!(
238 "find_short_term_with_pic_num: {}, found position {:?}",
239 pic_num,
240 position
241 );
242
243 position
244 }
245
246 pub fn find_short_term_with_pic_num(&self, pic_num: i32) -> Option<&DpbEntry<T>> {
248 let position = self.find_short_term_with_pic_num_pos(pic_num)?;
249 Some(&self.entries[position])
250 }
251
252 fn find_long_term_with_long_term_pic_num_pos(&self, long_term_pic_num: u32) -> Option<usize> {
255 let position = self
256 .pictures()
257 .position(|p| matches!(p.reference(), Reference::LongTerm) && p.long_term_pic_num == long_term_pic_num);
258
259 log::debug!(
260 "find_long_term_with_long_term_pic_num: {}, found position {:?}",
261 long_term_pic_num,
262 position
263 );
264
265 position
266 }
267
268 pub fn find_long_term_with_long_term_pic_num(&self, long_term_pic_num: u32) -> Option<&DpbEntry<T>> {
271 let position = self.find_long_term_with_long_term_pic_num_pos(long_term_pic_num)?;
272 Some(&self.entries[position])
273 }
274
275 pub fn store_picture(&mut self, picture: RcPictureData, handle: Option<T>) -> Result<(), StorePictureError> {
277 let max_pics = if self.interlaced {
278 self.max_num_pics * 2
279 } else {
280 self.max_num_pics
281 };
282
283 if self.entries.len() >= max_pics {
284 return Err(StorePictureError::DpbIsFull);
285 }
286
287 let pic = picture.borrow();
288
289 let needed_for_output = !pic.nonexisting;
292
293 debug!(
294 "Stored picture POC {:?}, field {:?}, the DPB length is {:?}",
295 pic.pic_order_cnt,
296 pic.field,
297 self.entries.len()
298 );
299 drop(pic);
300
301 self.entries.push(DpbEntry {
302 pic: picture,
303 reference: handle.clone(),
304 decoded_frame: handle,
305 needed_for_output,
306 });
307
308 Ok(())
309 }
310
311 pub fn has_empty_frame_buffer(&self) -> bool {
313 let count = if !self.interlaced {
314 self.entries.len()
315 } else {
316 self.pictures()
317 .filter(|pic| {
318 matches!(pic.field_rank(), FieldRank::First(..))
319 || (matches!(pic.field_rank(), FieldRank::Single) && pic.field == Field::Frame)
320 })
321 .count()
322 };
323
324 count < self.max_num_pics
325 }
326
327 pub fn needs_bumping(&self, to_insert: &PictureData) -> bool {
330 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() && to_insert.pic_order_cnt > lowest_poc
365 }
366
367 fn find_lowest_poc_for_bumping(&self) -> Option<&DpbEntry<T>> {
369 self.entries
370 .iter()
371 .filter(|entry| entry.is_bumpable())
372 .min_by_key(|handle| handle.pic.borrow().pic_order_cnt)
373 }
374
375 fn find_lowest_poc_for_bumping_mut(&mut self) -> Option<&mut DpbEntry<T>> {
377 self.entries
378 .iter_mut()
379 .filter(|entry| entry.is_bumpable())
380 .min_by_key(|handle| handle.pic.borrow().pic_order_cnt)
381 }
382
383 fn bump(&mut self) -> Option<Option<T>> {
386 let dpb_entry = self.find_lowest_poc_for_bumping_mut()?;
387 let handle = dpb_entry.decoded_frame.take();
388 let pic = dpb_entry.pic.borrow();
389
390 debug!("Bumping picture {:#?} from the dpb", pic);
391
392 dpb_entry.needed_for_output = false;
393 if let FieldRank::First(second_field) = pic.field_rank() {
396 let second_field = second_field.upgrade();
397 drop(pic);
398 if let Some(second_field) =
399 second_field.and_then(|f| self.entries.iter_mut().find(|e| Rc::ptr_eq(&f, &e.pic)))
400 {
401 second_field.needed_for_output = false;
402 }
403 }
404
405 Some(handle)
406 }
407
408 pub fn drain(&mut self) -> Vec<Option<T>> {
410 debug!("Draining the DPB.");
411
412 let mut pics = vec![];
413
414 while let Some(pic) = self.bump() {
415 pics.push(pic);
416 }
417
418 self.clear();
419
420 pics
421 }
422
423 pub fn clear(&mut self) {
425 debug!("Clearing the DPB");
426
427 let max_num_pics = self.max_num_pics;
428 let interlaced = self.interlaced;
429
430 *self = Default::default();
431
432 self.max_num_pics = max_num_pics;
433 self.interlaced = interlaced;
434 }
435
436 pub fn short_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>> {
438 self.entries
439 .iter()
440 .filter(|&handle| matches!(handle.pic.borrow().reference(), Reference::ShortTerm))
441 }
442
443 pub fn long_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>> {
445 self.entries
446 .iter()
447 .filter(|&handle| matches!(handle.pic.borrow().reference(), Reference::LongTerm))
448 }
449
450 pub fn update_pic_nums(&mut self, frame_num: u32, max_frame_num: u32, current_pic: &PictureData) {
451 for mut pic in self.pictures_mut() {
452 if !pic.is_ref() {
453 continue;
454 }
455
456 if *pic.reference() == Reference::LongTerm {
457 pic.long_term_pic_num = if current_pic.field == Field::Frame {
458 pic.long_term_frame_idx
459 } else if current_pic.field == pic.field {
460 2 * pic.long_term_frame_idx + 1
461 } else {
462 2 * pic.long_term_frame_idx
463 };
464 } else {
465 pic.frame_num_wrap = if pic.frame_num > frame_num {
466 pic.frame_num as i32 - max_frame_num as i32
467 } else {
468 pic.frame_num as i32
469 };
470
471 pic.pic_num = if current_pic.field == Field::Frame {
472 pic.frame_num_wrap
473 } else if pic.field == current_pic.field {
474 2 * pic.frame_num_wrap + 1
475 } else {
476 2 * pic.frame_num_wrap
477 };
478 }
479 }
480 }
481
482 pub fn bump_as_needed(&mut self, current_pic: &PictureData) -> Vec<Option<T>> {
484 let mut pics = vec![];
485 while self.needs_bumping(current_pic) && self.len() >= self.max_num_reorder_frames {
486 match self.bump() {
487 Some(pic) => pics.push(pic),
488 None => return pics,
489 }
490 self.remove_unused();
491 }
492
493 pics
494 }
495
496 pub fn sliding_window_marking(&mut self, pic: &mut PictureData, sps: &Sps) {
498 if let FieldRank::Second(other_field) = pic.field_rank() {
504 if matches!(other_field.borrow().reference(), Reference::ShortTerm) {
505 pic.set_reference(Reference::ShortTerm, false);
506 return;
507 }
508 }
509
510 let mut num_ref_pics = self.num_ref_frames();
511 let max_num_ref_frames = std::cmp::max(1, sps.max_num_ref_frames as usize);
512
513 if num_ref_pics < max_num_ref_frames {
514 return;
515 }
516
517 while num_ref_pics >= max_num_ref_frames {
518 if let Some(to_unmark) = self.find_short_term_lowest_frame_num_wrap() {
519 to_unmark.pic.borrow_mut().set_reference(Reference::None, true);
520 num_ref_pics -= 1;
521 } else {
522 log::warn!("could not find a ShortTerm picture to unmark in the DPB");
523 break;
524 }
525 }
526
527 self.remove_unused();
528 }
529
530 pub fn mmco_op_1(&mut self, pic: &PictureData, marking: &RefPicMarkingInner) -> Result<(), MmcoError> {
531 let pic_num_x = pic.pic_num - (marking.difference_of_pic_nums_minus1 as i32 + 1);
532
533 log::debug!("MMCO op 1 for pic_num_x {}", pic_num_x);
534 log::trace!("Dpb state before MMCO=1: {:#?}", self);
535
536 let to_mark = self
537 .find_short_term_with_pic_num(pic_num_x)
538 .ok_or(MmcoError::NoShortTermPic)?;
539
540 to_mark
541 .pic
542 .borrow_mut()
543 .set_reference(Reference::None, matches!(pic.field, Field::Frame));
544
545 Ok(())
546 }
547
548 pub fn mmco_op_2(&mut self, pic: &PictureData, marking: &RefPicMarkingInner) -> Result<(), MmcoError> {
549 log::debug!("MMCO op 2 for long_term_pic_num {}", marking.long_term_pic_num);
550
551 log::trace!("Dpb state before MMCO=2: {:#?}", self);
552
553 let to_mark = self
554 .find_long_term_with_long_term_pic_num(marking.long_term_pic_num)
555 .ok_or(MmcoError::NoShortTermPic)?;
556
557 to_mark
558 .pic
559 .borrow_mut()
560 .set_reference(Reference::None, matches!(pic.field, Field::Frame));
561
562 Ok(())
563 }
564
565 pub fn mmco_op_3(&mut self, pic: &PictureData, marking: &RefPicMarkingInner) -> Result<(), MmcoError> {
566 let pic_num_x = pic.pic_num - (marking.difference_of_pic_nums_minus1 as i32 + 1);
567
568 log::debug!("MMCO op 3 for pic_num_x {}", pic_num_x);
569 log::trace!("Dpb state before MMCO=3: {:#?}", self);
570
571 let to_mark_as_long_pos = self
572 .find_short_term_with_pic_num_pos(pic_num_x)
573 .ok_or(MmcoError::NoShortTermPic)?;
574 let to_mark_as_long = &self.entries[to_mark_as_long_pos].pic;
575
576 if !matches!(to_mark_as_long.borrow().reference(), Reference::ShortTerm) {
577 return Err(MmcoError::ExpectedMarked);
578 }
579
580 if to_mark_as_long.borrow().nonexisting {
581 return Err(MmcoError::ExpectedExisting);
582 }
583
584 let to_mark_as_long_ptr = to_mark_as_long.as_ptr();
585 let to_mark_as_long_other_field_ptr = to_mark_as_long.borrow().other_field().map(|f| f.as_ptr());
586
587 let long_term_frame_idx = marking.long_term_frame_idx;
588
589 for mut picture in self.pictures_mut() {
590 let long_already_assigned = matches!(picture.reference(), Reference::LongTerm)
591 && picture.long_term_frame_idx == long_term_frame_idx;
592
593 if long_already_assigned {
594 let is_frame = matches!(picture.field, Field::Frame);
595
596 let is_complementary_field_pair = picture
597 .other_field()
598 .map(|f| {
599 let pic = f.borrow();
600 matches!(pic.reference(), Reference::LongTerm) && pic.long_term_frame_idx == long_term_frame_idx
601 })
602 .unwrap_or(false);
603
604 if is_frame || is_complementary_field_pair {
611 picture.set_reference(Reference::None, true);
612 break;
613 }
614
615 let reference_field_is_not_part_of_pic_x = match picture.other_field() {
621 None => true,
622 Some(other_field) => {
623 !std::ptr::eq(other_field.as_ptr(), to_mark_as_long_ptr)
625 && to_mark_as_long_other_field_ptr
626 .map(|p| !std::ptr::eq(p, &(*picture)))
627 .unwrap_or(true)
628 }
629 };
630
631 if reference_field_is_not_part_of_pic_x {
632 picture.set_reference(Reference::None, false);
633 break;
634 }
635 }
636 }
637
638 let is_frame = matches!(pic.field, Field::Frame);
639 let to_mark_as_long = &self.entries[to_mark_as_long_pos].pic;
640 to_mark_as_long
641 .borrow_mut()
642 .set_reference(Reference::LongTerm, is_frame);
643 to_mark_as_long.borrow_mut().long_term_frame_idx = long_term_frame_idx;
644
645 if let Some(other_field) = to_mark_as_long.borrow().other_field() {
646 let mut other_field = other_field.borrow_mut();
647 if matches!(other_field.reference(), Reference::LongTerm) {
648 other_field.long_term_frame_idx = long_term_frame_idx;
649
650 log::debug!(
651 "Assigned long_term_frame_idx {} to other_field {:#?}",
652 long_term_frame_idx,
653 &other_field
654 );
655 }
656 }
657
658 Ok(())
659 }
660
661 pub fn mmco_op_4(&mut self, marking: &RefPicMarkingInner) -> MaxLongTermFrameIdx {
663 log::debug!(
664 "MMCO op 4, max_long_term_frame_idx: {:?}",
665 marking.max_long_term_frame_idx
666 );
667
668 log::trace!("Dpb state before MMCO=4: {:#?}", self);
669
670 for mut dpb_pic in self
671 .pictures_mut()
672 .filter(|pic| matches!(pic.reference(), Reference::LongTerm))
673 .filter(|pic| marking.max_long_term_frame_idx < pic.long_term_frame_idx)
674 {
675 dpb_pic.set_reference(Reference::None, false);
676 }
677
678 marking.max_long_term_frame_idx
679 }
680
681 pub fn mmco_op_5(&mut self, pic: &mut PictureData) -> MaxLongTermFrameIdx {
683 log::debug!("MMCO op 5, marking all pictures in the DPB as unused for reference");
684 log::trace!("Dpb state before MMCO=5: {:#?}", self);
685
686 self.mark_all_as_unused_for_ref();
687
688 pic.has_mmco_5 = true;
689
690 pic.frame_num = 0;
697
698 match pic.field {
706 Field::Top => {
707 pic.top_field_order_cnt = 0;
708 pic.pic_order_cnt = 0;
709 }
710 Field::Bottom => {
711 pic.bottom_field_order_cnt = 0;
712 pic.pic_order_cnt = 0;
713 }
714 Field::Frame => {
715 pic.top_field_order_cnt -= pic.pic_order_cnt;
716 pic.bottom_field_order_cnt -= pic.pic_order_cnt;
717 pic.pic_order_cnt = std::cmp::min(pic.top_field_order_cnt, pic.bottom_field_order_cnt);
718 }
719 }
720
721 MaxLongTermFrameIdx::NoLongTermFrameIndices
722 }
723
724 pub fn mmco_op_6(&mut self, pic: &mut PictureData, marking: &RefPicMarkingInner) {
725 let long_term_frame_idx = marking.long_term_frame_idx;
726
727 log::debug!("MMCO op 6, long_term_frame_idx: {}", long_term_frame_idx);
728 log::trace!("Dpb state before MMCO=6: {:#?}", self);
729
730 for mut dpb_pic in self.pictures_mut() {
731 if matches!(dpb_pic.reference(), Reference::LongTerm) && dpb_pic.long_term_frame_idx == long_term_frame_idx
740 {
741 let is_frame = matches!(dpb_pic.field, Field::Frame);
742
743 let is_complementary_ref_field_pair = dpb_pic
744 .other_field()
745 .map(|f| {
746 let pic = f.borrow();
747 matches!(pic.reference(), Reference::LongTerm) && pic.long_term_frame_idx == long_term_frame_idx
748 })
749 .unwrap_or(false);
750
751 dpb_pic.set_reference(Reference::None, is_frame || is_complementary_ref_field_pair);
752
753 break;
754 }
755 }
756
757 let is_frame = matches!(pic.field, Field::Frame);
758
759 let is_second_ref_field = match pic.field_rank() {
760 FieldRank::Second(first_field) if *first_field.borrow().reference() == Reference::LongTerm => {
761 first_field.borrow_mut().long_term_frame_idx = long_term_frame_idx;
762 true
763 }
764 _ => false,
765 };
766
767 pic.set_reference(Reference::LongTerm, is_frame || is_second_ref_field);
768 pic.long_term_frame_idx = long_term_frame_idx;
769 }
770
771 #[cfg(debug_assertions)]
772 fn debug_ref_list_p(ref_pic_list: &[&DpbEntry<T>], field_pic: bool) {
773 debug!(
774 "ref_list_p0: (ShortTerm|LongTerm, pic_num) {:?}",
775 ref_pic_list
776 .iter()
777 .map(|h| {
778 let p = h.pic.borrow();
779 let reference = match p.reference() {
780 Reference::None => panic!("Not a reference."),
781 Reference::ShortTerm => "ShortTerm",
782 Reference::LongTerm => "LongTerm",
783 };
784
785 let field = if !p.is_second_field() {
786 "First field"
787 } else {
788 "Second field"
789 };
790
791 let field = format!("{}, {:?}", field, p.field);
792
793 let inner = match (field_pic, p.reference()) {
794 (false, _) => ("pic_num", p.pic_num, field),
795 (true, Reference::ShortTerm) => ("frame_num_wrap", p.frame_num_wrap, field),
796 (true, Reference::LongTerm) => ("long_term_frame_idx", p.long_term_frame_idx as i32, field),
797
798 _ => panic!("Not a reference."),
799 };
800 (reference, inner)
801 })
802 .collect::<Vec<_>>()
803 );
804 }
805
806 #[cfg(debug_assertions)]
807 fn debug_ref_list_b(ref_pic_list: &[&DpbEntry<T>], ref_pic_list_name: &str) {
808 debug!(
809 "{:?}: (ShortTerm|LongTerm, (POC|LongTermPicNum)) {:?}",
810 ref_pic_list_name,
811 ref_pic_list
812 .iter()
813 .map(|h| {
814 let p = h.pic.borrow();
815 let reference = match p.reference() {
816 Reference::None => panic!("Not a reference."),
817 Reference::ShortTerm => "ShortTerm",
818 Reference::LongTerm => "LongTerm",
819 };
820
821 let field = if !p.is_second_field() {
822 "First field"
823 } else {
824 "Second field"
825 };
826
827 let field = format!("{}, {:?}", field, p.field);
828
829 let inner = match p.reference() {
830 Reference::ShortTerm => ("POC", p.pic_order_cnt, field),
831 Reference::LongTerm => ("LongTermPicNum", p.long_term_pic_num as i32, field),
832 _ => panic!("Not a reference!"),
833 };
834 (reference, inner)
835 })
836 .collect::<Vec<_>>()
837 );
838 }
839
840 fn sort_pic_num_descending(pics: &mut [&DpbEntry<T>]) {
841 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().pic_num));
842 }
843
844 fn sort_frame_num_wrap_descending(pics: &mut [&DpbEntry<T>]) {
845 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().frame_num_wrap));
846 }
847
848 fn sort_long_term_pic_num_ascending(pics: &mut [&DpbEntry<T>]) {
849 pics.sort_by_key(|h| h.pic.borrow().long_term_pic_num);
850 }
851
852 fn sort_long_term_frame_idx_ascending(pics: &mut [&DpbEntry<T>]) {
853 pics.sort_by_key(|h| h.pic.borrow().long_term_frame_idx);
854 }
855
856 fn sort_poc_descending(pics: &mut [&DpbEntry<T>]) {
857 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().pic_order_cnt));
858 }
859
860 fn sort_poc_ascending(pics: &mut [&DpbEntry<T>]) {
861 pics.sort_by_key(|h| h.pic.borrow().pic_order_cnt);
862 }
863
864 fn swap_b1_if_needed(b0: &DpbPicRefList<T>, b1: &mut DpbPicRefList<T>) {
869 if b1.len() > 1 && b0.len() == b1.len() {
870 let mut equals = true;
871 for (x1, x2) in b0.iter().zip(b1.iter()) {
872 if !Rc::ptr_eq(&x1.pic, &x2.pic) {
873 equals = false;
874 break;
875 }
876 }
877
878 if equals {
879 b1.swap(0, 1);
880 }
881 }
882 }
883
884 fn init_ref_field_pic_list<'a>(
887 mut field: Field,
888 reference_type: Reference,
889 ref_frame_list: &mut DpbPicRefList<'a, T>,
890 ref_pic_list: &mut DpbPicRefList<'a, T>,
891 ) {
892 ref_frame_list.retain(|h| {
897 let p = h.pic.borrow();
898 let skip = p.nonexisting || *p.reference() != reference_type;
899 !skip
900 });
901
902 while let Some(position) = ref_frame_list.iter().position(|h| {
903 let p = h.pic.borrow();
904 let found = p.field == field;
905
906 if found {
907 field = field.opposite();
908 }
909
910 found
911 }) {
912 let pic = ref_frame_list.remove(position);
913 ref_pic_list.push(pic);
914 }
915
916 ref_pic_list.append(ref_frame_list);
917 }
918
919 fn build_ref_pic_list_p(&self) -> DpbPicRefList<T> {
922 let mut ref_pic_list_p0: Vec<_> = self
923 .short_term_refs_iter()
924 .filter(|h| !h.pic.borrow().is_second_field())
925 .collect();
926
927 Self::sort_pic_num_descending(&mut ref_pic_list_p0);
928
929 let num_short_term_refs = ref_pic_list_p0.len();
930
931 ref_pic_list_p0.extend(self.long_term_refs_iter().filter(|h| !h.pic.borrow().is_second_field()));
932 Self::sort_long_term_pic_num_ascending(&mut ref_pic_list_p0[num_short_term_refs..]);
933
934 #[cfg(debug_assertions)]
935 Self::debug_ref_list_p(&ref_pic_list_p0, false);
936
937 ref_pic_list_p0
938 }
939
940 fn build_ref_field_pic_list_p(&self, cur_pic: &PictureData) -> DpbPicRefList<T> {
943 let mut ref_pic_list_p0 = vec![];
944
945 let mut ref_frame_list_0_short_term: Vec<_> = self.short_term_refs_iter().collect();
946 Self::sort_frame_num_wrap_descending(&mut ref_frame_list_0_short_term);
947
948 let mut ref_frame_list_long_term: Vec<_> = self.long_term_refs_iter().collect();
949 Self::sort_long_term_pic_num_ascending(&mut ref_frame_list_long_term);
950
951 Self::init_ref_field_pic_list(
953 cur_pic.field,
954 Reference::ShortTerm,
955 &mut ref_frame_list_0_short_term,
956 &mut ref_pic_list_p0,
957 );
958 Self::init_ref_field_pic_list(
959 cur_pic.field,
960 Reference::LongTerm,
961 &mut ref_frame_list_long_term,
962 &mut ref_pic_list_p0,
963 );
964
965 #[cfg(debug_assertions)]
966 Self::debug_ref_list_p(&ref_pic_list_p0, true);
967
968 ref_pic_list_p0
969 }
970
971 fn build_ref_pic_list_b(&self, cur_pic: &PictureData) -> (DpbPicRefList<T>, DpbPicRefList<T>) {
974 let mut short_term_refs: Vec<_> = self
975 .short_term_refs_iter()
976 .filter(|h| !h.pic.borrow().is_second_field())
977 .collect();
978
979 if cur_pic.pic_order_cnt_type == 0 {
983 short_term_refs.retain(|h| !h.pic.borrow().nonexisting);
984 }
985
986 let mut ref_pic_list_b0 = vec![];
987 let mut ref_pic_list_b1 = vec![];
988 let mut remaining = vec![];
989 for &handle in &short_term_refs {
994 let pic = handle.pic.borrow();
995
996 if pic.pic_order_cnt < cur_pic.pic_order_cnt {
997 ref_pic_list_b0.push(handle);
998 } else {
999 remaining.push(handle);
1000 }
1001 }
1002
1003 Self::sort_poc_descending(&mut ref_pic_list_b0);
1004 Self::sort_poc_ascending(&mut remaining);
1005 ref_pic_list_b0.append(&mut remaining);
1006
1007 let mut long_term_refs: Vec<_> = self
1008 .long_term_refs_iter()
1009 .filter(|h| !h.pic.borrow().nonexisting)
1010 .filter(|h| !h.pic.borrow().is_second_field())
1011 .collect();
1012 Self::sort_long_term_pic_num_ascending(&mut long_term_refs);
1013
1014 ref_pic_list_b0.extend(long_term_refs.clone());
1015
1016 for &handle in &short_term_refs {
1021 let pic = handle.pic.borrow();
1022
1023 if pic.pic_order_cnt > cur_pic.pic_order_cnt {
1024 ref_pic_list_b1.push(handle);
1025 } else {
1026 remaining.push(handle);
1027 }
1028 }
1029
1030 Self::sort_poc_ascending(&mut ref_pic_list_b1);
1031 Self::sort_poc_descending(&mut remaining);
1032
1033 ref_pic_list_b1.extend(remaining);
1034 ref_pic_list_b1.extend(long_term_refs);
1035
1036 Self::swap_b1_if_needed(&ref_pic_list_b0, &mut ref_pic_list_b1);
1041
1042 #[cfg(debug_assertions)]
1043 Self::debug_ref_list_b(&ref_pic_list_b0, "ref_pic_list_b0");
1044 #[cfg(debug_assertions)]
1045 Self::debug_ref_list_b(&ref_pic_list_b1, "ref_pic_list_b1");
1046
1047 (ref_pic_list_b0, ref_pic_list_b1)
1048 }
1049
1050 fn build_ref_field_pic_list_b(&self, cur_pic: &PictureData) -> (DpbPicRefList<T>, DpbPicRefList<T>) {
1053 let mut ref_pic_list_b0 = vec![];
1054 let mut ref_pic_list_b1 = vec![];
1055 let mut ref_frame_list_0_short_term = vec![];
1056 let mut ref_frame_list_1_short_term = vec![];
1057
1058 let mut remaining = vec![];
1059
1060 let mut short_term_refs: Vec<_> = self.short_term_refs_iter().collect();
1061
1062 if cur_pic.pic_order_cnt_type == 0 {
1066 short_term_refs.retain(|h| !h.pic.borrow().nonexisting);
1067 }
1068
1069 for &handle in &short_term_refs {
1078 let pic = handle.pic.borrow();
1079
1080 if pic.pic_order_cnt <= cur_pic.pic_order_cnt {
1081 ref_frame_list_0_short_term.push(handle);
1082 } else {
1083 remaining.push(handle);
1084 }
1085 }
1086
1087 Self::sort_poc_descending(&mut ref_frame_list_0_short_term);
1088 Self::sort_poc_ascending(&mut remaining);
1089 ref_frame_list_0_short_term.append(&mut remaining);
1090
1091 for &handle in &short_term_refs {
1101 let pic = handle.pic.borrow();
1102
1103 if pic.pic_order_cnt > cur_pic.pic_order_cnt {
1104 ref_frame_list_1_short_term.push(handle);
1105 } else {
1106 remaining.push(handle);
1107 }
1108 }
1109
1110 Self::sort_poc_ascending(&mut ref_frame_list_1_short_term);
1111 Self::sort_poc_descending(&mut remaining);
1112 ref_frame_list_1_short_term.append(&mut remaining);
1113
1114 let mut ref_frame_list_long_term: Vec<_> = self
1123 .long_term_refs_iter()
1124 .filter(|h| !h.pic.borrow().nonexisting)
1125 .collect();
1126
1127 Self::sort_long_term_frame_idx_ascending(&mut ref_frame_list_long_term);
1128
1129 #[cfg(debug_assertions)]
1130 Self::debug_ref_list_b(&ref_frame_list_0_short_term, "ref_frame_list_0_short_term");
1131 #[cfg(debug_assertions)]
1132 Self::debug_ref_list_b(&ref_frame_list_1_short_term, "ref_frame_list_1_short_term");
1133 #[cfg(debug_assertions)]
1134 Self::debug_ref_list_b(&ref_frame_list_long_term, "ref_frame_list_long_term");
1135
1136 let field = cur_pic.field;
1138 Self::init_ref_field_pic_list(
1139 field,
1140 Reference::ShortTerm,
1141 &mut ref_frame_list_0_short_term,
1142 &mut ref_pic_list_b0,
1143 );
1144 Self::init_ref_field_pic_list(
1145 field,
1146 Reference::LongTerm,
1147 &mut ref_frame_list_long_term,
1148 &mut ref_pic_list_b0,
1149 );
1150
1151 Self::init_ref_field_pic_list(
1152 field,
1153 Reference::ShortTerm,
1154 &mut ref_frame_list_1_short_term,
1155 &mut ref_pic_list_b1,
1156 );
1157 Self::init_ref_field_pic_list(
1158 field,
1159 Reference::LongTerm,
1160 &mut ref_frame_list_long_term,
1161 &mut ref_pic_list_b1,
1162 );
1163
1164 Self::swap_b1_if_needed(&ref_pic_list_b0, &mut ref_pic_list_b1);
1169
1170 #[cfg(debug_assertions)]
1171 Self::debug_ref_list_b(&ref_pic_list_b0, "ref_pic_list_b0");
1172 #[cfg(debug_assertions)]
1173 Self::debug_ref_list_b(&ref_pic_list_b1, "ref_pic_list_b1");
1174
1175 (ref_pic_list_b0, ref_pic_list_b1)
1176 }
1177
1178 pub fn build_ref_pic_lists(&self, pic: &PictureData) -> ReferencePicLists {
1180 let num_refs = self.pictures().filter(|p| p.is_ref() && !p.nonexisting).count();
1181
1182 if num_refs == 0 {
1188 return Default::default();
1189 }
1190
1191 let (ref_pic_list_p0, (ref_pic_list_b0, ref_pic_list_b1)) = if matches!(pic.field, Field::Frame) {
1192 (self.build_ref_pic_list_p(), self.build_ref_pic_list_b(pic))
1193 } else {
1194 (
1195 self.build_ref_field_pic_list_p(pic),
1196 self.build_ref_field_pic_list_b(pic),
1197 )
1198 };
1199
1200 let dpb_start = self.entries.as_ptr();
1201 let refs_to_index = |refs: Vec<_>| {
1202 refs.into_iter()
1203 .map(|r| r as *const DpbEntry<T>)
1204 .map(|r| unsafe { r.offset_from(dpb_start) })
1205 .map(|i| i as usize)
1206 .collect()
1207 };
1208
1209 ReferencePicLists {
1210 ref_pic_list_p0: refs_to_index(ref_pic_list_p0),
1211 ref_pic_list_b0: refs_to_index(ref_pic_list_b0),
1212 ref_pic_list_b1: refs_to_index(ref_pic_list_b1),
1213 }
1214 }
1215}
1216
1217impl<T> Default for Dpb<T> {
1218 fn default() -> Self {
1219 Self {
1222 entries: Default::default(),
1223 max_num_pics: Default::default(),
1224 max_num_reorder_frames: Default::default(),
1225 interlaced: Default::default(),
1226 }
1227 }
1228}
1229
1230impl<T> std::fmt::Debug for Dpb<T> {
1231 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1232 let pics = self.entries.iter().map(|h| &h.pic).enumerate().collect::<Vec<_>>();
1233 f.debug_struct("Dpb")
1234 .field("pictures", &pics)
1235 .field("max_num_pics", &self.max_num_pics)
1236 .field("interlaced", &self.interlaced)
1237 .finish()
1238 }
1239}