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!("find_short_term_with_pic_num: {}, found position {:?}", pic_num, position);
238
239 position
240 }
241
242 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 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 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 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 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 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 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()
365 && to_insert.pic_order_cnt > lowest_poc
366 }
367
368 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 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 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 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 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 pub fn clear(&mut self) {
426 debug!("Clearing the DPB");
427
428 let max_num_pics = self.max_num_pics;
429 let interlaced = self.interlaced;
430
431 *self = Default::default();
432
433 self.max_num_pics = max_num_pics;
434 self.interlaced = interlaced;
435 }
436
437 pub fn short_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>> {
439 self.entries
440 .iter()
441 .filter(|&handle| matches!(handle.pic.borrow().reference(), Reference::ShortTerm))
442 }
443
444 pub fn long_term_refs_iter(&self) -> impl Iterator<Item = &DpbEntry<T>> {
446 self.entries
447 .iter()
448 .filter(|&handle| matches!(handle.pic.borrow().reference(), Reference::LongTerm))
449 }
450
451 pub fn update_pic_nums(
452 &mut self,
453 frame_num: u32,
454 max_frame_num: u32,
455 current_pic: &PictureData,
456 ) {
457 for mut pic in self.pictures_mut() {
458 if !pic.is_ref() {
459 continue;
460 }
461
462 if *pic.reference() == Reference::LongTerm {
463 pic.long_term_pic_num = if current_pic.field == Field::Frame {
464 pic.long_term_frame_idx
465 } else if current_pic.field == pic.field {
466 2 * pic.long_term_frame_idx + 1
467 } else {
468 2 * pic.long_term_frame_idx
469 };
470 } else {
471 pic.frame_num_wrap = if pic.frame_num > frame_num {
472 pic.frame_num as i32 - max_frame_num as i32
473 } else {
474 pic.frame_num as i32
475 };
476
477 pic.pic_num = if current_pic.field == Field::Frame {
478 pic.frame_num_wrap
479 } else if pic.field == current_pic.field {
480 2 * pic.frame_num_wrap + 1
481 } else {
482 2 * pic.frame_num_wrap
483 };
484 }
485 }
486 }
487
488 pub fn bump_as_needed(&mut self, current_pic: &PictureData) -> Vec<Option<T>> {
490 let mut pics = vec![];
491 while self.needs_bumping(current_pic) && self.len() >= self.max_num_reorder_frames {
492 match self.bump() {
493 Some(pic) => pics.push(pic),
494 None => return pics,
495 }
496 self.remove_unused();
497 }
498
499 pics
500 }
501
502 pub fn sliding_window_marking(&mut self, pic: &mut PictureData, sps: &Sps) {
504 if let FieldRank::Second(other_field) = pic.field_rank() {
510 if matches!(other_field.borrow().reference(), Reference::ShortTerm) {
511 pic.set_reference(Reference::ShortTerm, false);
512 return;
513 }
514 }
515
516 let mut num_ref_pics = self.num_ref_frames();
517 let max_num_ref_frames = std::cmp::max(1, sps.max_num_ref_frames as usize);
518
519 if num_ref_pics < max_num_ref_frames {
520 return;
521 }
522
523 while num_ref_pics >= max_num_ref_frames {
524 if let Some(to_unmark) = self.find_short_term_lowest_frame_num_wrap() {
525 to_unmark.pic.borrow_mut().set_reference(Reference::None, true);
526 num_ref_pics -= 1;
527 } else {
528 log::warn!("could not find a ShortTerm picture to unmark in the DPB");
529 break;
530 }
531 }
532
533 self.remove_unused();
534 }
535
536 pub fn mmco_op_1(
537 &mut self,
538 pic: &PictureData,
539 marking: &RefPicMarkingInner,
540 ) -> Result<(), MmcoError> {
541 let pic_num_x = pic.pic_num - (marking.difference_of_pic_nums_minus1 as i32 + 1);
542
543 log::debug!("MMCO op 1 for pic_num_x {}", pic_num_x);
544 log::trace!("Dpb state before MMCO=1: {:#?}", self);
545
546 let to_mark =
547 self.find_short_term_with_pic_num(pic_num_x).ok_or(MmcoError::NoShortTermPic)?;
548
549 to_mark.pic.borrow_mut().set_reference(Reference::None, matches!(pic.field, Field::Frame));
550
551 Ok(())
552 }
553
554 pub fn mmco_op_2(
555 &mut self,
556 pic: &PictureData,
557 marking: &RefPicMarkingInner,
558 ) -> Result<(), MmcoError> {
559 log::debug!("MMCO op 2 for long_term_pic_num {}", marking.long_term_pic_num);
560
561 log::trace!("Dpb state before MMCO=2: {:#?}", self);
562
563 let to_mark = self
564 .find_long_term_with_long_term_pic_num(marking.long_term_pic_num)
565 .ok_or(MmcoError::NoShortTermPic)?;
566
567 to_mark.pic.borrow_mut().set_reference(Reference::None, matches!(pic.field, Field::Frame));
568
569 Ok(())
570 }
571
572 pub fn mmco_op_3(
573 &mut self,
574 pic: &PictureData,
575 marking: &RefPicMarkingInner,
576 ) -> Result<(), MmcoError> {
577 let pic_num_x = pic.pic_num - (marking.difference_of_pic_nums_minus1 as i32 + 1);
578
579 log::debug!("MMCO op 3 for pic_num_x {}", pic_num_x);
580 log::trace!("Dpb state before MMCO=3: {:#?}", self);
581
582 let to_mark_as_long_pos =
583 self.find_short_term_with_pic_num_pos(pic_num_x).ok_or(MmcoError::NoShortTermPic)?;
584 let to_mark_as_long = &self.entries[to_mark_as_long_pos].pic;
585
586 if !matches!(to_mark_as_long.borrow().reference(), Reference::ShortTerm) {
587 return Err(MmcoError::ExpectedMarked);
588 }
589
590 if to_mark_as_long.borrow().nonexisting {
591 return Err(MmcoError::ExpectedExisting);
592 }
593
594 let to_mark_as_long_ptr = to_mark_as_long.as_ptr();
595 let to_mark_as_long_other_field_ptr =
596 to_mark_as_long.borrow().other_field().map(|f| f.as_ptr());
597
598 let long_term_frame_idx = marking.long_term_frame_idx;
599
600 for mut picture in self.pictures_mut() {
601 let long_already_assigned = matches!(picture.reference(), Reference::LongTerm)
602 && picture.long_term_frame_idx == long_term_frame_idx;
603
604 if long_already_assigned {
605 let is_frame = matches!(picture.field, Field::Frame);
606
607 let is_complementary_field_pair = picture
608 .other_field()
609 .map(|f| {
610 let pic = f.borrow();
611 matches!(pic.reference(), Reference::LongTerm)
612 && pic.long_term_frame_idx == long_term_frame_idx
613 })
614 .unwrap_or(false);
615
616 if is_frame || is_complementary_field_pair {
623 picture.set_reference(Reference::None, true);
624 break;
625 }
626
627 let reference_field_is_not_part_of_pic_x = match picture.other_field() {
633 None => true,
634 Some(other_field) => {
635 !std::ptr::eq(other_field.as_ptr(), to_mark_as_long_ptr)
637 && to_mark_as_long_other_field_ptr
638 .map(|p| !std::ptr::eq(p, &(*picture)))
639 .unwrap_or(true)
640 }
641 };
642
643 if reference_field_is_not_part_of_pic_x {
644 picture.set_reference(Reference::None, false);
645 break;
646 }
647 }
648 }
649
650 let is_frame = matches!(pic.field, Field::Frame);
651 let to_mark_as_long = &self.entries[to_mark_as_long_pos].pic;
652 to_mark_as_long.borrow_mut().set_reference(Reference::LongTerm, is_frame);
653 to_mark_as_long.borrow_mut().long_term_frame_idx = long_term_frame_idx;
654
655 if let Some(other_field) = to_mark_as_long.borrow().other_field() {
656 let mut other_field = other_field.borrow_mut();
657 if matches!(other_field.reference(), Reference::LongTerm) {
658 other_field.long_term_frame_idx = long_term_frame_idx;
659
660 log::debug!(
661 "Assigned long_term_frame_idx {} to other_field {:#?}",
662 long_term_frame_idx,
663 &other_field
664 );
665 }
666 }
667
668 Ok(())
669 }
670
671 pub fn mmco_op_4(&mut self, marking: &RefPicMarkingInner) -> MaxLongTermFrameIdx {
673 log::debug!("MMCO op 4, max_long_term_frame_idx: {:?}", marking.max_long_term_frame_idx);
674
675 log::trace!("Dpb state before MMCO=4: {:#?}", self);
676
677 for mut dpb_pic in self
678 .pictures_mut()
679 .filter(|pic| matches!(pic.reference(), Reference::LongTerm))
680 .filter(|pic| marking.max_long_term_frame_idx < pic.long_term_frame_idx)
681 {
682 dpb_pic.set_reference(Reference::None, false);
683 }
684
685 marking.max_long_term_frame_idx
686 }
687
688 pub fn mmco_op_5(&mut self, pic: &mut PictureData) -> MaxLongTermFrameIdx {
690 log::debug!("MMCO op 5, marking all pictures in the DPB as unused for reference");
691 log::trace!("Dpb state before MMCO=5: {:#?}", self);
692
693 self.mark_all_as_unused_for_ref();
694
695 pic.has_mmco_5 = true;
696
697 pic.frame_num = 0;
704
705 match pic.field {
713 Field::Top => {
714 pic.top_field_order_cnt = 0;
715 pic.pic_order_cnt = 0;
716 }
717 Field::Bottom => {
718 pic.bottom_field_order_cnt = 0;
719 pic.pic_order_cnt = 0;
720 }
721 Field::Frame => {
722 pic.top_field_order_cnt -= pic.pic_order_cnt;
723 pic.bottom_field_order_cnt -= pic.pic_order_cnt;
724 pic.pic_order_cnt =
725 std::cmp::min(pic.top_field_order_cnt, pic.bottom_field_order_cnt);
726 }
727 }
728
729 MaxLongTermFrameIdx::NoLongTermFrameIndices
730 }
731
732 pub fn mmco_op_6(&mut self, pic: &mut PictureData, marking: &RefPicMarkingInner) {
733 let long_term_frame_idx = marking.long_term_frame_idx;
734
735 log::debug!("MMCO op 6, long_term_frame_idx: {}", long_term_frame_idx);
736 log::trace!("Dpb state before MMCO=6: {:#?}", self);
737
738 for mut dpb_pic in self.pictures_mut() {
739 if matches!(dpb_pic.reference(), Reference::LongTerm)
748 && dpb_pic.long_term_frame_idx == long_term_frame_idx
749 {
750 let is_frame = matches!(dpb_pic.field, Field::Frame);
751
752 let is_complementary_ref_field_pair = dpb_pic
753 .other_field()
754 .map(|f| {
755 let pic = f.borrow();
756 matches!(pic.reference(), Reference::LongTerm)
757 && pic.long_term_frame_idx == long_term_frame_idx
758 })
759 .unwrap_or(false);
760
761 dpb_pic.set_reference(Reference::None, is_frame || is_complementary_ref_field_pair);
762
763 break;
764 }
765 }
766
767 let is_frame = matches!(pic.field, Field::Frame);
768
769 let is_second_ref_field = match pic.field_rank() {
770 FieldRank::Second(first_field)
771 if *first_field.borrow().reference() == Reference::LongTerm =>
772 {
773 first_field.borrow_mut().long_term_frame_idx = long_term_frame_idx;
774 true
775 }
776 _ => false,
777 };
778
779 pic.set_reference(Reference::LongTerm, is_frame || is_second_ref_field);
780 pic.long_term_frame_idx = long_term_frame_idx;
781 }
782
783 #[cfg(debug_assertions)]
784 fn debug_ref_list_p(ref_pic_list: &[&DpbEntry<T>], field_pic: bool) {
785 debug!(
786 "ref_list_p0: (ShortTerm|LongTerm, pic_num) {:?}",
787 ref_pic_list
788 .iter()
789 .map(|h| {
790 let p = h.pic.borrow();
791 let reference = match p.reference() {
792 Reference::None => panic!("Not a reference."),
793 Reference::ShortTerm => "ShortTerm",
794 Reference::LongTerm => "LongTerm",
795 };
796
797 let field = if !p.is_second_field() { "First field" } else { "Second field" };
798
799 let field = format!("{}, {:?}", field, p.field);
800
801 let inner = match (field_pic, p.reference()) {
802 (false, _) => ("pic_num", p.pic_num, field),
803 (true, Reference::ShortTerm) => ("frame_num_wrap", p.frame_num_wrap, field),
804 (true, Reference::LongTerm) => {
805 ("long_term_frame_idx", p.long_term_frame_idx as i32, field)
806 }
807
808 _ => panic!("Not a reference."),
809 };
810 (reference, inner)
811 })
812 .collect::<Vec<_>>()
813 );
814 }
815
816 #[cfg(debug_assertions)]
817 fn debug_ref_list_b(ref_pic_list: &[&DpbEntry<T>], ref_pic_list_name: &str) {
818 debug!(
819 "{:?}: (ShortTerm|LongTerm, (POC|LongTermPicNum)) {:?}",
820 ref_pic_list_name,
821 ref_pic_list
822 .iter()
823 .map(|h| {
824 let p = h.pic.borrow();
825 let reference = match p.reference() {
826 Reference::None => panic!("Not a reference."),
827 Reference::ShortTerm => "ShortTerm",
828 Reference::LongTerm => "LongTerm",
829 };
830
831 let field = if !p.is_second_field() { "First field" } else { "Second field" };
832
833 let field = format!("{}, {:?}", field, p.field);
834
835 let inner = match p.reference() {
836 Reference::ShortTerm => ("POC", p.pic_order_cnt, field),
837 Reference::LongTerm => {
838 ("LongTermPicNum", p.long_term_pic_num as i32, field)
839 }
840 _ => panic!("Not a reference!"),
841 };
842 (reference, inner)
843 })
844 .collect::<Vec<_>>()
845 );
846 }
847
848 fn sort_pic_num_descending(pics: &mut [&DpbEntry<T>]) {
849 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().pic_num));
850 }
851
852 fn sort_frame_num_wrap_descending(pics: &mut [&DpbEntry<T>]) {
853 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().frame_num_wrap));
854 }
855
856 fn sort_long_term_pic_num_ascending(pics: &mut [&DpbEntry<T>]) {
857 pics.sort_by_key(|h| h.pic.borrow().long_term_pic_num);
858 }
859
860 fn sort_long_term_frame_idx_ascending(pics: &mut [&DpbEntry<T>]) {
861 pics.sort_by_key(|h| h.pic.borrow().long_term_frame_idx);
862 }
863
864 fn sort_poc_descending(pics: &mut [&DpbEntry<T>]) {
865 pics.sort_by_key(|h| std::cmp::Reverse(h.pic.borrow().pic_order_cnt));
866 }
867
868 fn sort_poc_ascending(pics: &mut [&DpbEntry<T>]) {
869 pics.sort_by_key(|h| h.pic.borrow().pic_order_cnt);
870 }
871
872 fn swap_b1_if_needed(b0: &DpbPicRefList<T>, b1: &mut DpbPicRefList<T>) {
877 if b1.len() > 1 && b0.len() == b1.len() {
878 let mut equals = true;
879 for (x1, x2) in b0.iter().zip(b1.iter()) {
880 if !Rc::ptr_eq(&x1.pic, &x2.pic) {
881 equals = false;
882 break;
883 }
884 }
885
886 if equals {
887 b1.swap(0, 1);
888 }
889 }
890 }
891
892 fn init_ref_field_pic_list<'a>(
895 mut field: Field,
896 reference_type: Reference,
897 ref_frame_list: &mut DpbPicRefList<'a, T>,
898 ref_pic_list: &mut DpbPicRefList<'a, T>,
899 ) {
900 ref_frame_list.retain(|h| {
905 let p = h.pic.borrow();
906 let skip = p.nonexisting || *p.reference() != reference_type;
907 !skip
908 });
909
910 while let Some(position) = ref_frame_list.iter().position(|h| {
911 let p = h.pic.borrow();
912 let found = p.field == field;
913
914 if found {
915 field = field.opposite();
916 }
917
918 found
919 }) {
920 let pic = ref_frame_list.remove(position);
921 ref_pic_list.push(pic);
922 }
923
924 ref_pic_list.append(ref_frame_list);
925 }
926
927 fn build_ref_pic_list_p(&self) -> DpbPicRefList<T> {
930 let mut ref_pic_list_p0: Vec<_> =
931 self.short_term_refs_iter().filter(|h| !h.pic.borrow().is_second_field()).collect();
932
933 Self::sort_pic_num_descending(&mut ref_pic_list_p0);
934
935 let num_short_term_refs = ref_pic_list_p0.len();
936
937 ref_pic_list_p0
938 .extend(self.long_term_refs_iter().filter(|h| !h.pic.borrow().is_second_field()));
939 Self::sort_long_term_pic_num_ascending(&mut ref_pic_list_p0[num_short_term_refs..]);
940
941 #[cfg(debug_assertions)]
942 Self::debug_ref_list_p(&ref_pic_list_p0, false);
943
944 ref_pic_list_p0
945 }
946
947 fn build_ref_field_pic_list_p(&self, cur_pic: &PictureData) -> DpbPicRefList<T> {
950 let mut ref_pic_list_p0 = vec![];
951
952 let mut ref_frame_list_0_short_term: Vec<_> = self.short_term_refs_iter().collect();
953 Self::sort_frame_num_wrap_descending(&mut ref_frame_list_0_short_term);
954
955 let mut ref_frame_list_long_term: Vec<_> = self.long_term_refs_iter().collect();
956 Self::sort_long_term_pic_num_ascending(&mut ref_frame_list_long_term);
957
958 Self::init_ref_field_pic_list(
960 cur_pic.field,
961 Reference::ShortTerm,
962 &mut ref_frame_list_0_short_term,
963 &mut ref_pic_list_p0,
964 );
965 Self::init_ref_field_pic_list(
966 cur_pic.field,
967 Reference::LongTerm,
968 &mut ref_frame_list_long_term,
969 &mut ref_pic_list_p0,
970 );
971
972 #[cfg(debug_assertions)]
973 Self::debug_ref_list_p(&ref_pic_list_p0, true);
974
975 ref_pic_list_p0
976 }
977
978 fn build_ref_pic_list_b(&self, cur_pic: &PictureData) -> (DpbPicRefList<T>, DpbPicRefList<T>) {
981 let mut short_term_refs: Vec<_> =
982 self.short_term_refs_iter().filter(|h| !h.pic.borrow().is_second_field()).collect();
983
984 if cur_pic.pic_order_cnt_type == 0 {
988 short_term_refs.retain(|h| !h.pic.borrow().nonexisting);
989 }
990
991 let mut ref_pic_list_b0 = vec![];
992 let mut ref_pic_list_b1 = vec![];
993 let mut remaining = vec![];
994 for &handle in &short_term_refs {
999 let pic = handle.pic.borrow();
1000
1001 if pic.pic_order_cnt < cur_pic.pic_order_cnt {
1002 ref_pic_list_b0.push(handle);
1003 } else {
1004 remaining.push(handle);
1005 }
1006 }
1007
1008 Self::sort_poc_descending(&mut ref_pic_list_b0);
1009 Self::sort_poc_ascending(&mut remaining);
1010 ref_pic_list_b0.append(&mut remaining);
1011
1012 let mut long_term_refs: Vec<_> = self
1013 .long_term_refs_iter()
1014 .filter(|h| !h.pic.borrow().nonexisting)
1015 .filter(|h| !h.pic.borrow().is_second_field())
1016 .collect();
1017 Self::sort_long_term_pic_num_ascending(&mut long_term_refs);
1018
1019 ref_pic_list_b0.extend(long_term_refs.clone());
1020
1021 for &handle in &short_term_refs {
1026 let pic = handle.pic.borrow();
1027
1028 if pic.pic_order_cnt > cur_pic.pic_order_cnt {
1029 ref_pic_list_b1.push(handle);
1030 } else {
1031 remaining.push(handle);
1032 }
1033 }
1034
1035 Self::sort_poc_ascending(&mut ref_pic_list_b1);
1036 Self::sort_poc_descending(&mut remaining);
1037
1038 ref_pic_list_b1.extend(remaining);
1039 ref_pic_list_b1.extend(long_term_refs);
1040
1041 Self::swap_b1_if_needed(&ref_pic_list_b0, &mut ref_pic_list_b1);
1046
1047 #[cfg(debug_assertions)]
1048 Self::debug_ref_list_b(&ref_pic_list_b0, "ref_pic_list_b0");
1049 #[cfg(debug_assertions)]
1050 Self::debug_ref_list_b(&ref_pic_list_b1, "ref_pic_list_b1");
1051
1052 (ref_pic_list_b0, ref_pic_list_b1)
1053 }
1054
1055 fn build_ref_field_pic_list_b(
1058 &self,
1059 cur_pic: &PictureData,
1060 ) -> (DpbPicRefList<T>, DpbPicRefList<T>) {
1061 let mut ref_pic_list_b0 = vec![];
1062 let mut ref_pic_list_b1 = vec![];
1063 let mut ref_frame_list_0_short_term = vec![];
1064 let mut ref_frame_list_1_short_term = vec![];
1065
1066 let mut remaining = vec![];
1067
1068 let mut short_term_refs: Vec<_> = self.short_term_refs_iter().collect();
1069
1070 if cur_pic.pic_order_cnt_type == 0 {
1074 short_term_refs.retain(|h| !h.pic.borrow().nonexisting);
1075 }
1076
1077 for &handle in &short_term_refs {
1086 let pic = handle.pic.borrow();
1087
1088 if pic.pic_order_cnt <= cur_pic.pic_order_cnt {
1089 ref_frame_list_0_short_term.push(handle);
1090 } else {
1091 remaining.push(handle);
1092 }
1093 }
1094
1095 Self::sort_poc_descending(&mut ref_frame_list_0_short_term);
1096 Self::sort_poc_ascending(&mut remaining);
1097 ref_frame_list_0_short_term.append(&mut remaining);
1098
1099 for &handle in &short_term_refs {
1109 let pic = handle.pic.borrow();
1110
1111 if pic.pic_order_cnt > cur_pic.pic_order_cnt {
1112 ref_frame_list_1_short_term.push(handle);
1113 } else {
1114 remaining.push(handle);
1115 }
1116 }
1117
1118 Self::sort_poc_ascending(&mut ref_frame_list_1_short_term);
1119 Self::sort_poc_descending(&mut remaining);
1120 ref_frame_list_1_short_term.append(&mut remaining);
1121
1122 let mut ref_frame_list_long_term: Vec<_> =
1131 self.long_term_refs_iter().filter(|h| !h.pic.borrow().nonexisting).collect();
1132
1133 Self::sort_long_term_frame_idx_ascending(&mut ref_frame_list_long_term);
1134
1135 #[cfg(debug_assertions)]
1136 Self::debug_ref_list_b(&ref_frame_list_0_short_term, "ref_frame_list_0_short_term");
1137 #[cfg(debug_assertions)]
1138 Self::debug_ref_list_b(&ref_frame_list_1_short_term, "ref_frame_list_1_short_term");
1139 #[cfg(debug_assertions)]
1140 Self::debug_ref_list_b(&ref_frame_list_long_term, "ref_frame_list_long_term");
1141
1142 let field = cur_pic.field;
1144 Self::init_ref_field_pic_list(
1145 field,
1146 Reference::ShortTerm,
1147 &mut ref_frame_list_0_short_term,
1148 &mut ref_pic_list_b0,
1149 );
1150 Self::init_ref_field_pic_list(
1151 field,
1152 Reference::LongTerm,
1153 &mut ref_frame_list_long_term,
1154 &mut ref_pic_list_b0,
1155 );
1156
1157 Self::init_ref_field_pic_list(
1158 field,
1159 Reference::ShortTerm,
1160 &mut ref_frame_list_1_short_term,
1161 &mut ref_pic_list_b1,
1162 );
1163 Self::init_ref_field_pic_list(
1164 field,
1165 Reference::LongTerm,
1166 &mut ref_frame_list_long_term,
1167 &mut ref_pic_list_b1,
1168 );
1169
1170 Self::swap_b1_if_needed(&ref_pic_list_b0, &mut ref_pic_list_b1);
1175
1176 #[cfg(debug_assertions)]
1177 Self::debug_ref_list_b(&ref_pic_list_b0, "ref_pic_list_b0");
1178 #[cfg(debug_assertions)]
1179 Self::debug_ref_list_b(&ref_pic_list_b1, "ref_pic_list_b1");
1180
1181 (ref_pic_list_b0, ref_pic_list_b1)
1182 }
1183
1184 pub fn build_ref_pic_lists(&self, pic: &PictureData) -> ReferencePicLists {
1186 let num_refs = self.pictures().filter(|p| p.is_ref() && !p.nonexisting).count();
1187
1188 if num_refs == 0 {
1194 return Default::default();
1195 }
1196
1197 let (ref_pic_list_p0, (ref_pic_list_b0, ref_pic_list_b1)) =
1198 if matches!(pic.field, Field::Frame) {
1199 (self.build_ref_pic_list_p(), self.build_ref_pic_list_b(pic))
1200 } else {
1201 (self.build_ref_field_pic_list_p(pic), self.build_ref_field_pic_list_b(pic))
1202 };
1203
1204 let dpb_start = self.entries.as_ptr();
1205 let refs_to_index = |refs: Vec<_>| {
1206 refs.into_iter()
1207 .map(|r| r as *const DpbEntry<T>)
1208 .map(|r| unsafe { r.offset_from(dpb_start) })
1209 .map(|i| i as usize)
1210 .collect()
1211 };
1212
1213 ReferencePicLists {
1214 ref_pic_list_p0: refs_to_index(ref_pic_list_p0),
1215 ref_pic_list_b0: refs_to_index(ref_pic_list_b0),
1216 ref_pic_list_b1: refs_to_index(ref_pic_list_b1),
1217 }
1218 }
1219}
1220
1221impl<T> Default for Dpb<T> {
1222 fn default() -> Self {
1223 Self {
1226 entries: Default::default(),
1227 max_num_pics: Default::default(),
1228 max_num_reorder_frames: Default::default(),
1229 interlaced: Default::default(),
1230 }
1231 }
1232}
1233
1234impl<T> std::fmt::Debug for Dpb<T> {
1235 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1236 let pics = self.entries.iter().map(|h| &h.pic).enumerate().collect::<Vec<_>>();
1237 f.debug_struct("Dpb")
1238 .field("pictures", &pics)
1239 .field("max_num_pics", &self.max_num_pics)
1240 .field("interlaced", &self.interlaced)
1241 .finish()
1242 }
1243}