X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-itu%2Fsrc%2Fcodecs%2Fh264%2Fpic_ref.rs;h=b027d06504fbee77afdb85d4acd10e1f50033cee;hb=HEAD;hp=fd2ae974fa557e7ee8203cdae60858d08191b3c6;hpb=93839abd64a4c725e0194a790ffd743dd8c19916;p=nihav.git diff --git a/nihav-itu/src/codecs/h264/pic_ref.rs b/nihav-itu/src/codecs/h264/pic_ref.rs index fd2ae97..b027d06 100644 --- a/nihav-itu/src/codecs/h264/pic_ref.rs +++ b/nihav-itu/src/codecs/h264/pic_ref.rs @@ -1,5 +1,5 @@ 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; @@ -10,10 +10,13 @@ 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: NABufferRef, @@ -53,7 +56,16 @@ pub struct SliceRefs { pub cur_id: u32, } +#[allow(dead_code)] 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 { @@ -139,6 +151,139 @@ impl SliceRefs { } } +#[derive(Clone)] +pub struct SimplePictureInfo<'a> { + pub full_id: u32, + pub buf: SimpleFrame<'a>, + pub long_term: bool, + pub mv_info: &'a FrameMV, +} + +#[derive(Clone)] +pub struct SimplifiedSliceRefs<'a> { + pub ref_list0: Vec>>, + pub ref_list1: Vec>>, + pub cur_id: u32, +} + +impl<'a> SimplifiedSliceRefs<'a> { + pub fn new(srefs: &'a SliceRefs) -> Self { + let mut ref_list0 = Vec::with_capacity(srefs.ref_list0.len()); + let mut ref_list1 = Vec::with_capacity(srefs.ref_list1.len()); + for entry in srefs.ref_list0.iter() { + ref_list0.push(entry.as_ref().map(|pic| SimplePictureInfo { + full_id: pic.full_id, + buf: SimpleFrame::new(&pic.buf), + long_term: pic.long_term.is_some(), + mv_info: &pic.mv_info, + })); + } + for entry in srefs.ref_list1.iter() { + ref_list1.push(entry.as_ref().map(|pic| SimplePictureInfo { + full_id: pic.full_id, + buf: SimpleFrame::new(&pic.buf), + long_term: pic.long_term.is_some(), + mv_info: &pic.mv_info, + })); + } + Self { + cur_id: srefs.cur_id, + ref_list0, ref_list1 + } + } + 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<&SimpleFrame> { + 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) + } 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) + } 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; + 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, @@ -171,6 +316,18 @@ impl FrameRefs { 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 {