]> granicus.if.org Git - libvpx/commitdiff
a new way of determining reference motion vector
authorYaowu Xu <yaowu@google.com>
Mon, 6 Aug 2012 17:51:20 +0000 (10:51 -0700)
committerYaowu Xu <yaowu@google.com>
Tue, 7 Aug 2012 18:25:57 +0000 (11:25 -0700)
Using surrounding reconstructed pixels from left and above to select
best matching mv to use as reference motion vector for mv encoding.

Test results:
       AVGPSNR  GLBPSNR VPXSSIM
Derf:  1.107%   1.062%  0.992%
Std-hd:1.209%   1.176%  1.029%

Change-Id: I8f10e09ee6538c05df2fb9f069abcaf1edb3fca6

13 files changed:
configure
vp8/common/blockd.h
vp8/common/findnearmv.c
vp8/common/findnearmv.h
vp8/decoder/decodemv.c
vp8/decoder/decodframe.c
vp8/decoder/onyxd_if.c
vp8/encoder/bitstream.c
vp8/encoder/encodeframe.c
vp8/encoder/onyx_int.h
vp8/encoder/rdopt.c
vp8/encoder/sad_c.c
vp8/encoder/tokenize.c

index b135874bdeb5d6450ac6fd9dff4ef7de598b5307..2593a0e60c8efccd20c54d2b71e8b7f3edb912cf 100755 (executable)
--- a/configure
+++ b/configure
@@ -226,6 +226,7 @@ EXPERIMENT_LIST="
     hybridtransform8x8
     switchable_interp
     tx16x16
+    newbestrefmv
 "
 CONFIG_LIST="
     external_build
index 2932fd4973990eedb65c46a40abaa5636ea9ac21..a0fe46cfa8135a3bcb51b663228a58da10908bc4 100644 (file)
@@ -267,6 +267,9 @@ typedef struct {
   MV_REFERENCE_FRAME ref_frame, second_ref_frame;
   TX_SIZE txfm_size;
   int_mv mv, second_mv;
+#if CONFIG_NEWBESTREFMV
+  int_mv ref_mv, second_ref_mv;
+#endif
   unsigned char partitioning;
   unsigned char mb_skip_coeff;                                /* does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens */
   unsigned char need_to_clamp_mvs;
@@ -423,6 +426,9 @@ typedef struct MacroBlockD {
 #endif
 
   int mb_index;   // Index of the MB in the SB (0..3)
+#if CONFIG_NEWBESTREFMV
+  int_mv ref_mv[4];
+#endif
 
 #if CONFIG_HYBRIDTRANSFORM
   int q_index;
index d35e2c4d480e67727226e4936df6f161c2fe06ee..303893d9dbe9458f42db265134bee042773cb6f1 100644 (file)
@@ -10,6 +10,7 @@
 
 
 #include "findnearmv.h"
+#include <limits.h>
 
 const unsigned char vp8_mbsplit_offset[4][16] = {
   { 0,  8,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
@@ -18,6 +19,15 @@ const unsigned char vp8_mbsplit_offset[4][16] = {
   { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15}
 };
 
+static void lower_mv_precision(int_mv *mv)
+{
+  if (mv->as_mv.row & 1)
+    mv->as_mv.row += (mv->as_mv.row > 0 ? -1 : 1);
+  if (mv->as_mv.col & 1)
+    mv->as_mv.col += (mv->as_mv.col > 0 ? -1 : 1);
+}
+
+
 /* Predict motion vectors using those from already-decoded nearby blocks.
    Note that we only consider one 4x4 subblock from each candidate 16x16
    macroblock.   */
@@ -32,8 +42,7 @@ void vp8_find_near_mvs
   int_mv *best_mv,
   int cnt[4],
   int refframe,
-  int *ref_frame_sign_bias
-) {
+  int *ref_frame_sign_bias) {
   const MODE_INFO *above = here - xd->mode_info_stride;
   const MODE_INFO *left = here - 1;
   const MODE_INFO *aboveleft = above - 1;
@@ -43,16 +52,30 @@ void vp8_find_near_mvs
   int             *cntx = cnt;
   enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV};
 
+#if CONFIG_NEWBESTREFMV
+  int_mv          *ref_mv = xd->ref_mv;
+#endif
+
   /* Zero accumulators */
   mv[0].as_int = mv[1].as_int = mv[2].as_int = 0;
   cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
+#if CONFIG_NEWBESTREFMV
+  ref_mv[0].as_int = ref_mv[1].as_int
+                   = ref_mv[2].as_int
+                   = ref_mv[3].as_int
+                   = 0;
+#endif
 
   /* Process above */
   if (above->mbmi.ref_frame != INTRA_FRAME) {
     if (above->mbmi.mv.as_int) {
-      (++mv)->as_int = above->mbmi.mv.as_int;
+      ++ mv;
+      mv->as_int = above->mbmi.mv.as_int;
       mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame],
               refframe, mv, ref_frame_sign_bias);
+#if CONFIG_NEWBESTREFMV
+      ref_mv[0].as_int = mv->as_int;
+#endif
       ++cntx;
     }
     *cntx += 2;
@@ -65,10 +88,13 @@ void vp8_find_near_mvs
       this_mv.as_int = left->mbmi.mv.as_int;
       mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame],
               refframe, &this_mv, ref_frame_sign_bias);
-
+#if CONFIG_NEWBESTREFMV
+      ref_mv[1].as_int = this_mv.as_int;
+#endif
       if (this_mv.as_int != mv->as_int) {
-        (++mv)->as_int = this_mv.as_int;
-        ++cntx;
+        ++ mv;
+        mv->as_int = this_mv.as_int;
+        ++ cntx;
       }
       *cntx += 2;
     } else
@@ -79,9 +105,21 @@ void vp8_find_near_mvs
       (lf_here->mbmi.ref_frame == LAST_FRAME && refframe == LAST_FRAME)) {
     if (aboveleft->mbmi.mv.as_int) {
       third = aboveleft;
+#if CONFIG_NEWBESTREFMV
+      ref_mv[2].as_int = aboveleft->mbmi.mv.as_int;
+      mv_bias(ref_frame_sign_bias[aboveleft->mbmi.ref_frame],
+              refframe, (ref_mv+2), ref_frame_sign_bias);
+#endif
     } else if (lf_here->mbmi.mv.as_int) {
       third = lf_here;
     }
+#if CONFIG_NEWBESTREFMV
+    if (lf_here->mbmi.mv.as_int) {
+      ref_mv[3].as_int = lf_here->mbmi.mv.as_int;
+      mv_bias(ref_frame_sign_bias[lf_here->mbmi.ref_frame],
+              refframe, (ref_mv+3), ref_frame_sign_bias);
+    }
+#endif
     if (third) {
       int_mv this_mv;
       this_mv.as_int = third->mbmi.mv.as_int;
@@ -89,8 +127,9 @@ void vp8_find_near_mvs
               refframe, &this_mv, ref_frame_sign_bias);
 
       if (this_mv.as_int != mv->as_int) {
-        (++mv)->as_int = this_mv.as_int;
-        ++cntx;
+        ++ mv;
+        mv->as_int = this_mv.as_int;
+        ++ cntx;
       }
       *cntx += 1;
     } else
@@ -134,18 +173,9 @@ void vp8_find_near_mvs
    * is not being used, by truncating the last bit towards 0
    */
   if (!xd->allow_high_precision_mv) {
-    if (best_mv->as_mv.row & 1)
-      best_mv->as_mv.row += (best_mv->as_mv.row > 0 ? -1 : 1);
-    if (best_mv->as_mv.col & 1)
-      best_mv->as_mv.col += (best_mv->as_mv.col > 0 ? -1 : 1);
-    if (nearest->as_mv.row & 1)
-      nearest->as_mv.row += (nearest->as_mv.row > 0 ? -1 : 1);
-    if (nearest->as_mv.col & 1)
-      nearest->as_mv.col += (nearest->as_mv.col > 0 ? -1 : 1);
-    if (nearby->as_mv.row & 1)
-      nearby->as_mv.row += (nearby->as_mv.row > 0 ? -1 : 1);
-    if (nearby->as_mv.col & 1)
-      nearby->as_mv.col += (nearby->as_mv.col > 0 ? -1 : 1);
+    lower_mv_precision(best_mv);
+    lower_mv_precision(nearest);
+    lower_mv_precision(nearby);
   }
 
   // TODO: move clamp outside findnearmv
@@ -163,3 +193,72 @@ vp8_prob *vp8_mv_ref_probs(VP8_COMMON *pc,
   p[3] = pc->fc.vp8_mode_contexts [near_mv_ref_ct[3]] [3];
   return p;
 }
+
+#if CONFIG_NEWBESTREFMV
+/* check a list of motion vectors by sad score using a number rows of pixels
+ * above and a number cols of pixels in the left to select the one with best
+ * score to use as ref motion vector
+ */
+void vp8_find_best_ref_mvs(MACROBLOCKD *xd,
+                           unsigned char *ref_y_buffer,
+                           int ref_y_stride,
+                           int_mv *best_mv){
+  int_mv *ref_mv = xd->ref_mv;
+  int bestsad = INT_MAX;
+  int i;
+  unsigned char *above_src;
+  unsigned char *left_src;
+  unsigned char *above_ref;
+  unsigned char *left_ref;
+  int sad;
+
+  above_src = xd->dst.y_buffer - xd->dst.y_stride * 2;
+  left_src  = xd->dst.y_buffer - 2;
+  above_ref = ref_y_buffer - ref_y_stride * 2;
+  left_ref  = ref_y_buffer - 2;
+
+  bestsad = vp8_sad16x2_c(above_src, xd->dst.y_stride,
+                          above_ref, ref_y_stride,
+                          INT_MAX);
+  bestsad += vp8_sad2x16_c(left_src, xd->dst.y_stride,
+                           left_ref, ref_y_stride,
+                           INT_MAX);
+  best_mv->as_int = 0;
+
+  for(i = 0; i < 4; ++i) {
+    if (ref_mv[i].as_int) {
+      int_mv this_mv;
+      int offset=0;
+      int row_offset, col_offset;
+      this_mv.as_int = ref_mv[i].as_int;
+      vp8_clamp_mv(&this_mv,
+                   xd->mb_to_left_edge - LEFT_TOP_MARGIN + 16,
+                   xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
+                   xd->mb_to_top_edge - LEFT_TOP_MARGIN + 16,
+                   xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
+
+      row_offset = (this_mv.as_mv.row > 0) ?
+        ((this_mv.as_mv.row + 3) >> 3):((this_mv.as_mv.row + 4) >> 3);
+      col_offset = (this_mv.as_mv.col > 0) ?
+        ((this_mv.as_mv.col + 3) >> 3):((this_mv.as_mv.col + 4) >> 3);
+      offset = ref_y_stride * row_offset + col_offset;
+
+      sad = vp8_sad16x2_c(above_src, xd->dst.y_stride,
+                          above_ref + offset, ref_y_stride, INT_MAX);
+
+      sad += vp8_sad2x16_c(left_src, xd->dst.y_stride,
+                           left_ref + offset, ref_y_stride, INT_MAX);
+
+      if (sad < bestsad) {
+        bestsad = sad;
+        best_mv->as_int = this_mv.as_int;
+      }
+    }
+  }
+  if (!xd->allow_high_precision_mv)
+    lower_mv_precision(best_mv);
+
+  vp8_clamp_mv2(best_mv, xd);
+}
+
+#endif
index d4769e6085ad4035596204c0eeec9b50b03f6340..3bb2024c238a74d251e4f9b057b79fe7ecec9329 100644 (file)
@@ -33,20 +33,14 @@ static void mv_bias(int refmb_ref_frame_sign_bias, int refframe, int_mv *mvp, co
 
 #define LEFT_TOP_MARGIN (16 << 3)
 #define RIGHT_BOTTOM_MARGIN (16 << 3)
-static void vp8_clamp_mv2(int_mv *mv, const MACROBLOCKD *xd) {
-  if (mv->as_mv.col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
-    mv->as_mv.col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
-  else if (mv->as_mv.col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
-    mv->as_mv.col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
-
-  if (mv->as_mv.row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
-    mv->as_mv.row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
-  else if (mv->as_mv.row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
-    mv->as_mv.row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
-}
 
-static void vp8_clamp_mv(int_mv *mv, int mb_to_left_edge, int mb_to_right_edge,
-                         int mb_to_top_edge, int mb_to_bottom_edge) {
+
+
+static void vp8_clamp_mv(int_mv *mv,
+                         int mb_to_left_edge,
+                         int mb_to_right_edge,
+                         int mb_to_top_edge,
+                         int mb_to_bottom_edge) {
   mv->as_mv.col = (mv->as_mv.col < mb_to_left_edge) ?
                   mb_to_left_edge : mv->as_mv.col;
   mv->as_mv.col = (mv->as_mv.col > mb_to_right_edge) ?
@@ -56,15 +50,26 @@ static void vp8_clamp_mv(int_mv *mv, int mb_to_left_edge, int mb_to_right_edge,
   mv->as_mv.row = (mv->as_mv.row > mb_to_bottom_edge) ?
                   mb_to_bottom_edge : mv->as_mv.row;
 }
-static unsigned int vp8_check_mv_bounds(int_mv *mv, int mb_to_left_edge,
-                                        int mb_to_right_edge, int mb_to_top_edge,
+
+static void vp8_clamp_mv2(int_mv *mv, const MACROBLOCKD *xd) {
+  vp8_clamp_mv(mv,
+              xd->mb_to_left_edge - LEFT_TOP_MARGIN,
+              xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
+              xd->mb_to_top_edge - LEFT_TOP_MARGIN,
+              xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
+}
+
+
+
+static unsigned int vp8_check_mv_bounds(int_mv *mv,
+                                        int mb_to_left_edge,
+                                        int mb_to_right_edge,
+                                        int mb_to_top_edge,
                                         int mb_to_bottom_edge) {
-  unsigned int need_to_clamp;
-  need_to_clamp = (mv->as_mv.col < mb_to_left_edge) ? 1 : 0;
-  need_to_clamp |= (mv->as_mv.col > mb_to_right_edge) ? 1 : 0;
-  need_to_clamp |= (mv->as_mv.row < mb_to_top_edge) ? 1 : 0;
-  need_to_clamp |= (mv->as_mv.row > mb_to_bottom_edge) ? 1 : 0;
-  return need_to_clamp;
+  return (mv->as_mv.col < mb_to_left_edge) ||
+         (mv->as_mv.col > mb_to_right_edge) ||
+         (mv->as_mv.row < mb_to_top_edge) ||
+         (mv->as_mv.row > mb_to_bottom_edge);
 }
 
 void vp8_find_near_mvs
index 5a11f646c99445400203785b497cfa5e9d7503a9..2e0049df0762d541ca7bca28a9cac0ecb9f1c6ad 100644 (file)
@@ -619,10 +619,44 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
     int_mv nearest_second, nearby_second, best_mv_second;
     vp8_prob mv_ref_p [VP8_MVREFS - 1];
 
+#if CONFIG_NEWBESTREFMV
+    int recon_y_stride, recon_yoffset;
+    int recon_uv_stride, recon_uvoffset;
+#endif
+
     vp8_find_near_mvs(xd, mi,
                       prev_mi,
                       &nearest, &nearby, &best_mv, rct,
-                      mbmi->ref_frame, pbi->common.ref_frame_sign_bias);
+                      mbmi->ref_frame, cm->ref_frame_sign_bias);
+#if CONFIG_NEWBESTREFMV
+    {
+      int ref_fb_idx;
+
+      /* Select the appropriate reference frame for this MB */
+      if (mbmi->ref_frame == LAST_FRAME)
+        ref_fb_idx = cm->lst_fb_idx;
+      else if (mbmi->ref_frame == GOLDEN_FRAME)
+        ref_fb_idx = cm->gld_fb_idx;
+      else
+        ref_fb_idx = cm->alt_fb_idx;
+
+      recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride  ;
+      recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
+
+      recon_yoffset = (mb_row * recon_y_stride * 16) + (mb_col * 16);
+      recon_uvoffset = (mb_row * recon_uv_stride * 8) + (mb_col * 8);
+
+      xd->pre.y_buffer = cm->yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;
+      xd->pre.u_buffer = cm->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
+      xd->pre.v_buffer = cm->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
+
+      vp8_find_best_ref_mvs(xd,
+                            xd->pre.y_buffer,
+                            recon_y_stride,
+                            &best_mv);
+    }
+#endif
+
     vp8_mv_ref_probs(&pbi->common, mv_ref_p, rct);
 
     // Is the segment level mode feature enabled for this segment
@@ -672,11 +706,41 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
       mbmi->second_ref_frame = mbmi->ref_frame + 1;
       if (mbmi->second_ref_frame == 4)
         mbmi->second_ref_frame = 1;
-
-      vp8_find_near_mvs(xd, mi,
-                        prev_mi,
-                        &nearest_second, &nearby_second, &best_mv_second, rct,
-                        mbmi->second_ref_frame, pbi->common.ref_frame_sign_bias);
+#if CONFIG_NEWBESTREFMV
+      if (mbmi->second_ref_frame) {
+        int second_ref_fb_idx;
+        /* Select the appropriate reference frame for this MB */
+        if (mbmi->second_ref_frame == LAST_FRAME)
+          second_ref_fb_idx = cm->lst_fb_idx;
+        else if (mbmi->second_ref_frame ==
+          GOLDEN_FRAME)
+          second_ref_fb_idx = cm->gld_fb_idx;
+        else
+          second_ref_fb_idx = cm->alt_fb_idx;
+
+        xd->second_pre.y_buffer =
+          cm->yv12_fb[second_ref_fb_idx].y_buffer + recon_yoffset;
+        xd->second_pre.u_buffer =
+          cm->yv12_fb[second_ref_fb_idx].u_buffer + recon_uvoffset;
+        xd->second_pre.v_buffer =
+          cm->yv12_fb[second_ref_fb_idx].v_buffer + recon_uvoffset;
+        vp8_find_near_mvs(xd, mi, prev_mi,
+                          &nearest_second, &nearby_second, &best_mv_second,
+                          rct,
+                          mbmi->second_ref_frame,
+                          cm->ref_frame_sign_bias);
+        vp8_find_best_ref_mvs(xd,
+                              xd->second_pre.y_buffer,
+                              recon_y_stride,
+                              &best_mv_second);
+      }
+#else
+      vp8_find_near_mvs(xd, mi, prev_mi,
+                        &nearest_second, &nearby_second, &best_mv_second,
+                        rct,
+                        mbmi->second_ref_frame,
+                        pbi->common.ref_frame_sign_bias);
+#endif
     } else {
       mbmi->second_ref_frame = 0;
     }
@@ -941,7 +1005,7 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
       }
     } else {
       mbmi->uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(
-                     bc, pbi->common.fc.uv_mode_prob[mbmi->mode]);
+        bc, pbi->common.fc.uv_mode_prob[mbmi->mode]);
       pbi->common.fc.uv_mode_counts[mbmi->mode][mbmi->uv_mode]++;
     }
 
@@ -1021,7 +1085,7 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi) {
 void vpx_decode_mode_mvs_init(VP8D_COMP *pbi){
   VP8_COMMON *cm = &pbi->common;
   mb_mode_mv_init(pbi);
-  if (cm->frame_type == KEY_FRAME &&!cm->kf_ymode_probs_update)
+  if (cm->frame_type == KEY_FRAME && !cm->kf_ymode_probs_update)
     cm->kf_ymode_probs_index = vp8_read_literal(&pbi->bc, 3);
 }
 void vpx_decode_mb_mode_mv(VP8D_COMP *pbi,
index 59f453edff0547a8bb36b705f12307da2074b89a..ffa7f0cc1e9417f41e3e0e31b8b9fb9ed741c227 100644 (file)
@@ -631,10 +631,6 @@ decode_sb_row(VP8D_COMP *pbi, VP8_COMMON *pc, int mbrow, MACROBLOCKD *xd) {
       xd->up_available = (mb_row != 0);
       xd->left_available = (mb_col != 0);
 
-      if(pbi->interleaved_decoding)
-        vpx_decode_mb_mode_mv(pbi, xd, mb_row, mb_col);
-
-      update_blockd_bmi(xd);
 
       recon_yoffset = (mb_row * recon_y_stride * 16) + (mb_col * 16);
       recon_uvoffset = (mb_row * recon_uv_stride * 8) + (mb_col * 8);
@@ -643,6 +639,11 @@ decode_sb_row(VP8D_COMP *pbi, VP8_COMMON *pc, int mbrow, MACROBLOCKD *xd) {
       xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
       xd->dst.v_buffer = pc->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
 
+      if(pbi->interleaved_decoding)
+        vpx_decode_mb_mode_mv(pbi, xd, mb_row, mb_col);
+
+      update_blockd_bmi(xd);
+
       /* Select the appropriate reference frame for this MB */
       if (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME)
         ref_fb_idx = pc->lst_fb_idx;
index f7d93b20157b1e84890f1795c0d59fa5686fcac4..f9195b6263a09bc019ba50daed3badd72aec23f6 100644 (file)
@@ -149,7 +149,7 @@ VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf) {
 
   pbi->decoded_key_frame = 0;
 
-  pbi->interleaved_decoding = 1;
+  pbi->interleaved_decoding = CONFIG_NEWBESTREFMV;
 
   return (VP8D_PTR) pbi;
 }
index 574427cf70ffffb66e041991cf72b2259a700020..103391c2c6cf6e23071f5a4dd55f37b97c46357e 100644 (file)
@@ -933,6 +933,9 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) {
 
             vp8_find_near_mvs(xd, m, prev_m, &n1, &n2, &best_mv, ct,
                               rf, cpi->common.ref_frame_sign_bias);
+#if CONFIG_NEWBESTREFMV
+            best_mv.as_int = mi->ref_mv.as_int;
+#endif
             vp8_mv_ref_probs(&cpi->common, mv_ref_p, ct);
 
 #ifdef ENTROPY_STATS
@@ -983,7 +986,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) {
             vp8_find_near_mvs(xd, m,
                               prev_m,
                               &n1, &n2, &best_second_mv, ct,
-                              mi->second_ref_frame, cpi->common.ref_frame_sign_bias);
+                              mi->second_ref_frame,
+                              cpi->common.ref_frame_sign_bias);
+#if CONFIG_NEWBESTREFMV
+            best_second_mv.as_int = mi->second_ref_mv.as_int;
+#endif
           }
 
           // does the feature use compound prediction or not
index e1d0bf4a7060927a8610ae78c572e35ce5ac1e2a..460c160ac529621a4b63897dbb650ba7c9c5994c 100644 (file)
@@ -47,7 +47,8 @@ int enc_debug = 0;
 int mb_row_debug, mb_col_debug;
 #endif
 
-extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t);
+extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x,
+                         TOKENEXTRA **t, int dry_run);
 
 extern void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex);
 extern void vp8_auto_select_speed(VP8_COMP *cpi);
@@ -1467,8 +1468,12 @@ void vp8cx_encode_intra_macro_block(VP8_COMP *cpi,
   if (output_enabled) {
     // Tokenize
     sum_intra_stats(cpi, x);
-    vp8_tokenize_mb(cpi, &x->e_mbd, t);
+    vp8_tokenize_mb(cpi, &x->e_mbd, t, 0);
   }
+#if CONFIG_NEWBESTREFMV
+  else
+    vp8_tokenize_mb(cpi, &x->e_mbd, t, 1);
+#endif
 }
 #ifdef SPEEDSTATS
 extern int cnt_pm;
@@ -1624,8 +1629,9 @@ void vp8cx_encode_inter_macroblock (VP8_COMP *cpi, MACROBLOCK *x,
       fflush(stdout);
     }
 #endif
-    if (output_enabled)
-      vp8_tokenize_mb(cpi, xd, t);
+
+    vp8_tokenize_mb(cpi, xd, t, !output_enabled);
+
 #ifdef ENC_DEBUG
     if (enc_debug) {
       printf("Tokenized\n");
@@ -1640,12 +1646,14 @@ void vp8cx_encode_inter_macroblock (VP8_COMP *cpi, MACROBLOCK *x,
       0;
     if (cpi->common.mb_no_coeff_skip) {
       xd->mode_info_context->mbmi.mb_skip_coeff = 1;
-      cpi->skip_true_count[mb_skip_context]++;
+      if (output_enabled)
+        cpi->skip_true_count[mb_skip_context]++;
       vp8_fix_contexts(xd);
     } else {
-      vp8_stuff_mb(cpi, xd, t);
+      vp8_stuff_mb(cpi, xd, t, !output_enabled);
       xd->mode_info_context->mbmi.mb_skip_coeff = 0;
-      cpi->skip_false_count[mb_skip_context]++;
+      if (output_enabled)
+        cpi->skip_false_count[mb_skip_context]++;
     }
   }
 }
index 6a0a902128a125179e42aec8ff27d635921ba363..6b6167b2396615e560e1814d1deadb9100ab23f4 100644 (file)
@@ -761,7 +761,7 @@ void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x);
 
 int rd_cost_intra_mb(MACROBLOCKD *x);
 
-void vp8_tokenize_mb(VP8_COMP *, MACROBLOCKD *, TOKENEXTRA **);
+void vp8_tokenize_mb(VP8_COMP *, MACROBLOCKD *, TOKENEXTRA **, int dry_run);
 
 void vp8_set_speed_features(VP8_COMP *cpi);
 
index 67bf33d6fdbbdba21bdbe2b338193bd57df55abf..df76fc316e8013c4e51018f5f2239bbbd916a845 100644 (file)
@@ -2730,6 +2730,10 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
 #if CONFIG_PRED_FILTER
   int best_filter_state;
 #endif
+#if CONFIG_NEWBESTREFMV
+  int_mv ref_mv[MAX_REF_FRAMES] = {0};
+#endif
+
   // int all_rds[MAX_MODES];        // Experimental debug code.
   // int all_rates[MAX_MODES];
   // int all_dist[MAX_MODES];
@@ -2789,6 +2793,13 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
     y_buffer[LAST_FRAME] = lst_yv12->y_buffer + recon_yoffset;
     u_buffer[LAST_FRAME] = lst_yv12->u_buffer + recon_uvoffset;
     v_buffer[LAST_FRAME] = lst_yv12->v_buffer + recon_uvoffset;
+#if CONFIG_NEWBESTREFMV
+    vp8_find_best_ref_mvs(&x->e_mbd,
+                          y_buffer[LAST_FRAME],
+                          lst_yv12->y_stride,
+                          &frame_best_ref_mv[LAST_FRAME]);
+    ref_mv[LAST_FRAME].as_int = frame_best_ref_mv[LAST_FRAME].as_int;
+#endif
   }
 
   if (cpi->ref_frame_flags & VP8_GOLD_FLAG) {
@@ -2802,6 +2813,13 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
     y_buffer[GOLDEN_FRAME] = gld_yv12->y_buffer + recon_yoffset;
     u_buffer[GOLDEN_FRAME] = gld_yv12->u_buffer + recon_uvoffset;
     v_buffer[GOLDEN_FRAME] = gld_yv12->v_buffer + recon_uvoffset;
+#if CONFIG_NEWBESTREFMV
+    vp8_find_best_ref_mvs(&x->e_mbd,
+                          y_buffer[GOLDEN_FRAME],
+                          gld_yv12->y_stride,
+                          &frame_best_ref_mv[GOLDEN_FRAME]);
+    ref_mv[GOLDEN_FRAME].as_int = frame_best_ref_mv[GOLDEN_FRAME].as_int;
+#endif
   }
 
   if (cpi->ref_frame_flags & VP8_ALT_FLAG) {
@@ -2815,6 +2833,13 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
     y_buffer[ALTREF_FRAME] = alt_yv12->y_buffer + recon_yoffset;
     u_buffer[ALTREF_FRAME] = alt_yv12->u_buffer + recon_uvoffset;
     v_buffer[ALTREF_FRAME] = alt_yv12->v_buffer + recon_uvoffset;
+#if CONFIG_NEWBESTREFMV
+    vp8_find_best_ref_mvs(&x->e_mbd,
+                          y_buffer[ALTREF_FRAME],
+                          alt_yv12->y_stride,
+                          &frame_best_ref_mv[ALTREF_FRAME]);
+    ref_mv[ALTREF_FRAME].as_int = frame_best_ref_mv[ALTREF_FRAME].as_int;
+#endif
   }
 
   *returnintra = INT64_MAX;
@@ -2872,6 +2897,12 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
       vp8_mode_order[mode_index].ref_frame;
     xd->mode_info_context->mbmi.second_ref_frame =
       vp8_mode_order[mode_index].second_ref_frame;
+#if CONFIG_NEWBESTREFMV
+    x->e_mbd.mode_info_context->mbmi.ref_mv =
+      ref_mv[x->e_mbd.mode_info_context->mbmi.ref_frame];
+    x->e_mbd.mode_info_context->mbmi.second_ref_mv =
+      ref_mv[x->e_mbd.mode_info_context->mbmi.second_ref_frame];
+#endif
 #if CONFIG_PRED_FILTER
     xd->mode_info_context->mbmi.pred_filter_enabled = 0;
 #endif
@@ -3851,8 +3882,14 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
   }
 
   // macroblock modes
-  vpx_memcpy(&x->e_mbd.mode_info_context->mbmi, &best_mbmode, sizeof(MB_MODE_INFO));
-
+  vpx_memcpy(&x->e_mbd.mode_info_context->mbmi,
+             &best_mbmode, sizeof(MB_MODE_INFO));
+#if CONFIG_NEWBESTREFMV
+  x->e_mbd.mode_info_context->mbmi.ref_mv =
+    ref_mv[best_mbmode.ref_frame];
+  x->e_mbd.mode_info_context->mbmi.second_ref_mv =
+    ref_mv[best_mbmode.second_ref_frame];
+#endif
   if (best_mbmode.mode == B_PRED) {
     for (i = 0; i < 16; i++) {
       xd->mode_info_context->bmi[i].as_mode = best_bmodes[i].as_mode;
index 5ce13ec129eac1937cf249675179822cdca6155d..78a87f392c0798b3ff26678e41e5c37f0778c253 100644 (file)
@@ -104,7 +104,24 @@ unsigned int vp8_sad4x4_c(
 
   return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 4, 4);
 }
-
+#if CONFIG_NEWBESTREFMV
+unsigned int vp8_sad2x16_c(
+  const unsigned char *src_ptr,
+  int  src_stride,
+  const unsigned char *ref_ptr,
+  int  ref_stride,
+  int max_sad){
+  return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 2, 16);
+}
+unsigned int vp8_sad16x2_c(
+  const unsigned char *src_ptr,
+  int  src_stride,
+  const unsigned char *ref_ptr,
+  int  ref_stride,
+  int max_sad){
+  return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 16, 2);
+}
+#endif
 void vp8_sad16x16x3_c(
   const unsigned char *src_ptr,
   int  src_stride,
index 105aa6a7c75d3d9d081593ca748c2284a0f07bd5..a8b6436efda76114213d814d6e665f4fd8f6a18b 100644 (file)
@@ -38,10 +38,13 @@ extern unsigned int tree_update_hist_16x16[BLOCK_TYPES_16X16][COEF_BANDS]
                     [PREV_COEF_CONTEXTS][ENTROPY_NODES] [2];
 #endif
 #endif
-void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t);
-void vp8_stuff_mb_8x8(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t);
+void vp8_stuff_mb(VP8_COMP *cpi,
+                  MACROBLOCKD *x, TOKENEXTRA **t, int dry_run);
+void vp8_stuff_mb_8x8(VP8_COMP *cpi,
+                      MACROBLOCKD *x, TOKENEXTRA **t, int dry_run);
 #if CONFIG_TX16X16
-void vp8_stuff_mb_16x16(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t);
+void vp8_stuff_mb_16x16(VP8_COMP *cpi, MACROBLOCKD *x,
+                        TOKENEXTRA **t, int dry_run);
 #endif
 void vp8_fix_contexts(MACROBLOCKD *x);
 
@@ -110,9 +113,15 @@ static void fill_value_tokens() {
 }
 
 #if CONFIG_TX16X16
-static void tokenize1st_order_b_16x16(MACROBLOCKD *xd, const BLOCKD *const b, TOKENEXTRA **tp,
-                                      const int type, const FRAME_TYPE frametype, ENTROPY_CONTEXT *a,
-                                      ENTROPY_CONTEXT *l, VP8_COMP *cpi) {
+static void tokenize1st_order_b_16x16(MACROBLOCKD *xd,
+                                      const BLOCKD *const b,
+                                      TOKENEXTRA **tp,
+                                      const int type,
+                                      const FRAME_TYPE frametype,
+                                      ENTROPY_CONTEXT *a,
+                                      ENTROPY_CONTEXT *l,
+                                      VP8_COMP *cpi,
+                                      int dry_run) {
   int pt; /* near block/prev token context index */
   int c = 0;                  /* start at DC unless type 0 */
   const int eob = b->eob;     /* one beyond last nonzero coeff */
@@ -147,8 +156,8 @@ static void tokenize1st_order_b_16x16(MACROBLOCKD *xd, const BLOCKD *const b, TO
     t->context_tree = cpi->common.fc.coef_probs_16x16[type][band][pt];
 
     t->skip_eob_node = pt == 0 && ((band > 0 && type > 0) || (band > 1 && type == 0));
-
-    ++cpi->coef_counts_16x16[type][band][pt][x];
+    if (!dry_run)
+      ++cpi->coef_counts_16x16[type][band][pt][x];
   } while (pt = vp8_prev_token_class[x], ++t, c < eob  &&  ++c < seg_eob);
 
   *tp = t;
@@ -166,8 +175,8 @@ static void tokenize2nd_order_b_8x8
   const FRAME_TYPE frametype,
   ENTROPY_CONTEXT *a,
   ENTROPY_CONTEXT *l,
-  VP8_COMP *cpi
-) {
+  VP8_COMP *cpi,
+  int dry_run) {
   int pt; /* near block/prev token context index */
   int c = 0;          /* start at DC */
   const int eob = b->eob;     /* one beyond last nonzero coeff */
@@ -213,8 +222,8 @@ static void tokenize2nd_order_b_8x8
              x, vp8_coef_encodings[x].Len, t->skip_eob_node, eob, c, band, type,
              cpi->count, mb_row_debug, mb_col_debug);
 #endif
-
-    ++cpi->coef_counts_8x8       [type] [band] [pt] [x];
+    if (!dry_run)
+      ++cpi->coef_counts_8x8       [type] [band] [pt] [x];
   } while (pt = vp8_prev_token_class[x], ++t, c < eob  &&  ++c < seg_eob);
 
 
@@ -224,8 +233,10 @@ static void tokenize2nd_order_b_8x8
 
 }
 
-static void tokenize2nd_order_b(MACROBLOCKD *xd, TOKENEXTRA **tp,
-                                VP8_COMP *cpi) {
+static void tokenize2nd_order_b(MACROBLOCKD *xd,
+                                TOKENEXTRA **tp,
+                                VP8_COMP *cpi,
+                                int dry_run) {
   int pt;             /* near block/prev token context index */
   int c;              /* start at DC */
   TOKENEXTRA *t = *tp;/* store tokens starting here */
@@ -261,7 +272,8 @@ static void tokenize2nd_order_b(MACROBLOCKD *xd, TOKENEXTRA **tp,
 
     t->skip_eob_node = ((pt == 0) && (band > 0));
 
-    ++cpi->coef_counts       [1] [band] [pt] [token];
+    if (!dry_run)
+      ++cpi->coef_counts       [1] [band] [pt] [token];
 
     pt = vp8_prev_token_class[token];
     t++;
@@ -274,7 +286,8 @@ static void tokenize2nd_order_b(MACROBLOCKD *xd, TOKENEXTRA **tp,
 
     t->skip_eob_node = ((pt == 0) && (band > 0));
 
-    ++cpi->coef_counts       [1] [band] [pt] [DCT_EOB_TOKEN];
+    if (!dry_run)
+      ++cpi->coef_counts       [1] [band] [pt] [DCT_EOB_TOKEN];
 
     t++;
   }
@@ -295,8 +308,8 @@ static void tokenize1st_order_b_8x8
   const FRAME_TYPE frametype,
   ENTROPY_CONTEXT *a,
   ENTROPY_CONTEXT *l,
-  VP8_COMP *cpi
-) {
+  VP8_COMP *cpi,
+  int dry_run) {
   int pt; /* near block/prev token context index */
   int c = type ? 0 : 1;       /* start at DC unless type 0 */
   TOKENEXTRA *t = *tp;        /* store tokens starting here */
@@ -324,7 +337,9 @@ static void tokenize1st_order_b_8x8
     t->context_tree = cpi->common.fc.coef_probs_8x8[type][band][pt];
 
     t->skip_eob_node = pt == 0 && ((band > 0 && type > 0) || (band > 1 && type == 0));
-    ++cpi->coef_counts_8x8[type][band][pt][x];
+
+    if (!dry_run)
+      ++cpi->coef_counts_8x8[type][band][pt][x];
 
     pt = vp8_prev_token_class[x];
     ++t;
@@ -337,7 +352,8 @@ static void tokenize1st_order_b_8x8
     t->context_tree = cpi->common.fc.coef_probs_8x8 [type] [band] [pt];
     t->skip_eob_node = pt == 0 && ((band > 0 && type > 0) || (band > 1 && type == 0));
 
-    ++cpi->coef_counts_8x8[type][band][pt][DCT_EOB_TOKEN];
+    if (!dry_run)
+      ++cpi->coef_counts_8x8[type][band][pt][DCT_EOB_TOKEN];
     ++t;
   }
 
@@ -350,7 +366,8 @@ static void tokenize1st_order_b_8x8
 static void tokenize1st_order_ht(   MACROBLOCKD *xd,
                                     TOKENEXTRA **tp,
                                     int type,
-                                    VP8_COMP    *cpi) {
+                                    VP8_COMP *cpi,
+                                    int dry_run) {
   unsigned int block;
   const BLOCKD *b;
   int pt;             /* near block/prev token context index */
@@ -428,7 +445,8 @@ static void tokenize1st_order_ht(   MACROBLOCKD *xd,
       t->skip_eob_node = pt == 0 &&
           ((band > 0 && type > 0) || (band > 1 && type == 0));
 
-      ++cpi->coef_counts       [type] [band] [pt] [token];
+      if (!dry_run)
+        ++cpi->coef_counts       [type] [band] [pt] [token];
 
       pt = vp8_prev_token_class[token];
       t++;
@@ -441,8 +459,8 @@ static void tokenize1st_order_ht(   MACROBLOCKD *xd,
 
       t->skip_eob_node = pt == 0 &&
           ((band > 0 && type > 0) || (band > 1 && type == 0));
-
-      ++cpi->coef_counts       [type] [band] [pt] [DCT_EOB_TOKEN];
+      if (!dry_run)
+        ++cpi->coef_counts       [type] [band] [pt] [DCT_EOB_TOKEN];
 
       t++;
     }
@@ -478,7 +496,8 @@ static void tokenize1st_order_ht(   MACROBLOCKD *xd,
 
       t->skip_eob_node = ((pt == 0) && (band > 0));
 
-      ++cpi->coef_counts       [2] [band] [pt] [token];
+      if (!dry_run)
+        ++cpi->coef_counts       [2] [band] [pt] [token];
 
       pt = vp8_prev_token_class[token];
       t++;
@@ -490,9 +509,8 @@ static void tokenize1st_order_ht(   MACROBLOCKD *xd,
       t->context_tree = cpi->common.fc.coef_probs [2] [band] [pt];
 
       t->skip_eob_node = ((pt == 0) && (band > 0));
-
-      ++cpi->coef_counts       [2] [band] [pt] [DCT_EOB_TOKEN];
-
+      if (!dry_run)
+        ++cpi->coef_counts       [2] [band] [pt] [DCT_EOB_TOKEN];
       t++;
     }
 
@@ -510,8 +528,8 @@ static void tokenize1st_order_chroma
   MACROBLOCKD *xd,
   TOKENEXTRA **tp,
   int type,           /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
-  VP8_COMP *cpi
-) {
+  VP8_COMP *cpi,
+  int dry_run) {
   unsigned int block;
   const BLOCKD *b;
   int pt;             /* near block/prev token context index */
@@ -557,7 +575,8 @@ static void tokenize1st_order_chroma
 
       t->skip_eob_node = ((pt == 0) && (band > 0));
 
-      ++cpi->coef_counts       [2] [band] [pt] [token];
+      if (!dry_run)
+        ++cpi->coef_counts       [2] [band] [pt] [token];
 
       pt = vp8_prev_token_class[token];
       t++;
@@ -570,7 +589,8 @@ static void tokenize1st_order_chroma
 
       t->skip_eob_node = ((pt == 0) && (band > 0));
 
-      ++cpi->coef_counts       [2] [band] [pt] [DCT_EOB_TOKEN];
+      if (!dry_run)
+        ++cpi->coef_counts       [2] [band] [pt] [DCT_EOB_TOKEN];
 
       t++;
     }
@@ -586,8 +606,8 @@ static void tokenize1st_order_b
   MACROBLOCKD *xd,
   TOKENEXTRA **tp,
   int type,           /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
-  VP8_COMP *cpi
-) {
+  VP8_COMP *cpi,
+  int dry_run) {
   unsigned int block;
   const BLOCKD *b;
   int pt;             /* near block/prev token context index */
@@ -626,8 +646,8 @@ static void tokenize1st_order_b
 
       t->skip_eob_node = pt == 0 &&
                          ((band > 0 && type > 0) || (band > 1 && type == 0));
-
-      ++cpi->coef_counts       [type] [band] [pt] [token];
+      if (!dry_run)
+        ++cpi->coef_counts       [type] [band] [pt] [token];
 
       pt = vp8_prev_token_class[token];
       t++;
@@ -640,8 +660,8 @@ static void tokenize1st_order_b
 
       t->skip_eob_node = pt == 0 &&
                          ((band > 0 && type > 0) || (band > 1 && type == 0));
-
-      ++cpi->coef_counts       [type] [band] [pt] [DCT_EOB_TOKEN];
+      if (!dry_run)
+        ++cpi->coef_counts       [type] [band] [pt] [DCT_EOB_TOKEN];
 
       t++;
     }
@@ -671,7 +691,8 @@ static void tokenize1st_order_b
 
       t->skip_eob_node = ((pt == 0) && (band > 0));
 
-      ++cpi->coef_counts       [2] [band] [pt] [token];
+      if (!dry_run)
+        ++cpi->coef_counts       [2] [band] [pt] [token];
 
       pt = vp8_prev_token_class[token];
       t++;
@@ -684,7 +705,8 @@ static void tokenize1st_order_b
 
       t->skip_eob_node = ((pt == 0) && (band > 0));
 
-      ++cpi->coef_counts       [2] [band] [pt] [DCT_EOB_TOKEN];
+      if (!dry_run)
+        ++cpi->coef_counts       [2] [band] [pt] [DCT_EOB_TOKEN];
 
       t++;
     }
@@ -757,12 +779,16 @@ int mb_is_skippable_16x16(MACROBLOCKD *x) {
 }
 #endif
 
-void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
+void vp8_tokenize_mb(VP8_COMP *cpi,
+                     MACROBLOCKD *x,
+                     TOKENEXTRA **t,
+                     int dry_run) {
   int plane_type;
   int has_y2_block;
   int b;
   int tx_type = x->mode_info_context->mbmi.txfm_size;
   int mb_skip_context = get_pred_context(&cpi->common, x, PRED_MBSKIP);
+  TOKENEXTRA *t_backup = *t;
 
   // If the MB is going to be skipped because of a segment level flag
   // exclude this from the skip count stats used to calculate the
@@ -804,25 +830,28 @@ void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
   }
 
   if (x->mode_info_context->mbmi.mb_skip_coeff) {
-    cpi->skip_true_count[mb_skip_context] += skip_inc;
+    if (!dry_run)
+      cpi->skip_true_count[mb_skip_context] += skip_inc;
     if (!cpi->common.mb_no_coeff_skip) {
 #if CONFIG_TX16X16
       if (tx_type == TX_16X16)
-        vp8_stuff_mb_16x16(cpi, x, t);
+        vp8_stuff_mb_16x16(cpi, x, t, dry_run);
       else
 #endif
       if (tx_type == TX_8X8)
-        vp8_stuff_mb_8x8(cpi, x, t);
+        vp8_stuff_mb_8x8(cpi, x, t, dry_run);
       else
-        vp8_stuff_mb(cpi, x, t);
+        vp8_stuff_mb(cpi, x, t, dry_run);
     } else {
       vp8_fix_contexts(x);
     }
-
+    if (dry_run)
+      *t = t_backup;
     return;
   }
 
-  cpi->skip_false_count[mb_skip_context] += skip_inc;
+  if (!dry_run)
+    cpi->skip_false_count[mb_skip_context] += skip_inc;
 
   plane_type = 3;
   if (has_y2_block) {
@@ -832,9 +861,10 @@ void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
       tokenize2nd_order_b_8x8(x,
                               x->block + 24, t, 1, x->frame_type,
                               A + vp8_block2above_8x8[24],
-                              L + vp8_block2left_8x8[24], cpi);
+                              L + vp8_block2left_8x8[24],
+                              cpi, dry_run);
     } else
-      tokenize2nd_order_b(x, t, cpi);
+      tokenize2nd_order_b(x, t, cpi, dry_run);
 
     plane_type = 0;
   }
@@ -843,14 +873,15 @@ void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
   if (tx_type == TX_16X16) {
     ENTROPY_CONTEXT * A = (ENTROPY_CONTEXT *)x->above_context;
     ENTROPY_CONTEXT * L = (ENTROPY_CONTEXT *)x->left_context;
-    tokenize1st_order_b_16x16(x, x->block, t, 3, x->frame_type, A, L, cpi);
+    tokenize1st_order_b_16x16(x, x->block, t, 3,
+                              x->frame_type, A, L, cpi, dry_run);
     for (b = 1; b < 16; b++) {
       *(A + vp8_block2above[b]) = *(A);
       *(L + vp8_block2left[b] ) = *(L);
     }
     for (b = 16; b < 24; b += 4) {
       tokenize1st_order_b_8x8(x, x->block + b, t, 2, x->frame_type,
-          A + vp8_block2above_8x8[b], L + vp8_block2left_8x8[b], cpi);
+          A + vp8_block2above_8x8[b], L + vp8_block2left_8x8[b], cpi, dry_run);
       *(A + vp8_block2above_8x8[b]+1) = *(A + vp8_block2above_8x8[b]);
       *(L + vp8_block2left_8x8[b]+1 ) = *(L + vp8_block2left_8x8[b]);
     }
@@ -867,7 +898,7 @@ void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
                               x->block + b, t, plane_type, x->frame_type,
                               A + vp8_block2above_8x8[b],
                               L + vp8_block2left_8x8[b],
-                              cpi);
+                              cpi, dry_run);
       *(A + vp8_block2above_8x8[b] + 1) = *(A + vp8_block2above_8x8[b]);
       *(L + vp8_block2left_8x8[b] + 1)  = *(L + vp8_block2left_8x8[b]);
     }
@@ -876,14 +907,14 @@ void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
                               x->block + b, t, 2, x->frame_type,
                               A + vp8_block2above_8x8[b],
                               L + vp8_block2left_8x8[b],
-                              cpi);
+                              cpi, dry_run);
       *(A + vp8_block2above_8x8[b] + 1) = *(A + vp8_block2above_8x8[b]);
       *(L + vp8_block2left_8x8[b] + 1) = *(L + vp8_block2left_8x8[b]);
     }
   } else {
 #if CONFIG_HYBRIDTRANSFORM
     if(active_ht) {
-      tokenize1st_order_ht(x, t, plane_type, cpi);
+      tokenize1st_order_ht(x, t, plane_type, cpi, dry_run);
     } else {
 
 #if CONFIG_HYBRIDTRANSFORM8X8
@@ -896,23 +927,25 @@ void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
                                   x->frame_type,
                                   A + vp8_block2above_8x8[b],
                                   L + vp8_block2left_8x8[b],
-                                  cpi);
+                                  cpi, dry_run);
           *(A + vp8_block2above_8x8[b] + 1) = *(A + vp8_block2above_8x8[b]);
           *(L + vp8_block2left_8x8[b] + 1)  = *(L + vp8_block2left_8x8[b]);
         }
-        tokenize1st_order_chroma(x, t, PLANE_TYPE_UV, cpi);
+        tokenize1st_order_chroma(x, t, PLANE_TYPE_UV, cpi, dry_run);
       } else {
-        tokenize1st_order_b(x, t, plane_type, cpi);
+        tokenize1st_order_b(x, t, plane_type, cpi, dry_run);
       }
 #else
-      tokenize1st_order_b(x, t, plane_type, cpi);
+      tokenize1st_order_b(x, t, plane_type, cpi, dry_run);
 #endif
 
     }
 #else
-    tokenize1st_order_b(x, t, plane_type, cpi);
+    tokenize1st_order_b(x, t, plane_type, cpi, dry_run);
 #endif
   }
+  if (dry_run)
+    *t = t_backup;
 }
 
 
@@ -1178,16 +1211,15 @@ void vp8_tokenize_initialize() {
 }
 
 
-static __inline void stuff2nd_order_b_8x8
-(
+static __inline void stuff2nd_order_b_8x8(
   const BLOCKD *const b,
   TOKENEXTRA **tp,
   const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
   const FRAME_TYPE frametype,
   ENTROPY_CONTEXT *a,
   ENTROPY_CONTEXT *l,
-  VP8_COMP *cpi
-) {
+  VP8_COMP *cpi,
+  int dry_run) {
   int pt; /* near block/prev token context index */
   TOKENEXTRA *t = *tp;        /* store tokens starting here */
   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -1202,7 +1234,8 @@ static __inline void stuff2nd_order_b_8x8
   ++t;
 
   *tp = t;
-  ++cpi->coef_counts_8x8       [1] [0] [pt] [DCT_EOB_TOKEN];
+  if (!dry_run)
+    ++cpi->coef_counts_8x8       [1] [0] [pt] [DCT_EOB_TOKEN];
   pt = 0;
   *a = *l = pt;
 
@@ -1216,8 +1249,8 @@ static __inline void stuff1st_order_b_8x8
   const FRAME_TYPE frametype,
   ENTROPY_CONTEXT *a,
   ENTROPY_CONTEXT *l,
-  VP8_COMP *cpi
-) {
+  VP8_COMP *cpi,
+  int dry_run) {
   int pt; /* near block/prev token context index */
   TOKENEXTRA *t = *tp;        /* store tokens starting here */
   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -1231,7 +1264,8 @@ static __inline void stuff1st_order_b_8x8
   t->skip_eob_node = 0;
   ++t;
   *tp = t;
-  ++cpi->coef_counts_8x8       [0] [1] [pt] [DCT_EOB_TOKEN];
+  if (!dry_run)
+    ++cpi->coef_counts_8x8[0] [1] [pt] [DCT_EOB_TOKEN];
   pt = 0; /* 0 <-> all coeff data is zero */
   *a = *l = pt;
 
@@ -1247,8 +1281,8 @@ void stuff1st_order_buv_8x8
   const FRAME_TYPE frametype,
   ENTROPY_CONTEXT *a,
   ENTROPY_CONTEXT *l,
-  VP8_COMP *cpi
-) {
+  VP8_COMP *cpi,
+  int dry_run) {
   int pt; /* near block/prev token context index */
   TOKENEXTRA *t = *tp;        /* store tokens starting here */
   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -1262,13 +1296,17 @@ void stuff1st_order_buv_8x8
   t->skip_eob_node = 0;
   ++t;
   *tp = t;
-  ++cpi->coef_counts_8x8[2] [0] [pt] [DCT_EOB_TOKEN];
+  if (!dry_run)
+    ++cpi->coef_counts_8x8[2] [0] [pt] [DCT_EOB_TOKEN];
   pt = 0; /* 0 <-> all coeff data is zero */
   *a = *l = pt;
 
 }
 
-void vp8_stuff_mb_8x8(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
+void vp8_stuff_mb_8x8(VP8_COMP *cpi,
+                      MACROBLOCKD *x,
+                      TOKENEXTRA **t,
+                      int dry_run) {
   ENTROPY_CONTEXT *A = (ENTROPY_CONTEXT *)x->above_context;
   ENTROPY_CONTEXT *L = (ENTROPY_CONTEXT *)x->left_context;
   int plane_type;
@@ -1276,14 +1314,14 @@ void vp8_stuff_mb_8x8(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
 
   stuff2nd_order_b_8x8(x->block + 24, t, 1, x->frame_type,
                        A + vp8_block2above_8x8[24],
-                       L + vp8_block2left_8x8[24], cpi);
+                       L + vp8_block2left_8x8[24], cpi, dry_run);
   plane_type = 0;
 
   for (b = 0; b < 16; b += 4) {
     stuff1st_order_b_8x8(x->block + b, t, plane_type, x->frame_type,
                          A + vp8_block2above_8x8[b],
                          L + vp8_block2left_8x8[b],
-                         cpi);
+                         cpi, dry_run);
     *(A + vp8_block2above_8x8[b] + 1) = *(A + vp8_block2above_8x8[b]);
     *(L + vp8_block2left_8x8[b] + 1)  = *(L + vp8_block2left_8x8[b]);
   }
@@ -1292,7 +1330,7 @@ void vp8_stuff_mb_8x8(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
     stuff1st_order_buv_8x8(x->block + b, t, 2, x->frame_type,
                            A + vp8_block2above[b],
                            L + vp8_block2left[b],
-                           cpi);
+                           cpi, dry_run);
     *(A + vp8_block2above_8x8[b] + 1) = *(A + vp8_block2above_8x8[b]);
     *(L + vp8_block2left_8x8[b] + 1) = *(L + vp8_block2left_8x8[b]);
   }
@@ -1301,9 +1339,13 @@ void vp8_stuff_mb_8x8(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
 
 #if CONFIG_TX16X16
 static __inline
-void stuff1st_order_b_16x16(const BLOCKD *const b, TOKENEXTRA **tp, const FRAME_TYPE frametype,
-                            ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l, VP8_COMP *cpi)
-{
+void stuff1st_order_b_16x16(const BLOCKD *const b,
+                            TOKENEXTRA **tp,
+                            const FRAME_TYPE frametype,
+                            ENTROPY_CONTEXT *a,
+                            ENTROPY_CONTEXT *l,
+                            VP8_COMP *cpi,
+                            int dry_run){
     int pt; /* near block/prev token context index */
     TOKENEXTRA *t = *tp;        /* store tokens starting here */
     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -1315,17 +1357,21 @@ void stuff1st_order_b_16x16(const BLOCKD *const b, TOKENEXTRA **tp, const FRAME_
     t->skip_eob_node = 0;
     ++t;
     *tp = t;
-    ++cpi->coef_counts_16x16[3][1][pt][DCT_EOB_TOKEN];
+    if (!dry_run)
+      ++cpi->coef_counts_16x16[3][1][pt][DCT_EOB_TOKEN];
     pt = 0; /* 0 <-> all coeff data is zero */
     *a = *l = pt;
 }
 
-void vp8_stuff_mb_16x16(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
+void vp8_stuff_mb_16x16(VP8_COMP *cpi,
+                        MACROBLOCKD *x,
+                        TOKENEXTRA **t,
+                        int dry_run) {
   ENTROPY_CONTEXT * A = (ENTROPY_CONTEXT *)x->above_context;
   ENTROPY_CONTEXT * L = (ENTROPY_CONTEXT *)x->left_context;
   int b, i;
 
-  stuff1st_order_b_16x16(x->block, t, x->frame_type, A, L, cpi);
+  stuff1st_order_b_16x16(x->block, t, x->frame_type, A, L, cpi, dry_run);
   for (i = 1; i < 16; i++) {
     *(A + vp8_block2above[i]) = *(A);
     *(L +  vp8_block2left[i]) = *(L);
@@ -1334,7 +1380,7 @@ void vp8_stuff_mb_16x16(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
     stuff1st_order_buv_8x8(x->block + b, t, 2, x->frame_type,
         A + vp8_block2above[b],
         L + vp8_block2left[b],
-        cpi);
+        cpi, dry_run);
     *(A + vp8_block2above_8x8[b]+1) = *(A + vp8_block2above_8x8[b]);
     *(L + vp8_block2left_8x8[b]+1 ) = *(L + vp8_block2left_8x8[b]);
   }
@@ -1348,8 +1394,8 @@ static __inline void stuff2nd_order_b
   TOKENEXTRA **tp,
   ENTROPY_CONTEXT *a,
   ENTROPY_CONTEXT *l,
-  VP8_COMP *cpi
-) {
+  VP8_COMP *cpi,
+  int dry_run) {
   int pt; /* near block/prev token context index */
   TOKENEXTRA *t = *tp;        /* store tokens starting here */
   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -1359,20 +1405,19 @@ static __inline void stuff2nd_order_b
   t->skip_eob_node = 0;
   ++t;
   *tp = t;
-  ++cpi->coef_counts       [1] [0] [pt] [DCT_EOB_TOKEN];
+  if (!dry_run)
+    ++cpi->coef_counts       [1] [0] [pt] [DCT_EOB_TOKEN];
 
   pt = 0;
   *a = *l = pt;
 
 }
 
-static __inline void stuff1st_order_b
-(
-  TOKENEXTRA **tp,
-  ENTROPY_CONTEXT *a,
-  ENTROPY_CONTEXT *l,
-  VP8_COMP *cpi
-) {
+static __inline void stuff1st_order_b(TOKENEXTRA **tp,
+                                      ENTROPY_CONTEXT *a,
+                                      ENTROPY_CONTEXT *l,
+                                      VP8_COMP *cpi,
+                                      int dry_run) {
   int pt; /* near block/prev token context index */
   TOKENEXTRA *t = *tp;        /* store tokens starting here */
   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -1382,7 +1427,8 @@ static __inline void stuff1st_order_b
   t->skip_eob_node = 0;
   ++t;
   *tp = t;
-  ++cpi->coef_counts       [0] [1] [pt] [DCT_EOB_TOKEN];
+  if (!dry_run)
+    ++cpi->coef_counts[0] [1] [pt] [DCT_EOB_TOKEN];
   pt = 0; /* 0 <-> all coeff data is zero */
   *a = *l = pt;
 
@@ -1393,8 +1439,8 @@ void stuff1st_order_buv
   TOKENEXTRA **tp,
   ENTROPY_CONTEXT *a,
   ENTROPY_CONTEXT *l,
-  VP8_COMP *cpi
-) {
+  VP8_COMP *cpi,
+  int dry_run) {
   int pt; /* near block/prev token context index */
   TOKENEXTRA *t = *tp;        /* store tokens starting here */
   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -1404,31 +1450,39 @@ void stuff1st_order_buv
   t->skip_eob_node = 0;
   ++t;
   *tp = t;
-  ++cpi->coef_counts[2] [0] [pt] [DCT_EOB_TOKEN];
+  if (!dry_run)
+    ++cpi->coef_counts[2] [0] [pt] [DCT_EOB_TOKEN];
   pt = 0; /* 0 <-> all coeff data is zero */
   *a = *l = pt;
 }
 
-void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) {
+void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t, int dry_run) {
   ENTROPY_CONTEXT *A = (ENTROPY_CONTEXT *)x->above_context;
   ENTROPY_CONTEXT *L = (ENTROPY_CONTEXT *)x->left_context;
   int plane_type;
   int b;
+  TOKENEXTRA *t_backup = *t;
 
   stuff2nd_order_b(t,
-                   A + vp8_block2above[24], L + vp8_block2left[24], cpi);
+                   A + vp8_block2above[24],
+                   L + vp8_block2left[24],
+                   cpi, dry_run);
   plane_type = 0;
 
   for (b = 0; b < 16; b++)
     stuff1st_order_b(t,
                      A + vp8_block2above[b],
-                     L + vp8_block2left[b], cpi);
+                     L + vp8_block2left[b],
+                     cpi, dry_run);
 
   for (b = 16; b < 24; b++)
     stuff1st_order_buv(t,
                        A + vp8_block2above[b],
-                       L + vp8_block2left[b], cpi);
+                       L + vp8_block2left[b],
+                       cpi, dry_run);
 
+  if (dry_run)
+    *t = t_backup;
 }
 void vp8_fix_contexts(MACROBLOCKD *x) {
   /* Clear entropy contexts for Y2 blocks */