Adds an error-resilient mode with test

Adds an error-resilient mode where frames can be continued
to be decoded even when there are errors (due to network losses)
on a prior frame. Specifically, backward updates are turned off
and probabilities of various symbols are reset to defaults at
the beginning of each frame. Further, the last frame's mvs are
not used for the mv reference list, and the sorting of the
initial list based on search on previous frames is turned off
as well.

Also adds a test where an arbitrary set of frames are skipped
from decoding to simulate errors. The test verifies (1) that if
the error frames are droppable - i.e. frame buffer updates have
been turned off - there are no mismatch errors for the remaining
frames after the error frames; and (2) if the error-frames are non
droppable, there are not only no decoding errors but the mismatch
PSNR between the decoder's version of the post-error frames and the
encoder's version is at least 20 dB.

Change-Id: Ie6e2bcd436b1e8643270356d3a930e8989ff52a5
diff --git a/test/decode_test_driver.h b/test/decode_test_driver.h
index 5daa165..ed70690 100644
--- a/test/decode_test_driver.h
+++ b/test/decode_test_driver.h
@@ -81,7 +81,7 @@
 // Common test functionality for all Decoder tests.
 class DecoderTest {
  public:
-  // Main loop.
+  // Main decoding loop
   virtual void RunLoop(CompressedVideoSource *video);
 
   // Hook to be called on every decompressed frame.
diff --git a/test/encode_test_driver.cc b/test/encode_test_driver.cc
index 9475ee9..b2b6e0d 100644
--- a/test/encode_test_driver.cc
+++ b/test/encode_test_driver.cc
@@ -7,6 +7,7 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
+
 #include "vpx_config.h"
 #include "test/codec_factory.h"
 #include "test/encode_test_driver.h"
@@ -129,6 +130,11 @@
   return match;
 }
 
+void EncoderTest::MismatchHook(const vpx_image_t *img1,
+                               const vpx_image_t *img2) {
+  ASSERT_TRUE(0) << "Encode/Decode mismatch found";
+}
+
 void EncoderTest::RunLoop(VideoSource *video) {
   vpx_codec_dec_cfg_t dec_cfg = {0};
 
@@ -149,7 +155,6 @@
                                                    &stats_);
     ASSERT_TRUE(encoder != NULL);
     Decoder* const decoder = codec_->CreateDecoder(dec_cfg, 0);
-    bool has_cxdata = false;
     bool again;
     for (again = true, video->Begin(); again; video->Next()) {
       again = video->img() != NULL;
@@ -160,15 +165,18 @@
 
       CxDataIterator iter = encoder->GetCxData();
 
+      bool has_cxdata = false;
+      bool has_dxdata = false;
       while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
         again = true;
-
         switch (pkt->kind) {
           case VPX_CODEC_CX_FRAME_PKT:
             has_cxdata = true;
-            if (decoder)
+            if (decoder && DoDecode()) {
               decoder->DecodeFrame((const uint8_t*)pkt->data.frame.buf,
                                    pkt->data.frame.sz);
+              has_dxdata = true;
+            }
             ASSERT_GE(pkt->data.frame.pts, last_pts_);
             last_pts_ = pkt->data.frame.pts;
             FramePktHook(pkt);
@@ -183,16 +191,17 @@
         }
       }
 
-      if (decoder && has_cxdata) {
+      if (has_dxdata && has_cxdata) {
         const vpx_image_t *img_enc = encoder->GetPreviewFrame();
         DxDataIterator dec_iter = decoder->GetDxData();
         const vpx_image_t *img_dec = dec_iter.Next();
-        if(img_enc && img_dec) {
+        if (img_enc && img_dec) {
           const bool res = compare_img(img_enc, img_dec);
-          ASSERT_TRUE(res)<< "Encoder/Decoder mismatch found.";
+          if (!res) {  // Mismatch
+            MismatchHook(img_enc, img_dec);
+          }
         }
       }
-
       if (!Continue())
         break;
     }
@@ -207,4 +216,5 @@
       break;
   }
 }
+
 }  // namespace libvpx_test
diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h
index 6182572..0944dc2 100644
--- a/test/encode_test_driver.h
+++ b/test/encode_test_driver.h
@@ -9,6 +9,8 @@
  */
 #ifndef TEST_ENCODE_TEST_DRIVER_H_
 #define TEST_ENCODE_TEST_DRIVER_H_
+
+#include "./vpx_config.h"
 #include <string>
 #include <vector>
 #include "third_party/googletest/src/include/gtest/gtest.h"
@@ -162,7 +164,7 @@
   // Map the TestMode enum to the deadline_ and passes_ variables.
   void SetMode(TestMode mode);
 
-  // Main loop.
+  // Main loop
   virtual void RunLoop(VideoSource *video);
 
   // Hook to be called at the beginning of a pass.
@@ -185,6 +187,13 @@
   virtual bool Continue() const { return !abort_; }
 
   const CodecFactory   *codec_;
+  // Hook to determine whether to decode frame after encoding
+  virtual bool DoDecode() const { return 1; }
+
+  // Hook to handle encode/decode mismatch
+  virtual void MismatchHook(const vpx_image_t *img1,
+                            const vpx_image_t *img2);
+
   bool                 abort_;
   vpx_codec_enc_cfg_t  cfg_;
   unsigned int         passes_;
diff --git a/test/error_resilience_test.cc b/test/error_resilience_test.cc
index be90439..f33c722 100644
--- a/test/error_resilience_test.cc
+++ b/test/error_resilience_test.cc
@@ -7,6 +7,7 @@
   in the file PATENTS.  All contributing project authors may
   be found in the AUTHORS file in the root of the source tree.
 */
+
 #include "third_party/googletest/src/include/gtest/gtest.h"
 #include "test/codec_factory.h"
 #include "test/encode_test_driver.h"
@@ -15,14 +16,28 @@
 
 namespace {
 
+const int kMaxErrorFrames = 8;
+const int kMaxDroppableFrames = 8;
+
 class ErrorResilienceTest : public ::libvpx_test::EncoderTest,
     public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
  protected:
-  ErrorResilienceTest() : EncoderTest(GET_PARAM(0)), psnr_(0.0), nframes_(0),
-      encoding_mode_(GET_PARAM(1)) {}
+  ErrorResilienceTest() : EncoderTest(GET_PARAM(0)),
+                          psnr_(0.0),
+                          nframes_(0),
+                          mismatch_psnr_(0.0),
+                          mismatch_nframes_(0),
+                          encoding_mode_(GET_PARAM(1)) {
+    Reset();
+  }
 
   virtual ~ErrorResilienceTest() {}
 
+  void Reset() {
+    error_nframes_ = 0;
+    droppable_nframes_ = 0;
+  }
+
   virtual void SetUp() {
     InitializeConfig();
     SetMode(encoding_mode_);
@@ -31,6 +46,8 @@
   virtual void BeginPassHook(unsigned int /*pass*/) {
     psnr_ = 0.0;
     nframes_ = 0;
+    mismatch_psnr_ = 0.0;
+    mismatch_nframes_ = 0;
   }
 
   virtual bool Continue() const {
@@ -42,15 +59,92 @@
     nframes_++;
   }
 
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video) {
+    frame_flags_ &= ~(VP8_EFLAG_NO_UPD_LAST |
+                      VP8_EFLAG_NO_UPD_GF |
+                      VP8_EFLAG_NO_UPD_ARF);
+    if (droppable_nframes_ > 0 &&
+        (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
+      for (unsigned int i = 0; i < droppable_nframes_; ++i) {
+        if (droppable_frames_[i] == nframes_) {
+          std::cout << "             Encoding droppable frame: "
+                    << droppable_frames_[i] << "\n";
+          frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST |
+                           VP8_EFLAG_NO_UPD_GF |
+                           VP8_EFLAG_NO_UPD_ARF);
+          return;
+        }
+      }
+    }
+  }
+
   double GetAveragePsnr() const {
     if (nframes_)
       return psnr_ / nframes_;
     return 0.0;
   }
 
+  double GetAverageMismatchPsnr() const {
+    if (mismatch_nframes_)
+      return mismatch_psnr_ / mismatch_nframes_;
+    return 0.0;
+  }
+
+  virtual bool DoDecode() const {
+    if (error_nframes_ > 0 &&
+        (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
+      for (unsigned int i = 0; i < error_nframes_; ++i) {
+        if (error_frames_[i] == nframes_ - 1) {
+          std::cout << "             Skipping decoding frame: "
+                    << error_frames_[i] << "\n";
+          return 0;
+        }
+      }
+    }
+    return 1;
+  }
+
+  virtual void MismatchHook(const vpx_image_t *img1,
+                            const vpx_image_t *img2) {
+    double mismatch_psnr = compute_psnr(img1, img2);
+    mismatch_psnr_ += mismatch_psnr;
+    ++mismatch_nframes_;
+    // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
+  }
+
+  void SetErrorFrames(int num, unsigned int *list) {
+    if (num > kMaxErrorFrames)
+      num = kMaxErrorFrames;
+    else if (num < 0)
+      num = 0;
+    error_nframes_ = num;
+    for (unsigned int i = 0; i < error_nframes_; ++i)
+      error_frames_[i] = list[i];
+  }
+
+  void SetDroppableFrames(int num, unsigned int *list) {
+    if (num > kMaxDroppableFrames)
+      num = kMaxDroppableFrames;
+    else if (num < 0)
+      num = 0;
+    droppable_nframes_ = num;
+    for (unsigned int i = 0; i < droppable_nframes_; ++i)
+      droppable_frames_[i] = list[i];
+  }
+
+  unsigned int GetMismatchFrames() {
+    return mismatch_nframes_;
+  }
+
  private:
   double psnr_;
   unsigned int nframes_;
+  unsigned int error_nframes_;
+  unsigned int droppable_nframes_;
+  double mismatch_psnr_;
+  unsigned int mismatch_nframes_;
+  unsigned int error_frames_[kMaxErrorFrames];
+  unsigned int droppable_frames_[kMaxDroppableFrames];
   libvpx_test::TestMode encoding_mode_;
 };
 
@@ -85,5 +179,50 @@
   }
 }
 
+TEST_P(ErrorResilienceTest, DropFramesWithoutRecovery) {
+  const vpx_rational timebase = { 33333333, 1000000000 };
+  cfg_.g_timebase = timebase;
+  cfg_.rc_target_bitrate = 2000;
+  cfg_.g_lag_in_frames = 5;
+
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                     timebase.den, timebase.num, 0, 30);
+
+  // Error resilient mode ON.
+  cfg_.g_error_resilient = 1;
+
+  // Set an arbitrary set of error frames same as droppable frames
+  unsigned int num_droppable_frames = 2;
+  unsigned int droppable_frame_list[] = {5, 16};
+  SetDroppableFrames(num_droppable_frames, droppable_frame_list);
+  SetErrorFrames(num_droppable_frames, droppable_frame_list);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  // Test that no mismatches have been found
+  std::cout << "             Mismatch frames: "
+            << GetMismatchFrames() << "\n";
+  EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
+
+  // reset previously set error/droppable frames
+  Reset();
+
+  // Now set an arbitrary set of error frames that are non-droppable
+  unsigned int num_error_frames = 3;
+  unsigned int error_frame_list[] = {3, 10, 20};
+  SetErrorFrames(num_error_frames, error_frame_list);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  // Test that dropping an arbitrary set of inter frames does not hurt too much
+  // Note the Average Mismatch PSNR is the average of the PSNR between
+  // decoded frame and encoder's version of the same frame for all frames
+  // with mismatch.
+  const double psnr_resilience_mismatch = GetAverageMismatchPsnr();
+  std::cout << "             Mismatch PSNR: "
+            << psnr_resilience_mismatch << "\n";
+  EXPECT_GT(psnr_resilience_mismatch, 20.0);
+}
+
 VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTest, ONE_PASS_TEST_MODES);
+VP9_INSTANTIATE_TEST_CASE(ErrorResilienceTest, ONE_PASS_TEST_MODES);
+
 }  // namespace
diff --git a/test/test.mk b/test/test.mk
index e3667da..f275a47 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -15,9 +15,10 @@
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += config_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += cq_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += datarate_test.cc
+
 LIBVPX_TEST_SRCS-yes                   += encode_test_driver.cc
 LIBVPX_TEST_SRCS-yes                   += encode_test_driver.h
-LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += error_resilience_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += error_resilience_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += i420_video_source.h
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += keyframe_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += resize_test.cc
@@ -26,6 +27,8 @@
 LIBVPX_TEST_SRCS-yes                   += decode_test_driver.cc
 LIBVPX_TEST_SRCS-yes                   += decode_test_driver.h
 LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += ivf_video_source.h
+
+
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += test_vector_test.cc
 ##
 ## WHITE BOX TESTS
@@ -70,6 +73,7 @@
 #LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct16x16_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += variance_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct32x32_test.cc
+
 endif # VP9
 
 
@@ -79,7 +83,8 @@
 ##
 ## TEST DATA
 ##
-LIBVPX_TEST_DATA-$(CONFIG_VP8_ENCODER) += hantro_collage_w352h288.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288.yuv
+
 LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf
 LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-002.ivf
 LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-003.ivf
diff --git a/test/util.h b/test/util.h
index 06a70cc..533a1db 100644
--- a/test/util.h
+++ b/test/util.h
@@ -11,8 +11,38 @@
 #ifndef TEST_UTIL_H_
 #define TEST_UTIL_H_
 
+#include <stdio.h>
+#include <math.h>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "vpx/vpx_image.h"
+
 // Macros
 #define PARAMS(...) ::testing::TestWithParam< std::tr1::tuple< __VA_ARGS__ > >
 #define GET_PARAM(k) std::tr1::get< k >(GetParam())
 
+static double compute_psnr(const vpx_image_t *img1,
+                           const vpx_image_t *img2) {
+  assert((img1->fmt == img2->fmt) &&
+         (img1->d_w == img2->d_w) &&
+         (img1->d_h == img2->d_h));
+
+  const unsigned int width_y  = img1->d_w;
+  const unsigned int height_y = img1->d_h;
+  unsigned int i, j;
+
+  int64_t sqrerr = 0;
+  for (i = 0; i < height_y; ++i)
+    for (j = 0; j < width_y; ++j) {
+      int64_t d = img1->planes[VPX_PLANE_Y][i * img1->stride[VPX_PLANE_Y] + j] -
+                  img2->planes[VPX_PLANE_Y][i * img2->stride[VPX_PLANE_Y] + j];
+      sqrerr += d * d;
+    }
+  double mse = sqrerr / (width_y * height_y);
+  double psnr = 100.0;
+  if (mse > 0.0) {
+    psnr = 10 * log10(255.0 * 255.0 / mse);
+  }
+  return psnr;
+}
+
 #endif  // TEST_UTIL_H_
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index f2107d7..2b7ab2e 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -146,6 +146,7 @@
 
   return 0;
 }
+
 void vp9_setup_version(VP9_COMMON *cm) {
   if (cm->version & 0x4) {
     if (!CONFIG_EXPERIMENTAL)
diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c
index ecae5e0..30e5336 100644
--- a/vp9/common/vp9_entropymode.c
+++ b/vp9/common/vp9_entropymode.c
@@ -11,9 +11,10 @@
 
 #include "vp9/common/vp9_onyxc_int.h"
 #include "vp9/common/vp9_modecont.h"
+#include "vp9/common/vp9_seg_common.h"
+#include "vp9/common/vp9_alloccommon.h"
 #include "vpx_mem/vpx_mem.h"
 
-
 static const unsigned int kf_y_mode_cts[8][VP9_YMODES] = {
   /* DC V   H  D45 135 117 153 D27 D63 TM i8x8 BPRED */
   {12,  6,  5,  5,  5,  5,  5,  5,  5,  2, 22, 200},
@@ -344,6 +345,9 @@
 #if CONFIG_COMP_INTERINTRA_PRED
   x->fc.interintra_prob = VP9_DEF_INTERINTRA_PROB;
 #endif
+  x->ref_pred_probs[0] = 120;
+  x->ref_pred_probs[1] = 80;
+  x->ref_pred_probs[2] = 40;
 }
 
 
@@ -480,7 +484,7 @@
 
 #define MVREF_COUNT_SAT 20
 #define MVREF_MAX_UPDATE_FACTOR 128
-void vp9_update_mode_context(VP9_COMMON *pc) {
+void vp9_adapt_mode_context(VP9_COMMON *pc) {
   int i, j;
   unsigned int (*mv_ref_ct)[4][2];
   int (*mode_context)[4];
@@ -631,3 +635,65 @@
   }
 #endif
 }
+
+static void set_default_lf_deltas(MACROBLOCKD *xd) {
+  xd->mode_ref_lf_delta_enabled = 1;
+  xd->mode_ref_lf_delta_update = 1;
+
+  xd->ref_lf_deltas[INTRA_FRAME] = 2;
+  xd->ref_lf_deltas[LAST_FRAME] = 0;
+  xd->ref_lf_deltas[GOLDEN_FRAME] = -2;
+  xd->ref_lf_deltas[ALTREF_FRAME] = -2;
+
+  xd->mode_lf_deltas[0] = 4;               // BPRED
+  xd->mode_lf_deltas[1] = -2;              // Zero
+  xd->mode_lf_deltas[2] = 2;               // New mv
+  xd->mode_lf_deltas[3] = 4;               // Split mv
+}
+
+void vp9_setup_past_independence(VP9_COMMON *cm, MACROBLOCKD *xd) {
+  // Reset the segment feature data to the default stats:
+  // Features disabled, 0, with delta coding (Default state).
+  int i;
+  vp9_clearall_segfeatures(xd);
+  xd->mb_segment_abs_delta = SEGMENT_DELTADATA;
+  if (cm->last_frame_seg_map)
+    vpx_memset(cm->last_frame_seg_map, 0, (cm->mb_rows * cm->mb_cols));
+
+  /* reset the mode ref deltas for loop filter */
+  vpx_memset(xd->last_ref_lf_deltas, 0, sizeof(xd->last_ref_lf_deltas));
+  vpx_memset(xd->last_mode_lf_deltas, 0, sizeof(xd->last_mode_lf_deltas));
+  set_default_lf_deltas(xd);
+
+  vp9_default_coef_probs(cm);
+  vp9_init_mbmode_probs(cm);
+  vp9_default_bmode_probs(cm->fc.bmode_prob);
+  vp9_kf_default_bmode_probs(cm->kf_bmode_prob);
+  vp9_init_mv_probs(cm);
+  // To force update of the sharpness
+  cm->last_sharpness_level = -1;
+
+  vp9_init_mode_contexts(cm);
+
+  for (i = 0; i < NUM_FRAME_CONTEXTS; i++) {
+    vpx_memcpy(&cm->frame_contexts[i], &cm->fc, sizeof(cm->fc));
+  }
+
+  vpx_memset(cm->prev_mip, 0,
+             (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO));
+  vpx_memset(cm->mip, 0,
+             (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO));
+
+  vp9_update_mode_info_border(cm, cm->mip);
+  vp9_update_mode_info_in_image(cm, cm->mi);
+
+#if CONFIG_NEW_MVREF
+  // Defaults probabilities for encoding the MV ref id signal
+  vpx_memset(xd->mb_mv_ref_probs, VP9_DEFAULT_MV_REF_PROB,
+             sizeof(xd->mb_mv_ref_probs));
+#endif
+  cm->ref_frame_sign_bias[GOLDEN_FRAME] = 0;
+  cm->ref_frame_sign_bias[ALTREF_FRAME] = 0;
+
+  cm->frame_context_idx = 0;
+}
diff --git a/vp9/common/vp9_entropymode.h b/vp9/common/vp9_entropymode.h
index e03c6fe..aa06e49 100644
--- a/vp9/common/vp9_entropymode.h
+++ b/vp9/common/vp9_entropymode.h
@@ -76,11 +76,14 @@
 
 struct VP9Common;
 
+/* sets up common features to forget past dependence */
+void vp9_setup_past_independence(struct VP9Common *cm, MACROBLOCKD *xd);
+
 void vp9_init_mbmode_probs(struct VP9Common *x);
 
 extern void vp9_init_mode_contexts(struct VP9Common *pc);
 
-extern void vp9_update_mode_context(struct VP9Common *pc);
+extern void vp9_adapt_mode_context(struct VP9Common *pc);
 
 extern void vp9_accum_mv_refs(struct VP9Common *pc,
                               MB_PREDICTION_MODE m,
diff --git a/vp9/common/vp9_findnearmv.c b/vp9/common/vp9_findnearmv.c
index 41d18db..88f2ea9 100644
--- a/vp9/common/vp9_findnearmv.c
+++ b/vp9/common/vp9_findnearmv.c
@@ -141,130 +141,136 @@
   int_mv sorted_mvs[MAX_MV_REF_CANDIDATES];
   int zero_seen = FALSE;
 
-  // Default all to 0,0 if nothing else available
-  nearest->as_int = near->as_int = 0;
-  vpx_memset(sorted_mvs, 0, sizeof(sorted_mvs));
+  if (ref_y_buffer) {
 
-  above_src = xd->dst.y_buffer - xd->dst.y_stride * 2;
-  above_ref = ref_y_buffer - ref_y_stride * 2;
+    // Default all to 0,0 if nothing else available
+    nearest->as_int = near->as_int = 0;
+    vpx_memset(sorted_mvs, 0, sizeof(sorted_mvs));
+
+    above_src = xd->dst.y_buffer - xd->dst.y_stride * 2;
+    above_ref = ref_y_buffer - ref_y_stride * 2;
 #if CONFIG_ABOVESPREFMV
-  above_src -= 4;
-  above_ref -= 4;
+    above_src -= 4;
+    above_ref -= 4;
 #else
-  left_src  = xd->dst.y_buffer - 2;
-  left_ref  = ref_y_buffer - 2;
+    left_src  = xd->dst.y_buffer - 2;
+    left_ref  = ref_y_buffer - 2;
 #endif
 
-  // Limit search to the predicted best few candidates
-  for(i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
-    int_mv this_mv;
-    int offset = 0;
-    int row_offset, col_offset;
+    // Limit search to the predicted best few candidates
+    for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
+      int_mv this_mv;
+      int offset = 0;
+      int row_offset, col_offset;
 
-    this_mv.as_int = mvlist[i].as_int;
+      this_mv.as_int = mvlist[i].as_int;
 
-    // If we see a 0,0 vector for a second time we have reached the end of
-    // the list of valid candidate vectors.
-    if (!this_mv.as_int && zero_seen)
-      break;
-
-    zero_seen = zero_seen || !this_mv.as_int;
-
-#if !CONFIG_ABOVESPREFMV
-    clamp_mv(&this_mv,
-             xd->mb_to_left_edge - LEFT_TOP_MARGIN + 24,
-             xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
-             xd->mb_to_top_edge - LEFT_TOP_MARGIN + 24,
-             xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
-#else
-    clamp_mv(&this_mv,
-             xd->mb_to_left_edge - LEFT_TOP_MARGIN + 32,
-             xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
-             xd->mb_to_top_edge - LEFT_TOP_MARGIN + 24,
-             xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
-#endif
-
-    row_offset = this_mv.as_mv.row >> 3;
-    col_offset = this_mv.as_mv.col >> 3;
-    offset = ref_y_stride * row_offset + col_offset;
-    score = 0;
-    if (xd->up_available) {
-      vp9_sub_pixel_variance16x2(above_ref + offset, ref_y_stride,
-                                 SP(this_mv.as_mv.col),
-                                 SP(this_mv.as_mv.row),
-                                 above_src, xd->dst.y_stride, &sse);
-      score += sse;
-      if (xd->mode_info_context->mbmi.sb_type >= BLOCK_SIZE_SB32X32) {
-        vp9_sub_pixel_variance16x2(above_ref + offset + 16,
-                                   ref_y_stride,
-                                   SP(this_mv.as_mv.col),
-                                   SP(this_mv.as_mv.row),
-                                   above_src + 16, xd->dst.y_stride, &sse);
-        score += sse;
-      }
-      if (xd->mode_info_context->mbmi.sb_type >= BLOCK_SIZE_SB64X64) {
-        vp9_sub_pixel_variance16x2(above_ref + offset + 32,
-                                   ref_y_stride,
-                                   SP(this_mv.as_mv.col),
-                                   SP(this_mv.as_mv.row),
-                                   above_src + 32, xd->dst.y_stride, &sse);
-        score += sse;
-        vp9_sub_pixel_variance16x2(above_ref + offset + 48,
-                                   ref_y_stride,
-                                   SP(this_mv.as_mv.col),
-                                   SP(this_mv.as_mv.row),
-                                   above_src + 48, xd->dst.y_stride, &sse);
-        score += sse;
-      }
-    }
-#if !CONFIG_ABOVESPREFMV
-    if (xd->left_available) {
-      vp9_sub_pixel_variance2x16_c(left_ref + offset, ref_y_stride,
-                                   SP(this_mv.as_mv.col),
-                                   SP(this_mv.as_mv.row),
-                                   left_src, xd->dst.y_stride, &sse);
-      score += sse;
-      if (xd->mode_info_context->mbmi.sb_type >= BLOCK_SIZE_SB32X32) {
-        vp9_sub_pixel_variance2x16_c(left_ref + offset + ref_y_stride * 16,
-                                     ref_y_stride,
-                                     SP(this_mv.as_mv.col),
-                                     SP(this_mv.as_mv.row),
-                                     left_src + xd->dst.y_stride * 16,
-                                     xd->dst.y_stride, &sse);
-        score += sse;
-      }
-      if (xd->mode_info_context->mbmi.sb_type >= BLOCK_SIZE_SB64X64) {
-        vp9_sub_pixel_variance2x16_c(left_ref + offset + ref_y_stride * 32,
-                                     ref_y_stride,
-                                     SP(this_mv.as_mv.col),
-                                     SP(this_mv.as_mv.row),
-                                     left_src + xd->dst.y_stride * 32,
-                                     xd->dst.y_stride, &sse);
-        score += sse;
-        vp9_sub_pixel_variance2x16_c(left_ref + offset + ref_y_stride * 48,
-                                     ref_y_stride,
-                                     SP(this_mv.as_mv.col),
-                                     SP(this_mv.as_mv.row),
-                                     left_src + xd->dst.y_stride * 48,
-                                     xd->dst.y_stride, &sse);
-        score += sse;
-      }
-    }
-#endif
-    // Add the entry to our list and then resort the list on score.
-    ref_scores[i] = score;
-    sorted_mvs[i].as_int = this_mv.as_int;
-    j = i;
-    while (j > 0) {
-      if (ref_scores[j] < ref_scores[j-1]) {
-        ref_scores[j] = ref_scores[j-1];
-        sorted_mvs[j].as_int = sorted_mvs[j-1].as_int;
-        ref_scores[j-1] = score;
-        sorted_mvs[j-1].as_int = this_mv.as_int;
-        j--;
-      } else
+      // If we see a 0,0 vector for a second time we have reached the end of
+      // the list of valid candidate vectors.
+      if (!this_mv.as_int && zero_seen)
         break;
+
+      zero_seen = zero_seen || !this_mv.as_int;
+
+#if !CONFIG_ABOVESPREFMV
+      clamp_mv(&this_mv,
+               xd->mb_to_left_edge - LEFT_TOP_MARGIN + 24,
+               xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
+               xd->mb_to_top_edge - LEFT_TOP_MARGIN + 24,
+               xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
+#else
+      clamp_mv(&this_mv,
+               xd->mb_to_left_edge - LEFT_TOP_MARGIN + 32,
+               xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
+               xd->mb_to_top_edge - LEFT_TOP_MARGIN + 24,
+               xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
+#endif
+
+      row_offset = this_mv.as_mv.row >> 3;
+      col_offset = this_mv.as_mv.col >> 3;
+      offset = ref_y_stride * row_offset + col_offset;
+      score = 0;
+      if (xd->up_available) {
+        vp9_sub_pixel_variance16x2(above_ref + offset, ref_y_stride,
+                                   SP(this_mv.as_mv.col),
+                                   SP(this_mv.as_mv.row),
+                                   above_src, xd->dst.y_stride, &sse);
+        score += sse;
+        if (xd->mode_info_context->mbmi.sb_type >= BLOCK_SIZE_SB32X32) {
+          vp9_sub_pixel_variance16x2(above_ref + offset + 16,
+                                     ref_y_stride,
+                                     SP(this_mv.as_mv.col),
+                                     SP(this_mv.as_mv.row),
+                                     above_src + 16, xd->dst.y_stride, &sse);
+          score += sse;
+        }
+        if (xd->mode_info_context->mbmi.sb_type >= BLOCK_SIZE_SB64X64) {
+          vp9_sub_pixel_variance16x2(above_ref + offset + 32,
+                                     ref_y_stride,
+                                     SP(this_mv.as_mv.col),
+                                     SP(this_mv.as_mv.row),
+                                     above_src + 32, xd->dst.y_stride, &sse);
+          score += sse;
+          vp9_sub_pixel_variance16x2(above_ref + offset + 48,
+                                     ref_y_stride,
+                                     SP(this_mv.as_mv.col),
+                                     SP(this_mv.as_mv.row),
+                                     above_src + 48, xd->dst.y_stride, &sse);
+          score += sse;
+        }
+      }
+#if !CONFIG_ABOVESPREFMV
+      if (xd->left_available) {
+        vp9_sub_pixel_variance2x16_c(left_ref + offset, ref_y_stride,
+                                     SP(this_mv.as_mv.col),
+                                     SP(this_mv.as_mv.row),
+                                     left_src, xd->dst.y_stride, &sse);
+        score += sse;
+        if (xd->mode_info_context->mbmi.sb_type >= BLOCK_SIZE_SB32X32) {
+          vp9_sub_pixel_variance2x16_c(left_ref + offset + ref_y_stride * 16,
+                                       ref_y_stride,
+                                       SP(this_mv.as_mv.col),
+                                       SP(this_mv.as_mv.row),
+                                       left_src + xd->dst.y_stride * 16,
+                                       xd->dst.y_stride, &sse);
+          score += sse;
+        }
+        if (xd->mode_info_context->mbmi.sb_type >= BLOCK_SIZE_SB64X64) {
+          vp9_sub_pixel_variance2x16_c(left_ref + offset + ref_y_stride * 32,
+                                     ref_y_stride,
+                                       SP(this_mv.as_mv.col),
+                                       SP(this_mv.as_mv.row),
+                                       left_src + xd->dst.y_stride * 32,
+                                       xd->dst.y_stride, &sse);
+          score += sse;
+          vp9_sub_pixel_variance2x16_c(left_ref + offset + ref_y_stride * 48,
+                                       ref_y_stride,
+                                       SP(this_mv.as_mv.col),
+                                       SP(this_mv.as_mv.row),
+                                       left_src + xd->dst.y_stride * 48,
+                                       xd->dst.y_stride, &sse);
+          score += sse;
+        }
+      }
+#endif
+      // Add the entry to our list and then resort the list on score.
+      ref_scores[i] = score;
+      sorted_mvs[i].as_int = this_mv.as_int;
+      j = i;
+      while (j > 0) {
+        if (ref_scores[j] < ref_scores[j-1]) {
+          ref_scores[j] = ref_scores[j-1];
+          sorted_mvs[j].as_int = sorted_mvs[j-1].as_int;
+          ref_scores[j-1] = score;
+          sorted_mvs[j-1].as_int = this_mv.as_int;
+          j--;
+        } else {
+          break;
+        }
+      }
     }
+  } else {
+    vpx_memcpy(sorted_mvs, mvlist, sizeof(sorted_mvs));
   }
 
   // Make sure all the candidates are properly clamped etc
diff --git a/vp9/common/vp9_findnearmv.h b/vp9/common/vp9_findnearmv.h
index a66a7de..de06482 100644
--- a/vp9/common/vp9_findnearmv.h
+++ b/vp9/common/vp9_findnearmv.h
@@ -28,7 +28,8 @@
                            int_mv *nearest,
                            int_mv *near);
 
-static void mv_bias(int refmb_ref_frame_sign_bias, int refframe, int_mv *mvp, const int *ref_frame_sign_bias) {
+static void mv_bias(int refmb_ref_frame_sign_bias, int refframe,
+                    int_mv *mvp, const int *ref_frame_sign_bias) {
   MV xmv;
   xmv = mvp->as_mv;
 
diff --git a/vp9/common/vp9_loopfilter.c b/vp9/common/vp9_loopfilter.c
index fb05055..4182104 100644
--- a/vp9/common/vp9_loopfilter.c
+++ b/vp9/common/vp9_loopfilter.c
@@ -109,6 +109,9 @@
   loop_filter_info_n *lfi = &cm->lf_info;
 
   /* update limits if sharpness has changed */
+  // printf("vp9_loop_filter_frame_init %d\n", default_filt_lvl);
+  // printf("sharpness level: %d [%d]\n",
+  //        cm->sharpness_level, cm->last_sharpness_level);
   if (cm->last_sharpness_level != cm->sharpness_level) {
     vp9_loop_filter_update_sharpness(lfi, cm->sharpness_level);
     cm->last_sharpness_level = cm->sharpness_level;
@@ -202,6 +205,7 @@
           mbmi1->mv[mbmi1->ref_frame].as_int) &&
          mbmi0->ref_frame != INTRA_FRAME;
 }
+
 void vp9_loop_filter_frame(VP9_COMMON *cm,
                            MACROBLOCKD *xd,
                            int frame_filter_level,
@@ -271,7 +275,6 @@
               vp9_loop_filter_bv(y_ptr, u_ptr, v_ptr, post->y_stride,
                                  post->uv_stride, &lfi);
             }
-
           }
           /* don't apply across umv border */
           if (mb_row > 0 &&
diff --git a/vp9/common/vp9_mvref_common.c b/vp9/common/vp9_mvref_common.c
index 786b021..8d4980f 100644
--- a/vp9/common/vp9_mvref_common.c
+++ b/vp9/common/vp9_mvref_common.c
@@ -259,12 +259,14 @@
       split_count += (candidate_mi->mbmi.mode == SPLITMV);
     }
   }
-  // Look in the last frame
-  candidate_mi = lf_here;
-  if (get_matching_candidate(candidate_mi, ref_frame, &c_refmv)) {
-    clamp_mv(xd, &c_refmv);
-    addmv_and_shuffle(candidate_mvs, candidate_scores,
-                      &index, c_refmv, 18);
+  // Look in the last frame if it exists
+  if (lf_here) {
+    candidate_mi = lf_here;
+    if (get_matching_candidate(candidate_mi, ref_frame, &c_refmv)) {
+      clamp_mv(xd, &c_refmv);
+      addmv_and_shuffle(candidate_mvs, candidate_scores,
+                        &index, c_refmv, 18);
+    }
   }
   // More distant neigbours
   for (i = 2; (i < MVREF_NEIGHBOURS) &&
@@ -316,8 +318,8 @@
       }
     }
   }
-  // Look at the last frame
-  if (index < (MAX_MV_REF_CANDIDATES - 1)) {
+  // Look at the last frame if it exists
+  if (index < (MAX_MV_REF_CANDIDATES - 1) && lf_here) {
     candidate_mi = lf_here;
     get_non_matching_candidates(candidate_mi, ref_frame,
                                 &c_ref_frame, &c_refmv,
@@ -366,7 +368,7 @@
 
   // 0,0 is always a valid reference.
   for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
-    if (candidate_mvs[i].as_int == 0)
+     if (candidate_mvs[i].as_int == 0)
       break;
   }
   if (i == MAX_MV_REF_CANDIDATES) {
diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h
index e4ad72f..46ae2f0 100644
--- a/vp9/common/vp9_onyx.h
+++ b/vp9/common/vp9_onyx.h
@@ -159,6 +159,12 @@
 
     int encode_breakout;  // early breakout encode threshold : for video conf recommend 800
 
+    /* Bitfield defining the error resiliency features to enable.
+     * Can provide decodable frames after losses in previous
+     * frames and decodable partitions after losses in the same frame.
+     */
+    unsigned int error_resilient_mode;
+
     int arnr_max_frames;
     int arnr_strength;
     int arnr_type;
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index 0f40e9f..4e2fa37 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -276,6 +276,7 @@
   int use_interintra;
 #endif
 
+  int error_resilient_mode;
 } VP9_COMMON;
 
 static int get_free_fb(VP9_COMMON *cm) {
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index eef9e6e..31ae257 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -293,7 +293,10 @@
     mv->col = read_nmv_component_fp(r, mv->col, ref->col, &mvctx->comps[1],
                                     usehp);
   }
-  //printf("  %d: %d %d ref: %d %d\n", usehp, mv->row, mv-> col, ref->row, ref->col);
+  /*
+  printf("MV: %d %d REF: %d %d\n", mv->row + ref->row, mv->col + ref->col,
+	 ref->row, ref->col);
+	 */
 }
 
 static void update_nmv(vp9_reader *bc, vp9_prob *const p,
@@ -716,6 +719,11 @@
   else
     mbmi->ref_frame = read_ref_frame(pbi, bc, mbmi->segment_id);
 
+  /*
+  if (pbi->common.current_video_frame == 1)
+    printf("ref frame: %d [%d %d]\n", mbmi->ref_frame, mb_row, mb_col);
+    */
+
   // If reference frame is an Inter frame
   if (mbmi->ref_frame) {
     int_mv nearest, nearby, best_mv;
@@ -747,12 +755,25 @@
         printf("%d %d\n", xd->mode_info_context->mbmi.mv[0].as_mv.row,
                xd->mode_info_context->mbmi.mv[0].as_mv.col);
 #endif
-      vp9_find_mv_refs(xd, mi, prev_mi,
+      // if (cm->current_video_frame == 1 && mb_row == 4 && mb_col == 5)
+      //  printf("Dello\n");
+      vp9_find_mv_refs(xd, mi, cm->error_resilient_mode ? 0 : prev_mi,
                        ref_frame, mbmi->ref_mvs[ref_frame],
                        cm->ref_frame_sign_bias);
 
       vp9_mv_ref_probs(&pbi->common, mv_ref_p,
                        mbmi->mb_mode_context[ref_frame]);
+      /*
+      if (pbi->common.current_video_frame == 1) {
+	int k = mbmi->mb_mode_context[ref_frame];
+	printf("vp9_mode_contexts: [%d %d %d %d] %d %d %d %d\n",
+	       mb_row, mb_col, ref_frame, k,
+	       cm->fc.vp9_mode_contexts[k][0],
+	       cm->fc.vp9_mode_contexts[k][1],
+	       cm->fc.vp9_mode_contexts[k][2],
+	       cm->fc.vp9_mode_contexts[k][3]);
+      }
+      */
 
       // Is the segment level mode feature enabled for this segment
       if (vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_MODE)) {
@@ -770,7 +791,8 @@
 
       if (mbmi->mode != ZEROMV) {
         vp9_find_best_ref_mvs(xd,
-                              xd->pre.y_buffer,
+                              pbi->common.error_resilient_mode ?
+                              0 : xd->pre.y_buffer,
                               recon_y_stride,
                               mbmi->ref_mvs[ref_frame],
                               &nearest, &nearby);
@@ -822,14 +844,15 @@
         xd->second_pre.v_buffer =
           cm->yv12_fb[second_ref_fb_idx].v_buffer + recon_uvoffset;
 
-        vp9_find_mv_refs(xd, mi, prev_mi,
+        vp9_find_mv_refs(xd, mi, cm->error_resilient_mode ? 0 : prev_mi,
                          mbmi->second_ref_frame,
                          mbmi->ref_mvs[mbmi->second_ref_frame],
                          cm->ref_frame_sign_bias);
 
         if (mbmi->mode != ZEROMV) {
           vp9_find_best_ref_mvs(xd,
-                                xd->second_pre.y_buffer,
+                                pbi->common.error_resilient_mode ?
+                                0 : xd->second_pre.y_buffer,
                                 recon_y_stride,
                                 mbmi->ref_mvs[mbmi->second_ref_frame],
                                 &nearest_second,
@@ -1136,6 +1159,10 @@
       pbi->common.fc.uv_mode_counts[mbmi->mode][mbmi->uv_mode]++;
     }
   }
+  /*
+  if (pbi->common.current_video_frame == 1)
+    printf("mode: %d skip: %d\n", mbmi->mode, mbmi->mb_skip_coeff);
+    */
 
   if (cm->txfm_mode == TX_MODE_SELECT && mbmi->mb_skip_coeff == 0 &&
       ((mbmi->ref_frame == INTRA_FRAME && mbmi->mode <= I8X8_PRED) ||
@@ -1177,6 +1204,7 @@
 
   mb_mode_mv_init(pbi, bc);
 }
+
 void vp9_decode_mb_mode_mv(VP9D_COMP* const pbi,
                            MACROBLOCKD* const xd,
                            int mb_row,
diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c
index 18e09e4..10bcbf9 100644
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -32,7 +32,6 @@
 #include "vp9/decoder/vp9_dboolhuff.h"
 
 #include "vp9/common/vp9_seg_common.h"
-#include "vp9/common/vp9_entropy.h"
 #include "vp9_rtcd.h"
 
 #include <assert.h>
@@ -1255,54 +1254,14 @@
   MACROBLOCKD *const xd  = &pbi->mb;
 
   if (pc->frame_type == KEY_FRAME) {
-    int i;
-
-    if (pc->last_frame_seg_map)
-      vpx_memset(pc->last_frame_seg_map, 0, (pc->mb_rows * pc->mb_cols));
-
-    vp9_init_mv_probs(pc);
-
-    vp9_init_mbmode_probs(pc);
-    vp9_default_bmode_probs(pc->fc.bmode_prob);
-
-    vp9_default_coef_probs(pc);
-    vp9_kf_default_bmode_probs(pc->kf_bmode_prob);
-
-    // Reset the segment feature data to the default stats:
-    // Features disabled, 0, with delta coding (Default state).
-    vp9_clearall_segfeatures(xd);
-
-    xd->mb_segment_abs_delta = SEGMENT_DELTADATA;
-
-    /* reset the mode ref deltasa for loop filter */
-    vpx_memset(xd->ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas));
-    vpx_memset(xd->mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas));
-
+    vp9_setup_past_independence(pc, xd);
     /* All buffers are implicitly updated on key frames. */
     pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
+  } else if (pc->error_resilient_mode) {
+    vp9_setup_past_independence(pc, xd);
+  }
 
-    /* Note that Golden and Altref modes cannot be used on a key frame so
-     * ref_frame_sign_bias[] is undefined and meaningless
-     */
-    pc->ref_frame_sign_bias[GOLDEN_FRAME] = 0;
-    pc->ref_frame_sign_bias[ALTREF_FRAME] = 0;
-
-    vp9_init_mode_contexts(&pbi->common);
-
-    for (i = 0; i < NUM_FRAME_CONTEXTS; i++)
-      vpx_memcpy(&pc->frame_contexts[i], &pc->fc, sizeof(pc->fc));
-
-    vpx_memset(pc->prev_mip, 0,
-               (pc->mb_cols + 1) * (pc->mb_rows + 1)* sizeof(MODE_INFO));
-    vpx_memset(pc->mip, 0,
-               (pc->mb_cols + 1) * (pc->mb_rows + 1)* sizeof(MODE_INFO));
-
-    vp9_update_mode_info_border(pc, pc->mip);
-    vp9_update_mode_info_in_image(pc, pc->mi);
-
-
-  } else {
-
+  if (pc->frame_type != KEY_FRAME) {
     if (!pc->use_bilinear_mc_filter)
       pc->mcomp_filter_type = EIGHTTAP;
     else
@@ -1322,7 +1281,6 @@
   xd->fullpixel_mask = 0xffffffff;
   if (pc->full_pixel)
     xd->fullpixel_mask = 0xfffffff8;
-
 }
 
 static void read_coef_probs_common(BOOL_DECODER* const bc,
@@ -1383,6 +1341,7 @@
   int i, j;
   int corrupt_tokens = 0;
 
+  // printf("Decoding frame %d\n", pc->current_video_frame);
   /* start with no corruption of current frame */
   xd->corrupted = 0;
   pc->yv12_fb[pc->new_fb_idx].corrupted = 0;
@@ -1452,9 +1411,6 @@
       }
     }
   }
-#ifdef DEC_DEBUG
-  printf("Decode frame %d\n", pc->current_video_frame);
-#endif
 
   if ((!pbi->decoded_key_frame && pc->frame_type != KEY_FRAME) ||
       pc->Width == 0 || pc->Height == 0) {
@@ -1472,6 +1428,7 @@
     pc->clamp_type  = (CLAMP_TYPE)vp9_read_bit(&header_bc);
   }
 
+  pc->error_resilient_mode = vp9_read_bit(&header_bc);
   /* Is segmentation enabled */
   xd->segmentation_enabled = (unsigned char)vp9_read_bit(&header_bc);
 
@@ -1687,11 +1644,7 @@
 
 #if CONFIG_NEW_MVREF
   // If Key frame reset mv ref id probabilities to defaults
-  if (pc->frame_type == KEY_FRAME) {
-    // Defaults probabilities for encoding the MV ref id signal
-    vpx_memset(xd->mb_mv_ref_probs, VP9_DEFAULT_MV_REF_PROB,
-               sizeof(xd->mb_mv_ref_probs));
-  } else {
+  if (pc->frame_type != KEY_FRAME) {
     // Read any mv_ref index probability updates
     int i, j;
 
@@ -1818,11 +1771,14 @@
                          "A stream must start with a complete key frame");
   }
 
-  vp9_adapt_coef_probs(pc);
+  if (!pc->error_resilient_mode)
+    vp9_adapt_coef_probs(pc);
   if (pc->frame_type != KEY_FRAME) {
-    vp9_adapt_mode_probs(pc);
-    vp9_adapt_nmv_probs(pc, xd->allow_high_precision_mv);
-    vp9_update_mode_context(&pbi->common);
+    if (!pc->error_resilient_mode) {
+      vp9_adapt_mode_probs(pc);
+      vp9_adapt_nmv_probs(pc, xd->allow_high_precision_mv);
+      vp9_adapt_mode_context(&pbi->common);
+    }
   }
 
   if (pc->refresh_entropy_probs) {
@@ -1839,7 +1795,6 @@
     fclose(f);
   }
 #endif
-  // printf("Frame %d Done\n", frame_count++);
 
   /* Find the end of the coded buffer */
   while (residual_bc.count > CHAR_BIT
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 1a9d33d..34d27d1 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -189,15 +189,7 @@
   int old_cost, new_cost;
 
   // Set the prediction probability structures to defaults
-  if (cm->frame_type == KEY_FRAME) {
-    // Set the prediction probabilities to defaults
-    cm->ref_pred_probs[0] = 120;
-    cm->ref_pred_probs[1] = 80;
-    cm->ref_pred_probs[2] = 40;
-
-    vpx_memset(cpi->ref_pred_probs_update, 0,
-               sizeof(cpi->ref_pred_probs_update));
-  } else {
+  if (cm->frame_type != KEY_FRAME) {
     // From the prediction counts set the probabilities for each context
     for (i = 0; i < PREDICTION_PROBS; i++) {
       new_pred_probs[i] = get_binary_prob(cpi->ref_pred_count[i][0],
@@ -219,7 +211,6 @@
         cm->ref_pred_probs[i] = new_pred_probs[i];
       } else
         cpi->ref_pred_probs_update[i] = 0;
-
     }
   }
 }
@@ -508,7 +499,8 @@
               vp9_sub_mv_ref_encoding_array - LEFT4X4 + m);
 }
 
-static void write_nmv(vp9_writer *bc, const MV *mv, const int_mv *ref,
+static void write_nmv(VP9_COMP *cpi, vp9_writer *bc,
+                      const MV *mv, const int_mv *ref,
                       const nmv_context *nmvc, int usehp) {
   MV e;
   e.row = mv->row - ref->as_mv.row;
@@ -801,7 +793,6 @@
 
     vp9_mv_ref_probs(&cpi->common, mv_ref_p, mi->mb_mode_context[rf]);
 
-    // #ifdef ENTROPY_STATS
 #ifdef ENTROPY_STATS
     accum_mv_refs(mode, ct);
     active_section = 3;
@@ -878,12 +869,12 @@
 #ifdef ENTROPY_STATS
         active_section = 5;
 #endif
-        write_nmv(bc, &mi->mv[0].as_mv, &mi->best_mv,
+        write_nmv(cpi, bc, &mi->mv[0].as_mv, &mi->best_mv,
                   (const nmv_context*) nmvc,
                   xd->allow_high_precision_mv);
 
         if (mi->second_ref_frame > 0) {
-          write_nmv(bc, &mi->mv[1].as_mv, &mi->best_second_mv,
+          write_nmv(cpi, bc, &mi->mv[1].as_mv, &mi->best_second_mv,
                     (const nmv_context*) nmvc,
                     xd->allow_high_precision_mv);
         }
@@ -926,12 +917,12 @@
 #ifdef ENTROPY_STATS
             active_section = 11;
 #endif
-            write_nmv(bc, &blockmv.as_mv, &mi->best_mv,
+            write_nmv(cpi, bc, &blockmv.as_mv, &mi->best_mv,
                       (const nmv_context*) nmvc,
                       xd->allow_high_precision_mv);
 
             if (mi->second_ref_frame > 0) {
-              write_nmv(bc,
+              write_nmv(cpi, bc,
                         &cpi->mb.partition_info->bmi[j].second_mv.as_mv,
                         &mi->best_second_mv,
                         (const nmv_context*) nmvc,
@@ -1551,6 +1542,9 @@
     vp9_start_encode(&header_bc, cx_data);
   }
 
+  // error resilient mode
+  vp9_write_bit(&header_bc, pc->error_resilient_mode);
+
   // Signal whether or not Segmentation is enabled
   vp9_write_bit(&header_bc, (xd->segmentation_enabled) ? 1 : 0);
 
@@ -1967,7 +1961,7 @@
     if (pc->mcomp_filter_type == SWITCHABLE)
       update_switchable_interp_probs(cpi, &header_bc);
 
-    #if CONFIG_COMP_INTERINTRA_PRED
+#if CONFIG_COMP_INTERINTRA_PRED
     if (pc->use_interintra) {
       vp9_cond_prob_update(&header_bc,
                            &pc->fc.interintra_prob,
@@ -2030,7 +2024,8 @@
     // if (!cpi->dummy_packing) vp9_zero(cpi->NMVcount);
     write_modes(cpi, &residual_bc);
 
-    vp9_update_mode_context(&cpi->common);
+    if (!cpi->common.error_resilient_mode)
+      vp9_adapt_mode_context(&cpi->common);
   }
 
   vp9_stop_encode(&residual_bc);
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 0d33edc..8a4b7e6 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -646,6 +646,10 @@
   const int idx_map = mb_row * cm->mb_cols + mb_col;
   const int idx_str = xd->mode_info_stride * mb_row + mb_col;
 
+#ifdef ENC_DEBUG
+  enc_debug = (cpi->common.current_video_frame == 2 &&
+               mb_row == 4 && mb_col == 5);
+#endif
   // entropy context structures
   xd->above_context = cm->above_context + mb_col;
   xd->left_context  = cm->left_context + (mb_row & 3);
@@ -2007,8 +2011,8 @@
   assert(!xd->mode_info_context->mbmi.sb_type);
 
 #ifdef ENC_DEBUG
-  enc_debug = (cpi->common.current_video_frame == 46 &&
-               mb_row == 5 && mb_col == 2);
+  enc_debug = (cpi->common.current_video_frame == 2 &&
+               mb_row == 5 && mb_col == 18);
   if (enc_debug)
     printf("Encode MB %d %d output %d\n", mb_row, mb_col, output_enabled);
 #endif
@@ -2150,7 +2154,7 @@
   }
 
   if (!x->skip) {
-#ifdef ENC_DEBUG
+#if 0  // def ENC_DEBUG
     if (enc_debug) {
       int i, j;
       printf("\n");
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index c288f93..a141657 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -1355,7 +1355,6 @@
 
       if (cpi->oxcf.cpu_used > 5)
         cpi->oxcf.cpu_used = 5;
-
       break;
 
     case MODE_SECONDPASS_BEST:
@@ -2823,6 +2822,8 @@
     for (i = 0; i < MAX_MODES; i++) {
       cpi->rd_thresh_mult[i] = 128;
     }
+
+    cm->error_resilient_mode = (cpi->oxcf.error_resilient_mode != 0);
   }
 
   // Test code for new segment features
@@ -3100,10 +3101,21 @@
       }
 
       // Set up entropy depending on frame type.
-      if (cm->frame_type == KEY_FRAME)
+      if (cm->frame_type == KEY_FRAME) {
+        /* Choose which entropy context to use. When using a forward reference
+	 * frame, it immediately follows the keyframe, and thus benefits from
+	 * using the same entropy context established by the keyframe. Otherwise,
+	 * use the default context 0.
+	 */
+        cm->frame_context_idx = cpi->oxcf.play_alternate;
         vp9_setup_key_frame(cpi);
-      else
+      } else {
+	/* Choose which entropy context to use. Currently there are only two
+	 * contexts used, one for normal frames and one for alt ref frames.
+	 */
+        cpi->common.frame_context_idx = cpi->refresh_alt_ref_frame;
         vp9_setup_inter_frame(cpi);
+      }
     }
 
     // transform / motion compensation build reconstruction frame
@@ -3437,7 +3449,8 @@
   vp9_copy(cpi->common.fc.hybrid_coef_counts_16x16,
            cpi->hybrid_coef_counts_16x16);
   vp9_copy(cpi->common.fc.coef_counts_32x32, cpi->coef_counts_32x32);
-  vp9_adapt_coef_probs(&cpi->common);
+  if (!cpi->common.error_resilient_mode)
+    vp9_adapt_coef_probs(&cpi->common);
   if (cpi->common.frame_type != KEY_FRAME) {
     vp9_copy(cpi->common.fc.sb_ymode_counts, cpi->sb_ymode_count);
     vp9_copy(cpi->common.fc.ymode_counts, cpi->ymode_count);
@@ -3449,14 +3462,12 @@
 #if CONFIG_COMP_INTERINTRA_PRED
     vp9_copy(cpi->common.fc.interintra_counts, cpi->interintra_count);
 #endif
-    vp9_adapt_mode_probs(&cpi->common);
+    if (!cpi->common.error_resilient_mode)
+      vp9_adapt_mode_probs(&cpi->common);
 
     cpi->common.fc.NMVcount = cpi->NMVcount;
-    /*
-    printf("2: %d %d %d %d\n", cpi->NMVcount.joints[0], cpi->NMVcount.joints[1],
-                      cpi->NMVcount.joints[2], cpi->NMVcount.joints[3]);
-                      */
-    vp9_adapt_nmv_probs(&cpi->common, cpi->mb.e_mbd.allow_high_precision_mv);
+    if (!cpi->common.error_resilient_mode)
+      vp9_adapt_nmv_probs(&cpi->common, cpi->mb.e_mbd.allow_high_precision_mv);
   }
 #if CONFIG_COMP_INTERINTRA_PRED
   if (cm->frame_type != KEY_FRAME)
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index be87326..bb608ab 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -25,6 +25,7 @@
 #include "vp9/common/vp9_systemdependent.h"
 #include "vp9/encoder/vp9_encodemv.h"
 #include "vp9/common/vp9_quant_common.h"
+#include "vp9/common/vp9_seg_common.h"
 
 #define MIN_BPB_FACTOR          0.005
 #define MAX_BPB_FACTOR          50
@@ -238,76 +239,30 @@
 #endif
 }
 
-
 void vp9_setup_key_frame(VP9_COMP *cpi) {
   VP9_COMMON *cm = &cpi->common;
-  int i;
+  MACROBLOCKD *xd = &cpi->mb.e_mbd;
 
-  // Setup for Key frame:
-  vp9_default_coef_probs(& cpi->common);
-  vp9_kf_default_bmode_probs(cpi->common.kf_bmode_prob);
-  vp9_init_mbmode_probs(& cpi->common);
-  vp9_default_bmode_probs(cm->fc.bmode_prob);
-
-  if(cm->last_frame_seg_map)
-    vpx_memset(cm->last_frame_seg_map, 0, (cm->mb_rows * cm->mb_cols));
-
-  vp9_init_mv_probs(& cpi->common);
-
-  // cpi->common.filter_level = 0;      // Reset every key frame.
-  cpi->common.filter_level = cpi->common.base_qindex * 3 / 8;
+  vp9_setup_past_independence(cm, xd);
 
   // interval before next GF
   cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
-
+  /* All buffers are implicitly updated on key frames. */
   cpi->refresh_golden_frame = TRUE;
   cpi->refresh_alt_ref_frame = TRUE;
-
-  vp9_init_mode_contexts(&cpi->common);
-
-  for (i = 0; i < NUM_FRAME_CONTEXTS; i++)
-    vpx_memcpy(&cpi->common.frame_contexts[i], &cpi->common.fc,
-               sizeof(cpi->common.fc));
-
-  vpx_memset(cm->prev_mip, 0,
-    (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO));
-  vpx_memset(cm->mip, 0,
-    (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO));
-
-  vp9_update_mode_info_border(cm, cm->mip);
-  vp9_update_mode_info_in_image(cm, cm->mi);
-
-#if CONFIG_NEW_MVREF
-  if (1) {
-    MACROBLOCKD *xd = &cpi->mb.e_mbd;
-
-    // Defaults probabilities for encoding the MV ref id signal
-    vpx_memset(xd->mb_mv_ref_probs, VP9_DEFAULT_MV_REF_PROB,
-               sizeof(xd->mb_mv_ref_probs));
-  }
-#endif
-
-  /* Choose which entropy context to use. When using a forward reference
-   * frame, it immediately follows the keyframe, and thus benefits from
-   * using the same entropy context established by the keyframe. Otherwise,
-   * use the default context 0.
-   */
-  cm->frame_context_idx = cpi->oxcf.play_alternate;
 }
 
 void vp9_setup_inter_frame(VP9_COMP *cpi) {
-  /* Choose which entropy context to use. Currently there are only two
-   * contexts used, one for normal frames and one for alt ref frames.
-   */
-  cpi->common.frame_context_idx = cpi->refresh_alt_ref_frame;
-
-  assert(cpi->common.frame_context_idx < NUM_FRAME_CONTEXTS);
-  vpx_memcpy(&cpi->common.fc,
-             &cpi->common.frame_contexts[cpi->common.frame_context_idx],
-             sizeof(cpi->common.fc));
+  VP9_COMMON *cm = &cpi->common;
+  MACROBLOCKD *xd = &cpi->mb.e_mbd;
+  if (cm->error_resilient_mode) {
+    vp9_setup_past_independence(cm, xd);
+  }
+  assert(cm->frame_context_idx < NUM_FRAME_CONTEXTS);
+  vpx_memcpy(&cm->fc, &cm->frame_contexts[cm->frame_context_idx],
+             sizeof(cm->fc));
 }
 
-
 static int estimate_bits_at_q(int frame_kind, int Q, int MBs,
                               double correction_factor) {
   int Bpm = (int)(.5 + correction_factor * vp9_bits_per_mb(frame_kind, Q));
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 5252bfd..f860e94 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -3177,19 +3177,21 @@
 
   // Gets an initial list of candidate vectors from neighbours and orders them
   vp9_find_mv_refs(xd, xd->mode_info_context,
-                   xd->prev_mode_info_context,
+                   cpi->common.error_resilient_mode ?
+                   0 : xd->prev_mode_info_context,
                    frame_type,
                    mbmi->ref_mvs[frame_type],
                    cpi->common.ref_frame_sign_bias);
 
   // Candidate refinement carried out at encoder and decoder
-  vp9_find_best_ref_mvs(xd, y_buffer[frame_type],
+  vp9_find_best_ref_mvs(xd,
+                        cpi->common.error_resilient_mode ?
+                        0 : y_buffer[frame_type],
                         yv12->y_stride,
                         mbmi->ref_mvs[frame_type],
                         &frame_nearest_mv[frame_type],
                         &frame_near_mv[frame_type]);
 
-
   // Further refinement that is encode side only to test the top few candidates
   // in full and choose the best as the centre point for subsequent searches.
   mv_pred(cpi, x, y_buffer[frame_type], yv12->y_stride,
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 1ef5ff1..0c82d06 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -313,33 +313,35 @@
   oxcf->lossless = vp8_cfg.lossless;
 #endif
 
+  oxcf->error_resilient_mode = cfg.g_error_resilient;
   /*
-      printf("Current VP8 Settings: \n");
-      printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
-      printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
-      printf("Sharpness: %d\n",    oxcf->Sharpness);
-      printf("cpu_used: %d\n",  oxcf->cpu_used);
-      printf("Mode: %d\n",     oxcf->Mode);
-      printf("delete_first_pass_file: %d\n",  oxcf->delete_first_pass_file);
-      printf("auto_key: %d\n",  oxcf->auto_key);
-      printf("key_freq: %d\n", oxcf->key_freq);
-      printf("end_usage: %d\n", oxcf->end_usage);
-      printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
-      printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
-      printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
-      printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
-      printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
-      printf("fixed_q: %d\n",  oxcf->fixed_q);
-      printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
-      printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
-      printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
-      printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
-      printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
-      printf("allow_lag: %d\n", oxcf->allow_lag);
-      printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
-      printf("play_alternate: %d\n", oxcf->play_alternate);
-      printf("Version: %d\n", oxcf->Version);
-      printf("encode_breakout: %d\n", oxcf->encode_breakout);
+  printf("Current VP9 Settings: \n");
+  printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
+  printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
+  printf("Sharpness: %d\n",    oxcf->Sharpness);
+  printf("cpu_used: %d\n",  oxcf->cpu_used);
+  printf("Mode: %d\n",     oxcf->Mode);
+  // printf("delete_first_pass_file: %d\n",  oxcf->delete_first_pass_file);
+  printf("auto_key: %d\n",  oxcf->auto_key);
+  printf("key_freq: %d\n", oxcf->key_freq);
+  printf("end_usage: %d\n", oxcf->end_usage);
+  printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
+  printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
+  printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
+  printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
+  printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
+  printf("fixed_q: %d\n",  oxcf->fixed_q);
+  printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
+  printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
+  printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
+  printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
+  printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
+  printf("allow_lag: %d\n", oxcf->allow_lag);
+  printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
+  printf("play_alternate: %d\n", oxcf->play_alternate);
+  printf("Version: %d\n", oxcf->Version);
+  printf("encode_breakout: %d\n", oxcf->encode_breakout);
+  printf("error resilient: %d\n", oxcf->error_resilient_mode);
   */
   return VPX_CODEC_OK;
 }
diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c
index 05d4edb..293df2e 100644
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -431,7 +431,7 @@
                                   long                   deadline) {
   const uint8_t *data_start = data;
   const uint8_t *data_end = data + data_sz;
-  vpx_codec_err_t res;
+  vpx_codec_err_t res = 0;
 
   do {
     res = decode_one(ctx, &data_start, data_sz, user_priv, deadline);
diff --git a/vpxenc.c b/vpxenc.c
index 3fc8da1..7b784f3 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -1449,14 +1449,16 @@
 #define mmin(a, b)  ((a) < (b) ? (a) : (b))
 static void find_mismatch(vpx_image_t *img1, vpx_image_t *img2,
                           int yloc[2], int uloc[2], int vloc[2]) {
+  static const int bsize = 64;
+  static const int bsize2 = bsize >> 1;
   int match = 1;
   int i, j;
   yloc[0] = yloc[1] = -1;
-  for (i = 0, match = 1; match && i < img1->d_h; i+=32) {
-    for (j = 0; match && j < img1->d_w; j+=32) {
+  for (i = 0, match = 1; match && i < img1->d_h; i += bsize) {
+    for (j = 0; match && j < img1->d_w; j += bsize) {
       int k, l;
-      int si = mmin(i + 32, img1->d_h) - i;
-      int sj = mmin(j + 32, img1->d_w) - j;
+      int si = mmin(i + bsize, img1->d_h) - i;
+      int sj = mmin(j + bsize, img1->d_w) - j;
       for (k = 0; match && k < si; k++)
         for (l = 0; match && l < sj; l++) {
           if (*(img1->planes[VPX_PLANE_Y] +
@@ -1472,11 +1474,11 @@
     }
   }
   uloc[0] = uloc[1] = -1;
-  for (i = 0, match = 1; match && i < (img1->d_h + 1) / 2; i+=16) {
-    for (j = 0; j < match && (img1->d_w + 1) / 2; j+=16) {
+  for (i = 0, match = 1; match && i < (img1->d_h + 1) / 2; i += bsize2) {
+    for (j = 0; j < match && (img1->d_w + 1) / 2; j += bsize2) {
       int k, l;
-      int si = mmin(i + 16, (img1->d_h + 1) / 2) - i;
-      int sj = mmin(j + 16, (img1->d_w + 1) / 2) - j;
+      int si = mmin(i + bsize2, (img1->d_h + 1) / 2) - i;
+      int sj = mmin(j + bsize2, (img1->d_w + 1) / 2) - j;
       for (k = 0; match && k < si; k++)
         for (l = 0; match && l < sj; l++) {
           if (*(img1->planes[VPX_PLANE_U] +
@@ -1492,11 +1494,11 @@
     }
   }
   vloc[0] = vloc[1] = -1;
-  for (i = 0, match = 1; match && i < (img1->d_h + 1) / 2; i+=16) {
-    for (j = 0; j < match && (img1->d_w + 1) / 2; j+=16) {
+  for (i = 0, match = 1; match && i < (img1->d_h + 1) / 2; i += bsize2) {
+    for (j = 0; j < match && (img1->d_w + 1) / 2; j += bsize2) {
       int k, l;
-      int si = mmin(i + 16, (img1->d_h + 1) / 2) - i;
-      int sj = mmin(j + 16, (img1->d_w + 1) / 2) - j;
+      int si = mmin(i + bsize2, (img1->d_h + 1) / 2) - i;
+      int sj = mmin(j + bsize2, (img1->d_w + 1) / 2) - j;
       for (k = 0; match && k < si; k++)
         for (l = 0; match && l < sj; l++) {
           if (*(img1->planes[VPX_PLANE_V] +