]> git.nihav.org Git - nihav.git/commitdiff
h264: split current slice references into a separate structure
authorKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 14 Jun 2023 16:41:31 +0000 (18:41 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 14 Jun 2023 16:41:31 +0000 (18:41 +0200)
This will become useful when decoding a whole frame at once.

nihav-itu/src/codecs/h264/decoder_st.rs
nihav-itu/src/codecs/h264/mb_recon.rs
nihav-itu/src/codecs/h264/pic_ref.rs
nihav-itu/src/codecs/h264/types.rs

index d906e592d6155213d5327e923f98db21fec67e61..3cffc6a278c04f3dae0d6e27513b3e7d9f54d353 100644 (file)
@@ -272,7 +272,7 @@ println!("PAFF?");
 
         Ok(())
     }
-    fn pred_mv(sstate: &mut SliceState, frame_refs: &FrameRefs, mb_info: &mut CurrentMBInfo, cur_id: u16, temporal_mv: bool, direct_8x8: bool) {
+    fn pred_mv(sstate: &mut SliceState, frame_refs: &SliceRefs, mb_info: &mut CurrentMBInfo, cur_id: u16, temporal_mv: bool, direct_8x8: bool) {
         let mb_type = mb_info.mb_type;
         if !mb_type.is_4x4() {
             let (pw, ph) = mb_type.size();
@@ -399,7 +399,7 @@ println!("PAFF?");
             self.sstate.reset_mb_mv();
         }
         if !mb_info.mb_type.is_intra() {
-            Self::pred_mv(&mut self.sstate, &self.frame_refs, mb_info, self.cur_id, self.temporal_mv, self.sps[self.cur_sps].direct_8x8_inference);
+            Self::pred_mv(&mut self.sstate, &self.frame_refs.cur_refs, mb_info, self.cur_id, self.temporal_mv, self.sps[self.cur_sps].direct_8x8_inference);
         }
         if !pps.constrained_intra_pred && mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
             self.sstate.fill_ipred(IntraPredMode::DC);
@@ -417,7 +417,7 @@ println!("PAFF?");
                     } else {
                         0
                     };
-                recon_mb(&mut frm, slice_hdr, mb_info, &mut self.sstate, &self.frame_refs, &mut self.mc_dsp, weight_mode);
+                recon_mb(&mut frm, slice_hdr, mb_info, &mut self.sstate, &self.frame_refs.cur_refs, &mut self.mc_dsp, weight_mode);
             } else {
                 for (dline, src) in frm.data[frm.offset[0] + xpos + ypos * frm.stride[0]..].chunks_mut(frm.stride[0]).take(16).zip(self.ipcm_buf.chunks(16)) {
                     dline[..16].copy_from_slice(src);
@@ -451,13 +451,13 @@ _ => {},
                 mb.mv[blk4] = self.sstate.get_cur_blk4(blk4).mv;
             }
             for blk8 in 0..4 {
-                mb.ref_poc[blk8] = self.frame_refs.map_refs(self.sstate.get_cur_blk8(blk8).ref_idx);
+                mb.ref_poc[blk8] = self.frame_refs.cur_refs.map_refs(self.sstate.get_cur_blk8(blk8).ref_idx);
                 mb.ref_idx[blk8] = self.sstate.get_cur_blk8(blk8).ref_idx;
             }
             mv_info.mbs[mb_pos] = mb;
         }
         if !self.deblock_skip && self.deblock_mode != 1 {
-            self.sstate.fill_deblock(&self.frame_refs, self.deblock_mode, self.is_s);
+            self.sstate.fill_deblock(&self.frame_refs.cur_refs, self.deblock_mode, self.is_s);
             if let Some(ref mut pic) = self.cur_pic {
                 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
                 loop_filter_mb(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
index e17095b6c39d4c877eb55fe775b0ffaa9868a168..eb32792d6d8369ef65864766a48ae45ab5f2197c 100644 (file)
@@ -2,7 +2,7 @@ use nihav_core::frame::*;
 use nihav_codec_support::codecs::MV;
 use super::{CurrentMBInfo, I4X4_SCAN};
 use super::dsp::*;
-use super::pic_ref::FrameRefs;
+use super::pic_ref::SliceRefs;
 use super::slice::{SliceHeader, WeightInfo, DEF_WEIGHT_INFO};
 use super::types::*;
 
@@ -368,7 +368,7 @@ fn do_b_mc(frm: &mut NASimpleVideoFrame<u8>, mode: BMode, xpos: usize, ypos: usi
     }
 }
 
-fn get_weights(slice_hdr: &SliceHeader, frame_refs: &FrameRefs, mode: BMode, weight_mode: u8, ref_l0: PicRef, ref_l1: PicRef) -> (WeightInfo, WeightInfo) {
+fn get_weights(slice_hdr: &SliceHeader, frame_refs: &SliceRefs, mode: BMode, weight_mode: u8, ref_l0: PicRef, ref_l1: PicRef) -> (WeightInfo, WeightInfo) {
     let idx_l0 = ref_l0.index();
     let idx_l1 = ref_l1.index();
     if mode != BMode::Bi || weight_mode != 2 {
@@ -418,7 +418,7 @@ fn get_weights(slice_hdr: &SliceHeader, frame_refs: &FrameRefs, mode: BMode, wei
     }
 }
 
-pub fn recon_mb(frm: &mut NASimpleVideoFrame<u8>, slice_hdr: &SliceHeader, mb_info: &CurrentMBInfo, sstate: &mut SliceState, frame_refs: &FrameRefs, mc_dsp: &mut H264MC, weight_mode: u8) {
+pub fn recon_mb(frm: &mut NASimpleVideoFrame<u8>, slice_hdr: &SliceHeader, mb_info: &CurrentMBInfo, sstate: &mut SliceState, frame_refs: &SliceRefs, mc_dsp: &mut H264MC, weight_mode: u8) {
     let xpos = sstate.mb_x * 16;
     let ypos = sstate.mb_y * 16;
 
index cafcc56b5e73485388d4c35f25547c292293b24d..bf838be4204e1cc4bf096e8fa02edb03da1bc552 100644 (file)
@@ -45,12 +45,103 @@ 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 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>>,
-    pub cur_id:         u32,
 
     prev_poc_msb:       u32,
     prev_poc_lsb:       u16,
@@ -64,10 +155,12 @@ 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(),
-            cur_id:     0,
 
             prev_poc_msb:       0,
             prev_poc_lsb:       0,
@@ -222,14 +315,15 @@ impl FrameRefs {
     }
     #[allow(clippy::cognitive_complexity)]
     pub fn select_refs(&mut self, sps: &SeqParameterSet, slice_hdr: &SliceHeader, cur_id: u32) {
-        self.cur_id = cur_id;
-        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 {
@@ -237,7 +331,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 {
@@ -249,26 +343,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);
@@ -285,26 +379,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 {
@@ -320,11 +414,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);
@@ -368,89 +462,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 {
-            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
-            }
-        }
-    }
 }
 
 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) {
index 319ebf5f5aafb9817aa75c04e0cb117c04f3c3c1..9df866e829348526c92e92f7f1d6d91903560354 100644 (file)
@@ -1,7 +1,7 @@
 use nihav_core::frame::NASimpleVideoFrame;
 use nihav_codec_support::codecs::{MV, ZERO_MV};
 use nihav_codec_support::data::GenericCache;
-use super::FrameRefs;
+use super::SliceRefs;
 use super::pic_ref::FrameMBInfo;
 
 #[repr(u8)]
@@ -490,7 +490,7 @@ impl SliceState {
             }
         }
     }
-    pub fn fill_deblock(&mut self, frefs: &FrameRefs, deblock_mode: u8, is_s: bool) {
+    pub fn fill_deblock(&mut self, frefs: &SliceRefs, deblock_mode: u8, is_s: bool) {
         if deblock_mode == 1 {
             return;
         }
@@ -744,7 +744,7 @@ impl SliceState {
         self.fill_mv (0, 0, 16, 16, 0, mv);
         self.fill_ref(0, 0, 16, 16, 0, ref_idx);
     }
-    pub fn predict_direct_mb(&mut self, frame_refs: &FrameRefs, temporal_mv: bool, direct_8x8: bool, cur_id: u16) {
+    pub fn predict_direct_mb(&mut self, frame_refs: &SliceRefs, temporal_mv: bool, direct_8x8: bool, cur_id: u16) {
         let (col_mb, r1_poc, r1_long) = frame_refs.get_colocated_info(self.mb_x, self.mb_y);
         if direct_8x8 {
             for blk4 in 0..16 {
@@ -764,7 +764,7 @@ impl SliceState {
             }
         }
     }
-    pub fn predict_direct_sub(&mut self, frame_refs: &FrameRefs, temporal_mv: bool, direct8x8: bool, cur_id: u16, blk4: usize) {
+    pub fn predict_direct_sub(&mut self, frame_refs: &SliceRefs, temporal_mv: bool, direct8x8: bool, cur_id: u16, blk4: usize) {
         let src_blk = if !direct8x8 { blk4 } else { BLK4_TO_D8[blk4] };
         let (mbi, r1_poc, r1_long) = frame_refs.get_colocated_info(self.mb_x, self.mb_y);
         let (mv0, ref0, mv1, ref1) = self.get_direct_mv(frame_refs, &mbi, r1_poc, r1_long, temporal_mv, cur_id, src_blk);
@@ -772,7 +772,7 @@ impl SliceState {
         self.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx = [ref0, ref1];
     }
     #[allow(clippy::nonminimal_bool)]
-    pub fn get_direct_mv(&self, frame_refs: &FrameRefs, mbi: &FrameMBInfo, r1_poc: u16, r1_long: bool, temporal_mv: bool, cur_id: u16, blk4: usize) -> (MV, PicRef, MV, PicRef) {
+    pub fn get_direct_mv(&self, frame_refs: &SliceRefs, mbi: &FrameMBInfo, r1_poc: u16, r1_long: bool, temporal_mv: bool, cur_id: u16, blk4: usize) -> (MV, PicRef, MV, PicRef) {
         let blk8 = blk4_to_blk8(blk4);
         let (col_mv, r0_poc, col_idx) = if mbi.ref_poc[blk8] == [MISSING_POC; 2] {
                 (ZERO_MV, MISSING_POC, MISSING_REF)