h264: miscellaneous micro-optimisations
[nihav.git] / nihav-itu / src / codecs / h264 / decoder_st.rs
index d906e592d6155213d5327e923f98db21fec67e61..7e8b83a8187777cc0a62a1ce51e2aaf250d90fa0 100644 (file)
@@ -1,3 +1,5 @@
+use std::sync::Arc;
+
 use nihav_core::codecs::*;
 use nihav_core::io::bitreader::*;
 
@@ -9,9 +11,9 @@ struct H264Decoder {
     height:     usize,
     num_mbs:    usize,
     nal_len:    u8,
-    sps:        Vec<SeqParameterSet>,
+    sps:        Vec<Arc<SeqParameterSet>>,
     cur_sps:    usize,
-    pps:        Vec<PicParameterSet>,
+    pps:        Vec<Arc<PicParameterSet>>,
     cur_pps:    usize,
 
     skip_mode:      FrameSkipMode,
@@ -104,7 +106,7 @@ impl H264Decoder {
                 let mut br = BitReader::new(&src[..(full_size + 7)/8], BitReaderMode::BE);
                                                     br.skip(8)?;
 
-                let slice_hdr = parse_slice_header(&mut br, &self.sps, &self.pps, is_idr, nal_ref_idc)?;
+                let slice_hdr = parse_slice_header(&mut br, self.sps.as_slice(), self.pps.as_slice(), is_idr, nal_ref_idc)?;
                 validate!(br.tell() < full_size);
                 let full_id;
                 if slice_hdr.first_mb_in_slice == 0 {
@@ -201,12 +203,15 @@ println!("PAFF?");
                     self.cur_pic = Some(PictureInfo {
                             id: slice_hdr.frame_num,
                             full_id,
+                            user_id:    full_id,
+                            time:       NATimeInfo::new(None, None, None, 0, 0),
                             pic_type: slice_hdr.slice_type.to_frame_type(),
                             buf,
                             cur_mb: 0,
                             is_ref: nal_ref_idc != 0,
+                            is_idr,
                             long_term: get_long_term_id(is_idr, &slice_hdr),
-                            mv_info: FrameMV::new(sps.pic_width_in_mbs, sps.pic_height_in_mbs),
+                            mv_info: NABufferRef::new(FrameMV::new(sps.pic_width_in_mbs, sps.pic_height_in_mbs)),
                         });
                 }
 
@@ -217,7 +222,7 @@ println!("PAFF?");
                     self.has_pic = self.decode_slice_cavlc(&mut br, &slice_hdr, full_size)?;
                 } else {
                     br.align();
-                    let start = (br.tell() / 8) as usize;
+                    let start = br.tell() / 8;
                     let csrc = &src[start..];
                     validate!(csrc.len() >= 2);
                     let mut cabac = CABAC::new(csrc, slice_hdr.slice_type, slice_hdr.slice_qp, slice_hdr.cabac_init_idc as usize)?;
@@ -245,7 +250,7 @@ println!("PAFF?");
              6 => {}, //SEI
              7 => {
                 let sps = parse_sps(&src[1..])?;
-                self.sps.push(sps);
+                self.sps.push(Arc::new(sps));
             },
              8 => {
                 validate!(full_size >= 8 + 16);
@@ -253,7 +258,7 @@ println!("PAFF?");
                 let mut found = false;
                 for stored_pps in self.pps.iter_mut() {
                     if stored_pps.pic_parameter_set_id == pps.pic_parameter_set_id {
-                        *stored_pps = pps.clone();
+                        *stored_pps = Arc::clone(&pps);
                         found = true;
                         break;
                     }
@@ -272,7 +277,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();
@@ -357,25 +362,29 @@ println!("PAFF?");
                 mb_info.coeffs[i][0] = mb_info.coeffs[24][i];
             }
         }
-        if !mb_info.transform_size_8x8 {
-            let quant_dc = !mb_info.mb_type.is_intra16x16();
-            for i in 0..16 {
-                if mb_info.coded[i] {
-                    if !tx_bypass {
-                        idct(&mut mb_info.coeffs[i], qp_y, quant_dc);
+        if !tx_bypass {
+            if !mb_info.transform_size_8x8 {
+                let quant_dc = !mb_info.mb_type.is_intra16x16();
+                for (coded, coeffs) in mb_info.coded[..16].iter_mut().zip(mb_info.coeffs[..16].iter_mut()) {
+                    if *coded {
+                        idct(coeffs, qp_y, quant_dc);
+                    } else if has_dc {
+                        idct_dc(coeffs, qp_y, quant_dc);
+                        *coded = true;
                     }
-                } else if has_dc {
-                    if !tx_bypass {
-                        idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc);
+                }
+            } else {
+                for i in 0..4 {
+                    if mb_info.coded[(i & 1) * 2 + (i & 2) * 4] {
+                        dequant8x8(&mut mb_info.coeffs8x8[i].coeffs, &pps.scaling_list_8x8[!mb_info.mb_type.is_intra() as usize]);
+                        idct8x8(&mut mb_info.coeffs8x8[i].coeffs, qp_y);
                     }
-                    mb_info.coded[i] = true;
                 }
             }
-        } else {
-            for i in 0..4 {
-                if mb_info.coded[(i & 1) * 2 + (i & 2) * 4] && !tx_bypass {
-                    dequant8x8(&mut mb_info.coeffs8x8[i].coeffs, &pps.scaling_list_8x8[!mb_info.mb_type.is_intra() as usize]);
-                    idct8x8(&mut mb_info.coeffs8x8[i].coeffs, qp_y);
+        } else if !mb_info.transform_size_8x8 {
+            for i in 0..16 {
+                if !mb_info.coded[i] && has_dc {
+                    mb_info.coded[i] = true;
                 }
             }
         }
@@ -399,7 +408,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 +426,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 +460,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);
@@ -477,7 +486,7 @@ _ => {},
             17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41
         ];
 
-        let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
+        let mut mb_idx = slice_hdr.first_mb_in_slice;
         let mut mb_info = CurrentMBInfo { qp_y: slice_hdr.slice_qp, ..Default::default() };
         let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
         while br.tell() < full_size && mb_idx < self.num_mbs {
@@ -571,7 +580,7 @@ _ => {},
         Ok(mb_idx == self.num_mbs)
     }
     fn decode_slice_cabac(&mut self, cabac: &mut CABAC, slice_hdr: &SliceHeader) -> DecoderResult<bool> {
-        let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
+        let mut mb_idx = slice_hdr.first_mb_in_slice;
         let mut prev_mb_skipped = false;
         let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
         let mut last_qp_diff = false;
@@ -758,7 +767,7 @@ impl NADecoder for H264Decoder {
             }
 
             let num_bufs = if !self.sps.is_empty() {
-                    self.sps[0].num_ref_frames as usize + 1
+                    self.sps[0].num_ref_frames + 1
                 } else {
                     3
                 }.max(16 + 1);