From 59a200f1ea73d2327746fff3d35a05aec10e436f Mon Sep 17 00:00:00 2001
From: Paul Wilkins <paulwilkins@google.com>
Date: Wed, 8 Feb 2012 15:52:07 +0000
Subject: [PATCH] Changes to coding of dual_pred flag.

Further use of common prediction functions and experiments
with alternate contexts based on mode and reference frame.

For the Derf set using reference frame as basis of context
gives +0.18% Overall Psnr and +0.08 SSIM

Change-Id: Ie7eb76f329f74c9c698614f01ece31de0b6bfc9e
---
 vp8/common/pred_common.c  | 29 ++++++++++++++++++++++++-----
 vp8/encoder/bitstream.c   | 39 +++++++++++++++++++++++++++++++--------
 vp8/encoder/encodeframe.c | 18 +++++++++++++-----
 3 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/vp8/common/pred_common.c b/vp8/common/pred_common.c
index affdae4ba6..810c11d2fe 100644
--- a/vp8/common/pred_common.c
+++ b/vp8/common/pred_common.c
@@ -39,10 +39,27 @@ unsigned char get_pred_context( VP8_COMMON *const cm,
         break;
 
     case PRED_DUAL:
-        // Second ref not INTRA indicates use of dual pred in neighbour
-        pred_context =
-            ((m - 1)->mbmi.second_ref_frame != INTRA_FRAME) +
-            ((m - cm->mode_info_stride)->mbmi.second_ref_frame != INTRA_FRAME);
+        // Context based on use of dual pred flag by neighbours
+        //pred_context =
+        //    ((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;
+        //else
+        //    pred_context = 2;
+
+        // 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;
+
         break;
 #endif
 
@@ -79,7 +96,9 @@ vp8_prob get_pred_prob( VP8_COMMON *const cm,
         break;
 
     case PRED_DUAL:
-        // Second ref non zero indicates use of dual pred in neighbour
+        // In keeping with convention elsewhre the probability returned is
+        // the probability of a "0" outcome which in this case means the
+        // probability of dual pred off.
         pred_probability = cm->prob_dualpred[pred_context];
         break;
 #endif
diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c
index d027b03b42..2d4bb4badb 100644
--- a/vp8/encoder/bitstream.c
+++ b/vp8/encoder/bitstream.c
@@ -1057,8 +1057,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
     int row, col;
 
     int prob_skip_false = 0;
+
 #if CONFIG_DUALPRED
+#if !CONFIG_COMPRED
     int prob_dual_pred[3];
+#endif
 #endif /* CONFIG_DUALPRED */
 
     // Values used in prediction model coding
@@ -1111,8 +1114,20 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
         {
             if (cpi->single_pred_count[i] + cpi->dual_pred_count[i])
             {
+#if CONFIG_COMPRED
+                pc->prob_dualpred[i] = cpi->single_pred_count[i] * 255 /
+                    (cpi->single_pred_count[i] + cpi->dual_pred_count[i]);
+                if (pc->prob_dualpred[i] < 1)
+                    pc->prob_dualpred[i] = 1;
+            }
+            else
+            {
+                pc->prob_dualpred[i] = 128;
+            }
+            vp8_write_literal(w, pc->prob_dualpred[i], 8);
+#else
                 prob_dual_pred[i] = cpi->single_pred_count[i] * 256 /
-                            (cpi->single_pred_count[i] + cpi->dual_pred_count[i]);
+                    (cpi->single_pred_count[i] + cpi->dual_pred_count[i]);
                 if (prob_dual_pred[i] < 1)
                     prob_dual_pred[i] = 1;
                 else if (prob_dual_pred[i] > 255)
@@ -1123,9 +1138,6 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
                 prob_dual_pred[i] = 128;
             }
             vp8_write_literal(w, prob_dual_pred[i], 8);
-
-#if CONFIG_COMPRED
-            pc->prob_dualpred[i] = prob_dual_pred[i];
 #endif
         }
     }
@@ -1457,7 +1469,9 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
     int prob_skip_false = 0;
 
 #if CONFIG_DUALPRED
+#if !CONFIG_COMPRED
     int prob_dual_pred[3];
+#endif
 #endif /* CONFIG_DUALPRED */
 
     // Values used in prediction model coding
@@ -1507,8 +1521,20 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
         {
             if (cpi->single_pred_count[i] + cpi->dual_pred_count[i])
             {
+#if CONFIG_COMPRED
+                pc->prob_dualpred[i] = cpi->single_pred_count[i] * 255 /
+                    (cpi->single_pred_count[i] + cpi->dual_pred_count[i]);
+                if (pc->prob_dualpred[i] < 1)
+                    pc->prob_dualpred[i] = 1;
+            }
+            else
+            {
+                pc->prob_dualpred[i] = 128;
+            }
+            vp8_write_literal(w, pc->prob_dualpred[i], 8);
+#else
                 prob_dual_pred[i] = cpi->single_pred_count[i] * 256 /
-                            (cpi->single_pred_count[i] + cpi->dual_pred_count[i]);
+                    (cpi->single_pred_count[i] + cpi->dual_pred_count[i]);
                 if (prob_dual_pred[i] < 1)
                     prob_dual_pred[i] = 1;
                 else if (prob_dual_pred[i] > 255)
@@ -1519,9 +1545,6 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
                 prob_dual_pred[i] = 128;
             }
             vp8_write_literal(w, prob_dual_pred[i], 8);
-
-#if CONFIG_COMPRED
-            pc->prob_dualpred[i] = prob_dual_pred[i];
 #endif
         }
     }
diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c
index 388d8a6bb2..b12a41aa04 100644
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -1811,13 +1811,21 @@ int vp8cx_encode_inter_macroblock
         if (x->e_mbd.mode_info_context->mbmi.ref_frame &&
             x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
         {
-            MB_MODE_INFO *t = &x->e_mbd.mode_info_context[-cpi->common.mode_info_stride].mbmi;
+            unsigned char pred_context;
+
+#if CONFIG_COMPRED
+            pred_context = get_pred_context( cm, xd, PRED_DUAL );
+#else
+            MB_MODE_INFO *t = &x->e_mbd.mode_info_context
+                              [-cpi->common.mode_info_stride].mbmi;
             MB_MODE_INFO *l = &x->e_mbd.mode_info_context[-1].mbmi;
-            int cnt = (t->second_ref_frame != INTRA_FRAME) + (l->second_ref_frame != INTRA_FRAME);
-            if (x->e_mbd.mode_info_context->mbmi.second_ref_frame == INTRA_FRAME)
-                cpi->single_pred_count[cnt]++;
+            pred_context = (t->second_ref_frame != INTRA_FRAME) +
+                           (l->second_ref_frame != INTRA_FRAME);
+#endif
+            if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME)
+                cpi->single_pred_count[pred_context]++;
             else
-                cpi->dual_pred_count[cnt]++;
+                cpi->dual_pred_count[pred_context]++;
         }
 #endif /* CONFIG_DUALPRED */
 
-- 
GitLab