diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index d6882d5859f16c015d4767fefafbe686fb7bc44f..4b49b17a29661cd1b1f7f7fd477a945d8a242499 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -96,6 +96,7 @@ struct macroblock {
   signed int act_zbin_adj;
 
   int mv_best_ref_index[MAX_REF_FRAMES];
+  unsigned int max_mv_context[MAX_REF_FRAMES];
 
   int nmvjointcost[MV_JOINTS];
   int nmvcosts[2][MV_VALS];
diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c
index 500f57442e68e9496574efb053786c716c96b133..7c6f292d5ff6abe239e515b4b00373266062d3a2 100644
--- a/vp9/encoder/vp9_encodemv.c
+++ b/vp9/encoder/vp9_encodemv.c
@@ -486,11 +486,11 @@ void vp9_encode_mv(VP9_COMP* cpi, vp9_writer* w,
   if (mv_joint_horizontal(j))
     encode_mv_component(w, diff.col, &mvctx->comps[1], usehp);
 
-  // If auto_mv_step_size is enabled and it is an arf/non shown frame
-  // then keep track of the largest motion vector component used.
-  if (cpi->sf.auto_mv_step_size && !cpi->common.show_frame) {
-    cpi->max_mv_magnitude = MAX((MAX(abs(mv->row), abs(mv->col)) >> 3),
-                                cpi->max_mv_magnitude);
+  // If auto_mv_step_size is enabled then keep track of the largest
+  // motion vector component used.
+  if (!cpi->dummy_packing && cpi->sf.auto_mv_step_size) {
+    unsigned int maxv = MAX(abs(mv->row), abs(mv->col)) >> 3;
+    cpi->max_mv_magnitude = MAX(maxv, cpi->max_mv_magnitude);
   }
 }
 
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index fe276fa6b790e0d2fa3ec87be0a8b9e1a1145a3e..8d846e0fbed072d3872ee6ff910ef55bdd61d991 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -706,12 +706,6 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
     cpi->mode_chosen_counts[i] = 0;
   }
 
-  // Initialize cpi->max_mv_magnitude if appropriate.
-  if ((cpi->common.frame_type == KEY_FRAME) || cpi->common.intra_only ||
-    (cpi->common.show_frame == 0)) {
-    cpi->max_mv_magnitude = 0;
-  }
-
   // best quality defaults
   sf->RD = 1;
   sf->search_method = NSTEP;
@@ -773,7 +767,6 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
 #else
       sf->static_segmentation = 0;
 #endif
-      sf->auto_mv_step_size = 1;
       sf->use_avoid_tested_higherror = 1;
       sf->adaptive_rd_thresh = 1;
       sf->last_chroma_intra_mode = TM_PRED;
@@ -798,6 +791,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
         sf->last_chroma_intra_mode = H_PRED;
         sf->use_rd_breakout = 1;
         sf->skip_encode_sb = 1;
+        sf->auto_mv_step_size = 1;
       }
       if (speed == 2) {
         sf->adjust_thresholds_by_speed = 1;
@@ -824,6 +818,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
         sf->using_small_partition_info = 1;
         sf->disable_splitmv =
             (MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0;
+        sf->auto_mv_step_size = 1;
       }
       if (speed == 3) {
         sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
@@ -840,6 +835,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
         sf->use_rd_breakout = 1;
         sf->skip_encode_sb = 1;
         sf->disable_splitmv = 1;
+        sf->auto_mv_step_size = 1;
       }
       if (speed == 4) {
         sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
@@ -856,6 +852,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
                                      FLAG_SKIP_COMP_REFMISMATCH;
         sf->use_rd_breakout = 1;
         sf->optimize_coefficients = 0;
+        sf->auto_mv_step_size = 1;
         // sf->reduce_first_step_size = 1;
         // sf->reference_masking = 1;
 
@@ -2515,6 +2512,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
   int undershoot_seen = 0;
 
   SPEED_FEATURES *sf = &cpi->sf;
+  unsigned int max_mv_def = MIN(cpi->common.width, cpi->common.height);
 #if RESET_FOREACH_FILTER
   int q_low0;
   int q_high0;
@@ -2587,6 +2585,24 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
   // Set default state for segment based loop filter update flags
   xd->lf.mode_ref_delta_update = 0;
 
+  // Initialize cpi->mv_step_param to default based on max resolution
+  cpi->mv_step_param = vp9_init_search_range(cpi, max_mv_def);
+  // Initialize cpi->max_mv_magnitude and cpi->mv_step_param if appropriate.
+  if (sf->auto_mv_step_size) {
+    if ((cpi->common.frame_type == KEY_FRAME) || cpi->common.intra_only) {
+      // initialize max_mv_magnitude for use in the first INTER frame
+      // after a key/intra-only frame
+      cpi->max_mv_magnitude = max_mv_def;
+    } else {
+      if (cm->show_frame)
+        // allow mv_steps to correspond to twice the max mv magnitude found
+        // in the previous frame, capped by the default max_mv_magnitude based
+        // on resolution
+        cpi->mv_step_param = vp9_init_search_range(
+            cpi, MIN(max_mv_def, 2 * cpi->max_mv_magnitude));
+      cpi->max_mv_magnitude = 0;
+    }
+  }
 
   // Set various flags etc to special state if it is a key frame
   if (cm->frame_type == KEY_FRAME) {
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 2c65fecd17ec10f8361f836c270b6c752c65ded7..345fe2a16df5fcd920695568aa09d657e327f2e6 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -504,6 +504,7 @@ typedef struct VP9_COMP {
   int error_bins[1024];
 
   unsigned int max_mv_magnitude;
+  int mv_step_param;
 
   // Data used for real time conferencing mode to help determine if it would be good to update the gf
   int inter_zz_count;
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 2b268554b808817c6dde0f4a08dd998678821975..ebd4bf15e60544fbf83c33d57dee498226bb512d 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -1938,9 +1938,24 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x,
               if (i == 2)
                 bsi->mvp.as_int =
                 x->e_mbd.mode_info_context->bmi[i - 2].as_mv[0].as_int;
-              step_param = 2;
             }
           }
+          if (cpi->sf.auto_mv_step_size && cpi->common.show_frame) {
+            // Take wtd average of the step_params based on the last frame's
+            // max mv magnitude and the best ref mvs of the current block for
+            // the given reference.
+            if (i == 0)
+              step_param = (vp9_init_search_range(
+                  cpi, x->max_mv_context[mbmi->ref_frame[0]]) +
+                  cpi->mv_step_param) >> 1;
+            else
+              step_param = (vp9_init_search_range(
+                  cpi, MAX(abs(bsi->mvp.as_mv.row),
+                           abs(bsi->mvp.as_mv.col)) >> 3) +
+                  cpi->mv_step_param) >> 1;
+          } else {
+            step_param = cpi->mv_step_param;
+          }
 
           further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
 
@@ -2225,6 +2240,7 @@ static void mv_pred(VP9_COMP *cpi, MACROBLOCK *x,
   int best_index = 0;
   int best_sad = INT_MAX;
   int this_sad = INT_MAX;
+  unsigned int max_mv = 0;
 
   uint8_t *src_y_ptr = x->plane[0].src.buf;
   uint8_t *ref_y_ptr;
@@ -2234,6 +2250,8 @@ static void mv_pred(VP9_COMP *cpi, MACROBLOCK *x,
   for (i = 0; i < MAX_MV_REF_CANDIDATES; i++) {
     this_mv.as_int = mbmi->ref_mvs[ref_frame][i].as_int;
 
+    max_mv = MAX(max_mv,
+                 MAX(abs(this_mv.as_mv.row), abs(this_mv.as_mv.col)) >> 3);
     // The list is at an end if we see 0 for a second time.
     if (!this_mv.as_int && zero_seen)
       break;
@@ -2257,6 +2275,7 @@ static void mv_pred(VP9_COMP *cpi, MACROBLOCK *x,
 
   // Note the index of the mv that worked best in the reference list.
   x->mv_best_ref_index[ref_frame] = best_index;
+  x->max_mv_context[ref_frame] = max_mv;
 }
 
 static void estimate_ref_frame_costs(VP9_COMP *cpi, int segment_id,
@@ -2503,12 +2522,14 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
     // Work out the size of the first step in the mv step search.
     // 0 here is maximum length first step. 1 is MAX >> 1 etc.
     if (cpi->sf.auto_mv_step_size && cpi->common.show_frame) {
-      step_param = vp9_init_search_range(cpi, cpi->max_mv_magnitude);
+      // Take wtd average of the step_params based on the last frame's
+      // max mv magnitude and that based on the best ref mvs of the current
+      // block for the given reference.
+      step_param = (vp9_init_search_range(cpi, x->max_mv_context[ref]) +
+                    cpi->mv_step_param) >> 1;
     } else {
-      step_param = vp9_init_search_range(
-                     cpi, MIN(cpi->common.width, cpi->common.height));
+      step_param = cpi->mv_step_param;
     }
-
     // mvp_full.as_int = ref_mv[0].as_int;
     mvp_full.as_int =
         mbmi->ref_mvs[ref][x->mv_best_ref_index[ref]].as_int;