X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-itu%2Fsrc%2Fcodecs%2Fh264%2Fpic_ref.rs;h=cafcc56b5e73485388d4c35f25547c292293b24d;hb=42005e259dd77147b77c7a0057aa3cf033e331d0;hp=81889a2cf3ad79591bb85110393ca519346440ec;hpb=4a1ca15c9298340e8f2cb2ad6016109375cc45b9;p=nihav.git diff --git a/nihav-itu/src/codecs/h264/pic_ref.rs b/nihav-itu/src/codecs/h264/pic_ref.rs index 81889a2..cafcc56 100644 --- a/nihav-itu/src/codecs/h264/pic_ref.rs +++ b/nihav-itu/src/codecs/h264/pic_ref.rs @@ -50,12 +50,14 @@ pub struct FrameRefs { pub ref_list0: Vec>, pub ref_list1: Vec>, pub long_term: Vec>, + pub cur_id: u32, prev_poc_msb: u32, prev_poc_lsb: u16, prev_ref_poc_lsb: u16, prev_frame_num: u16, frame_num_offset: u32, + max_frame_num: i32, } impl FrameRefs { @@ -65,15 +67,18 @@ impl FrameRefs { ref_list0: Vec::with_capacity(3), ref_list1: Vec::with_capacity(3), long_term: Vec::new(), + cur_id: 0, prev_poc_msb: 0, prev_poc_lsb: 0, prev_ref_poc_lsb: 0, prev_frame_num: 0, frame_num_offset: 0, + max_frame_num: 0, } } pub fn calc_picture_num(&mut self, slice_hdr: &SliceHeader, is_idr: bool, ref_id: u8, sps: &SeqParameterSet) -> u32 { + self.max_frame_num = 1 << sps.log2_max_frame_num; match sps.pic_order_cnt_type { 0 => { if is_idr { @@ -200,8 +205,8 @@ impl FrameRefs { self.long_term.resize(arg1 as usize, None); }, 5 => { - self.ref_pics.truncate(0); - self.long_term.truncate(0); + self.ref_pics.clear(); + self.long_term.clear(); }, 6 => { // assign an long term index to current pic - done elsewhere @@ -212,13 +217,14 @@ impl FrameRefs { Ok(()) } pub fn clear_refs(&mut self) { - self.ref_pics.truncate(0); - self.long_term.truncate(0); + self.ref_pics.clear(); + self.long_term.clear(); } - #[allow(clippy::cyclomatic_complexity)] + #[allow(clippy::cognitive_complexity)] pub fn select_refs(&mut self, sps: &SeqParameterSet, slice_hdr: &SliceHeader, cur_id: u32) { - self.ref_list0.truncate(0); - self.ref_list1.truncate(0); + self.cur_id = cur_id; + self.ref_list0.clear(); + self.ref_list1.clear(); let pic_num_mask = if sps.log2_max_frame_num == 16 { 0xFFFF } else { @@ -328,7 +334,20 @@ impl FrameRefs { } pub fn add_short_term(&mut self, cpic: PictureInfo, num_ref_frames: usize) { if !self.ref_pics.is_empty() && self.ref_pics.len() >= num_ref_frames { - self.ref_pics.remove(0); + let base_id = i32::from(cpic.id); + let mut min_id = base_id; + let mut min_idx = 0; + for (i, pic) in self.ref_pics.iter().enumerate() { + let mut pic_id = i32::from(pic.id); + if pic_id > base_id { + pic_id -= self.max_frame_num; + } + if pic_id < min_id { + min_id = pic_id; + min_idx = i; + } + } + self.ref_pics.remove(min_idx); } if self.ref_pics.is_empty() || self.ref_pics.last().unwrap().full_id < cpic.full_id { self.ref_pics.push(cpic); @@ -352,11 +371,7 @@ impl FrameRefs { pub fn select_ref_pic(&self, list_id: u8, ref_id: usize) -> Option> { let ref_list = if list_id == 0 { &self.ref_list0 } else { &self.ref_list1 }; if ref_list.len() > ref_id { - if let Some(ref pic) = ref_list[ref_id] { - Some(pic.buf.clone()) - } else { - None - } + ref_list[ref_id].as_ref().map(|pic| pic.buf.clone()) } else { None } @@ -407,6 +422,35 @@ impl FrameRefs { }; [ref0, ref1] } + pub fn cmp_refs(&self, ref1: [PicRef; 2], ref2: [PicRef; 2]) -> bool { + if ref1 != ref2 { + self.cmp_ref(ref1[0], ref2[0], 0) && self.cmp_ref(ref1[1], ref2[1], 1) + } else { + true + } + } + fn cmp_ref(&self, ref1: PicRef, ref2: PicRef, list: u8) -> bool { + if ref1 == ref2 { + true + } else { + let idx0 = ref1.index(); + let idx1 = ref2.index(); + if idx0 == idx1 { + return true; + } + let src = if list == 0 { &self.ref_list0 } else { &self.ref_list1 }; + if idx0 >= src.len() || idx1 >= src.len() { +//panic!("wrong refs"); + return false; + } + if let (Some(ref pic0), Some(ref pic1)) = (&src[idx0], &src[idx1]) { + pic0.full_id == pic1.full_id + } else { +//panic!("missing pics"); + false + } + } + } } fn form_ref_list(ref_list: &mut Vec>, ref_pics: &[PictureInfo], long_term: &[Option], reord_info: &ReorderingInfo, cur_id: u16, pic_num_mask: u16) {