From 78c51dcb3b8d5ff5de8887f7dfede0b4a93d8b17 Mon Sep 17 00:00:00 2001
From: Frank Bossen <fbossen@gmail.com>
Date: Sat, 13 Oct 2018 11:19:23 +0800
Subject: [PATCH] Reduce bit width of ref_frames and avoid wrapping subs

---
 src/api.rs       | 12 +++++++-----
 src/encoder.rs   | 10 +++++-----
 src/me.rs        |  2 +-
 src/partition.rs |  2 +-
 4 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/src/api.rs b/src/api.rs
index 9c091809..e19cfc1d 100644
--- a/src/api.rs
+++ b/src/api.rs
@@ -253,14 +253,16 @@ impl Context {
 
       self.fi.primary_ref_frame = (ref_in_previous_group - LAST_FRAME) as u32;
 
+      assert!(group_src_len <= REF_FRAMES as u64);
       for i in 0..INTER_REFS_PER_FRAME {
-        self.fi.ref_frames[i] = if i == second_ref_frame - LAST_FRAME {
-          (slot_idx as u64 + if lvl == 0 { 6 * group_src_len } else { group_src_len >> lvl }) & 7
+        self.fi.ref_frames[i] = (slot_idx as u8 +
+        if i == second_ref_frame - LAST_FRAME {
+          if lvl == 0 { (REF_FRAMES as u64 - 2) * group_src_len } else { group_src_len >> lvl }
         } else if i == ref_in_previous_group - LAST_FRAME {
-          (slot_idx as u64 - group_src_len) & 7
+          REF_FRAMES as u64 - group_src_len
         } else {
-          (slot_idx as u64 - (group_src_len >> lvl)) & 7
-        } as usize;
+          REF_FRAMES as u64 - (group_src_len >> lvl)
+        } as u8) & 7;
       }
 
       self.fi.number = segment_idx * key_frame_interval + self.fi.order_hint as u64;
diff --git a/src/encoder.rs b/src/encoder.rs
index 0e1d8291..ac098bae 100644
--- a/src/encoder.rs
+++ b/src/encoder.rs
@@ -364,7 +364,7 @@ pub struct FrameInvariants {
     pub cdef_uv_strengths: [u8; 8],
     pub delta_q_present: bool,
     pub config: EncoderConfig,
-    pub ref_frames: [usize; INTER_REFS_PER_FRAME],
+    pub ref_frames: [u8; INTER_REFS_PER_FRAME],
     pub ref_frame_sign_bias: [bool; INTER_REFS_PER_FRAME],
     pub rec_buffer: ReferenceFramesSet,
     pub base_q_idx: u8,
@@ -1047,7 +1047,7 @@ impl<W: io::Write> UncompressedHeader for BitWriter<W, BigEndian> {
                 let prev_ref_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE {
                     [1, 0, 0, 0, 0, -1, -1, -1]
                 } else {
-                    fi.rec_buffer.deblock[fi.ref_frames[fi.primary_ref_frame as usize]].ref_deltas
+                    fi.rec_buffer.deblock[fi.ref_frames[fi.primary_ref_frame as usize] as usize].ref_deltas
                 };
                 for i in 0..REF_FRAMES {
                     let update = fs.deblock.ref_deltas[i] != prev_ref_deltas[i];
@@ -1060,7 +1060,7 @@ impl<W: io::Write> UncompressedHeader for BitWriter<W, BigEndian> {
                 let prev_mode_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE {
                     [0, 0]
                 } else {
-                    fi.rec_buffer.deblock[fi.ref_frames[fi.primary_ref_frame as usize]].mode_deltas
+                    fi.rec_buffer.deblock[fi.ref_frames[fi.primary_ref_frame as usize] as usize].mode_deltas
                 };
                 for i in 0..2 {
                     let update = fs.deblock.mode_deltas[i] != prev_mode_deltas[i];
@@ -1965,7 +1965,7 @@ fn encode_tile(sequence: &mut Sequence, fi: &FrameInvariants, fs: &mut FrameStat
     let fc = if fi.primary_ref_frame == PRIMARY_REF_NONE {
       CDFContext::new(fi.base_q_idx)
     } else {
-      match fi.rec_buffer.frames[fi.ref_frames[fi.primary_ref_frame as usize]] {
+      match fi.rec_buffer.frames[fi.ref_frames[fi.primary_ref_frame as usize] as usize] {
         Some(ref rec) => rec.cdfs.clone(),
         None => CDFContext::new(fi.base_q_idx)
       }
@@ -2054,7 +2054,7 @@ pub fn encode_frame(sequence: &mut Sequence, fi: &mut FrameInvariants, fs: &mut
                 fi.ref_frame_sign_bias[i] =
                 if !sequence.enable_order_hint {
                     false
-                } else if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[i]] {
+                } else if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[i] as usize] {
                     let hint = rec.order_hint;
                     sequence.get_relative_dist(hint, fi.order_hint) > 0
                 } else {
diff --git a/src/me.rs b/src/me.rs
index 1525245a..c95b01e3 100644
--- a/src/me.rs
+++ b/src/me.rs
@@ -39,7 +39,7 @@ pub fn motion_estimation(
   fi: &FrameInvariants, fs: &FrameState, bsize: BlockSize,
   bo: &BlockOffset, ref_frame: usize, pmv: &MotionVector
 ) -> MotionVector {
-  match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME]] {
+  match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME] as usize] {
     Some(ref rec) => {
       let po = PlaneOffset {
         x: (bo.x as isize) << BLOCK_TO_PLANE_SHIFT,
diff --git a/src/partition.rs b/src/partition.rs
index d60c1f4f..29dee4a6 100644
--- a/src/partition.rs
+++ b/src/partition.rs
@@ -932,7 +932,7 @@ impl PredictionMode {
   ) {
     assert!(!self.is_intra());
 
-    match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME]] {
+    match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME] as usize] {
       Some(ref rec) => {
         let rec_cfg = &rec.frame.planes[p].cfg;
         let shift_row = 3 + rec_cfg.ydec;
-- 
GitLab