1use std::sync::Arc;
2
3use h264_reader::nal::{
4 pps::PicParameterSet,
5 slice::{
6 DecRefPicMarking, MemoryManagementControlOperation, ModificationOfPicNums, NumRefIdxActive,
7 RefPicListModifications, SliceHeader,
8 },
9 sps::SeqParameterSet,
10};
11
12use crate::{parameters::MissedFrameHandling, parser::decoder_instructions::DecoderInstruction};
13
14use super::nalu_parser::{Slice, SpsExt};
15
16#[derive(Debug, thiserror::Error)]
17pub enum ReferenceManagementError {
18 #[error("SI frames are not supported")]
19 SIFramesNotSupported,
20
21 #[error("SP frames are not supported")]
22 SPFramesNotSupported,
23
24 #[error("PicOrderCntType {0} is not supperted")]
25 PicOrderCntTypeNotSupported(u8),
26
27 #[error("The H.264 bytestream is not spec compliant: {0}.")]
28 IncorrectData(String),
29
30 #[error("Missing frame. Decoder is in a corrupted state. Waiting for IDR frame")]
31 MissingFrame,
32}
33
34#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
35pub(crate) struct ReferenceId(usize);
36
37#[derive(Debug, Clone, Copy)]
38enum BFrameReferenceListKind {
39 L0,
40 L1,
41}
42
43#[derive(Debug, Default)]
44#[allow(non_snake_case)]
45pub(crate) struct ReferenceContext {
46 pictures: ReferencePictures,
47 next_reference_id: ReferenceId,
48 prevFrameNum: u16,
49 PrevRefFrameNum: u16,
50 prev_pic_order_cnt_msb: i32,
51 prev_pic_order_cnt_lsb: i32,
52 MaxLongTermFrameIdx: MaxLongTermFrameIdx,
53 prevFrameNumOffset: i64,
54 previous_picture_included_mmco_equal_5: bool,
55 detected_missed_frames: bool,
56 missed_frame_handling: MissedFrameHandling,
57}
58
59#[derive(Debug, Default)]
60enum MaxLongTermFrameIdx {
61 #[default]
62 NoLongTermFrameIndices,
63 Idx(u64),
64}
65
66impl ReferenceContext {
67 pub fn new(missed_frame_handling: MissedFrameHandling) -> Self {
68 Self {
69 missed_frame_handling,
70 ..Default::default()
71 }
72 }
73
74 fn next_reference_id(&mut self) -> ReferenceId {
75 let result = self.next_reference_id;
76 self.next_reference_id = ReferenceId(result.0 + 1);
77 result
78 }
79
80 fn reset_state(&mut self) {
81 *self = Self {
82 pictures: ReferencePictures::default(),
83 next_reference_id: ReferenceId::default(),
84 prevFrameNum: 0,
85 PrevRefFrameNum: 0,
86 prev_pic_order_cnt_msb: 0,
87 prev_pic_order_cnt_lsb: 0,
88 MaxLongTermFrameIdx: MaxLongTermFrameIdx::NoLongTermFrameIndices,
89 prevFrameNumOffset: 0,
90 previous_picture_included_mmco_equal_5: false,
91 detected_missed_frames: false,
92 missed_frame_handling: self.missed_frame_handling,
93 };
94 }
95
96 #[allow(non_snake_case)]
97 fn add_long_term_reference(
98 &mut self,
99 header: Arc<SliceHeader>,
100 LongTermFrameIdx: u64,
101 pic_order_cnt: [i32; 2],
102 ) -> ReferenceId {
103 let id = self.next_reference_id();
104 self.pictures.long_term.push(LongTermReferencePicture {
105 header,
106 id,
107 LongTermFrameIdx,
108 pic_order_cnt,
109 });
110
111 id
112 }
113
114 fn add_short_term_reference(
115 &mut self,
116 header: Arc<SliceHeader>,
117 pic_order_cnt: [i32; 2],
118 ) -> ReferenceId {
119 let id = self.next_reference_id();
120 self.pictures.short_term.push(ShortTermReferencePicture {
121 header,
122 id,
123 pic_order_cnt,
124 });
125 id
126 }
127
128 pub(crate) fn mark_missed_frames(&mut self) {
129 self.detected_missed_frames = true;
130 }
131
132 pub(crate) fn put_picture(
133 &mut self,
134 mut slices: Vec<(Slice, Option<u64>)>,
135 ) -> Result<Vec<DecoderInstruction>, ReferenceManagementError> {
136 let header = slices.last().unwrap().0.header.clone();
137 let sps = slices.last().unwrap().0.sps.clone();
138 let pps = slices.last().unwrap().0.pps.clone();
139 let pts = slices.last().unwrap().1;
140
141 let is_ref_frame = header.dec_ref_pic_marking.is_some();
142 let is_idr = matches!(
143 &header.dec_ref_pic_marking,
144 Some(DecRefPicMarking::Idr { .. })
145 );
146 if is_ref_frame && !is_idr && self.missed_frame_handling == MissedFrameHandling::Strict {
147 self.verify_frame_num(&sps, &header)?;
148 }
149
150 let mut rbsp_bytes = Vec::new();
153 let mut slice_indices = Vec::new();
154 for (slice, _) in &mut slices {
155 if slice.rbsp_bytes.is_empty() {
156 continue;
157 }
158 slice_indices.push(rbsp_bytes.len());
159 rbsp_bytes.append(&mut slice.rbsp_bytes);
160 }
161
162 let decode_info = self.decode_information_for_frame(
163 header.clone(),
164 slice_indices,
165 rbsp_bytes,
166 &sps,
167 &pps,
168 pts,
169 )?;
170
171 let decoder_instructions = match &header.clone().dec_ref_pic_marking {
172 Some(DecRefPicMarking::Idr {
173 long_term_reference_flag,
174 ..
175 }) => self.reference_picture_marking_process_idr(
176 header.clone(),
177 decode_info,
178 *long_term_reference_flag,
179 )?,
180
181 Some(DecRefPicMarking::SlidingWindow) => self
182 .reference_picture_marking_process_sliding_window(
183 &sps,
184 header.clone(),
185 decode_info,
186 )?,
187 Some(DecRefPicMarking::Adaptive(memory_management_control_operations)) => self
188 .reference_picture_marking_process_adaptive(
189 &sps,
190 header.clone(),
191 decode_info,
192 memory_management_control_operations,
193 )?,
194
195 None => {
197 let reference_id = self.next_reference_id();
198 vec![
199 DecoderInstruction::Decode {
200 decode_info,
201 reference_id,
202 },
203 DecoderInstruction::Drop {
204 reference_ids: vec![reference_id],
205 },
206 ]
207 }
208 };
209
210 self.previous_picture_included_mmco_equal_5 = header.includes_mmco_equal_5();
211 self.prevFrameNum = header.frame_num;
212 if is_ref_frame {
213 self.PrevRefFrameNum = header.frame_num;
214 }
215
216 Ok(decoder_instructions)
217 }
218
219 fn remove_long_term_ref(
220 &mut self,
221 long_term_frame_idx: u64,
222 ) -> Result<LongTermReferencePicture, ReferenceManagementError> {
223 for (i, frame) in self.pictures.long_term.iter().enumerate() {
224 if frame.LongTermFrameIdx == long_term_frame_idx {
225 return Ok(self.pictures.long_term.remove(i));
226 }
227 }
228
229 Err(ReferenceManagementError::IncorrectData(format!(
230 "cannot remove long term reference with id {long_term_frame_idx}, because it does not exist"
231 )))
232 }
233
234 #[allow(non_snake_case)]
235 fn remove_short_term_ref(
236 &mut self,
237 current_frame_num: i64,
238 sps: &SeqParameterSet,
239 pic_num_to_remove: i64,
240 ) -> Result<ShortTermReferencePicture, ReferenceManagementError> {
241 for (i, picture) in self.pictures.short_term.iter().enumerate() {
242 let PicNum = decode_picture_numbers_for_short_term_ref(
243 picture.header.frame_num.into(),
244 current_frame_num,
245 sps,
246 )
247 .PicNum;
248
249 if PicNum == pic_num_to_remove {
250 return Ok(self.pictures.short_term.remove(i));
251 }
252 }
253
254 Err(ReferenceManagementError::IncorrectData(format!(
255 "cannot remove short term reference with pic num {pic_num_to_remove}, because it does not exist"
256 )))
257 }
258
259 fn reference_picture_marking_process_adaptive(
260 &mut self,
261 sps: &SeqParameterSet,
262 header: Arc<SliceHeader>,
263 decode_info: DecodeInformation,
264 memory_management_control_operations: &[MemoryManagementControlOperation],
265 ) -> Result<Vec<DecoderInstruction>, ReferenceManagementError> {
266 let mut decoder_instructions = Vec::new();
267
268 let mut new_long_term_frame_idx = None;
269
270 for memory_management_control_operation in memory_management_control_operations {
271 match memory_management_control_operation {
272 MemoryManagementControlOperation::ShortTermUnusedForRef {
273 difference_of_pic_nums_minus1,
274 } => {
275 let pic_num_to_remove =
276 header.frame_num as i64 - (*difference_of_pic_nums_minus1 as i64 + 1);
277
278 let removed = self.remove_short_term_ref(
279 header.frame_num.into(),
280 sps,
281 pic_num_to_remove,
282 )?;
283
284 decoder_instructions.push(DecoderInstruction::Drop {
285 reference_ids: vec![removed.id],
286 });
287 }
288
289 MemoryManagementControlOperation::LongTermUnusedForRef { long_term_pic_num } => {
290 let removed = self.remove_long_term_ref(*long_term_pic_num as u64)?;
291
292 decoder_instructions.push(DecoderInstruction::Drop {
293 reference_ids: vec![removed.id],
294 });
295 }
296
297 MemoryManagementControlOperation::ShortTermUsedForLongTerm {
298 difference_of_pic_nums_minus1,
299 long_term_frame_idx,
300 } => {
301 if let Ok(removed) = self.remove_long_term_ref(*long_term_frame_idx as u64) {
302 decoder_instructions.push(DecoderInstruction::Drop {
303 reference_ids: vec![removed.id],
304 });
305 }
306
307 let pic_num_to_remove =
308 header.frame_num as i64 - (*difference_of_pic_nums_minus1 as i64 + 1);
309
310 let picture = self.remove_short_term_ref(
311 header.frame_num.into(),
312 sps,
313 pic_num_to_remove,
314 )?;
315
316 self.pictures.long_term.push(LongTermReferencePicture {
317 header: picture.header,
318 LongTermFrameIdx: *long_term_frame_idx as u64,
319 pic_order_cnt: picture.pic_order_cnt,
320 id: picture.id,
321 });
322 }
323
324 MemoryManagementControlOperation::MaxUsedLongTermFrameRef {
325 max_long_term_frame_idx_plus1,
326 } => {
327 if *max_long_term_frame_idx_plus1 != 0 {
328 self.MaxLongTermFrameIdx =
329 MaxLongTermFrameIdx::Idx(*max_long_term_frame_idx_plus1 as u64 - 1);
330 } else {
331 self.MaxLongTermFrameIdx = MaxLongTermFrameIdx::NoLongTermFrameIndices;
332 }
333
334 let max_idx = *max_long_term_frame_idx_plus1 as i128 - 1;
335
336 let reference_ids_to_remove = self
337 .pictures
338 .long_term
339 .iter()
340 .filter(|p| p.LongTermFrameIdx as i128 > max_idx)
341 .map(|p| p.id)
342 .collect();
343
344 self.pictures.long_term = self
345 .pictures
346 .long_term
347 .iter()
348 .filter(|p| p.LongTermFrameIdx as i128 <= max_idx)
349 .cloned()
350 .collect();
351
352 decoder_instructions.push(DecoderInstruction::Drop {
353 reference_ids: reference_ids_to_remove,
354 })
355 }
356
357 MemoryManagementControlOperation::AllRefPicturesUnused => {
358 let reference_ids = self
359 .pictures
360 .short_term
361 .drain(..)
362 .map(|p| p.id)
363 .chain(self.pictures.long_term.drain(..).map(|p| p.id))
364 .collect();
365
366 self.MaxLongTermFrameIdx = MaxLongTermFrameIdx::NoLongTermFrameIndices;
367
368 decoder_instructions.push(DecoderInstruction::Drop { reference_ids })
369 }
370 MemoryManagementControlOperation::CurrentUsedForLongTerm {
371 long_term_frame_idx,
372 } => {
373 if let Ok(picture) = self.remove_long_term_ref(*long_term_frame_idx as u64) {
374 decoder_instructions.push(DecoderInstruction::Drop {
375 reference_ids: vec![picture.id],
376 });
377 }
378
379 new_long_term_frame_idx = Some(*long_term_frame_idx as u64);
380 }
381 }
382 }
383
384 let reference_id = match new_long_term_frame_idx {
385 Some(long_term_frame_idx) => self.add_long_term_reference(
386 header,
387 long_term_frame_idx,
388 decode_info.picture_info.PicOrderCnt_as_reference_pic,
389 ),
390 None => self.add_short_term_reference(
391 header,
392 decode_info.picture_info.PicOrderCnt_as_reference_pic,
393 ),
394 };
395
396 decoder_instructions.insert(
397 0,
398 DecoderInstruction::Decode {
399 decode_info,
400 reference_id,
401 },
402 );
403
404 if let MaxLongTermFrameIdx::Idx(max) = self.MaxLongTermFrameIdx {
405 if self.pictures.long_term.len() > max as usize + 1 {
406 return Err(ReferenceManagementError::IncorrectData(format!(
407 "there are {} long-term references, but there shouldn't be more than {max}",
408 self.pictures.long_term.len()
409 )));
410 }
411 }
412
413 Ok(decoder_instructions)
414 }
415
416 fn reference_picture_marking_process_sliding_window(
417 &mut self,
418 sps: &SeqParameterSet,
419 header: Arc<SliceHeader>,
420 decode_info: DecodeInformation,
421 ) -> Result<Vec<DecoderInstruction>, ReferenceManagementError> {
422 let num_short_term = self.pictures.short_term.len();
423 let num_long_term = self.pictures.long_term.len();
424
425 let reference_id = self.add_short_term_reference(
426 header.clone(),
427 decode_info.picture_info.PicOrderCnt_as_reference_pic,
428 );
429
430 let mut decoder_instructions = vec![DecoderInstruction::Decode {
431 decode_info,
432 reference_id,
433 }];
434
435 if num_short_term + num_long_term == sps.max_num_ref_frames.max(1) as usize
436 && !self.pictures.short_term.is_empty()
437 {
438 let (idx, _) = self
439 .pictures
440 .short_term
441 .iter()
442 .enumerate()
443 .min_by_key(|(_, reference)| {
444 decode_picture_numbers_for_short_term_ref(
445 reference.header.frame_num.into(),
446 header.frame_num.into(),
447 sps,
448 )
449 .FrameNumWrap
450 })
451 .unwrap();
452
453 decoder_instructions.push(DecoderInstruction::Drop {
454 reference_ids: vec![self.pictures.short_term.remove(idx).id],
455 })
456 }
457
458 Ok(decoder_instructions)
459 }
460
461 fn reference_picture_marking_process_idr(
462 &mut self,
463 header: Arc<SliceHeader>,
464 decode_info: DecodeInformation,
465 long_term_reference_flag: bool,
466 ) -> Result<Vec<DecoderInstruction>, ReferenceManagementError> {
467 self.reset_state();
468
469 let reference_id = if long_term_reference_flag {
470 self.MaxLongTermFrameIdx = MaxLongTermFrameIdx::Idx(0);
471 self.add_long_term_reference(
472 header,
473 0,
474 decode_info.picture_info.PicOrderCnt_as_reference_pic,
475 )
476 } else {
477 self.MaxLongTermFrameIdx = MaxLongTermFrameIdx::NoLongTermFrameIndices;
478 self.add_short_term_reference(
479 header,
480 decode_info.picture_info.PicOrderCnt_as_reference_pic,
481 )
482 };
483
484 Ok(vec![DecoderInstruction::Idr {
485 decode_info,
486 reference_id,
487 }])
488 }
489
490 #[allow(non_snake_case)]
491 fn decode_information_for_frame(
492 &mut self,
493 header: Arc<SliceHeader>,
494 slice_indices: Vec<usize>,
495 rbsp_bytes: Vec<u8>,
496 sps: &SeqParameterSet,
497 pps: &PicParameterSet,
498 pts: Option<u64>,
499 ) -> Result<DecodeInformation, ReferenceManagementError> {
500 let PicOrderCnt_for_decoding = self.decode_pic_order_cnt(&header, sps)?;
501 let PicOrderCnt_as_reference_pic = if header.includes_mmco_equal_5() {
502 [0, 0]
503 } else {
504 PicOrderCnt_for_decoding
505 };
506
507 let (reference_list_l0, reference_list_l1) = match header.slice_type.family {
508 h264_reader::nal::slice::SliceFamily::P => {
509 let num_ref_idx_l0_active = header.num_ref_idx_l0_active(pps);
510
511 let mut reference_list_l0 =
512 self.initialize_reference_picture_list_for_p_frame(&header, sps)?;
513
514 match &header.ref_pic_list_modification {
515 Some(RefPicListModifications::P {
516 ref_pic_list_modification_l0,
517 }) => {
518 self.modify_reference_picture_list(
519 sps,
520 &header,
521 &mut reference_list_l0,
522 ref_pic_list_modification_l0,
523 )?;
524 }
525
526 None
527 | Some(RefPicListModifications::I)
528 | Some(RefPicListModifications::B { .. }) => return Err(ReferenceManagementError::IncorrectData(
529 "a slice marked 'P' slice family contains a reference picture list for a different family".into()
530 ))?,
531 }
532
533 reference_list_l0.truncate(num_ref_idx_l0_active as usize);
534
535 (Some(reference_list_l0), None)
536 }
537 h264_reader::nal::slice::SliceFamily::I => (None, None),
538 h264_reader::nal::slice::SliceFamily::B => {
539 let num_ref_idx_l0_active = header.num_ref_idx_l0_active(pps);
540 let num_ref_idx_l1_active = header.num_ref_idx_l1_active(pps)?;
541
542 let mut reference_list_l0 = self.initialize_reference_picture_list_for_b_frame(
543 PicOrderCnt_for_decoding,
544 BFrameReferenceListKind::L0,
545 )?;
546 let mut reference_list_l1 = self.initialize_reference_picture_list_for_b_frame(
547 PicOrderCnt_for_decoding,
548 BFrameReferenceListKind::L1,
549 )?;
550
551 match &header.ref_pic_list_modification {
552 Some(RefPicListModifications::B {
553 ref_pic_list_modification_l0,
554 ref_pic_list_modification_l1,
555 }) => {
556 self.modify_reference_picture_list(
557 sps,
558 &header,
559 &mut reference_list_l0,
560 ref_pic_list_modification_l0,
561 )?;
562
563 self.modify_reference_picture_list(
564 sps,
565 &header,
566 &mut reference_list_l1,
567 ref_pic_list_modification_l1
568 )?;
569 }
570
571 None
572 | Some(RefPicListModifications::I)
573 | Some(RefPicListModifications::P { .. }) => return Err(ReferenceManagementError::IncorrectData(
574 "a slice marked 'B' slice family contains a reference picture list for a different family".into()
575 ))?,
576 }
577
578 reference_list_l0.truncate(num_ref_idx_l0_active as usize);
579 reference_list_l1.truncate(num_ref_idx_l1_active as usize);
580
581 (Some(reference_list_l0), Some(reference_list_l1))
582 }
583 h264_reader::nal::slice::SliceFamily::SP => {
584 return Err(ReferenceManagementError::SPFramesNotSupported);
585 }
586 h264_reader::nal::slice::SliceFamily::SI => {
587 return Err(ReferenceManagementError::SIFramesNotSupported);
588 }
589 };
590
591 Ok(DecodeInformation {
592 reference_list_l0,
593 reference_list_l1,
594 header: header.clone(),
595 slice_indices,
596 rbsp_bytes,
597 sps_id: sps.id().id(),
598 pps_id: pps.pic_parameter_set_id.id(),
599 picture_info: PictureInfo {
600 non_existing: false,
601 used_for_long_term_reference: false,
602 PicOrderCnt_for_decoding,
603 PicOrderCnt_as_reference_pic,
604 FrameNum: header.frame_num,
605 },
606 pts,
607 })
608 }
609
610 fn decode_pic_order_cnt(
611 &mut self,
612 header: &SliceHeader,
613 sps: &SeqParameterSet,
614 ) -> Result<[i32; 2], ReferenceManagementError> {
615 match sps.pic_order_cnt {
616 h264_reader::nal::sps::PicOrderCntType::TypeZero {
617 log2_max_pic_order_cnt_lsb_minus4,
618 } => self.decode_pic_order_cnt_type_zero(header, log2_max_pic_order_cnt_lsb_minus4),
619
620 h264_reader::nal::sps::PicOrderCntType::TypeOne { .. } => {
621 Err(ReferenceManagementError::PicOrderCntTypeNotSupported(1))
622 }
623
624 h264_reader::nal::sps::PicOrderCntType::TypeTwo => {
625 self.decode_pic_order_cnt_type_two(header, sps)
626 }
627 }
628 }
629
630 #[allow(non_snake_case)]
631 fn decode_pic_order_cnt_type_two(
632 &mut self,
633 header: &SliceHeader,
634 sps: &SeqParameterSet,
635 ) -> Result<[i32; 2], ReferenceManagementError> {
636 let FrameNumOffset = if header.idr_pic_id.is_some() {
637 0
638 } else {
639 let prevFrameNumOffset = if self.previous_picture_included_mmco_equal_5 {
640 0
641 } else {
642 self.prevFrameNumOffset
643 };
644
645 if self.prevFrameNum > header.frame_num {
646 prevFrameNumOffset + sps.max_frame_num()
647 } else {
648 prevFrameNumOffset
649 }
650 };
651
652 let tempPicOrderCnt = if header.idr_pic_id.is_some() {
653 0
654 } else if header.dec_ref_pic_marking.is_none() {
655 2 * (FrameNumOffset as i32 + header.frame_num as i32) - 1
656 } else {
657 2 * (FrameNumOffset as i32 + header.frame_num as i32)
658 };
659
660 self.prevFrameNumOffset = FrameNumOffset;
661
662 Ok([tempPicOrderCnt; 2])
663 }
664
665 fn decode_pic_order_cnt_type_zero(
666 &mut self,
667 header: &SliceHeader,
668 log2_max_pic_order_cnt_lsb_minus4: u8,
669 ) -> Result<[i32; 2], ReferenceManagementError> {
670 let max_pic_order_cnt_lsb = 2_i32.pow(log2_max_pic_order_cnt_lsb_minus4 as u32 + 4);
674
675 let (prev_pic_order_cnt_msb, prev_pic_order_cnt_lsb) = if header.idr_pic_id.is_some() {
676 (0, 0)
677 } else {
678 (self.prev_pic_order_cnt_msb, self.prev_pic_order_cnt_lsb)
679 };
680
681 let (pic_order_cnt_lsb, delta_pic_order_cnt_bottom) = match header
682 .pic_order_cnt_lsb
683 .as_ref()
684 .ok_or(ReferenceManagementError::IncorrectData("pic_order_cnt_lsb is not present in a slice header, but is required for decoding".into()))?
685 {
686 h264_reader::nal::slice::PicOrderCountLsb::Frame(pic_order_cnt_lsb) => {
687 (*pic_order_cnt_lsb, 0)
688 }
689 h264_reader::nal::slice::PicOrderCountLsb::FieldsAbsolute {
690 pic_order_cnt_lsb,
691 delta_pic_order_cnt_bottom,
692 } => (*pic_order_cnt_lsb, *delta_pic_order_cnt_bottom),
693 h264_reader::nal::slice::PicOrderCountLsb::FieldsDelta(_) => {
694 Err(ReferenceManagementError::IncorrectData("pic_order_cnt_lsb is not present in a slice header, but is required for decoding".into()))?
695 }
696 };
697
698 let pic_order_cnt_lsb = pic_order_cnt_lsb as i32;
699
700 let pic_order_cnt_msb = if pic_order_cnt_lsb < prev_pic_order_cnt_lsb
701 && prev_pic_order_cnt_lsb - pic_order_cnt_lsb >= max_pic_order_cnt_lsb / 2
702 {
703 prev_pic_order_cnt_msb + max_pic_order_cnt_lsb
704 } else if pic_order_cnt_lsb > prev_pic_order_cnt_lsb
705 && pic_order_cnt_lsb - prev_pic_order_cnt_lsb > max_pic_order_cnt_lsb / 2
706 {
707 prev_pic_order_cnt_msb - max_pic_order_cnt_lsb
708 } else {
709 prev_pic_order_cnt_msb
710 };
711
712 let pic_order_cnt = if header.field_pic == h264_reader::nal::slice::FieldPic::Frame {
713 let top_field_order_cnt = pic_order_cnt_msb + pic_order_cnt_lsb;
714
715 let bottom_field_order_cnt = top_field_order_cnt + delta_pic_order_cnt_bottom;
716
717 top_field_order_cnt.min(bottom_field_order_cnt)
718 } else {
719 pic_order_cnt_msb + pic_order_cnt_lsb
720 };
721
722 self.prev_pic_order_cnt_msb = pic_order_cnt_msb;
723 self.prev_pic_order_cnt_lsb = pic_order_cnt_lsb;
724
725 Ok([pic_order_cnt; 2])
726 }
727
728 fn initialize_short_term_reference_picture_list_for_p_frame(
729 &self,
730 header: &SliceHeader,
731 sps: &SeqParameterSet,
732 ) -> Vec<ReferencePictureInfo> {
733 let mut short_term_reference_list = self
734 .pictures
735 .short_term
736 .iter()
737 .map(|reference| {
738 (
739 reference,
740 decode_picture_numbers_for_short_term_ref(
741 reference.header.frame_num.into(),
742 header.frame_num.into(),
743 sps,
744 ),
745 )
746 })
747 .collect::<Vec<_>>();
748
749 short_term_reference_list.sort_by_key(|(_, numbers)| -numbers.PicNum);
750
751 short_term_reference_list
752 .into_iter()
753 .map(|(reference, numbers)| ReferencePictureInfo {
754 id: reference.id,
755 LongTermPicNum: None,
756 FrameNum: numbers.FrameNum as u16,
757 non_existing: false,
758 PicOrderCnt: reference.pic_order_cnt,
759 })
760 .collect()
761 }
762
763 fn initialize_long_term_reference_picture_list_for_frame(&self) -> Vec<ReferencePictureInfo> {
764 let mut long_term_reference_list = self.pictures.long_term.clone();
765
766 long_term_reference_list.sort_by_key(|pic| pic.LongTermFrameIdx);
767
768 long_term_reference_list
769 .into_iter()
770 .map(|pic| ReferencePictureInfo {
771 id: pic.id,
772 LongTermPicNum: Some(pic.LongTermFrameIdx),
773 PicOrderCnt: pic.pic_order_cnt,
774 non_existing: false,
775 FrameNum: pic.header.frame_num,
776 })
777 .collect()
778 }
779
780 fn initialize_reference_picture_list_for_p_frame(
781 &self,
782 header: &SliceHeader,
783 sps: &SeqParameterSet,
784 ) -> Result<Vec<ReferencePictureInfo>, ReferenceManagementError> {
785 let short_term_reference_list =
786 self.initialize_short_term_reference_picture_list_for_p_frame(header, sps);
787
788 let long_term_reference_list = self.initialize_long_term_reference_picture_list_for_frame();
789
790 let reference_list = short_term_reference_list
791 .into_iter()
792 .chain(long_term_reference_list)
793 .collect::<Vec<_>>();
794
795 Ok(reference_list)
796 }
797
798 #[allow(non_snake_case)]
799 fn initialize_reference_picture_list_for_b_frame(
800 &self,
801 CurrPicOrderCnt: [i32; 2],
802 list_kind: BFrameReferenceListKind,
803 ) -> Result<Vec<ReferencePictureInfo>, ReferenceManagementError> {
804 let short_term_reference_list = self
805 .initialize_short_term_reference_picture_list_for_b_frame(CurrPicOrderCnt, list_kind)?;
806
807 let long_term_reference_list = self.initialize_long_term_reference_picture_list_for_frame();
808
809 let reference_list = short_term_reference_list
810 .into_iter()
811 .chain(long_term_reference_list)
812 .collect();
813
814 Ok(reference_list)
815 }
816
817 fn verify_frame_num(
818 &mut self,
819 sps: &SeqParameterSet,
820 header: &SliceHeader,
821 ) -> Result<(), ReferenceManagementError> {
822 let is_expected_frame_num = !sps.gaps_in_frame_num_value_allowed_flag
823 && header.frame_num != self.PrevRefFrameNum
824 && header.frame_num != ((self.PrevRefFrameNum as i64 + 1) % sps.max_frame_num()) as u16;
825 if is_expected_frame_num || self.detected_missed_frames {
826 self.detected_missed_frames = true;
827 return Err(ReferenceManagementError::MissingFrame);
828 }
829
830 Ok(())
831 }
832
833 #[allow(non_snake_case)]
834 fn initialize_short_term_reference_picture_list_for_b_frame(
835 &self,
836 CurrPicOrderCnt: [i32; 2],
837 list_kind: BFrameReferenceListKind,
838 ) -> Result<Vec<ReferencePictureInfo>, ReferenceManagementError> {
839 let mut reference_list = self
840 .pictures
841 .short_term
842 .iter()
843 .filter(|pic| match list_kind {
844 BFrameReferenceListKind::L0 => pic.pic_order_cnt < CurrPicOrderCnt,
845 BFrameReferenceListKind::L1 => pic.pic_order_cnt > CurrPicOrderCnt,
846 })
847 .collect::<Vec<_>>();
848
849 reference_list.sort_by_key(|pic| match list_kind {
850 BFrameReferenceListKind::L0 => -pic.pic_order_cnt[0],
851 BFrameReferenceListKind::L1 => pic.pic_order_cnt[0],
852 });
853
854 let reference_list = reference_list
855 .into_iter()
856 .map(|pic| ReferencePictureInfo {
857 LongTermPicNum: None,
858 FrameNum: pic.header.frame_num,
859 non_existing: false,
860 PicOrderCnt: pic.pic_order_cnt,
861 id: pic.id,
862 })
863 .collect();
864
865 Ok(reference_list)
866 }
867
868 #[allow(non_snake_case)]
869 fn modify_reference_picture_list(
870 &self,
871 sps: &SeqParameterSet,
872 header: &SliceHeader,
873 reference_list: &mut Vec<ReferencePictureInfo>,
874 ref_pic_list_modifications: &[ModificationOfPicNums],
875 ) -> Result<(), ReferenceManagementError> {
876 let mut refIdxLX = 0;
878 let mut picNumLXPred = header.frame_num as i64;
879
880 for ref_pic_list_modification in ref_pic_list_modifications {
881 match ref_pic_list_modification {
882 ModificationOfPicNums::Subtract(_) | ModificationOfPicNums::Add(_) => {
883 self.modify_short_term_reference_picture_list(
884 sps,
885 header,
886 reference_list,
887 ref_pic_list_modification,
888 &mut refIdxLX,
889 &mut picNumLXPred,
890 )?;
891 }
892
893 ModificationOfPicNums::LongTermRef(long_term_pic_num) => {
894 self.modify_long_term_reference_picture_list(
895 reference_list,
896 *long_term_pic_num,
897 &mut refIdxLX,
898 )?;
899 }
900 }
901 }
902
903 Ok(())
904 }
905
906 #[allow(non_snake_case)]
907 fn modify_long_term_reference_picture_list(
908 &self,
909 reference_list: &mut Vec<ReferencePictureInfo>,
910 picture_to_shift: u32,
911 refIdxLX: &mut usize,
912 ) -> Result<(), ReferenceManagementError> {
913 let shifted_picture_idx = reference_list
914 .iter()
915 .enumerate()
916 .find(|(_, pic)| match pic.LongTermPicNum {
917 Some(num) => num == picture_to_shift as u64,
918 None => false,
919 })
920 .map(|(i, _)| i)
921 .ok_or(ReferenceManagementError::IncorrectData(
922 format!("picture with LongTermPicNum = {picture_to_shift} is not present in the reference list during modification")
923 ))?;
924
925 if reference_list[shifted_picture_idx].non_existing {
926 return Err(ReferenceManagementError::IncorrectData(
927 "a reference picture marked for shifting in the long-term reference list modification process is marked as non-existing".into()
928 ));
929 }
930
931 let shifted_picture = reference_list.remove(shifted_picture_idx);
932 reference_list.insert(*refIdxLX, shifted_picture);
933 *refIdxLX += 1;
934
935 Ok(())
936 }
937
938 #[allow(non_snake_case)]
939 fn modify_short_term_reference_picture_list(
940 &self,
941 sps: &SeqParameterSet,
942 header: &SliceHeader,
943 reference_list: &mut Vec<ReferencePictureInfo>,
944 ref_pic_list_modification: &ModificationOfPicNums,
945 refIdxLX: &mut usize,
946 picNumLXPred: &mut i64,
947 ) -> Result<(), ReferenceManagementError> {
948 let picNumLXNoWrap = match *ref_pic_list_modification {
949 ModificationOfPicNums::Subtract(abs_diff_pic_num_minus_1) => {
950 let abs_diff_pic_num = abs_diff_pic_num_minus_1 as i64 + 1;
951 if *picNumLXPred - abs_diff_pic_num < 0 {
952 *picNumLXPred - abs_diff_pic_num + sps.max_frame_num()
953 } else {
954 *picNumLXPred - abs_diff_pic_num
955 }
956 }
957 ModificationOfPicNums::Add(abs_diff_pic_num_minus_1) => {
958 let abs_diff_pic_num = abs_diff_pic_num_minus_1 as i64 + 1;
959 if *picNumLXPred + abs_diff_pic_num >= sps.max_frame_num() {
960 *picNumLXPred + abs_diff_pic_num - sps.max_frame_num()
961 } else {
962 *picNumLXPred + abs_diff_pic_num
963 }
964 }
965 ModificationOfPicNums::LongTermRef(_) => return Ok(()),
966 };
967
968 *picNumLXPred = picNumLXNoWrap;
969
970 let picNumLX = if picNumLXNoWrap > header.frame_num as i64 {
971 picNumLXNoWrap - sps.max_frame_num()
972 } else {
973 picNumLXNoWrap
974 };
975
976 let mut shifted_picture_idx = reference_list
977 .iter()
978 .enumerate()
979 .find(|(_, picture_info)| decode_picture_numbers_for_short_term_ref(picture_info.FrameNum.into(), header.frame_num.into(), sps).PicNum == picNumLX)
980 .map(|(i, _)| i)
981 .ok_or(ReferenceManagementError::IncorrectData(
982 format!("picture with picNumLX = {picNumLX} is not present in the reference list during modification")
983 ))?;
984
985 if reference_list[shifted_picture_idx].non_existing {
986 return Err(ReferenceManagementError::IncorrectData(
987 "a short-term reference picture marked for shifting in the reference list modification process is marked as non-existing".into()
988 ));
989 }
990
991 if reference_list[shifted_picture_idx].is_long_term() {
992 return Err(ReferenceManagementError::IncorrectData(
993 "a long-term reference picture marked for shifting in the short-term reference list modification process".into()
994 ));
995 }
996
997 let shifted_picture_info = reference_list[shifted_picture_idx];
998 if *refIdxLX <= reference_list.len() {
999 reference_list.insert(*refIdxLX, shifted_picture_info);
1000 shifted_picture_idx = if *refIdxLX <= shifted_picture_idx {
1001 shifted_picture_idx + 1
1002 } else {
1003 shifted_picture_idx
1004 };
1005 }
1006 *refIdxLX += 1;
1007 reference_list.remove(shifted_picture_idx);
1008
1009 Ok(())
1010 }
1011}
1012
1013#[derive(Debug)]
1014struct ShortTermReferencePicture {
1015 header: Arc<SliceHeader>,
1016 id: ReferenceId,
1017 pic_order_cnt: [i32; 2],
1018}
1019
1020#[allow(non_snake_case)]
1021fn decode_picture_numbers_for_short_term_ref(
1022 frame_num: i64,
1023 current_frame_num: i64,
1024 sps: &SeqParameterSet,
1025) -> ShortTermReferencePictureNumbers {
1026 let MaxFrameNum = sps.max_frame_num();
1027
1028 let FrameNum = frame_num;
1029
1030 let FrameNumWrap = if FrameNum > current_frame_num {
1031 FrameNum - MaxFrameNum
1032 } else {
1033 FrameNum
1034 };
1035
1036 let PicNum = FrameNumWrap;
1038
1039 ShortTermReferencePictureNumbers {
1040 FrameNum,
1041 FrameNumWrap,
1042 PicNum,
1043 }
1044}
1045
1046#[derive(Debug, Clone)]
1047#[allow(non_snake_case)]
1048struct LongTermReferencePicture {
1049 header: Arc<SliceHeader>,
1050 LongTermFrameIdx: u64,
1051 id: ReferenceId,
1052 pic_order_cnt: [i32; 2],
1053}
1054
1055#[allow(non_snake_case)]
1056struct ShortTermReferencePictureNumbers {
1057 FrameNum: i64,
1058
1059 FrameNumWrap: i64,
1060
1061 PicNum: i64,
1062}
1063
1064#[derive(Debug, Default)]
1065struct ReferencePictures {
1066 long_term: Vec<LongTermReferencePicture>,
1067 short_term: Vec<ShortTermReferencePicture>,
1068}
1069
1070trait SliceHeaderExt {
1071 fn num_ref_idx_l0_active(&self, pps: &PicParameterSet) -> u32;
1072 fn num_ref_idx_l1_active(&self, pps: &PicParameterSet)
1073 -> Result<u32, ReferenceManagementError>;
1074 fn includes_mmco_equal_5(&self) -> bool;
1075}
1076
1077impl SliceHeaderExt for SliceHeader {
1078 fn num_ref_idx_l0_active(&self, pps: &PicParameterSet) -> u32 {
1079 self.num_ref_idx_active
1080 .as_ref()
1081 .map(|num| match num {
1082 NumRefIdxActive::P {
1083 num_ref_idx_l0_active_minus1,
1084 } => *num_ref_idx_l0_active_minus1,
1085 NumRefIdxActive::B {
1086 num_ref_idx_l0_active_minus1,
1087 ..
1088 } => *num_ref_idx_l0_active_minus1,
1089 })
1090 .unwrap_or(pps.num_ref_idx_l0_default_active_minus1)
1091 + 1
1092 }
1093
1094 fn num_ref_idx_l1_active(
1095 &self,
1096 pps: &PicParameterSet,
1097 ) -> Result<u32, ReferenceManagementError> {
1098 Ok(
1099 self
1100 .num_ref_idx_active
1101 .as_ref()
1102 .map(|num| match num {
1103 NumRefIdxActive::P { .. } => Err(ReferenceManagementError::IncorrectData(
1104 "requested num_ref_idx_l1_active, but the header contains the information for a P-frame, which does not include it".into()
1105 )),
1106 NumRefIdxActive::B { num_ref_idx_l1_active_minus1, .. } => Ok(*num_ref_idx_l1_active_minus1)
1107 })
1108 .unwrap_or(Ok(pps.num_ref_idx_l1_default_active_minus1))? + 1
1109 )
1110 }
1111
1112 fn includes_mmco_equal_5(&self) -> bool {
1113 let Some(DecRefPicMarking::Adaptive(ref mmcos)) = self.dec_ref_pic_marking else {
1114 return false;
1115 };
1116
1117 mmcos
1118 .iter()
1119 .any(|mmco| matches!(mmco, MemoryManagementControlOperation::AllRefPicturesUnused))
1120 }
1121}
1122
1123#[derive(Clone, derivative::Derivative)]
1124#[derivative(Debug)]
1125pub struct DecodeInformation {
1126 pub(crate) reference_list_l0: Option<Vec<ReferencePictureInfo>>,
1127 pub(crate) reference_list_l1: Option<Vec<ReferencePictureInfo>>,
1128 #[derivative(Debug = "ignore")]
1129 pub(crate) rbsp_bytes: Vec<u8>,
1130 pub(crate) slice_indices: Vec<usize>,
1131 #[derivative(Debug = "ignore")]
1132 pub(crate) header: Arc<SliceHeader>,
1133 pub(crate) sps_id: u8,
1134 pub(crate) pps_id: u8,
1135 pub(crate) picture_info: PictureInfo,
1136 pub(crate) pts: Option<u64>,
1137}
1138
1139#[derive(Debug, Clone, Copy)]
1140#[allow(non_snake_case)]
1141pub(crate) struct ReferencePictureInfo {
1142 pub(crate) id: ReferenceId,
1143 pub(crate) LongTermPicNum: Option<u64>,
1144 pub(crate) non_existing: bool,
1145 pub(crate) FrameNum: u16,
1146 pub(crate) PicOrderCnt: [i32; 2],
1147}
1148
1149impl ReferencePictureInfo {
1150 pub fn is_long_term(&self) -> bool {
1151 self.LongTermPicNum.is_some()
1152 }
1153}
1154
1155#[derive(Debug, Clone, Copy)]
1156#[allow(non_snake_case)]
1157pub(crate) struct PictureInfo {
1158 pub(crate) used_for_long_term_reference: bool,
1159 pub(crate) non_existing: bool,
1160 pub(crate) FrameNum: u16,
1161 pub(crate) PicOrderCnt_for_decoding: [i32; 2],
1162 pub(crate) PicOrderCnt_as_reference_pic: [i32; 2],
1163}