fix clippy warnings
[nihav.git] / nihav-itu / src / codecs / h264 / pic_ref.rs
index c366b25aa1b6e508061d601760b7263e842e66d8..a24e9d0e0a4fb582b4cb9806501c891819673bea 100644 (file)
@@ -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<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)]
@@ -45,10 +49,110 @@ impl FrameMV {
     }
 }
 
-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,
@@ -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<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 {
@@ -217,13 +339,15 @@ impl FrameRefs {
     }
     #[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 {
@@ -231,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 {
@@ -243,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);
@@ -279,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 {
@@ -314,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);
@@ -328,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);
@@ -349,93 +486,6 @@ impl FrameRefs {
             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) {