From 8266abfe96cb1b46f537aec66b3dfcf22da2bb1c Mon Sep 17 00:00:00 2001
From: Paul Wilkins <paulwilkins@google.com>
Date: Thu, 9 Feb 2012 15:44:18 +0000
Subject: [PATCH] Dual pred flag

Further changes to make experiments with the context
used for coding the dual pred flag easier.

Current best performing method tested on derf is a two
element context based on reference frame. I also tried
various combinations of mode and reference frame as
shown in commented out case using up to 6 contexts.

Derf +0.26 overall psnr +0.15% ssim vs original method.

Change-Id: I64c21ddec0abbb27feaaeaa1da2e9f164ebaca03
---
 vp8/common/onyxc_int.h    | 10 +++++++++-
 vp8/common/pred_common.c  | 19 ++++++++----------
 vp8/decoder/decodemv.c    |  6 +++---
 vp8/encoder/bitstream.c   |  8 ++++----
 vp8/encoder/encodeframe.c | 41 +++++++++++++++++++++++++--------------
 vp8/encoder/onyx_if.c     |  5 ++---
 vp8/encoder/onyx_int.h    |  3 ++-
 7 files changed, 54 insertions(+), 38 deletions(-)

diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h
index b05bf2596c..d6f5b13152 100644
--- a/vp8/common/onyxc_int.h
+++ b/vp8/common/onyxc_int.h
@@ -48,6 +48,14 @@ void vp8_initialize_common(void);
 
 #define MAX_PARTITIONS 9
 
+#if CONFIG_DUALPRED
+#if CONFIG_COMPRED
+#define DUAL_PRED_CONTEXTS   2
+#else
+#define DUAL_PRED_CONTEXTS   3
+#endif
+#endif /* CONFIG_DUALPRED */
+
 typedef struct frame_contexts
 {
     vp8_prob bmode_prob [VP8_BINTRAMODES-1];
@@ -242,7 +250,7 @@ typedef struct VP8Common
 #endif
 
 #if CONFIG_DUALPRED
-    vp8_prob prob_dualpred[3];
+    vp8_prob prob_dualpred[DUAL_PRED_CONTEXTS];
 #endif /* CONFIG_DUALPRED */
 
     FRAME_CONTEXT lfc_a; /* last alt ref entropy */
diff --git a/vp8/common/pred_common.c b/vp8/common/pred_common.c
index 810c11d2fe..6d82568127 100644
--- a/vp8/common/pred_common.c
+++ b/vp8/common/pred_common.c
@@ -41,24 +41,21 @@ unsigned char get_pred_context( VP8_COMMON *const cm,
     case PRED_DUAL:
         // Context based on use of dual pred flag by neighbours
         //pred_context =
-        //    ((m - 1)->mbmi.second_ref_frame != INTRA_FRAME) +
+        //   ((m - 1)->mbmi.second_ref_frame != INTRA_FRAME) +
         //    ((m - cm->mode_info_stride)->mbmi.second_ref_frame != INTRA_FRAME);
 
-        // Context based on mode
-        //if ( m->mbmi.mode == ZEROMV )
-        //    pred_context = 0;
-        //else if ( (m->mbmi.mode == NEARESTMV) || (m->mbmi.mode == NEARMV) )
-        //    pred_context = 1;
+        // Context based on mode and reference frame
+        //if ( m->mbmi.ref_frame == LAST_FRAME )
+        //    pred_context = 0 + (m->mbmi.mode != ZEROMV);
+        //else if ( m->mbmi.ref_frame == GOLDEN_FRAME )
+        //    pred_context = 2 + (m->mbmi.mode != ZEROMV);
         //else
-        //    pred_context = 2;
+        //    pred_context = 4 + (m->mbmi.mode != ZEROMV);
 
-        // Context based on reference frame
         if ( m->mbmi.ref_frame == LAST_FRAME )
             pred_context = 0;
-        else if ( m->mbmi.ref_frame == GOLDEN_FRAME )
-            pred_context = 1;
         else
-            pred_context = 2;
+            pred_context = 1;
 
         break;
 #endif
diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c
index d87c328ed1..23d22c09a6 100644
--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -521,9 +521,9 @@ static void mb_mode_mv_init(VP8D_COMP *pbi)
             cm->dual_pred_mode += vp8_read(bc, 128);
         if (cm->dual_pred_mode == HYBRID_PREDICTION)
         {
-            cm->prob_dualpred[0] = (vp8_prob)vp8_read_literal(bc, 8);
-            cm->prob_dualpred[1] = (vp8_prob)vp8_read_literal(bc, 8);
-            cm->prob_dualpred[2] = (vp8_prob)vp8_read_literal(bc, 8);
+            int i;
+            for ( i = 0; i < DUAL_PRED_CONTEXTS; i++ )
+                cm->prob_dualpred[i] = (vp8_prob)vp8_read_literal(bc, 8);
         }
 #endif /* CONFIG_DUALPRED */
 
diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c
index 2d4bb4badb..dd8d3d7a6a 100644
--- a/vp8/encoder/bitstream.c
+++ b/vp8/encoder/bitstream.c
@@ -1060,7 +1060,7 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
 
 #if CONFIG_DUALPRED
 #if !CONFIG_COMPRED
-    int prob_dual_pred[3];
+    int prob_dual_pred[DUAL_PRED_CONTEXTS];
 #endif
 #endif /* CONFIG_DUALPRED */
 
@@ -1110,7 +1110,7 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
     {
         vp8_write(w, 1, 128);
         vp8_write(w, 1, 128);
-        for (i = 0; i < 3; i++)
+        for (i = 0; i < DUAL_PRED_CONTEXTS; i++)
         {
             if (cpi->single_pred_count[i] + cpi->dual_pred_count[i])
             {
@@ -1470,7 +1470,7 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
 
 #if CONFIG_DUALPRED
 #if !CONFIG_COMPRED
-    int prob_dual_pred[3];
+    int prob_dual_pred[DUAL_PRED_CONTEXTS];
 #endif
 #endif /* CONFIG_DUALPRED */
 
@@ -1517,7 +1517,7 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
     {
         vp8_write(w, 1, 128);
         vp8_write(w, 1, 128);
-        for (i = 0; i < 3; i++)
+        for (i = 0; i < DUAL_PRED_CONTEXTS; i++)
         {
             if (cpi->single_pred_count[i] + cpi->dual_pred_count[i])
             {
diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c
index b12a41aa04..c79ce67dfa 100644
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -1284,8 +1284,8 @@ static void encode_frame_internal(VP8_COMP *cpi)
     init_encode_frame_mb_context(cpi);
 #if CONFIG_DUALPRED
     cpi->rd_single_diff = cpi->rd_dual_diff = cpi->rd_hybrid_diff = 0;
-    cpi->single_pred_count[0] = cpi->single_pred_count[1] = cpi->single_pred_count[2] = 0;
-    cpi->dual_pred_count[0]   = cpi->dual_pred_count[1]   = cpi->dual_pred_count[2]   = 0;
+    vpx_memset(cpi->single_pred_count, 0, sizeof(cpi->single_pred_count));
+    vpx_memset(cpi->dual_pred_count, 0, sizeof(cpi->dual_pred_count));
 #endif /* CONFIG_DUALPRED */
 
     {
@@ -1513,15 +1513,21 @@ void vp8_encode_frame(VP8_COMP *cpi)
         }
         else if (cpi->common.dual_pred_mode == HYBRID_PREDICTION)
         {
-            if (cpi->dual_pred_count[0] == 0 &&
-                cpi->dual_pred_count[1] == 0 &&
-                cpi->dual_pred_count[2] == 0)
+            int single_count_zero = 0;
+            int dual_count_zero = 0;
+            int i;
+
+            for ( i = 0; i < DUAL_PRED_CONTEXTS; i++ )
+            {
+                single_count_zero += cpi->single_pred_count[i];
+                dual_count_zero += cpi->dual_pred_count[i];
+            }
+
+            if (dual_count_zero == 0)
             {
                 cpi->common.dual_pred_mode = SINGLE_PREDICTION_ONLY;
             }
-            else if (cpi->single_pred_count[0] == 0 &&
-                     cpi->single_pred_count[1] == 0 &&
-                     cpi->single_pred_count[2] == 0)
+            else if (single_count_zero == 0)
             {
                 cpi->common.dual_pred_mode = DUAL_PREDICTION_ONLY;
             }
@@ -1533,22 +1539,27 @@ void vp8_encode_frame(VP8_COMP *cpi)
             }
         }
 
-
         if (redo)
         {
             encode_frame_internal(cpi);
 
             if (cpi->common.dual_pred_mode == HYBRID_PREDICTION)
             {
-                if (cpi->dual_pred_count[0] == 0 &&
-                    cpi->dual_pred_count[1] == 0 &&
-                    cpi->dual_pred_count[2] == 0)
+                int single_count_zero = 0;
+                int dual_count_zero = 0;
+                int i;
+
+                for ( i = 0; i < DUAL_PRED_CONTEXTS; i++ )
+                {
+                    single_count_zero += cpi->single_pred_count[i];
+                    dual_count_zero += cpi->dual_pred_count[i];
+                }
+
+                if (dual_count_zero == 0)
                 {
                     cpi->common.dual_pred_mode = SINGLE_PREDICTION_ONLY;
                 }
-                else if (cpi->single_pred_count[0] == 0 &&
-                         cpi->single_pred_count[1] == 0 &&
-                         cpi->single_pred_count[2] == 0)
+                else if (single_count_zero == 0)
                 {
                     cpi->common.dual_pred_mode = DUAL_PREDICTION_ONLY;
                 }
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index b427f96ad1..a4b730442a 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -2354,9 +2354,8 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
     cm->prob_gf_coded                 = 128;
     cm->prob_intra_coded              = 63;
 #if CONFIG_DUALPRED
-    cm->prob_dualpred[0]             = 128;
-    cm->prob_dualpred[1]             = 128;
-    cm->prob_dualpred[2]             = 128;
+    for ( i = 0; i < DUAL_PRED_CONTEXTS; i++ )
+        cm->prob_dualpred[i]         = 128;
 #endif /* CONFIG_DUALPRED */
 
     // Prime the recent reference frame useage counters.
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index 892d514ebc..ad5592fc18 100644
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -365,7 +365,8 @@ typedef struct VP8_COMP
 #if CONFIG_DUALPRED
     int rd_single_diff, rd_dual_diff, rd_hybrid_diff;
     int rd_prediction_type_threshes[4][NB_PREDICTION_TYPES];
-    int dual_pred_count[3], single_pred_count[3];
+    int dual_pred_count[DUAL_PRED_CONTEXTS];
+    int single_pred_count[DUAL_PRED_CONTEXTS];
 #endif /* CONFIG_DUALPRED */
 
     int RDMULT;
-- 
GitLab