]> granicus.if.org Git - libvpx/commitdiff
made vp8_mode_context adaptive
authorYaowu Xu <yaowu@google.com>
Tue, 6 Dec 2011 20:03:42 +0000 (12:03 -0800)
committerYaowu Xu <yaowu@google.com>
Wed, 7 Dec 2011 19:01:59 +0000 (11:01 -0800)
vp8_mode_contexts[] is an entropy table used to code inter mode
choices. It was a fixed constant table. This commit made the entropy
context adaptive. Tests on derf set showed very good consistent gains
on all metrics: avg psnr .47%, overall psnr .46% and ssim .40%.

http://www.corp.google.com/~yaowu/no_crawl/newModeContext.html

Change-Id: Ia62b14485c948e2b74586118619c5eb2068b43b2

14 files changed:
vp8/common/alloccommon.c
vp8/common/entropymode.c
vp8/common/findnearmv.c
vp8/common/findnearmv.h
vp8/common/modecont.c
vp8/common/modecont.h
vp8/common/onyxc_int.h
vp8/decoder/decodemv.c
vp8/decoder/decodframe.c
vp8/encoder/bitstream.c
vp8/encoder/mcomp.c
vp8/encoder/pickinter.c
vp8/encoder/ratectrl.c
vp8/encoder/rdopt.c

index 61bb317770e5215368cfd9072823d09340c56a36..0c7a9ef8d719e7e6884c1e2883799602a1e27020 100644 (file)
@@ -190,6 +190,13 @@ void vp8_create_common(VP8_COMMON *oci)
     vp8_machine_specific_config(oci);
 
     vp8_init_mbmode_probs(oci);
+#if CONFIG_NEWNEAR
+    vp8_init_mv_ref_counts(oci);
+#endif
+    vpx_memcpy( oci->vp8_mode_contexts,
+                default_vp8_mode_contexts,
+                sizeof(default_vp8_mode_contexts));
+
     vp8_default_bmode_probs(oci->fc.bmode_prob);
 
     oci->mb_no_coeff_skip = 1;
index 8b99344610505b88948f24ed6829fea1f4fb2027..15fbc41b6518aef714ff66d8fac8a81421728353 100644 (file)
@@ -385,3 +385,103 @@ void vp8_entropy_mode_init()
 
     vp8_tokens_from_tree(vp8_small_mvencodings, vp8_small_mvtree);
 }
+
+#if CONFIG_NEWNEAR
+void vp8_init_mv_ref_counts(VP8_COMMON *pc)
+{
+    vpx_memset(pc->mv_ref_ct, 0, sizeof(pc->mv_ref_ct));
+}
+
+void vp8_accum_mv_refs(VP8_COMMON *pc,
+                       MB_PREDICTION_MODE m,
+                       const int ct[4])
+{
+    if (m == ZEROMV)
+    {
+        ++pc->mv_ref_ct [ct[0]] [0] [0];
+    }
+    else
+    {
+        ++pc->mv_ref_ct [ct[0]] [0] [1];
+        if (m == NEARESTMV)
+        {
+            ++pc->mv_ref_ct [ct[1]] [1] [0];
+        }
+        else
+        {
+            ++pc->mv_ref_ct [ct[1]] [1] [1];
+            if (m == NEARMV)
+            {
+                ++pc->mv_ref_ct [ct[2]] [2] [0];
+            }
+            else
+            {
+                ++pc->mv_ref_ct [ct[2]] [2] [1];
+                if (m == NEWMV)
+                {
+                    ++pc->mv_ref_ct [ct[3]] [3] [0];
+                }
+                else
+                {
+                    ++pc->mv_ref_ct [ct[3]] [3] [1];
+                }
+            }
+        }
+    }
+}
+
+void vp8_update_mode_context(VP8_COMMON *pc)
+{
+    int i, j;
+    for (j = 0; j < 6; j++)
+    {
+        for (i = 0; i < 4; i++)
+        {
+            int this_prob;
+            int count;
+            // context probs
+            count = pc->mv_ref_ct[j][i][0] + pc->mv_ref_ct[j][i][1];
+            if (count)
+                this_prob = 256 * pc->mv_ref_ct[j][i][0] / count;
+            else
+                this_prob = 128;
+            if (this_prob == 0)
+                this_prob = 1;
+            if (this_prob == 256)
+                this_prob = 255;
+
+            pc->mode_context[j][i] = this_prob;
+        }
+    }
+}
+#include "vp8/common/modecont.h"
+void print_mode_contexts(VP8_COMMON *pc)
+{
+    int j, i;
+    for(j=0; j<6; j++)
+    {
+        for (i = 0; i < 4; i++)
+        {
+            printf( "%4d ", pc->vp8_mode_contexts[j][i]);
+        }
+        printf("\n");
+    }
+}
+void print_mv_ref_cts(VP8_COMMON *pc)
+{
+    int j, i;
+    for(j=0; j<6; j++)
+    {
+        for (i = 0; i < 4; i++)
+        {
+            printf("(%4d:%4d) ",
+                    pc->mv_ref_ct[j][i][0],
+                    pc->mv_ref_ct[j][i][1]);
+        }
+        printf("\n");
+    }
+}
+
+
+#endif
+
index 23a28a7bda278df6a59bcbb2f842c87e4f6670dc..aace856b1624707b9321637c7e369ca8783cc712 100644 (file)
@@ -278,14 +278,14 @@ void vp8_find_near_mvs
 }
 #endif
 
-vp8_prob *vp8_mv_ref_probs(
+vp8_prob *vp8_mv_ref_probs(VP8_COMMON *pc,
     vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
 )
 {
-    p[0] = vp8_mode_contexts [near_mv_ref_ct[0]] [0];
-    p[1] = vp8_mode_contexts [near_mv_ref_ct[1]] [1];
-    p[2] = vp8_mode_contexts [near_mv_ref_ct[2]] [2];
-    p[3] = vp8_mode_contexts [near_mv_ref_ct[3]] [3];
+    p[0] = pc->vp8_mode_contexts [near_mv_ref_ct[0]] [0];
+    p[1] = pc->vp8_mode_contexts [near_mv_ref_ct[1]] [1];
+    p[2] = pc->vp8_mode_contexts [near_mv_ref_ct[2]] [2];
+    p[3] = pc->vp8_mode_contexts [near_mv_ref_ct[3]] [3];
     return p;
 }
 
index b07a54b5ccb5576baa773b0c01bf20dfbda99b64..b26f9873bafdba823db9d3585844698191b7d46a 100644 (file)
@@ -16,6 +16,7 @@
 #include "blockd.h"
 #include "modecont.h"
 #include "treecoder.h"
+#include "onyxc_int.h"
 
 
 static void mv_bias(int refmb_ref_frame_sign_bias, int refframe, int_mv *mvp, const int *ref_frame_sign_bias)
@@ -84,7 +85,7 @@ void vp8_find_near_mvs
     int *ref_frame_sign_bias
 );
 
-vp8_prob *vp8_mv_ref_probs(
+vp8_prob *vp8_mv_ref_probs(VP8_COMMON *pc,
     vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
 );
 
index 86a74bc0ff5544a6ffebd6630dbf7e4a38a26e3c..d7491f241e0180c4c53f7f19953a2a754a3f918a 100644 (file)
@@ -11,7 +11,7 @@
 
 #include "entropy.h"
 
-const int vp8_mode_contexts[6][4] =
+const int default_vp8_mode_contexts[6][4] =
 {
     {
         /* 0 */
index 24db88295f92aaa052d3303198101aac8725c848..476ae3fa9dd673394bc537d8b07bcef2d8a150e9 100644 (file)
@@ -12,6 +12,6 @@
 #ifndef __INC_MODECONT_H
 #define __INC_MODECONT_H
 
-extern const int vp8_mode_contexts[6][4];
+extern const int default_vp8_mode_contexts[6][4];
 
 #endif
index 08fc79501232189d957386931da142a9b58e9299..04f8507d62d4770cde7532bd5111a82b592e76db 100644 (file)
@@ -218,6 +218,13 @@ typedef struct VP8Common
     FRAME_CONTEXT lfc; /* last frame entropy */
     FRAME_CONTEXT fc;  /* this frame entropy */
 
+#if CONFIG_NEWNEAR
+    int mv_ref_ct[6][4][2];
+    int mode_context[6][4];
+#endif
+
+    int vp8_mode_contexts[6][4];
+
     unsigned int current_video_frame;
 
     int near_boffset[3];
index 8934b62a80539635ae3f13c2cd3fd891399c3f15..75d47dc187320ccb91e3da273acf59f4b82b09ac 100644 (file)
@@ -548,7 +548,7 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
 #endif
             &nearest, &nearby, &best_mv, rct,
                           mbmi->ref_frame, pbi->common.ref_frame_sign_bias);
-        vp8_mv_ref_probs(mv_ref_p, rct);
+        vp8_mv_ref_probs(&pbi->common, mv_ref_p, rct);
 
 //#if CONFIG_SEGFEATURES
         // Is the segment level mode feature enabled for this segment
@@ -560,6 +560,10 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
         else
         {
             mbmi->mode = read_mv_ref(bc, mv_ref_p);
+
+#if CONFIG_NEWNEAR
+            vp8_accum_mv_refs(&pbi->common, mbmi->mode, rct);
+#endif
         }
 
         mbmi->uv_mode = DC_PRED;
index 2ad5d1b87cd352af269bb8d2f45ed265164d2162..b9fefa94e363042620437de9bcf2c2ea4f040247 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "decodemv.h"
 #include "vp8/common/extend.h"
+#include "vp8/common/modecont.h"
 #if CONFIG_ERROR_CONCEALMENT
 #include "error_concealment.h"
 #endif
@@ -862,7 +863,9 @@ static void init_frame(VP8D_COMP *pbi)
         vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc));
         vpx_memcpy(&pc->lfc_a, &pc->fc, sizeof(pc->fc));
 #endif
-
+#if CONFIG_NEWNEAR
+        vp8_init_mv_ref_counts(&pbi->common);
+#endif
     }
     else
     {
@@ -1364,8 +1367,30 @@ int vp8_decode_frame(VP8D_COMP *pbi)
     /* Read the mb_no_coeff_skip flag */
     pc->mb_no_coeff_skip = (int)vp8_read_bit(bc);
 
-
     vp8_decode_mode_mvs(pbi);
+#if CONFIG_NEWNEAR
+    if(!pbi->common.refresh_alt_ref_frame)
+    {
+        vp8_update_mode_context(&pbi->common);
+        vpx_memcpy( pc->vp8_mode_contexts,
+                    pbi->common.mode_context,
+                    sizeof(pbi->common.mode_context));
+
+            if(0) //pbi->common.current_video_frame<2)
+            {
+                printf("mv_ref_ct on frame %d:\n",
+                        pbi->common.current_video_frame);
+                print_mv_ref_cts(&pbi->common);
+
+                printf("mode_contexts on frame %d:\n",
+                        pbi->common.current_video_frame);
+                print_mode_contexts();
+            }
+
+
+    }
+#endif
+
 
 #if CONFIG_ERROR_CONCEALMENT
     if (pbi->ec_active &&
index 43182b10dbac6e456993acebbf86bda2d8e795c1..955cc313325ec10cd1202fccb49aa473b5e42dba 100644 (file)
@@ -1156,18 +1156,20 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
             else
             {
                 int_mv best_mv;
+                int ct[4];
+
                 vp8_prob mv_ref_p [VP8_MVREFS-1];
 
                 {
                     int_mv n1, n2;
-                    int ct[4];
 
                     vp8_find_near_mvs(xd, m,
 #if CONFIG_NEWNEAR
                         prev_m,
 #endif
                         &n1, &n2, &best_mv, ct, rf, cpi->common.ref_frame_sign_bias);
-                    vp8_mv_ref_probs(mv_ref_p, ct);
+                    vp8_mv_ref_probs(&cpi->common, mv_ref_p, ct);
+
 
 #ifdef ENTROPY_STATS
                     accum_mv_refs(mode, ct);
@@ -1183,6 +1185,9 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
                 if ( !segfeature_active( xd, segment_id, SEG_LVL_MODE ) )
                 {
                     write_mv_ref(w, mode, mv_ref_p);
+#if CONFIG_NEWNEAR
+                    vp8_accum_mv_refs(&cpi->common, mode, ct);
+#endif
                 }
 
                 {
@@ -2326,6 +2331,28 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
     {
         pack_inter_mode_mvs(cpi);
 
+#if CONFIG_NEWNEAR
+        if(!cpi->common.refresh_alt_ref_frame)
+        {
+            vp8_update_mode_context(&cpi->common);
+            vpx_memcpy( pc->vp8_mode_contexts,
+                        cpi->common.mode_context,
+                        sizeof(cpi->common.mode_context));
+
+            if(0) //(cpi->common.current_video_frame<2)
+            {
+
+                printf("mv_ref_ct on frame %d:\n",
+                        cpi->common.current_video_frame);
+                print_mv_ref_cts(&cpi->common);
+
+                printf("mode_contexts on frame %d:\n",
+                        cpi->common.current_video_frame);
+                print_mode_contexts();
+            }
+        }
+#endif
+
 #ifdef ENTROPY_STATS
         active_section = 1;
 #endif
index aebcfce70cb8bebffbcf9c0d0f44654907c9527b..b23abffadc6a4ed7eb45f5148129b496b3726f34 100644 (file)
@@ -1852,41 +1852,28 @@ int vp8_refining_search_sadx4(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
         return INT_MAX;
 }
 
+
+
 #ifdef ENTROPY_STATS
 void print_mode_context(void)
 {
-    FILE *f = fopen("modecont.c", "w");
+    FILE *f = fopen("modecont.c", "a");
     int i, j;
 
     fprintf(f, "#include \"entropy.h\"\n");
-    fprintf(f, "const int vp8_mode_contexts[6][4] =\n");
+    fprintf(f, "const int vp8_mode_contexts[6][4] =");
     fprintf(f, "{\n");
-
     for (j = 0; j < 6; j++)
     {
-        fprintf(f, "  { // %d \n", j);
+        fprintf(f, "  {/* %d */ ", j);
         fprintf(f, "    ");
-
         for (i = 0; i < 4; i++)
         {
-            int overal_prob;
             int this_prob;
-            int count; // = mv_ref_ct[j][i][0]+mv_ref_ct[j][i][1];
-
-            // Overall probs
-            count = mv_mode_cts[i][0] + mv_mode_cts[i][1];
-
-            if (count)
-                overal_prob = 256 * mv_mode_cts[i][0] / count;
-            else
-                overal_prob = 128;
-
-            if (overal_prob == 0)
-                overal_prob = 1;
+            int count;
 
             // context probs
             count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1];
-
             if (count)
                 this_prob = 256 * mv_ref_ct[j][i][0] / count;
             else
@@ -1894,12 +1881,8 @@ void print_mode_context(void)
 
             if (this_prob == 0)
                 this_prob = 1;
-
             fprintf(f, "%5d, ", this_prob);
-            //fprintf(f,"%5d, %5d, %8d,", this_prob, overal_prob, (this_prob << 10)/overal_prob);
-            //fprintf(f,"%8d, ", (this_prob << 10)/overal_prob);
         }
-
         fprintf(f, "  },\n");
     }
 
@@ -1908,7 +1891,6 @@ void print_mode_context(void)
 }
 
 /* MV ref count ENTROPY_STATS stats code */
-#ifdef ENTROPY_STATS
 void init_mv_ref_counts()
 {
     vpx_memset(mv_ref_ct, 0, sizeof(mv_ref_ct));
@@ -1964,4 +1946,4 @@ void accum_mv_refs(MB_PREDICTION_MODE m, const int ct[4])
 
 #endif/* END MV ref count ENTROPY_STATS stats code */
 
-#endif
+
index 4b622d8bff76650532a0fae4340ec78770cc50cd..19ab4d434ec63de7a398549c2495bcc983ba4f4b 100644 (file)
@@ -47,7 +47,8 @@ extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
 extern const MV_REFERENCE_FRAME vp8_second_ref_frame_order[MAX_MODES];
 
 extern unsigned int (*vp8_get4x4sse_cs)(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride);
-extern int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4]);
+extern int vp8_cost_mv_ref(VP8_COMMON *pc,
+                           MB_PREDICTION_MODE m, const int near_mv_ref_ct[4]);
 
 
 int vp8_skip_fractional_mv_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d,
@@ -811,7 +812,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
                 ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max))
                 continue;
 
-            rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+            rate2 += vp8_cost_mv_ref(&cpi->common, this_mode, mdcounts);
             x->e_mbd.mode_info_context->mbmi.mv.as_int =
                                                     mode_mv[this_mode].as_int;
 
index d510ad958a66d309500a85cfde71241303b4cca0..d4ca381aea2d14125e327bdf3588e3b2b0aeb375 100644 (file)
@@ -267,6 +267,9 @@ void vp8_setup_key_frame(VP8_COMP *cpi)
     vpx_memcpy(&cpi->common.lfc_a, &cpi->common.fc, sizeof(cpi->common.fc));
 #endif
 
+#if CONFIG_NEWNEAR
+    vp8_init_mv_ref_counts(&cpi->common);
+#endif
 }
 #if CONFIG_MULCONTEXT
 void vp8_setup_inter_frame(VP8_COMP *cpi)
index 00055f9f18a4227844c87a02886e34402493fb26..f4a44baa730ac4828ba0e0be0e470537f3c50a2d 100644 (file)
@@ -1142,11 +1142,13 @@ static void rd_pick_intra_mbuv_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int
     x->e_mbd.mode_info_context->mbmi.uv_mode = mode_selected;
 }
 
-int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4])
+int vp8_cost_mv_ref(VP8_COMMON *pc,
+                    MB_PREDICTION_MODE m,
+                    const int near_mv_ref_ct[4])
 {
     vp8_prob p [VP8_MVREFS-1];
     assert(NEARESTMV <= m  &&  m <= SPLITMV);
-    vp8_mv_ref_probs(p, near_mv_ref_ct);
+    vp8_mv_ref_probs(pc, p, near_mv_ref_ct);
     return vp8_cost_token(vp8_mv_ref_tree, p,
                           vp8_mv_ref_encoding_array - NEARESTMV + m);
 }
@@ -1362,7 +1364,7 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x,
 
     // Segmentation method overheads
     rate = vp8_cost_token(vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings + segmentation);
-    rate += vp8_cost_mv_ref(SPLITMV, bsi->mdcounts);
+    rate += vp8_cost_mv_ref(&cpi->common, SPLITMV, bsi->mdcounts);
     this_segment_rd += RDCOST(x->rdmult, x->rddiv, rate, 0);
     br += rate;
 
@@ -2613,7 +2615,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
             //intermodecost[mode_index] = vp8_cost_mv_ref(this_mode, mdcounts);   // Experimental debug code
 
             // Add in the Mv/mode cost
-            rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+            rate2 += vp8_cost_mv_ref(&cpi->common, this_mode, mdcounts);
 
             // Y cost and distortion
             macro_block_yrd(x, &rate_y, &distortion, IF_RTCD(&cpi->rtcd.encodemb));
@@ -2674,7 +2676,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
             }
 
             /* Add in the Mv/mode cost */
-            rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+            rate2 += vp8_cost_mv_ref(&cpi->common,this_mode, mdcounts);
 
             vp8_clamp_mv2(&x->e_mbd.mode_info_context->mbmi.mv, xd);
             vp8_clamp_mv2(&x->e_mbd.mode_info_context->mbmi.second_mv, xd);