Merge "Merge branch 'master' into nextgenv2" into nextgenv2
diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h
index 27e33ba..5e41b6b 100644
--- a/vp10/common/blockd.h
+++ b/vp10/common/blockd.h
@@ -167,6 +167,9 @@
 
   int_mv mv[2];
   int_mv pred_mv[2];
+#if CONFIG_REF_MV
+  uint8_t ref_mv_idx;
+#endif
 } MB_MODE_INFO;
 
 typedef struct MODE_INFO {
diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c
index 44b0fc7..41c2565 100644
--- a/vp10/decoder/decodemv.c
+++ b/vp10/decoder/decodemv.c
@@ -1003,6 +1003,7 @@
 #endif  // CONFIG_EXT_INTER
   mode_ctx = vp10_mode_context_analyzer(inter_mode_ctx,
                                         mbmi->ref_frame, bsize, -1);
+  mbmi->ref_mv_idx = 0;
 #else
   mode_ctx = inter_mode_ctx[mbmi->ref_frame[0]];
 #endif
@@ -1015,9 +1016,8 @@
         return;
     }
   } else {
-    if (bsize >= BLOCK_8X8)
+    if (bsize >= BLOCK_8X8) {
 #if CONFIG_EXT_INTER
-    {
       if (is_compound)
         mbmi->mode = read_inter_compound_mode(cm, xd, r, mode_ctx);
       else
@@ -1027,9 +1027,12 @@
                                    mbmi,
 #endif  // CONFIG_REF_MV && CONFIG_EXT_INTER
                                    r, mode_ctx);
-#if CONFIG_EXT_INTER
+#if CONFIG_REF_MV
+    if (mbmi->mode == NEARMV && !is_compound)
+      if (xd->ref_mv_count[mbmi->ref_frame[0]] > 2)
+        mbmi->ref_mv_idx = vpx_read_bit(r);
+#endif
     }
-#endif  // CONFIG_EXT_INTER
   }
 
 #if CONFIG_EXT_INTER
@@ -1045,6 +1048,12 @@
   }
 
 #if CONFIG_REF_MV
+  if (mbmi->ref_mv_idx == 1) {
+    int_mv cur_mv = xd->ref_mv_stack[mbmi->ref_frame[0]][2].this_mv;
+    lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
+    nearmv[0] = cur_mv;
+  }
+
 #if CONFIG_EXT_INTER
   if (is_compound && bsize >= BLOCK_8X8 && mbmi->mode != ZERO_ZEROMV) {
 #else
diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index db2e8ee..837fd5b 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -988,6 +988,12 @@
                          has_second_ref(mbmi),
 #endif  // CONFIG_REF_MV && CONFIG_EXT_INTER
                          mode_ctx);
+
+#if CONFIG_REF_MV
+      if (mode == NEARMV && mbmi->ref_frame[1] == NONE)
+        if (mbmi_ext->ref_mv_count[mbmi->ref_frame[0]] > 2)
+          vpx_write_bit(w, mbmi->ref_mv_idx);
+#endif
       }
     }
 
@@ -1513,9 +1519,18 @@
       !m->mbmi.skip) {
     assert(*tok < tok_end);
     for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+      const int mbmi_txb_size = txsize_to_bsize[m->mbmi.tx_size];
+      const int num_4x4_w = num_4x4_blocks_wide_lookup[mbmi_txb_size];
+      const int num_4x4_h = num_4x4_blocks_high_lookup[mbmi_txb_size];
+      int row, col;
       TX_SIZE tx = plane ? get_uv_tx_size(&m->mbmi, &xd->plane[plane])
                          : m->mbmi.tx_size;
-      pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx);
+      BLOCK_SIZE txb_size = txsize_to_bsize[tx];
+      int bw = num_4x4_blocks_wide_lookup[txb_size];
+
+      for (row = 0; row < num_4x4_h; row += bw)
+        for (col = 0; col < num_4x4_w; col += bw)
+          pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx);
       assert(*tok < tok_end && (*tok)->token == EOSB_TOKEN);
       (*tok)++;
     }
diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c
index 1a6e6c54..32031ec 100644
--- a/vp10/encoder/rdopt.c
+++ b/vp10/encoder/rdopt.c
@@ -5715,6 +5715,9 @@
   int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
   int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
   MB_MODE_INFO best_mbmode;
+#if CONFIG_REF_MV
+  uint8_t best_ref_mv_idx[MAX_REF_FRAMES] = { 0 };
+#endif
   int best_mode_skippable = 0;
   int midx, best_mode_index = -1;
   unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
@@ -6273,6 +6276,102 @@
                                   single_skippable, &total_sse, best_rd,
                                   &mask_filter, filter_cache);
 
+#if CONFIG_REF_MV
+      mbmi->ref_mv_idx = 0;
+
+      if (!comp_pred && mbmi->mode == NEARMV &&
+          mbmi_ext->ref_mv_count[ref_frame] > 2) {
+        int_mv backup_mv = frame_mv[NEARMV][ref_frame];
+        int_mv cur_mv = mbmi_ext->ref_mv_stack[ref_frame][2].this_mv;
+        MB_MODE_INFO backup_mbmi = *mbmi;
+
+        int64_t tmp_alt_rd = INT64_MAX, tmp_ref_rd = this_rd;
+        int tmp_rate = 0, tmp_rate_y = 0, tmp_rate_uv = 0;
+        int tmp_skip = 1;
+        int64_t tmp_dist = 0, tmp_sse = 0;
+
+        lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
+        clamp_mv2(&cur_mv.as_mv, xd);
+
+        if (!mv_check_bounds(x, &cur_mv.as_mv)) {
+          int64_t dummy_filter_cache[SWITCHABLE_FILTER_CONTEXTS];
+          INTERP_FILTER dummy_single_inter_filter[MB_MODE_COUNT]
+                                                 [MAX_REF_FRAMES];
+          int dummy_single_skippable[MB_MODE_COUNT][MAX_REF_FRAMES];
+          int dummy_disable_skip = 0;
+          int64_t dummy_mask_filter = 0;
+#if CONFIG_EXT_INTER
+          int_mv dummy_single_newmvs[2][MAX_REF_FRAMES] =
+                                        { { { 0 } },  { { 0 } } };
+#else
+          int_mv dummy_single_newmv[MAX_REF_FRAMES] = { { 0 } };
+#endif
+
+          frame_mv[NEARMV][ref_frame] = cur_mv;
+          tmp_alt_rd = handle_inter_mode(cpi, x, bsize,
+                                         &tmp_rate, &tmp_dist, &tmp_skip,
+                                         &tmp_rate_y, &tmp_rate_uv,
+                                         &dummy_disable_skip, frame_mv,
+                                         mi_row, mi_col,
+#if CONFIG_EXT_INTER
+                                         dummy_single_newmvs,
+#else
+                                         dummy_single_newmv,
+#endif
+                                         dummy_single_inter_filter,
+                                         dummy_single_skippable,
+                                         &tmp_sse, best_rd,
+                                         &dummy_mask_filter,
+                                         dummy_filter_cache);
+        }
+
+        if (this_rd < INT64_MAX) {
+          if (RDCOST(x->rdmult, x->rddiv, rate_y + rate_uv, distortion2) <
+              RDCOST(x->rdmult, x->rddiv, 0, total_sse))
+            tmp_ref_rd = RDCOST(x->rdmult, x->rddiv,
+                rate2 + vp10_cost_bit(vp10_get_skip_prob(cm, xd), 0),
+                distortion2);
+          else
+            tmp_ref_rd = RDCOST(x->rdmult, x->rddiv,
+                rate2 + vp10_cost_bit(vp10_get_skip_prob(cm, xd), 1) -
+                rate_y - rate_uv,
+                total_sse);
+        }
+
+        if (tmp_alt_rd < INT64_MAX) {
+          if (RDCOST(x->rdmult, x->rddiv, tmp_rate_y + tmp_rate_uv, tmp_dist) <
+              RDCOST(x->rdmult, x->rddiv, 0, tmp_sse))
+            tmp_alt_rd = RDCOST(x->rdmult, x->rddiv,
+                tmp_rate + vp10_cost_bit(vp10_get_skip_prob(cm, xd), 0),
+                tmp_dist);
+          else
+            tmp_alt_rd = RDCOST(x->rdmult, x->rddiv,
+                tmp_rate + vp10_cost_bit(vp10_get_skip_prob(cm, xd), 1) -
+                tmp_rate_y - tmp_rate_uv,
+                tmp_sse);
+        }
+
+        if (tmp_ref_rd > tmp_alt_rd) {
+          rate2 = tmp_rate;
+          distortion2 = tmp_dist;
+          skippable = tmp_skip;
+          rate_y = tmp_rate_y;
+          rate_uv = tmp_rate_uv;
+          total_sse = tmp_sse;
+          this_rd = tmp_alt_rd;
+          mbmi->ref_mv_idx = 1;
+          // Indicator of the effective nearmv reference motion vector.
+          best_ref_mv_idx[ref_frame] = 1;
+        } else {
+          *mbmi = backup_mbmi;
+        }
+
+        frame_mv[NEARMV][ref_frame] = backup_mv;
+
+        rate2 += vp10_cost_bit(128, mbmi->ref_mv_idx);
+      }
+#endif
+
       if (this_rd == INT64_MAX)
         continue;
 
@@ -6482,6 +6581,14 @@
     int comp_pred_mode = refs[1] > INTRA_FRAME;
 #if CONFIG_REF_MV
     if (!comp_pred_mode) {
+      if (best_ref_mv_idx[best_mbmode.ref_frame[0]] == 1 &&
+          best_mbmode.ref_frame[1] == NONE) {
+        int_mv cur_mv =
+            mbmi_ext->ref_mv_stack[best_mbmode.ref_frame[0]][2].this_mv;
+        lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
+        frame_mv[NEARMV][refs[0]] = cur_mv;
+      }
+
       if (frame_mv[NEARESTMV][refs[0]].as_int == best_mbmode.mv[0].as_int)
         best_mbmode.mode = NEARESTMV;
       else if (frame_mv[NEARMV][refs[0]].as_int == best_mbmode.mv[0].as_int)
@@ -6593,6 +6700,9 @@
     if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET))
       best_mbmode.mode = ZEROMV;
   }
+
+  if (best_mbmode.mode == NEARMV && best_mbmode.ref_frame[1] == NONE)
+    best_mbmode.ref_mv_idx = best_ref_mv_idx[best_mbmode.ref_frame[0]];
 #endif
 
   if (best_mode_index < 0 || best_rd >= best_rd_so_far) {