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::*;
pub struct PictureInfo {
pub id: u16,
pub full_id: u32,
+ pub time: NATimeInfo,
+ pub user_id: u32,
pub pic_type: FrameType,
pub buf: NAVideoBufferRef<u8>,
pub cur_mb: usize,
pub is_ref: bool,
+ pub is_idr: bool,
pub long_term: Option<usize>,
- pub mv_info: FrameMV, //todo replace with refcounted index to a pool
+ pub mv_info: NABufferRef<FrameMV>,
}
#[derive(Clone,Copy,Default, Debug)]
}
}
-pub struct FrameRefs {
- pub ref_pics: Vec<PictureInfo>,
+#[derive(Clone)]
+pub struct SliceRefs {
pub ref_list0: Vec<Option<PictureInfo>>,
pub ref_list1: Vec<Option<PictureInfo>>,
+ pub cur_id: u32,
+}
+
+impl SliceRefs {
+ pub fn get_ref_id(&self, list_id: u8, ref_id: usize) -> Option<u32> {
+ 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<NAVideoBufferRef<u8>> {
+ 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<PictureInfo>,
+ pub cur_refs: SliceRefs,
pub long_term: Vec<Option<PictureInfo>>,
prev_poc_msb: u32,
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,
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<u32>) {
+ 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 {
}
#[allow(clippy::cognitive_complexity)]
pub fn select_refs(&mut self, sps: &SeqParameterSet, slice_hdr: &SliceHeader, cur_id: u32) {
- self.ref_list0.clear();
- self.ref_list1.clear();
+ 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 {
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 {
}
}
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);
}
}
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 {
};
}
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);
}
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);
self.long_term[lt_idx] = Some(cpic);
}
}
- pub fn select_ref_pic(&self, list_id: u8, ref_id: usize) -> Option<NAVideoBufferRef<u8>> {
- 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]
- }
- 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<Option<PictureInfo>>, ref_pics: &[PictureInfo], long_term: &[Option<PictureInfo>], reord_info: &ReorderingInfo, cur_id: u16, pic_num_mask: u16) {