h264: more micro-optimisations
[nihav.git] / nihav-itu / src / codecs / h264 / types.rs
index 00aa72e3e2d963bb17886f61f34c0c65f976986f..4bcdb4943547318d09df4c858f7412fa7aedd080 100644 (file)
@@ -1,9 +1,31 @@
-use nihav_core::frame::NASimpleVideoFrame;
+use nihav_core::frame::{NAVideoBuffer, NASimpleVideoFrame};
 use nihav_codec_support::codecs::{MV, ZERO_MV};
 use nihav_codec_support::data::GenericCache;
-use super::SliceRefs;
+use super::SimplifiedSliceRefs;
 use super::pic_ref::FrameMBInfo;
 
+#[derive(Clone,Copy)]
+pub struct SimpleFrame<'a> {
+    pub data:   &'a [u8],
+    pub offset: [usize; 3],
+    pub stride: [usize; 3],
+}
+
+impl<'a> SimpleFrame<'a> {
+    pub fn new(buf: &'a NAVideoBuffer<u8>) -> Self {
+        let mut offset = [0; 3];
+        let mut stride = [0; 3];
+        for (plane, (offs, strd)) in offset.iter_mut().zip(stride.iter_mut()).enumerate() {
+            *offs = buf.get_offset(plane);
+            *strd = buf.get_stride(plane);
+        }
+        Self {
+            data:   buf.get_data(),
+            offset, stride
+        }
+    }
+}
+
 #[repr(u8)]
 #[derive(Clone,Copy,Debug,PartialEq)]
 pub enum BMode {
@@ -361,8 +383,9 @@ pub struct MBData {
 }
 
 pub fn blk4_to_blk8(blk4: usize) -> usize {
-    const MAP: [usize; 16] = [ 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3 ];
-    MAP[blk4 & 0xF]
+    /*const MAP: [usize; 16] = [ 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3 ];
+    MAP[blk4 & 0xF]*/
+    ((blk4 & 2) >> 1) | ((blk4 & 8) >> 2)
 }
 
 #[derive(Clone,Copy)]
@@ -478,7 +501,7 @@ impl SliceState {
             }
         }
     }
-    pub fn fill_deblock(&mut self, frefs: &SliceRefs, deblock_mode: u8, is_s: bool) {
+    pub fn fill_deblock(&mut self, frefs: &SimplifiedSliceRefs, deblock_mode: u8, is_s: bool) {
         if deblock_mode == 1 {
             return;
         }
@@ -551,7 +574,7 @@ impl SliceState {
                         if cur_cc || top_cc {
                             self.deblock[y * 4 + x] |= 0x20;
                         } else {
-                            if mvdiff4(cur_mv[0], top_mv[0]) || mvdiff4(cur_mv[1], top_mv[1]) || !frefs.cmp_refs(cur_ref, top_ref) {
+                            if mvdiff4(cur_mv, top_mv) || !frefs.cmp_refs(cur_ref, top_ref) {
                                 self.deblock[y * 4 + x] |= 0x10;
                             }
                         }
@@ -574,7 +597,7 @@ impl SliceState {
                 } else if cur_cc || left_cc {
                     self.deblock[y * 4 + x] |= 2;
                 } else {
-                    if mvdiff4(cur_mv[0], left_mv[0]) || mvdiff4(cur_mv[1], left_mv[1]) || !frefs.cmp_refs(cur_ref, left_ref) {
+                    if mvdiff4(cur_mv, left_mv) || !frefs.cmp_refs(cur_ref, left_ref) {
                         self.deblock[y * 4 + x] |= 1;
                     }
                 }
@@ -773,7 +796,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: &SliceRefs, temporal_mv: bool, direct_8x8: bool, cur_id: u16) {
+    pub fn predict_direct_mb(&mut self, frame_refs: &SimplifiedSliceRefs, 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 {
@@ -793,7 +816,7 @@ impl SliceState {
             }
         }
     }
-    pub fn predict_direct_sub(&mut self, frame_refs: &SliceRefs, temporal_mv: bool, direct8x8: bool, cur_id: u16, blk4: usize) {
+    pub fn predict_direct_sub(&mut self, frame_refs: &SimplifiedSliceRefs, 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);
@@ -801,7 +824,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: &SliceRefs, 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: &SimplifiedSliceRefs, 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)
@@ -917,7 +940,27 @@ impl SliceState {
     }
 }
 
-fn mvdiff4(mv1: MV, mv2: MV) -> bool {
-    let mv = mv1 - mv2;
-    (mv.x.abs() >= 4) || (mv.y.abs() >= 4)
+#[cfg(not(target_arch="x86_64"))]
+fn mvdiff4(mv1: &[MV; 2], mv2: &[MV; 2]) -> bool {
+    let mvd0 = mv1[0] - mv2[0];
+    let mvd1 = mv1[1] - mv2[1];
+    (mvd0.x.abs() >= 4) || (mvd0.y.abs() >= 4) || (mvd1.x.abs() >= 4) || (mvd1.y.abs() >= 4)
+}
+
+#[cfg(target_arch="x86_64")]
+fn mvdiff4(mv1: &[MV; 2], mv2: &[MV; 2]) -> bool {
+    unsafe {
+        let mut flag = false;
+        let ptr = std::mem::transmute::<*const MV, *const u64>(mv1.as_ptr());
+        let mut m0 = *ptr;
+        let ptr = std::mem::transmute::<*const MV, *const u64>(mv2.as_ptr());
+        let mut m1 = *ptr;
+        for _ in 0..4 {
+            let tmp = m0.wrapping_sub(m1) as u16;
+            flag |= tmp.wrapping_add(3) > 6;
+            m0 >>= 16;
+            m1 >>= 16;
+        }
+        flag
+    }
 }