1use std::cell::Ref;
6use std::cell::RefMut;
7use std::rc::Rc;
8
9use log::debug;
10use thiserror::Error;
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)]
48pub struct DpbEntry<T> {
49 pub pic: RcPictureData,
50 pub handle: 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, Error)]
98pub enum StorePictureError {
99 #[error("DPB is full")]
100 DpbIsFull,
101}
102
103#[derive(Debug, Error)]
104pub enum MmcoError {
105 #[error("could not find a ShortTerm picture to mark in the DPB")]
106 NoShortTermPic,
107 #[error("a ShortTerm picture was expected to be marked for MMCO=3")]
108 ExpectedMarked,
109 #[error("picture cannot be marked as nonexisting for MMCO=3")]
110 ExpectedExisting,
111 #[error("unknown MMCO: {0}")]
112 UnknownMmco(u8),
113}
114
115impl<T: Clone> Dpb<T> {
116 fn pictures(&self) -> impl Iterator<Item = Ref<'_, PictureData>> {
119 self.entries.iter().map(|h| h.pic.borrow())
120 }
121
122 fn pictures_mut(&mut self) -> impl Iterator<Item = RefMut<'_, PictureData>> {
125 self.entries.iter().map(|h| h.pic.borrow_mut())
126 }
127
128 pub fn len(&self) -> usize {
130 self.entries.len()
131 }
132
133 pub fn is_empty(&self) -> bool {
134 self.len() == 0
135 }
136
137 pub fn entries(&self) -> &Vec<DpbEntry<T>> {
139 &self.entries
140 }
141
142 pub fn set_limits(&mut self, max_num_pics: usize, max_num_reorder_frames: usize) {
144 self.max_num_pics = max_num_pics;
145 self.max_num_reorder_frames = max_num_reorder_frames;
146 }
147
148 pub fn max_num_pics(&self) -> usize {
150 self.max_num_pics
151 }
152
153 pub fn num_ref_frames(&self) -> usize {
156 self.pictures()
157 .filter(|p| p.is_ref() && !p.is_second_field())
158 .count()
159 }
160
161 pub fn interlaced(&self) -> bool {
163 self.interlaced
164 }
165
166 pub fn set_interlaced(&mut self, interlaced: bool) {
168 self.interlaced = interlaced;
169 }
170
171 pub fn find_short_term_lowest_frame_num_wrap(&self) -> Option<&DpbEntry<T>> {
174 let lowest = self
175 .entries
176 .iter()
177 .filter(|h| {
178 let p = h.pic.borrow();
179 matches!(p.reference(), Reference::ShortTerm)
180 })
181 .min_by_key(|h| {
182 let p = h.pic.borrow();
183 p.frame_num_wrap
184 });
185
186 lowest
187 }
188
189 pub fn mark_all_as_unused_for_ref(&mut self) {
191 for mut picture in self.pictures_mut() {
192 picture.set_reference(Reference::None, false);
193 }
194 }
195
196 fn remove_unused(&mut self) {
199 self.entries.retain(|entry| {
200 let pic = entry.pic.borrow();
201 let discard = !pic.is_ref() && !entry.needed_for_output;
202
203 if discard {
204 log::debug!("Removing unused picture {:#?}", pic);
205 }
206
207 !discard
208 });
209 }
210
211 fn find_short_term_with_pic_num_pos(&self, pic_num: i32) -> Option<usize> {
213 let position = self
214 .pictures()
215 .position(|p| matches!(p.reference(), Reference::ShortTerm) && p.pic_num == pic_num);
216
217 log::debug!(
218 "find_short_term_with_pic_num: {}, found position {:?}",
219 pic_num,
220 position
221 );
222
223 position
224 }
225
226 pub fn find_short_term_with_pic_num(&self, pic_num: i32) -> Option<&DpbEntry<T>> {
228 let position = self.find_short_term_with_pic_num_pos(pic_num)?;
229 Some(&self.entries[position])
230 }
231
232 fn find_long_term_with_long_term_pic_num_pos(&self, long_term_pic_num: u32) -> Option<usize> {
235 let position = self.pictures().position(|p| {
236 matches!(p.reference(), Reference::LongTerm) && p.long_term_pic_num == long_term_pic_num
237 });
238
239 log::debug!(
240 "find_long_term_with_long_term_pic_num: {}, found position {:?}",
241 long_term_pic_num,
242 position
243 );
244
245 position
246 }
247
248 pub fn find_long_term_with_long_term_pic_num(
251 &self,
252 long_term_pic_num: u32,
253 ) -> Option<&DpbEntry<T>> {
254 let position = self.find_long_term_with_long_term_pic_num_pos(long_term_pic_num)?;
255 Some(&self.entries[position])
256 }
257
258 fn store_picture(
260 &mut self,
261 picture: RcPictureData,
262 handle: Option<T>,
263 ) -> Result<(), StorePictureError> {
264 let max_pics = if self.interlaced {
265 self.max_num_pics * 2
266 } else {
267 self.max_num_pics
268 };
269
270 if self.entries.len() >= max_pics {
271 return Err(StorePictureError::DpbIsFull);
272 }
273
274 let pic = picture.borrow();
275
276 let needed_for_output = !pic.nonexisting;
279
280 debug!(
281 "Stored picture POC {:?}, field {:?}, the DPB length is {:?}",
282 pic.pic_order_cnt,
283 pic.field,
284 self.entries.len()
285 );
286 drop(pic);
287
288 self.entries.push(DpbEntry {
289 pic: picture,
290 handle,
291 needed_for_output,
292 });
293
294 Ok(())
295 }
296
297 pub fn add_picture(
299 &mut self,
300 pic: RcPictureData,
301 handle: Option<T>,
302 last_field: &mut Option<(RcPictureData, T)>,
303 ) -> Result<(), StorePictureError> {
304 if !self.interlaced() {
305 assert!(last_field.is_none());
306
307 self.store_picture(pic, handle)?;
308 } else {
309 if pic
312 .borrow()
313 .other_field()
314 .zip(last_field.as_ref().map(|f| &f.0))
315 .map_or_else(
316 || false,
317 |(other_field, last_field)| Rc::ptr_eq(&other_field, last_field),
318 )
319 {
320 if let Some((last_field, last_field_handle)) = last_field.take() {
321 self.store_picture(last_field, Some(last_field_handle))?;
322 }
323 }
324
325 self.store_picture(pic, handle)?;
326 }
327
328 Ok(())
329 }
330
331 pub fn has_empty_frame_buffer(&self) -> bool {
333 let count = if !self.interlaced {
334 self.entries.len()
335 } else {
336 self.pictures()
337 .filter(|pic| {
338 matches!(pic.field_rank(), FieldRank::First(..))
339 || (matches!(pic.field_rank(), FieldRank::Single)
340 && pic.field == Field::Frame)
341 })
342 .count()
343 };
344
345 count < self.max_num_pics
346 }
347
348 pub fn needs_bumping(&self, to_insert: &PictureData) -> bool {
351 if self.has_empty_frame_buffer() {
368 return false;
369 }
370
371 if to_insert.nonexisting {
372 return true;
373 }
374
375 let non_idr_ref = to_insert.is_ref() && matches!(to_insert.is_idr, IsIdr::No);
376 if non_idr_ref {
377 return true;
378 }
379
380 let lowest_poc = match self.find_lowest_poc_for_bumping() {
381 Some(handle) => handle.pic.borrow().pic_order_cnt,
382 None => return false,
383 };
384
385 !to_insert.is_second_field_of_complementary_ref_pair()
386 && to_insert.pic_order_cnt > lowest_poc
387 }
388
389 fn find_lowest_poc_for_bumping(&self) -> Option<&DpbEntry<T>> {
391 self.entries
392 .iter()
393 .filter(|entry| entry.is_bumpable())
394 .min_by_key(|handle| handle.pic.borrow().pic_order_cnt)
395 }
396
397 fn find_lowest_poc_for_bumping_mut(&mut self) -> Option<&mut DpbEntry<T>> {
399 self.entries
400 .iter_mut()
401 .filter(|entry| entry.is_bumpable())
402 .min_by_key(|handle| handle.pic.borrow().pic_order_cnt)
403 }
404
405 fn bump(&mut self) -> Option<Option<T>> {
408 let dpb_entry = self.find_lowest_poc_for_bumping_mut()?;
409 let handle = dpb_entry.handle.clone();
410 let pic = dpb_entry.pic.borrow();
411
412 debug!("Bumping picture {:#?} from the dpb", pic);
413
414 dpb_entry.needed_for_output = false;
415 if let FieldRank::First(second_field) = pic.field_rank() {
418 let second_field = second_field.upgrade();
419 drop(pic);
420 if let Some(second_field) =
421 second_field.and_then(|f| self.entries.iter_mut().find(|e| Rc::ptr_eq(&f, &e.pic)))
422 {
423 second_field.needed_for_output = false;
424 }
425 }
426
427 Some(handle)
428 }
429
430 pub fn drain(&mut self) -> Vec<Option<T>> {
432 debug!("Draining the DPB.");
433
434 let mut pics = vec![];
435
436 while let Some(pic) = self.bump() {
437 pics.push(pic);
438 }
439
440 self.clear();
441
442 pics
443 }
444
445 pub fn clear(&mut self) {
447 debug!("Clearing the DPB");
448
449 let max_num_pics = self.max_num_pics;
450 let interlaced = self.interlaced;
451
452 *self = Default::default();
453
454 self.max_num_pics = max_num_pics;
455 self.interlaced = interlaced;
456 }
457
458 pub fn short_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>> {
460 self.entries
461 .iter()
462 .filter(|&handle| matches!(handle.pic.borrow().reference(), Reference::ShortTerm))
463 }
464
465 pub fn long_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>> {
467 self.entries
468 .iter()
469 .filter(|&handle| matches!(handle.pic.borrow().reference(), Reference::LongTerm))
470 }
471
472 pub fn update_pic_nums(
473 &mut self,
474 frame_num: u32,
475 max_frame_num: u32,
476 current_pic: &PictureData,
477 ) {
478 for mut pic in self.pictures_mut() {
479 if !pic.is_ref() {
480 continue;
481 }
482
483 if *pic.reference() == Reference::LongTerm {
484 pic.long_term_pic_num = if current_pic.field == Field::Frame {
485 pic.long_term_frame_idx
486 } else if current_pic.field == pic.field {
487 2 * pic.long_term_frame_idx + 1
488 } else {
489 2 * pic.long_term_frame_idx
490 };
491 } else {
492 pic.frame_num_wrap = if pic.frame_num > frame_num {
493 pic.frame_num as i32 - max_frame_num as i32
494 } else {
495 pic.frame_num as i32
496 };
497
498 pic.pic_num = if current_pic.field == Field::Frame {
499 pic.frame_num_wrap
500 } else if pic.field == current_pic.field {
501 2 * pic.frame_num_wrap + 1
502 } else {
503 2 * pic.frame_num_wrap
504 };
505 }
506 }
507 }
508
509 pub fn bump_as_needed(&mut self, current_pic: &PictureData) -> Vec<Option<T>> {
511 let mut pics = vec![];
512 while self.needs_bumping(current_pic) && self.len() >= self.max_num_reorder_frames {
513 match self.bump() {
514 Some(pic) => pics.push(pic),
515 None => return pics,
516 }
517 self.remove_unused();
518 }
519
520 pics
521 }
522
523 pub fn sliding_window_marking(&mut self, pic: &mut PictureData, sps: &Sps) {
525 if let FieldRank::Second(other_field) = pic.field_rank() {
531 if matches!(other_field.borrow().reference(), Reference::ShortTerm) {
532 pic.set_reference(Reference::ShortTerm, false);
533 return;
534 }
535 }
536
537 let mut num_ref_pics = self.num_ref_frames();
538 let max_num_ref_frames = std::cmp::max(1, sps.max_num_ref_frames as usize);
539
540 if num_ref_pics < max_num_ref_frames {
541 return;
542 }
543
544 while num_ref_pics >= max_num_ref_frames {
545 if let Some(to_unmark) = self.find_short_term_lowest_frame_num_wrap() {
546 to_unmark
547 .pic
548 .borrow_mut()
549 .set_reference(Reference::None, true);
550 num_ref_pics -= 1;
551 } else {
552 log::warn!("could not find a ShortTerm picture to unmark in the DPB");
553 break;
554 }
555 }
556
557 self.remove_unused();
558 }
559
560 pub fn mmco_op_1(
561 &mut self,
562 pic: &PictureData,
563 marking: &RefPicMarkingInner,
564 ) -> Result<(), MmcoError> {
565 let pic_num_x = pic.pic_num - (marking.difference_of_pic_nums_minus1 as i32 + 1);
566
567 log::debug!("MMCO op 1 for pic_num_x {}", pic_num_x);
568 log::trace!("Dpb state before MMCO=1: {:#?}", self);
569
570 let to_mark = self
571 .find_short_term_with_pic_num(pic_num_x)
572 .ok_or(MmcoError::NoShortTermPic)?;
573
574 to_mark
575 .pic
576 .borrow_mut()
577 .set_reference(Reference::None, matches!(pic.field, Field::Frame));
578
579 Ok(())
580 }
581
582 pub fn mmco_op_2(
583 &mut self,
584 pic: &PictureData,
585 marking: &RefPicMarkingInner,
586 ) -> Result<(), MmcoError> {
587 log::debug!(
588 "MMCO op 2 for long_term_pic_num {}",
589 marking.long_term_pic_num
590 );
591
592 log::trace!("Dpb state before MMCO=2: {:#?}", self);
593
594 let to_mark = self
595 .find_long_term_with_long_term_pic_num(marking.long_term_pic_num)
596 .ok_or(MmcoError::NoShortTermPic)?;
597
598 to_mark
599 .pic
600 .borrow_mut()
601 .set_reference(Reference::None, matches!(pic.field, Field::Frame));
602
603 Ok(())
604 }
605
606 pub fn mmco_op_3(
607 &mut self,
608 pic: &PictureData,
609 marking: &RefPicMarkingInner,
610 ) -> Result<(), MmcoError> {
611 let pic_num_x = pic.pic_num - (marking.difference_of_pic_nums_minus1 as i32 + 1);
612
613 log::debug!("MMCO op 3 for pic_num_x {}", pic_num_x);
614 log::trace!("Dpb state before MMCO=3: {:#?}", self);
615
616 let to_mark_as_long_pos = self
617 .find_short_term_with_pic_num_pos(pic_num_x)
618 .ok_or(MmcoError::NoShortTermPic)?;
619 let to_mark_as_long = &self.entries[to_mark_as_long_pos].pic;
620
621 if !matches!(to_mark_as_long.borrow().reference(), Reference::ShortTerm) {
622 return Err(MmcoError::ExpectedMarked);
623 }
624
625 if to_mark_as_long.borrow().nonexisting {
626 return Err(MmcoError::ExpectedExisting);
627 }
628
629 let to_mark_as_long_ptr = to_mark_as_long.as_ptr();
630 let to_mark_as_long_other_field_ptr =
631 to_mark_as_long.borrow().other_field().map(|f| f.as_ptr());
632
633 let long_term_frame_idx = marking.long_term_frame_idx;
634
635 for mut picture in self.pictures_mut() {
636 let long_already_assigned = matches!(picture.reference(), Reference::LongTerm)
637 && picture.long_term_frame_idx == long_term_frame_idx;
638
639 if long_already_assigned {
640 let is_frame = matches!(picture.field, Field::Frame);
641
642 let is_complementary_field_pair = picture
643 .other_field()
644 .map(|f| {
645 let pic = f.borrow();
646 matches!(pic.reference(), Reference::LongTerm)
647 && pic.long_term_frame_idx == long_term_frame_idx
648 })
649 .unwrap_or(false);
650
651 if is_frame || is_complementary_field_pair {
658 picture.set_reference(Reference::None, true);
659 break;
660 }
661
662 let reference_field_is_not_part_of_pic_x = match picture.other_field() {
668 None => true,
669 Some(other_field) => {
670 !std::ptr::eq(other_field.as_ptr(), to_mark_as_long_ptr)
672 && to_mark_as_long_other_field_ptr
673 .map(|p| !std::ptr::eq(p, &(*picture)))
674 .unwrap_or(true)
675 }
676 };
677
678 if reference_field_is_not_part_of_pic_x {
679 picture.set_reference(Reference::None, false);
680 break;
681 }
682 }
683 }
684
685 let is_frame = matches!(pic.field, Field::Frame);
686 let to_mark_as_long = &self.entries[to_mark_as_long_pos].pic;
687 to_mark_as_long
688 .borrow_mut()
689 .set_reference(Reference::LongTerm, is_frame);
690 to_mark_as_long.borrow_mut().long_term_frame_idx = long_term_frame_idx;
691
692 if let Some(other_field) = to_mark_as_long.borrow().other_field() {
693 let mut other_field = other_field.borrow_mut();
694 if matches!(other_field.reference(), Reference::LongTerm) {
695 other_field.long_term_frame_idx = long_term_frame_idx;
696
697 log::debug!(
698 "Assigned long_term_frame_idx {} to other_field {:#?}",
699 long_term_frame_idx,
700 &other_field
701 );
702 }
703 }
704
705 Ok(())
706 }
707
708 pub fn mmco_op_4(&mut self, marking: &RefPicMarkingInner) -> MaxLongTermFrameIdx {
710 log::debug!(
711 "MMCO op 4, max_long_term_frame_idx: {:?}",
712 marking.max_long_term_frame_idx
713 );
714
715 log::trace!("Dpb state before MMCO=4: {:#?}", self);
716
717 for mut dpb_pic in self
718 .pictures_mut()
719 .filter(|pic| matches!(pic.reference(), Reference::LongTerm))
720 .filter(|pic| marking.max_long_term_frame_idx < pic.long_term_frame_idx)
721 {
722 dpb_pic.set_reference(Reference::None, false);
723 }
724
725 marking.max_long_term_frame_idx
726 }
727
728 pub fn mmco_op_5(&mut self, pic: &mut PictureData) -> MaxLongTermFrameIdx {
730 log::debug!("MMCO op 5, marking all pictures in the DPB as unused for reference");
731 log::trace!("Dpb state before MMCO=5: {:#?}", self);
732
733 self.mark_all_as_unused_for_ref();
734
735 pic.has_mmco_5 = true;
736
737 pic.frame_num = 0;
744
745 match pic.field {
753 Field::Top => {
754 pic.top_field_order_cnt = 0;
755 pic.pic_order_cnt = 0;
756 }
757 Field::Bottom => {
758 pic.bottom_field_order_cnt = 0;
759 pic.pic_order_cnt = 0;
760 }
761 Field::Frame => {
762 pic.top_field_order_cnt -= pic.pic_order_cnt;
763 pic.bottom_field_order_cnt -= pic.pic_order_cnt;
764 pic.pic_order_cnt =
765 std::cmp::min(pic.top_field_order_cnt, pic.bottom_field_order_cnt);
766 }
767 }
768
769 MaxLongTermFrameIdx::NoLongTermFrameIndices
770 }
771
772 pub fn mmco_op_6(&mut self, pic: &mut PictureData, marking: &RefPicMarkingInner) {
773 let long_term_frame_idx = marking.long_term_frame_idx;
774
775 log::debug!("MMCO op 6, long_term_frame_idx: {}", long_term_frame_idx);
776 log::trace!("Dpb state before MMCO=6: {:#?}", self);
777
778 for mut dpb_pic in self.pictures_mut() {
779 if matches!(dpb_pic.reference(), Reference::LongTerm)
788 && dpb_pic.long_term_frame_idx == long_term_frame_idx
789 {
790 let is_frame = matches!(dpb_pic.field, Field::Frame);
791
792 let is_complementary_ref_field_pair = dpb_pic
793 .other_field()
794 .map(|f| {
795 let pic = f.borrow();
796 matches!(pic.reference(), Reference::LongTerm)
797 && pic.long_term_frame_idx == long_term_frame_idx
798 })
799 .unwrap_or(false);
800
801 dpb_pic.set_reference(Reference::None, is_frame || is_complementary_ref_field_pair);
802
803 break;
804 }
805 }
806
807 let is_frame = matches!(pic.field, Field::Frame);
808
809 let is_second_ref_field = match pic.field_rank() {
810 FieldRank::Second(first_field)
811 if *first_field.borrow().reference() == Reference::LongTerm =>
812 {
813 first_field.borrow_mut().long_term_frame_idx = long_term_frame_idx;
814 true
815 }
816 _ => false,
817 };
818
819 pic.set_reference(Reference::LongTerm, is_frame || is_second_ref_field);
820 pic.long_term_frame_idx = long_term_frame_idx;
821 }
822
823 #[cfg(debug_assertions)]
824 fn debug_ref_list_p(ref_pic_list: &[&DpbEntry<T>], field_pic: bool) {
825 debug!(
826 "ref_list_p0: (ShortTerm|LongTerm, pic_num) {:?}",
827 ref_pic_list
828 .iter()
829 .map(|h| {
830 let p = h.pic.borrow();
831 let reference = match p.reference() {
832 Reference::None => panic!("Not a reference."),
833 Reference::ShortTerm => "ShortTerm",
834 Reference::LongTerm => "LongTerm",
835 };
836
837 let field = if !p.is_second_field() {
838 "First field"
839 } else {
840 "Second field"
841 };
842
843 let field = format!("{}, {:?}", field, p.field);
844
845 let inner = match (field_pic, p.reference()) {
846 (false, _) => ("pic_num", p.pic_num, field),
847 (true, Reference::ShortTerm) => ("frame_num_wrap", p.frame_num_wrap, field),
848 (true, Reference::LongTerm) => {
849 ("long_term_frame_idx", p.long_term_frame_idx as i32, field)
850 }
851
852 _ => panic!("Not a reference."),
853 };
854 (reference, inner)
855 })
856 .collect::<Vec<_>>()
857 );
858 }
859
860 #[cfg(debug_assertions)]
861 fn debug_ref_list_b(ref_pic_list: &[&DpbEntry<T>], ref_pic_list_name: &str) {
862 debug!(
863 "{:?}: (ShortTerm|LongTerm, (POC|LongTermPicNum)) {:?}",
864 ref_pic_list_name,
865 ref_pic_list
866 .iter()
867 .map(|h| {
868 let p = h.pic.borrow();
869 let reference = match p.reference() {
870 Reference::None => panic!("Not a reference."),
871 Reference::ShortTerm => "ShortTerm",
872 Reference::LongTerm => "LongTerm",
873 };
874
875 let field = if !p.is_second_field() {
876 "First field"
877 } else {
878 "Second field"
879 };
880
881 let field = format!("{}, {:?}", field, p.field);
882
883 let inner = match p.reference() {
884 Reference::ShortTerm => ("POC", p.pic_order_cnt, field),
885 Reference::LongTerm => {
886 ("LongTermPicNum", p.long_term_pic_num as i32, field)
887 }
888 _ => panic!("Not a reference!"),
889 };
890 (reference, inner)
891 })
892 .collect::<Vec<_>>()
893 );
894 }
895
896 fn sort_pic_num_descending(pics: &mut [&DpbEntry<T>]) {
897 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().pic_num));
898 }
899
900 fn sort_frame_num_wrap_descending(pics: &mut [&DpbEntry<T>]) {
901 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().frame_num_wrap));
902 }
903
904 fn sort_long_term_pic_num_ascending(pics: &mut [&DpbEntry<T>]) {
905 pics.sort_by_key(|h| h.pic.borrow().long_term_pic_num);
906 }
907
908 fn sort_long_term_frame_idx_ascending(pics: &mut [&DpbEntry<T>]) {
909 pics.sort_by_key(|h| h.pic.borrow().long_term_frame_idx);
910 }
911
912 fn sort_poc_descending(pics: &mut [&DpbEntry<T>]) {
913 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().pic_order_cnt));
914 }
915
916 fn sort_poc_ascending(pics: &mut [&DpbEntry<T>]) {
917 pics.sort_by_key(|h| h.pic.borrow().pic_order_cnt);
918 }
919
920 fn swap_b1_if_needed(b0: &DpbPicRefList<T>, b1: &mut DpbPicRefList<T>) {
925 if b1.len() > 1 && b0.len() == b1.len() {
926 let mut equals = true;
927 for (x1, x2) in b0.iter().zip(b1.iter()) {
928 if !Rc::ptr_eq(&x1.pic, &x2.pic) {
929 equals = false;
930 break;
931 }
932 }
933
934 if equals {
935 b1.swap(0, 1);
936 }
937 }
938 }
939
940 fn init_ref_field_pic_list<'a>(
943 mut field: Field,
944 reference_type: Reference,
945 ref_frame_list: &mut DpbPicRefList<'a, T>,
946 ref_pic_list: &mut DpbPicRefList<'a, T>,
947 ) {
948 ref_frame_list.retain(|h| {
953 let p = h.pic.borrow();
954 let skip = p.nonexisting || *p.reference() != reference_type;
955 !skip
956 });
957
958 while let Some(position) = ref_frame_list.iter().position(|h| {
959 let p = h.pic.borrow();
960 let found = p.field == field;
961
962 if found {
963 field = field.opposite();
964 }
965
966 found
967 }) {
968 let pic = ref_frame_list.remove(position);
969 ref_pic_list.push(pic);
970 }
971
972 ref_pic_list.append(ref_frame_list);
973 }
974
975 fn build_ref_pic_list_p(&self) -> DpbPicRefList<T> {
978 let mut ref_pic_list_p0: Vec<_> = self
979 .short_term_refs_iter()
980 .filter(|h| !h.pic.borrow().is_second_field())
981 .collect();
982
983 Self::sort_pic_num_descending(&mut ref_pic_list_p0);
984
985 let num_short_term_refs = ref_pic_list_p0.len();
986
987 ref_pic_list_p0.extend(
988 self.long_term_refs_iter()
989 .filter(|h| !h.pic.borrow().is_second_field()),
990 );
991 Self::sort_long_term_pic_num_ascending(&mut ref_pic_list_p0[num_short_term_refs..]);
992
993 #[cfg(debug_assertions)]
994 Self::debug_ref_list_p(&ref_pic_list_p0, false);
995
996 ref_pic_list_p0
997 }
998
999 fn build_ref_field_pic_list_p(&self, cur_pic: &PictureData) -> DpbPicRefList<T> {
1002 let mut ref_pic_list_p0 = vec![];
1003
1004 let mut ref_frame_list_0_short_term: Vec<_> = self.short_term_refs_iter().collect();
1005 Self::sort_frame_num_wrap_descending(&mut ref_frame_list_0_short_term);
1006
1007 let mut ref_frame_list_long_term: Vec<_> = self.long_term_refs_iter().collect();
1008 Self::sort_long_term_pic_num_ascending(&mut ref_frame_list_long_term);
1009
1010 Self::init_ref_field_pic_list(
1012 cur_pic.field,
1013 Reference::ShortTerm,
1014 &mut ref_frame_list_0_short_term,
1015 &mut ref_pic_list_p0,
1016 );
1017 Self::init_ref_field_pic_list(
1018 cur_pic.field,
1019 Reference::LongTerm,
1020 &mut ref_frame_list_long_term,
1021 &mut ref_pic_list_p0,
1022 );
1023
1024 #[cfg(debug_assertions)]
1025 Self::debug_ref_list_p(&ref_pic_list_p0, true);
1026
1027 ref_pic_list_p0
1028 }
1029
1030 fn build_ref_pic_list_b(&self, cur_pic: &PictureData) -> (DpbPicRefList<T>, DpbPicRefList<T>) {
1033 let mut short_term_refs: Vec<_> = self
1034 .short_term_refs_iter()
1035 .filter(|h| !h.pic.borrow().is_second_field())
1036 .collect();
1037
1038 if cur_pic.pic_order_cnt_type == 0 {
1042 short_term_refs.retain(|h| !h.pic.borrow().nonexisting);
1043 }
1044
1045 let mut ref_pic_list_b0 = vec![];
1046 let mut ref_pic_list_b1 = vec![];
1047 let mut remaining = vec![];
1048 for &handle in &short_term_refs {
1053 let pic = handle.pic.borrow();
1054
1055 if pic.pic_order_cnt < cur_pic.pic_order_cnt {
1056 ref_pic_list_b0.push(handle);
1057 } else {
1058 remaining.push(handle);
1059 }
1060 }
1061
1062 Self::sort_poc_descending(&mut ref_pic_list_b0);
1063 Self::sort_poc_ascending(&mut remaining);
1064 ref_pic_list_b0.append(&mut remaining);
1065
1066 let mut long_term_refs: Vec<_> = self
1067 .long_term_refs_iter()
1068 .filter(|h| !h.pic.borrow().nonexisting)
1069 .filter(|h| !h.pic.borrow().is_second_field())
1070 .collect();
1071 Self::sort_long_term_pic_num_ascending(&mut long_term_refs);
1072
1073 ref_pic_list_b0.extend(long_term_refs.clone());
1074
1075 for &handle in &short_term_refs {
1080 let pic = handle.pic.borrow();
1081
1082 if pic.pic_order_cnt > cur_pic.pic_order_cnt {
1083 ref_pic_list_b1.push(handle);
1084 } else {
1085 remaining.push(handle);
1086 }
1087 }
1088
1089 Self::sort_poc_ascending(&mut ref_pic_list_b1);
1090 Self::sort_poc_descending(&mut remaining);
1091
1092 ref_pic_list_b1.extend(remaining);
1093 ref_pic_list_b1.extend(long_term_refs);
1094
1095 Self::swap_b1_if_needed(&ref_pic_list_b0, &mut ref_pic_list_b1);
1100
1101 #[cfg(debug_assertions)]
1102 Self::debug_ref_list_b(&ref_pic_list_b0, "ref_pic_list_b0");
1103 #[cfg(debug_assertions)]
1104 Self::debug_ref_list_b(&ref_pic_list_b1, "ref_pic_list_b1");
1105
1106 (ref_pic_list_b0, ref_pic_list_b1)
1107 }
1108
1109 fn build_ref_field_pic_list_b(
1112 &self,
1113 cur_pic: &PictureData,
1114 ) -> (DpbPicRefList<T>, DpbPicRefList<T>) {
1115 let mut ref_pic_list_b0 = vec![];
1116 let mut ref_pic_list_b1 = vec![];
1117 let mut ref_frame_list_0_short_term = vec![];
1118 let mut ref_frame_list_1_short_term = vec![];
1119
1120 let mut remaining = vec![];
1121
1122 let mut short_term_refs: Vec<_> = self.short_term_refs_iter().collect();
1123
1124 if cur_pic.pic_order_cnt_type == 0 {
1128 short_term_refs.retain(|h| !h.pic.borrow().nonexisting);
1129 }
1130
1131 for &handle in &short_term_refs {
1140 let pic = handle.pic.borrow();
1141
1142 if pic.pic_order_cnt <= cur_pic.pic_order_cnt {
1143 ref_frame_list_0_short_term.push(handle);
1144 } else {
1145 remaining.push(handle);
1146 }
1147 }
1148
1149 Self::sort_poc_descending(&mut ref_frame_list_0_short_term);
1150 Self::sort_poc_ascending(&mut remaining);
1151 ref_frame_list_0_short_term.append(&mut remaining);
1152
1153 for &handle in &short_term_refs {
1163 let pic = handle.pic.borrow();
1164
1165 if pic.pic_order_cnt > cur_pic.pic_order_cnt {
1166 ref_frame_list_1_short_term.push(handle);
1167 } else {
1168 remaining.push(handle);
1169 }
1170 }
1171
1172 Self::sort_poc_ascending(&mut ref_frame_list_1_short_term);
1173 Self::sort_poc_descending(&mut remaining);
1174 ref_frame_list_1_short_term.append(&mut remaining);
1175
1176 let mut ref_frame_list_long_term: Vec<_> = self
1185 .long_term_refs_iter()
1186 .filter(|h| !h.pic.borrow().nonexisting)
1187 .collect();
1188
1189 Self::sort_long_term_frame_idx_ascending(&mut ref_frame_list_long_term);
1190
1191 #[cfg(debug_assertions)]
1192 Self::debug_ref_list_b(&ref_frame_list_0_short_term, "ref_frame_list_0_short_term");
1193 #[cfg(debug_assertions)]
1194 Self::debug_ref_list_b(&ref_frame_list_1_short_term, "ref_frame_list_1_short_term");
1195 #[cfg(debug_assertions)]
1196 Self::debug_ref_list_b(&ref_frame_list_long_term, "ref_frame_list_long_term");
1197
1198 let field = cur_pic.field;
1200 Self::init_ref_field_pic_list(
1201 field,
1202 Reference::ShortTerm,
1203 &mut ref_frame_list_0_short_term,
1204 &mut ref_pic_list_b0,
1205 );
1206 Self::init_ref_field_pic_list(
1207 field,
1208 Reference::LongTerm,
1209 &mut ref_frame_list_long_term,
1210 &mut ref_pic_list_b0,
1211 );
1212
1213 Self::init_ref_field_pic_list(
1214 field,
1215 Reference::ShortTerm,
1216 &mut ref_frame_list_1_short_term,
1217 &mut ref_pic_list_b1,
1218 );
1219 Self::init_ref_field_pic_list(
1220 field,
1221 Reference::LongTerm,
1222 &mut ref_frame_list_long_term,
1223 &mut ref_pic_list_b1,
1224 );
1225
1226 Self::swap_b1_if_needed(&ref_pic_list_b0, &mut ref_pic_list_b1);
1231
1232 #[cfg(debug_assertions)]
1233 Self::debug_ref_list_b(&ref_pic_list_b0, "ref_pic_list_b0");
1234 #[cfg(debug_assertions)]
1235 Self::debug_ref_list_b(&ref_pic_list_b1, "ref_pic_list_b1");
1236
1237 (ref_pic_list_b0, ref_pic_list_b1)
1238 }
1239
1240 pub fn build_ref_pic_lists(&self, pic: &PictureData) -> ReferencePicLists {
1242 let num_refs = self
1243 .pictures()
1244 .filter(|p| p.is_ref() && !p.nonexisting)
1245 .count();
1246
1247 if num_refs == 0 {
1253 return Default::default();
1254 }
1255
1256 let (ref_pic_list_p0, (ref_pic_list_b0, ref_pic_list_b1)) =
1257 if matches!(pic.field, Field::Frame) {
1258 (self.build_ref_pic_list_p(), self.build_ref_pic_list_b(pic))
1259 } else {
1260 (
1261 self.build_ref_field_pic_list_p(pic),
1262 self.build_ref_field_pic_list_b(pic),
1263 )
1264 };
1265
1266 let dpb_start = self.entries.as_ptr();
1267 let refs_to_index = |refs: Vec<_>| {
1268 refs.into_iter()
1269 .map(|r| r as *const DpbEntry<T>)
1270 .map(|r| unsafe { r.offset_from(dpb_start) })
1271 .map(|i| i as usize)
1272 .collect()
1273 };
1274
1275 ReferencePicLists {
1276 ref_pic_list_p0: refs_to_index(ref_pic_list_p0),
1277 ref_pic_list_b0: refs_to_index(ref_pic_list_b0),
1278 ref_pic_list_b1: refs_to_index(ref_pic_list_b1),
1279 }
1280 }
1281}
1282
1283impl<T> Default for Dpb<T> {
1284 fn default() -> Self {
1285 Self {
1288 entries: Default::default(),
1289 max_num_pics: Default::default(),
1290 max_num_reorder_frames: Default::default(),
1291 interlaced: Default::default(),
1292 }
1293 }
1294}
1295
1296impl<T> std::fmt::Debug for Dpb<T> {
1297 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1298 let pics = self
1299 .entries
1300 .iter()
1301 .map(|h| &h.pic)
1302 .enumerate()
1303 .collect::<Vec<_>>();
1304 f.debug_struct("Dpb")
1305 .field("pictures", &pics)
1306 .field("max_num_pics", &self.max_num_pics)
1307 .field("interlaced", &self.interlaced)
1308 .finish()
1309 }
1310}