X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-itu%2Fsrc%2Fcodecs%2Fh264%2Fpic_ref.rs;h=a24e9d0e0a4fb582b4cb9806501c891819673bea;hb=e6aaad5c5273cd814b5748b7faf3751835a37217;hp=88d453d724fbbbae602ffbdbc91224bd65fd423d;hpb=696e4e20bf7167121352f247893370cb83213d5c;p=nihav.git diff --git a/nihav-itu/src/codecs/h264/pic_ref.rs b/nihav-itu/src/codecs/h264/pic_ref.rs index 88d453d..a24e9d0 100644 --- a/nihav-itu/src/codecs/h264/pic_ref.rs +++ b/nihav-itu/src/codecs/h264/pic_ref.rs @@ -1,5 +1,6 @@ use nihav_core::codecs::DecoderResult; -use nihav_core::frame::{FrameType, NAVideoBufferRef}; +use nihav_core::frame::{FrameType, NAVideoBufferRef, NATimeInfo}; +use nihav_core::refs::*; use nihav_codec_support::codecs::MV; use super::sets::SeqParameterSet; use super::slice::*; @@ -9,13 +10,16 @@ use super::types::*; pub struct PictureInfo { pub id: u16, pub full_id: u32, + pub time: NATimeInfo, + pub user_id: u32, pub pic_type: FrameType, pub buf: NAVideoBufferRef, pub cur_mb: usize, pub is_ref: bool, + pub is_idr: bool, pub long_term: Option, - pub mv_info: FrameMV, //todo replace with refcounted index to a pool + pub mv_info: NABufferRef, } #[derive(Clone,Copy,Default, Debug)] @@ -45,10 +49,110 @@ impl FrameMV { } } -pub struct FrameRefs { - pub ref_pics: Vec, +#[derive(Clone)] +pub struct SliceRefs { pub ref_list0: Vec>, pub ref_list1: Vec>, + pub cur_id: u32, +} + +impl SliceRefs { + pub fn get_ref_id(&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 { + ref_list[ref_id].as_ref().map(|pic| pic.full_id) + } else { + None + } + } + 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 { + ref_list[ref_id].as_ref().map(|pic| pic.buf.clone()) + } else { + None + } + } + pub fn get_colocated_info(&self, mb_x: usize, mb_y: usize) -> (FrameMBInfo, u16, bool) { + if let Some(ref ref_pic) = &self.ref_list1[0] { + let mv_info = &ref_pic.mv_info; + let mb = mv_info.mbs[mb_x + mb_y * mv_info.mb_stride]; + (mb, ref_pic.full_id as u16, ref_pic.long_term.is_some()) + } else { + (FrameMBInfo::default(), 0, false) + } + } + pub fn map_ref0(&self, ref0_id: u16) -> (PicRef, bool) { + let mut r0_idx = 0; + let mut long = false; + for (i, rpic0) in self.ref_list0.iter().enumerate() { + if let Some(ref pic) = rpic0 { + if (pic.full_id as u16) == ref0_id { + r0_idx = i as u8; + long = pic.long_term.is_some(); + break; + } + } + } + (PicRef::new(r0_idx), long) + } + pub fn map_refs(&self, ref_idx: [PicRef; 2]) -> [u16; 2] { + let r0 = ref_idx[0].index(); + let r1 = ref_idx[1].index(); + let ref0 = if r0 < self.ref_list0.len() { + if let Some(ref pic) = self.ref_list0[r0] { + pic.full_id as u16 + } else { + MISSING_POC + } + } else { + MISSING_POC + }; + let ref1 = if r1 < self.ref_list1.len() { + if let Some(ref pic) = self.ref_list1[r1] { + pic.full_id as u16 + } else { + MISSING_POC + } + } else { + MISSING_POC + }; + [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 + } + } + } +} + +pub struct FrameRefs { + pub ref_pics: Vec, + pub cur_refs: SliceRefs, pub long_term: Vec>, prev_poc_msb: u32, @@ -56,14 +160,18 @@ pub struct FrameRefs { prev_ref_poc_lsb: u16, prev_frame_num: u16, frame_num_offset: u32, + max_frame_num: i32, } impl FrameRefs { pub fn new() -> Self { Self { ref_pics: Vec::with_capacity(16), - ref_list0: Vec::with_capacity(3), - ref_list1: Vec::with_capacity(3), + cur_refs: SliceRefs { + ref_list0: Vec::with_capacity(3), + ref_list1: Vec::with_capacity(3), + cur_id: 0, + }, long_term: Vec::new(), prev_poc_msb: 0, @@ -71,9 +179,23 @@ impl FrameRefs { prev_ref_poc_lsb: 0, prev_frame_num: 0, frame_num_offset: 0, + max_frame_num: 0, + } + } + pub fn fill_ref_nums(&self, dst: &mut Vec) { + for pic in self.ref_pics.iter() { + if !dst.contains(&pic.full_id) { + dst.push(pic.full_id); + } + } + for pic in self.long_term.iter().flatten() { + if !dst.contains(&pic.full_id) { + dst.push(pic.full_id); + } } } 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 +322,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,17 +334,20 @@ 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::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_refs.cur_id = cur_id; + self.cur_refs.ref_list0.clear(); + self.cur_refs.ref_list1.clear(); let pic_num_mask = if sps.log2_max_frame_num == 16 { 0xFFFF } else { (1 << sps.log2_max_frame_num) - 1 }; + if !slice_hdr.slice_type.is_intra() { let has_reordering = slice_hdr.ref_pic_list_reordering_l0; if !has_reordering { @@ -230,7 +355,7 @@ impl FrameRefs { if slice_hdr.slice_type.is_p() { if !self.ref_pics.is_empty() { for pic in self.ref_pics.iter().rev().take(num_ref) { - self.ref_list0.push(Some(pic.clone())); + self.cur_refs.ref_list0.push(Some(pic.clone())); } } } else { @@ -242,26 +367,26 @@ impl FrameRefs { } } for pic in self.ref_pics[..pivot].iter().rev() { - if self.ref_list0.len() >= num_ref { + if self.cur_refs.ref_list0.len() >= num_ref { break; } - self.ref_list0.push(Some(pic.clone())); + self.cur_refs.ref_list0.push(Some(pic.clone())); } for pic in self.ref_pics.iter().skip(pivot) { - if self.ref_list0.len() >= num_ref { + if self.cur_refs.ref_list0.len() >= num_ref { break; } - self.ref_list0.push(Some(pic.clone())); + self.cur_refs.ref_list0.push(Some(pic.clone())); } } - if !self.long_term.is_empty() && self.ref_list0.len() < num_ref { - let copy_size = num_ref - self.ref_list0.len(); + if !self.long_term.is_empty() && self.cur_refs.ref_list0.len() < num_ref { + let copy_size = num_ref - self.cur_refs.ref_list0.len(); for ltpic in self.long_term.iter().take(copy_size) { - self.ref_list0.push(ltpic.clone()); + self.cur_refs.ref_list0.push(ltpic.clone()); } } } else { - form_ref_list(&mut self.ref_list0, + form_ref_list(&mut self.cur_refs.ref_list0, &self.ref_pics, &self.long_term, &slice_hdr.reordering_list_l0, slice_hdr.frame_num, pic_num_mask); @@ -278,26 +403,26 @@ impl FrameRefs { } } for pic in self.ref_pics.iter().skip(pivot) { - if self.ref_list1.len() >= num_ref { + if self.cur_refs.ref_list1.len() >= num_ref { break; } - self.ref_list1.push(Some(pic.clone())); + self.cur_refs.ref_list1.push(Some(pic.clone())); } for pic in self.ref_pics[..pivot].iter().rev() { - if self.ref_list1.len() >= num_ref { + if self.cur_refs.ref_list1.len() >= num_ref { break; } - self.ref_list1.push(Some(pic.clone())); + self.cur_refs.ref_list1.push(Some(pic.clone())); } - if !self.long_term.is_empty() && self.ref_list1.len() < num_ref { - let copy_size = num_ref - self.ref_list1.len(); + if !self.long_term.is_empty() && self.cur_refs.ref_list1.len() < num_ref { + let copy_size = num_ref - self.cur_refs.ref_list1.len(); for ltpic in self.long_term.iter().take(copy_size) { - self.ref_list1.push(ltpic.clone()); + self.cur_refs.ref_list1.push(ltpic.clone()); } } - if self.ref_list1.len() > 1 && self.ref_list0.len() == self.ref_list1.len() { + if self.cur_refs.ref_list1.len() > 1 && self.cur_refs.ref_list0.len() == self.cur_refs.ref_list1.len() { let mut equal = true; - for (pic1, pic2) in self.ref_list0.iter().zip(self.ref_list1.iter()) { + for (pic1, pic2) in self.cur_refs.ref_list0.iter().zip(self.cur_refs.ref_list1.iter()) { match (pic1, pic2) { (Some(p1), Some(p2)) => { if p1.full_id != p2.full_id { @@ -313,11 +438,11 @@ impl FrameRefs { }; } if equal { - self.ref_list1.swap(0, 1); + self.cur_refs.ref_list1.swap(0, 1); } } } else { - form_ref_list(&mut self.ref_list1, + form_ref_list(&mut self.cur_refs.ref_list1, &self.ref_pics, &self.long_term, &slice_hdr.reordering_list_l1, slice_hdr.frame_num, pic_num_mask); @@ -327,7 +452,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); @@ -348,67 +486,9 @@ impl FrameRefs { self.long_term[lt_idx] = Some(cpic); } } - 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 - } - } else { - None - } - } - pub fn get_colocated_info(&self, mb_x: usize, mb_y: usize) -> (FrameMBInfo, u16, bool) { - if let Some(ref ref_pic) = &self.ref_list1[0] { - let mv_info = &ref_pic.mv_info; - let mb = mv_info.mbs[mb_x + mb_y * mv_info.mb_stride]; - (mb, ref_pic.full_id as u16, ref_pic.long_term.is_some()) - } else { - (FrameMBInfo::default(), 0, false) - } - } - pub fn map_ref0(&self, ref0_id: u16) -> (PicRef, bool) { - let mut r0_idx = 0; - let mut long = false; - for (i, rpic0) in self.ref_list0.iter().enumerate() { - if let Some(ref pic) = rpic0 { - if (pic.full_id as u16) == ref0_id { - r0_idx = i as u8; - long = pic.long_term.is_some(); - break; - } - } - } - (PicRef::new(r0_idx), long) - } - pub fn map_refs(&self, ref_idx: [PicRef; 2]) -> [u16; 2] { - let r0 = ref_idx[0].index(); - let r1 = ref_idx[1].index(); - let ref0 = if r0 < self.ref_list0.len() { - if let Some(ref pic) = self.ref_list0[r0] { - pic.full_id as u16 - } else { - MISSING_POC - } - } else { - MISSING_POC - }; - let ref1 = if r1 < self.ref_list1.len() { - if let Some(ref pic) = self.ref_list1[r1] { - pic.full_id as u16 - } else { - MISSING_POC - } - } else { - MISSING_POC - }; - [ref0, ref1] - } } -fn form_ref_list(ref_list: &mut Vec>, ref_pics: &Vec, long_term: &Vec>, reord_info: &ReorderingInfo, cur_id: u16, pic_num_mask: u16) { +fn form_ref_list(ref_list: &mut Vec>, ref_pics: &[PictureInfo], long_term: &[Option], reord_info: &ReorderingInfo, cur_id: u16, pic_num_mask: u16) { let mut ref_pic_id = cur_id; for (&op, &num) in reord_info.reordering_of_pic_nums_idc.iter().zip(reord_info.abs_diff_or_num.iter()).take(reord_info.num_ops) { if op < 2 {