shithub: libvpx

Download patch

ref: 0c917fc9755108887901bc0ea44e1952de8a2c65
parent: 16e268668204566d7f4b2d4fc6775f996773d74d
author: Deb Mukherjee <debargha@google.com>
date: Wed Nov 7 01:50:25 EST 2012

Compound inter-intra experiment

A patch on compound inter-intra prediction.

In compound inter-intra prediction, a new predictor for
16x16 inter coded MBs are obtained by combining a single
inter predictor with a 16x16 intra predictor, in a manner
that the weight varies with distance from the top/left
boundary. The current search strategy is to combine the best
inter mode with the best intra mode obtained independently.

Results so far:

derf +0.31%
yt +0.32%
std-hd +0.35%
hd +0.42%

It is conceivable that the results would improve somewhat
with a more thorough search strategy where all intra modes
are searched given the best mv, or even a joint search for
the best mv and the best intra mode.

Change-Id: I7951f1ed0d6eb31ca32ac24d120f1585bcd8d79b

--- a/configure
+++ b/configure
@@ -246,6 +246,7 @@
     new_mvref
     implicit_segmentation
     newbintramodes
+    comp_interintra_pred
 "
 CONFIG_LIST="
     external_build
--- a/vp9/common/blockd.h
+++ b/vp9/common/blockd.h
@@ -214,6 +214,7 @@
 };
 
 typedef enum {
+  NONE = -1,
   INTRA_FRAME = 0,
   LAST_FRAME = 1,
   GOLDEN_FRAME = 2,
@@ -225,6 +226,9 @@
   MB_PREDICTION_MODE mode, uv_mode;
 #if CONFIG_COMP_INTRA_PRED
   MB_PREDICTION_MODE second_mode, second_uv_mode;
+#endif
+#if CONFIG_COMP_INTERINTRA_PRED
+  MB_PREDICTION_MODE interintra_mode, interintra_uv_mode;
 #endif
   MV_REFERENCE_FRAME ref_frame, second_ref_frame;
   TX_SIZE txfm_size;
--- a/vp9/common/entropymode.c
+++ b/vp9/common/entropymode.c
@@ -345,6 +345,9 @@
   vpx_memcpy(x->fc.mbsplit_prob, vp9_mbsplit_probs, sizeof(vp9_mbsplit_probs));
   vpx_memcpy(x->fc.switchable_interp_prob, vp9_switchable_interp_prob,
              sizeof(vp9_switchable_interp_prob));
+#if CONFIG_COMP_INTERINTRA_PRED
+  x->fc.interintra_prob = VP9_DEF_INTERINTRA_PROB;
+#endif
 }
 
 
@@ -547,6 +550,9 @@
   vp9_prob i8x8_mode_probs[VP9_I8X8_MODES - 1];
   vp9_prob sub_mv_ref_probs[VP9_SUBMVREFS - 1];
   vp9_prob mbsplit_probs[VP9_NUMMBSPLITS - 1];
+#if CONFIG_COMP_INTERINTRA_PRED
+  vp9_prob interintra_prob;
+#endif
 #ifdef MODE_COUNT_TESTING
   printf("static const unsigned int\nymode_counts"
          "[VP9_YMODES] = {\n");
@@ -581,7 +587,13 @@
          "[VP9_NUMMBSPLITS] = {\n");
   for (t = 0; t < VP9_NUMMBSPLITS; ++t) printf("%d, ", cm->fc.mbsplit_counts[t]);
   printf("};\n");
+#if CONFIG_COMP_INTERINTRA_PRED
+  printf("static const unsigned int\ninterintra_counts"
+         "[2] = {\n");
+  for (t = 0; t < 2; ++t) printf("%d, ", cm->fc.interintra_counts[t]);
+  printf("};\n");
 #endif
+#endif
   vp9_tree_probs_from_distribution(
     VP9_YMODES, vp9_ymode_encodings, vp9_ymode_tree,
     ymode_probs, branch_ct, cm->fc.ymode_counts,
@@ -673,4 +685,21 @@
     else if (prob > 255) cm->fc.mbsplit_prob[t] = 255;
     else cm->fc.mbsplit_prob[t] = prob;
   }
+#if CONFIG_COMP_INTERINTRA_PRED
+  if (cm->use_interintra) {
+    int prob;
+    interintra_prob = vp9_bin_prob_from_distribution(cm->fc.interintra_counts);
+    count = cm->fc.interintra_counts[0] + cm->fc.interintra_counts[1];
+    count = count > MODE_COUNT_SAT ? MODE_COUNT_SAT : count;
+    factor = (MODE_MAX_UPDATE_FACTOR * count / MODE_COUNT_SAT);
+    prob = ((int)cm->fc.pre_interintra_prob * (256 - factor) +
+            (int)interintra_prob * factor + 128) >> 8;
+    if (prob <= 0)
+      cm->fc.interintra_prob = 1;
+    else if (prob > 255)
+      cm->fc.interintra_prob = 255;
+    else
+      cm->fc.interintra_prob = prob;
+  }
+#endif
 }
--- a/vp9/common/entropymode.h
+++ b/vp9/common/entropymode.h
@@ -21,6 +21,13 @@
 #define DEFAULT_COMP_INTRA_PROB  32
 #endif
 
+#if CONFIG_COMP_INTERINTRA_PRED
+#define VP9_DEF_INTERINTRA_PROB 248
+#define VP9_UPD_INTERINTRA_PROB 192
+// whether to use a separate uv mode (1) or use the same as the y mode (0)
+#define SEPARATE_INTERINTRA_UV  0
+#endif
+
 typedef const int vp9_mbsplit[16];
 
 extern vp9_mbsplit vp9_mbsplits[VP9_NUMMBSPLITS];
--- a/vp9/common/findnearmv.h
+++ b/vp9/common/findnearmv.h
@@ -104,11 +104,14 @@
     --cur_mb;
 
     if (cur_mb->mbmi.mode != SPLITMV)
-      return cur_mb->mbmi.second_ref_frame ? cur_mb->mbmi.mv[1].as_int : cur_mb->mbmi.mv[0].as_int;
+      return cur_mb->mbmi.second_ref_frame > 0 ?
+          cur_mb->mbmi.mv[1].as_int : cur_mb->mbmi.mv[0].as_int;
     b += 4;
   }
 
-  return cur_mb->mbmi.second_ref_frame ? (cur_mb->bmi + b - 1)->as_mv.second.as_int : (cur_mb->bmi + b - 1)->as_mv.first.as_int;
+  return cur_mb->mbmi.second_ref_frame > 0 ?
+      (cur_mb->bmi + b - 1)->as_mv.second.as_int :
+      (cur_mb->bmi + b - 1)->as_mv.first.as_int;
 }
 
 static int above_block_mv(const MODE_INFO *cur_mb, int b, int mi_stride) {
@@ -130,11 +133,14 @@
     cur_mb -= mi_stride;
 
     if (cur_mb->mbmi.mode != SPLITMV)
-      return cur_mb->mbmi.second_ref_frame ? cur_mb->mbmi.mv[1].as_int : cur_mb->mbmi.mv[0].as_int;
+      return cur_mb->mbmi.second_ref_frame > 0 ?
+          cur_mb->mbmi.mv[1].as_int : cur_mb->mbmi.mv[0].as_int;
     b += 16;
   }
 
-  return cur_mb->mbmi.second_ref_frame ? (cur_mb->bmi + b - 4)->as_mv.second.as_int : (cur_mb->bmi + b - 4)->as_mv.first.as_int;
+  return cur_mb->mbmi.second_ref_frame > 0 ?
+      (cur_mb->bmi + b - 4)->as_mv.second.as_int :
+      (cur_mb->bmi + b - 4)->as_mv.first.as_int;
 }
 
 static B_PREDICTION_MODE left_block_mode(const MODE_INFO *cur_mb, int b) {
--- a/vp9/common/mvref_common.c
+++ b/vp9/common/mvref_common.c
@@ -54,7 +54,7 @@
     ret_val = TRUE;
 
     // Is there a second non zero vector we can use.
-    if ((candidate_mi->mbmi.second_ref_frame != INTRA_FRAME) &&
+    if ((candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) &&
         (candidate_mi->mbmi.mv[1].as_int != 0) &&
         (candidate_mi->mbmi.mv[1].as_int != c_mv->as_int)) {
       c2_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
@@ -68,7 +68,7 @@
     ret_val = TRUE;
 
     // Is there a second non zero vector we can use.
-    if ((candidate_mi->mbmi.ref_frame != INTRA_FRAME) &&
+    if ((candidate_mi->mbmi.ref_frame > INTRA_FRAME) &&
         (candidate_mi->mbmi.mv[0].as_int != 0) &&
         (candidate_mi->mbmi.mv[0].as_int != c_mv->as_int)) {
       c2_mv->as_int = candidate_mi->mbmi.mv[0].as_int;
@@ -76,13 +76,13 @@
     }
 
   // No ref frame matches so use first ref mv as first choice
-  } else if (candidate_mi->mbmi.ref_frame != INTRA_FRAME) {
+  } else if (candidate_mi->mbmi.ref_frame > INTRA_FRAME) {
     c_mv->as_int = candidate_mi->mbmi.mv[0].as_int;
     *c_ref_frame = candidate_mi->mbmi.ref_frame;
     ret_val = TRUE;
 
     // Is there a second non zero vector we can use.
-    if ((candidate_mi->mbmi.second_ref_frame != INTRA_FRAME) &&
+    if ((candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) &&
         (candidate_mi->mbmi.mv[1].as_int != 0) &&
         (candidate_mi->mbmi.mv[1].as_int != c_mv->as_int)) {
       c2_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
@@ -91,7 +91,7 @@
 
   // If only the second ref mv is valid:- (Should not trigger in current code
   // base given current possible compound prediction options).
-  } else if (candidate_mi->mbmi.second_ref_frame != INTRA_FRAME) {
+  } else if (candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) {
     c_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
     *c_ref_frame = candidate_mi->mbmi.second_ref_frame;
     ret_val = TRUE;
--- a/vp9/common/onyxc_int.h
+++ b/vp9/common/onyxc_int.h
@@ -106,6 +106,11 @@
   nmv_context_counts NMVcount;
   vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
                                  [VP9_SWITCHABLE_FILTERS - 1];
+#if CONFIG_COMP_INTERINTRA_PRED
+  unsigned int interintra_counts[2];
+  vp9_prob interintra_prob;
+  vp9_prob pre_interintra_prob;
+#endif
 
   int mode_context[INTER_MODE_CONTEXTS][4];
   int mode_context_a[INTER_MODE_CONTEXTS][4];
@@ -310,6 +315,9 @@
   // 1=enabled at the frame level (all MB filtered)
   // 2=specified per MB (1=filtered, 0=non-filtered)
   vp9_prob prob_pred_filter_off;
+#endif
+#if CONFIG_COMP_INTERINTRA_PRED
+  int use_interintra;
 #endif
 
 } VP9_COMMON;
--- a/vp9/common/pred_common.c
+++ b/vp9/common/pred_common.c
@@ -40,8 +40,8 @@
     case PRED_COMP:
       // Context based on use of comp pred flag by neighbours
       // pred_context =
-      //   ((m - 1)->mbmi.second_ref_frame != INTRA_FRAME) +
-      //    ((m - cm->mode_info_stride)->mbmi.second_ref_frame != INTRA_FRAME);
+      //   ((m - 1)->mbmi.second_ref_frame > INTRA_FRAME) +
+      //    ((m - cm->mode_info_stride)->mbmi.second_ref_frame > INTRA_FRAME);
 
       // Context based on mode and reference frame
       // if ( m->mbmi.ref_frame == LAST_FRAME )
--- a/vp9/common/reconinter.c
+++ b/vp9/common/reconinter.c
@@ -14,6 +14,7 @@
 #include "subpixel.h"
 #include "blockd.h"
 #include "reconinter.h"
+#include "vp9/common/reconintra.h"
 #if CONFIG_RUNTIME_CPU_DETECT
 #include "onyxc_int.h"
 #endif
@@ -511,7 +512,7 @@
       blockd[voffset].bmi.as_mv.first.as_mv.col =
         blockd[uoffset].bmi.as_mv.first.as_mv.col;
 
-      if (xd->mode_info_context->mbmi.second_ref_frame) {
+      if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
         temp = blockd[yoffset  ].bmi.as_mv.second.as_mv.row
                + blockd[yoffset + 1].bmi.as_mv.second.as_mv.row
                + blockd[yoffset + 4].bmi.as_mv.second.as_mv.row
@@ -559,7 +560,7 @@
       vp9_build_inter_predictors_b(d1, 8, xd->subpixel_predict);
     }
 
-    if (xd->mode_info_context->mbmi.second_ref_frame) {
+    if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
       vp9_build_2nd_inter_predictors_b(d0, 8, xd->subpixel_predict_avg);
       vp9_build_2nd_inter_predictors_b(d1, 8, xd->subpixel_predict_avg);
     }
@@ -777,7 +778,7 @@
       dst_u + y_idx *  8 * dst_uvstride + x_idx *  8,
       dst_v + y_idx *  8 * dst_uvstride + x_idx *  8,
       dst_ystride, dst_uvstride);
-    if (x->mode_info_context->mbmi.second_ref_frame) {
+    if (x->mode_info_context->mbmi.second_ref_frame > 0) {
       x->second_pre.y_buffer = y2 + y_idx * 16 * x->pre.y_stride  + x_idx * 16;
       x->second_pre.u_buffer = u2 + y_idx *  8 * x->pre.uv_stride + x_idx *  8;
       x->second_pre.v_buffer = v2 + y_idx *  8 * x->pre.uv_stride + x_idx *  8;
@@ -799,7 +800,7 @@
   x->pre.u_buffer = u1;
   x->pre.v_buffer = v1;
 
-  if (x->mode_info_context->mbmi.second_ref_frame) {
+  if (x->mode_info_context->mbmi.second_ref_frame > 0) {
     x->second_pre.y_buffer = y2;
     x->second_pre.u_buffer = u2;
     x->second_pre.v_buffer = v2;
@@ -979,7 +980,7 @@
       clamp_mv_to_umv_border(&blockd[ 2].bmi.as_mv.first.as_mv, xd);
       clamp_mv_to_umv_border(&blockd[ 8].bmi.as_mv.first.as_mv, xd);
       clamp_mv_to_umv_border(&blockd[10].bmi.as_mv.first.as_mv, xd);
-      if (mbmi->second_ref_frame) {
+      if (mbmi->second_ref_frame > 0) {
         clamp_mv_to_umv_border(&blockd[ 0].bmi.as_mv.second.as_mv, xd);
         clamp_mv_to_umv_border(&blockd[ 2].bmi.as_mv.second.as_mv, xd);
         clamp_mv_to_umv_border(&blockd[ 8].bmi.as_mv.second.as_mv, xd);
@@ -993,7 +994,7 @@
     vp9_build_inter_predictors4b(xd, &blockd[ 8], 16);
     vp9_build_inter_predictors4b(xd, &blockd[10], 16);
 
-    if (mbmi->second_ref_frame) {
+    if (mbmi->second_ref_frame > 0) {
       vp9_build_2nd_inter_predictors4b(xd, &blockd[ 0], 16);
       vp9_build_2nd_inter_predictors4b(xd, &blockd[ 2], 16);
       vp9_build_2nd_inter_predictors4b(xd, &blockd[ 8], 16);
@@ -1010,7 +1011,7 @@
       if (mbmi->need_to_clamp_mvs) {
         clamp_mv_to_umv_border(&blockd[i + 0].bmi.as_mv.first.as_mv, xd);
         clamp_mv_to_umv_border(&blockd[i + 1].bmi.as_mv.first.as_mv, xd);
-        if (mbmi->second_ref_frame) {
+        if (mbmi->second_ref_frame > 0) {
           clamp_mv_to_umv_border(&blockd[i + 0].bmi.as_mv.second.as_mv, xd);
           clamp_mv_to_umv_border(&blockd[i + 1].bmi.as_mv.second.as_mv, xd);
         }
@@ -1023,7 +1024,7 @@
         vp9_build_inter_predictors_b(d1, 16, xd->subpixel_predict);
       }
 
-      if (mbmi->second_ref_frame) {
+      if (mbmi->second_ref_frame > 0) {
         vp9_build_2nd_inter_predictors_b(d0, 16, xd->subpixel_predict_avg);
         vp9_build_2nd_inter_predictors_b(d1, 16, xd->subpixel_predict_avg);
       }
@@ -1041,7 +1042,7 @@
       vp9_build_inter_predictors_b(d1, 8, xd->subpixel_predict);
     }
 
-    if (mbmi->second_ref_frame) {
+    if (mbmi->second_ref_frame > 0) {
       vp9_build_2nd_inter_predictors_b(d0, 8, xd->subpixel_predict_avg);
       vp9_build_2nd_inter_predictors_b(d1, 8, xd->subpixel_predict_avg);
     }
@@ -1094,7 +1095,7 @@
       blockd[voffset].bmi.as_mv.first.as_mv.col =
         blockd[uoffset].bmi.as_mv.first.as_mv.col;
 
-      if (xd->mode_info_context->mbmi.second_ref_frame) {
+      if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
         temp = xd->mode_info_context->bmi[yoffset + 0].as_mv.second.as_mv.row
                + xd->mode_info_context->bmi[yoffset + 1].as_mv.second.as_mv.row
                + xd->mode_info_context->bmi[yoffset + 4].as_mv.second.as_mv.row
@@ -1146,7 +1147,7 @@
                                            &xd->predictor[256],
                                            &xd->predictor[320], 16, 8);
 
-    if (xd->mode_info_context->mbmi.second_ref_frame) {
+    if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
       /* 256 = offset of U plane in Y+U+V buffer;
        * 320 = offset of V plane in Y+U+V buffer.
        * (256=16x16, 320=16x16+8x8). */
@@ -1154,6 +1155,13 @@
                                              &xd->predictor[256],
                                              &xd->predictor[320], 16, 8);
     }
+#if CONFIG_COMP_INTERINTRA_PRED
+    else if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) {
+      vp9_build_interintra_16x16_predictors_mb(xd, xd->predictor,
+                                               &xd->predictor[256],
+                                               &xd->predictor[320], 16, 8);
+    }
+#endif
   } else {
     build_4x4uvmvs(xd);
     build_inter4x4_predictors_mb(xd);
--- a/vp9/common/reconintra.c
+++ b/vp9/common/reconintra.c
@@ -372,6 +372,294 @@
   }
 }
 
+#if CONFIG_COMP_INTERINTRA_PRED
+static void combine_interintra(MB_PREDICTION_MODE mode,
+                               unsigned char *interpred,
+                               int interstride,
+                               unsigned char *intrapred,
+                               int intrastride,
+                               int size) {
+  // TODO(debargha): Explore different ways of combining predictors
+  //                 or designing the tables below
+  static const int scale_bits = 8;
+  static const int scale_max = 1 << scale_bits;
+  static const int scale_round = (1 << scale_bits) - 1;
+  // This table is a function A + B*exp(-kx), where x is hor. index
+  static const int weights1d[32] = {
+    128, 122, 116, 111, 107, 103,  99,  96,
+    93, 90, 88, 85, 83, 81, 80, 78,
+    77, 76, 75, 74, 73, 72, 71, 70,
+    70, 69, 69, 68, 68, 68, 67, 67,
+  };
+  // This table is a function A + B*exp(-k.sqrt(xy)), where x, y are
+  // hor. and vert. indices
+  static const int weights2d[1024] = {
+    128, 128, 128, 128, 128, 128, 128, 128,
+    128, 128, 128, 128, 128, 128, 128, 128,
+    128, 128, 128, 128, 128, 128, 128, 128,
+    128, 128, 128, 128, 128, 128, 128, 128,
+    128, 122, 120, 118, 116, 115, 114, 113,
+    112, 111, 111, 110, 109, 109, 108, 107,
+    107, 106, 106, 105, 105, 104, 104, 104,
+    103, 103, 102, 102, 102, 101, 101, 101,
+    128, 120, 116, 114, 112, 111, 109, 108,
+    107, 106, 105, 104, 103, 102, 102, 101,
+    100, 100,  99,  99,  98,  97,  97,  96,
+    96,  96,  95,  95,  94,  94,  93,  93,
+    128, 118, 114, 111, 109, 107, 106, 104,
+    103, 102, 101, 100,  99,  98,  97,  97,
+    96,  95,  95,  94,  93,  93,  92,  92,
+    91,  91,  90,  90,  90,  89,  89,  88,
+    128, 116, 112, 109, 107, 105, 103, 102,
+    100,  99,  98,  97,  96,  95,  94,  93,
+    93,  92,  91,  91,  90,  90,  89,  89,
+    88,  88,  87,  87,  86,  86,  85,  85,
+    128, 115, 111, 107, 105, 103, 101,  99,
+    98,  97,  96,  94,  93,  93,  92,  91,
+    90,  89,  89,  88,  88,  87,  86,  86,
+    85,  85,  84,  84,  84,  83,  83,  82,
+    128, 114, 109, 106, 103, 101,  99,  97,
+    96,  95,  93,  92,  91,  90,  90,  89,
+    88,  87,  87,  86,  85,  85,  84,  84,
+    83,  83,  82,  82,  82,  81,  81,  80,
+    128, 113, 108, 104, 102,  99,  97,  96,
+    94,  93,  92,  91,  90,  89,  88,  87,
+    86,  85,  85,  84,  84,  83,  83,  82,
+    82,  81,  81,  80,  80,  79,  79,  79,
+    128, 112, 107, 103, 100,  98,  96,  94,
+    93,  91,  90,  89,  88,  87,  86,  85,
+    85,  84,  83,  83,  82,  82,  81,  80,
+    80,  80,  79,  79,  78,  78,  78,  77,
+    128, 111, 106, 102,  99,  97,  95,  93,
+    91,  90,  89,  88,  87,  86,  85,  84,
+    83,  83,  82,  81,  81,  80,  80,  79,
+    79,  78,  78,  77,  77,  77,  76,  76,
+    128, 111, 105, 101,  98,  96,  93,  92,
+    90,  89,  88,  86,  85,  84,  84,  83,
+    82,  81,  81,  80,  80,  79,  79,  78,
+    78,  77,  77,  76,  76,  76,  75,  75,
+    128, 110, 104, 100,  97,  94,  92,  91,
+    89,  88,  86,  85,  84,  83,  83,  82,
+    81,  80,  80,  79,  79,  78,  78,  77,
+    77,  76,  76,  75,  75,  75,  74,  74,
+    128, 109, 103,  99,  96,  93,  91,  90,
+    88,  87,  85,  84,  83,  82,  82,  81,
+    80,  79,  79,  78,  78,  77,  77,  76,
+    76,  75,  75,  75,  74,  74,  74,  73,
+    128, 109, 102,  98,  95,  93,  90,  89,
+    87,  86,  84,  83,  82,  81,  81,  80,
+    79,  78,  78,  77,  77,  76,  76,  75,
+    75,  75,  74,  74,  73,  73,  73,  73,
+    128, 108, 102,  97,  94,  92,  90,  88,
+    86,  85,  84,  83,  82,  81,  80,  79,
+    78,  78,  77,  77,  76,  76,  75,  75,
+    74,  74,  73,  73,  73,  73,  72,  72,
+    128, 107, 101,  97,  93,  91,  89,  87,
+    85,  84,  83,  82,  81,  80,  79,  78,
+    78,  77,  76,  76,  75,  75,  74,  74,
+    74,  73,  73,  73,  72,  72,  72,  71,
+    128, 107, 100,  96,  93,  90,  88,  86,
+    85,  83,  82,  81,  80,  79,  78,  78,
+    77,  76,  76,  75,  75,  74,  74,  73,
+    73,  73,  72,  72,  72,  71,  71,  71,
+    128, 106, 100,  95,  92,  89,  87,  85,
+    84,  83,  81,  80,  79,  78,  78,  77,
+    76,  76,  75,  75,  74,  74,  73,  73,
+    72,  72,  72,  72,  71,  71,  71,  70,
+    128, 106,  99,  95,  91,  89,  87,  85,
+    83,  82,  81,  80,  79,  78,  77,  76,
+    76,  75,  75,  74,  74,  73,  73,  72,
+    72,  72,  71,  71,  71,  71,  70,  70,
+    128, 105,  99,  94,  91,  88,  86,  84,
+    83,  81,  80,  79,  78,  77,  77,  76,
+    75,  75,  74,  74,  73,  73,  72,  72,
+    72,  71,  71,  71,  70,  70,  70,  70,
+    128, 105,  98,  93,  90,  88,  85,  84,
+    82,  81,  80,  79,  78,  77,  76,  75,
+    75,  74,  74,  73,  73,  72,  72,  71,
+    71,  71,  71,  70,  70,  70,  70,  69,
+    128, 104,  97,  93,  90,  87,  85,  83,
+    82,  80,  79,  78,  77,  76,  76,  75,
+    74,  74,  73,  73,  72,  72,  71,  71,
+    71,  70,  70,  70,  70,  69,  69,  69,
+    128, 104,  97,  92,  89,  86,  84,  83,
+    81,  80,  79,  78,  77,  76,  75,  74,
+    74,  73,  73,  72,  72,  71,  71,  71,
+    70,  70,  70,  70,  69,  69,  69,  69,
+    128, 104,  96,  92,  89,  86,  84,  82,
+    80,  79,  78,  77,  76,  75,  75,  74,
+    73,  73,  72,  72,  71,  71,  71,  70,
+    70,  70,  70,  69,  69,  69,  69,  68,
+    128, 103,  96,  91,  88,  85,  83,  82,
+    80,  79,  78,  77,  76,  75,  74,  74,
+    73,  72,  72,  72,  71,  71,  70,  70,
+    70,  70,  69,  69,  69,  69,  68,  68,
+    128, 103,  96,  91,  88,  85,  83,  81,
+    80,  78,  77,  76,  75,  75,  74,  73,
+    73,  72,  72,  71,  71,  70,  70,  70,
+    70,  69,  69,  69,  69,  68,  68,  68,
+    128, 102,  95,  90,  87,  84,  82,  81,
+    79,  78,  77,  76,  75,  74,  73,  73,
+    72,  72,  71,  71,  71,  70,  70,  70,
+    69,  69,  69,  69,  68,  68,  68,  68,
+    128, 102,  95,  90,  87,  84,  82,  80,
+    79,  77,  76,  75,  75,  74,  73,  73,
+    72,  72,  71,  71,  70,  70,  70,  69,
+    69,  69,  69,  68,  68,  68,  68,  68,
+    128, 102,  94,  90,  86,  84,  82,  80,
+    78,  77,  76,  75,  74,  73,  73,  72,
+    72,  71,  71,  70,  70,  70,  69,  69,
+    69,  69,  68,  68,  68,  68,  68,  67,
+    128, 101,  94,  89,  86,  83,  81,  79,
+    78,  77,  76,  75,  74,  73,  73,  72,
+    71,  71,  71,  70,  70,  69,  69,  69,
+    69,  68,  68,  68,  68,  68,  67,  67,
+    128, 101,  93,  89,  85,  83,  81,  79,
+    78,  76,  75,  74,  74,  73,  72,  72,
+    71,  71,  70,  70,  70,  69,  69,  69,
+    68,  68,  68,  68,  68,  67,  67,  67,
+    128, 101,  93,  88,  85,  82,  80,  79,
+    77,  76,  75,  74,  73,  73,  72,  71,
+    71,  70,  70,  70,  69,  69,  69,  68,
+    68,  68,  68,  68,  67,  67,  67,  67,
+  };
+  int size_scale = (size == 32 ? 1 :
+                    size == 16 ? 2 :
+                    size == 8  ? 4 : 8);
+  int i, j;
+  switch (mode) {
+    case V_PRED:
+      for (i = 0; i < size; ++i) {
+        for (j = 0; j < size; ++j) {
+          int k = i * interstride + j;
+          int scale = weights1d[i * size_scale];
+          interpred[k] =
+              ((scale_max - scale) * interpred[k] +
+               scale * intrapred[i * intrastride + j] + scale_round)
+              >> scale_bits;
+        }
+      }
+      break;
+
+    case H_PRED:
+      for (i = 0; i < size; ++i) {
+        for (j = 0; j < size; ++j) {
+          int k = i * interstride + j;
+          int scale = weights1d[j * size_scale];
+          interpred[k] =
+              ((scale_max - scale) * interpred[k] +
+               scale * intrapred[i * intrastride + j] + scale_round)
+              >> scale_bits;
+        }
+      }
+      break;
+
+    case D63_PRED:
+    case D117_PRED:
+      for (i = 0; i < size; ++i) {
+        for (j = 0; j < size; ++j) {
+          int k = i * interstride + j;
+          int scale = (weights2d[i * size_scale * 32 + j * size_scale] +
+                       weights1d[i * size_scale]) >> 1;
+          interpred[k] =
+              ((scale_max - scale) * interpred[k] +
+               scale * intrapred[i * intrastride + j] + scale_round)
+              >> scale_bits;
+        }
+      }
+      break;
+
+    case D27_PRED:
+    case D153_PRED:
+      for (i = 0; i < size; ++i) {
+        for (j = 0; j < size; ++j) {
+          int k = i * interstride + j;
+          int scale = (weights2d[i * size_scale * 32 + j * size_scale] +
+                       weights1d[j * size_scale]) >> 1;
+          interpred[k] =
+              ((scale_max - scale) * interpred[k] +
+               scale * intrapred[i * intrastride + j] + scale_round)
+              >> scale_bits;
+        }
+      }
+      break;
+
+    case D135_PRED:
+      for (i = 0; i < size; ++i) {
+        for (j = 0; j < size; ++j) {
+          int k = i * interstride + j;
+          int scale = weights2d[i * size_scale * 32 + j * size_scale];
+          interpred[k] =
+              ((scale_max - scale) * interpred[k] +
+               scale * intrapred[i * intrastride + j] + scale_round)
+              >> scale_bits;
+        }
+      }
+      break;
+
+    case D45_PRED:
+    case DC_PRED:
+    case TM_PRED:
+    default:
+      // simple average
+      for (i = 0; i < size; ++i) {
+        for (j = 0; j < size; ++j) {
+          int k = i * interstride + j;
+          interpred[k] = (interpred[k] + intrapred[i * intrastride + j]) >> 1;
+        }
+      }
+      break;
+  }
+}
+
+void vp9_build_interintra_16x16_predictors_mb(MACROBLOCKD *xd,
+                                              unsigned char *ypred,
+                                              unsigned char *upred,
+                                              unsigned char *vpred,
+                                              int ystride, int uvstride) {
+  vp9_build_interintra_16x16_predictors_mby(xd, ypred, ystride);
+  vp9_build_interintra_16x16_predictors_mbuv(xd, upred, vpred, uvstride);
+}
+
+void vp9_build_interintra_16x16_predictors_mby(MACROBLOCKD *xd,
+                                               unsigned char *ypred,
+                                               int ystride) {
+  static const int scale_bits = 6;
+  unsigned char intrapredictor[256];
+  int i, j;
+  vp9_build_intra_predictors_internal(
+      xd->dst.y_buffer, xd->dst.y_stride,
+      intrapredictor, 16,
+      xd->mode_info_context->mbmi.interintra_mode, 16,
+      xd->up_available, xd->left_available);
+  combine_interintra(xd->mode_info_context->mbmi.interintra_mode,
+                     ypred, ystride, intrapredictor, 16, 16);
+}
+
+void vp9_build_interintra_16x16_predictors_mbuv(MACROBLOCKD *xd,
+                                                unsigned char *upred,
+                                                unsigned char *vpred,
+                                                int uvstride) {
+  int i, j;
+  unsigned char uintrapredictor[64];
+  unsigned char vintrapredictor[64];
+  vp9_build_intra_predictors_internal(
+      xd->dst.u_buffer, xd->dst.uv_stride,
+      uintrapredictor, 8,
+      xd->mode_info_context->mbmi.interintra_uv_mode, 8,
+      xd->up_available, xd->left_available);
+  vp9_build_intra_predictors_internal(
+      xd->dst.v_buffer, xd->dst.uv_stride,
+      vintrapredictor, 8,
+      xd->mode_info_context->mbmi.interintra_uv_mode, 8,
+      xd->up_available, xd->left_available);
+  combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode,
+                     upred, uvstride, uintrapredictor, 8, 8);
+  combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode,
+                     vpred, uvstride, vintrapredictor, 8, 8);
+}
+#endif
+
 void vp9_build_intra_predictors_mby(MACROBLOCKD *xd) {
   vp9_build_intra_predictors_internal(xd->dst.y_buffer, xd->dst.y_stride,
                                       xd->predictor, 16,
@@ -460,11 +748,11 @@
   int i;
 
   vp9_build_intra_predictors_mbuv_internal(
-    xd, predictor[0][0], predictor[1][0], 8,
-    xd->mode_info_context->mbmi.uv_mode, 8);
+      xd, predictor[0][0], predictor[1][0], 8,
+      xd->mode_info_context->mbmi.uv_mode, 8);
   vp9_build_intra_predictors_mbuv_internal(
-    xd, predictor[0][1], predictor[1][1], 8,
-    xd->mode_info_context->mbmi.second_uv_mode, 8);
+      xd, predictor[0][1], predictor[1][1], 8,
+      xd->mode_info_context->mbmi.second_uv_mode, 8);
   for (i = 0; i < 64; i++) {
     xd->predictor[256 + i] = (predictor[0][0][i] + predictor[0][1][i] + 1) >> 1;
     xd->predictor[256 + 64 + i] = (predictor[1][0][i] +
@@ -526,6 +814,6 @@
 #endif
 
 /* TODO: try different ways of use Y-UV mode correlation
- Current code assumes that a uv 4x4 block use same mode
- as corresponding Y 8x8 area
- */
+   Current code assumes that a uv 4x4 block use same mode
+   as corresponding Y 8x8 area
+   */
--- a/vp9/common/reconintra.h
+++ b/vp9/common/reconintra.h
@@ -17,5 +17,20 @@
 extern B_PREDICTION_MODE vp9_find_dominant_direction(unsigned char *ptr,
                                                      int stride, int n);
 extern B_PREDICTION_MODE vp9_find_bpred_context(BLOCKD *x);
+#if CONFIG_COMP_INTERINTRA_PRED
+extern void vp9_build_interintra_16x16_predictors_mb(MACROBLOCKD *xd,
+                                                     unsigned char *ypred,
+                                                     unsigned char *upred,
+                                                     unsigned char *vpred,
+                                                     int ystride,
+                                                     int uvstride);
+extern void vp9_build_interintra_16x16_predictors_mby(MACROBLOCKD *xd,
+                                                      unsigned char *ypred,
+                                                      int ystride);
+extern void vp9_build_interintra_16x16_predictors_mbuv(MACROBLOCKD *xd,
+                                                       unsigned char *upred,
+                                                       unsigned char *vpred,
+                                                       int uvstride);
+#endif
 
 #endif  // __INC_RECONINTRA_H
--- a/vp9/decoder/decodemv.c
+++ b/vp9/decoder/decodemv.c
@@ -531,6 +531,12 @@
 #endif
     if (cm->mcomp_filter_type == SWITCHABLE)
       read_switchable_interp_probs(pbi, bc);
+#if CONFIG_COMP_INTERINTRA_PRED
+    if (cm->use_interintra) {
+      if (vp9_read(bc, VP9_UPD_INTERINTRA_PROB))
+        cm->fc.interintra_prob  = (vp9_prob)vp9_read_literal(bc, 8);
+    }
+#endif
     // Decode the baseline probabilities for decoding reference frame
     cm->prob_intra_coded = (vp9_prob)vp9_read_literal(bc, 8);
     cm->prob_last_coded  = (vp9_prob)vp9_read_literal(bc, 8);
@@ -671,7 +677,7 @@
   mb_to_bottom_edge += RIGHT_BOTTOM_MARGIN;
   mbmi->need_to_clamp_mvs = 0;
   mbmi->need_to_clamp_secondmv = 0;
-  mbmi->second_ref_frame = 0;
+  mbmi->second_ref_frame = NONE;
   /* Distance of Mb to the various image edges.
    * These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units
    */
@@ -819,7 +825,7 @@
       mbmi->second_ref_frame = mbmi->ref_frame + 1;
       if (mbmi->second_ref_frame == 4)
         mbmi->second_ref_frame = 1;
-      if (mbmi->second_ref_frame) {
+      if (mbmi->second_ref_frame > 0) {
         int second_ref_fb_idx;
         /* Select the appropriate reference frame for this MB */
         if (mbmi->second_ref_frame == LAST_FRAME)
@@ -852,7 +858,33 @@
       }
 
     } else {
-      mbmi->second_ref_frame = 0;
+#if CONFIG_COMP_INTERINTRA_PRED
+      if (pbi->common.use_interintra &&
+          mbmi->mode >= NEARESTMV && mbmi->mode < SPLITMV &&
+          mbmi->second_ref_frame == NONE) {
+        mbmi->second_ref_frame = (vp9_read(bc, pbi->common.fc.interintra_prob) ?
+                                  INTRA_FRAME : NONE);
+        // printf("-- %d (%d)\n", mbmi->second_ref_frame == INTRA_FRAME,
+        //        pbi->common.fc.interintra_prob);
+        pbi->common.fc.interintra_counts[
+            mbmi->second_ref_frame == INTRA_FRAME]++;
+        if (mbmi->second_ref_frame == INTRA_FRAME) {
+          mbmi->interintra_mode = (MB_PREDICTION_MODE)read_ymode(
+              bc, pbi->common.fc.ymode_prob);
+          pbi->common.fc.ymode_counts[mbmi->interintra_mode]++;
+#if SEPARATE_INTERINTRA_UV
+          mbmi->interintra_uv_mode = (MB_PREDICTION_MODE)read_uv_mode(
+              bc, pbi->common.fc.uv_mode_prob[mbmi->interintra_mode]);
+          pbi->common.fc.uv_mode_counts[mbmi->interintra_mode]
+                                       [mbmi->interintra_uv_mode]++;
+#else
+          mbmi->interintra_uv_mode = mbmi->interintra_mode;
+#endif
+          // printf("** %d %d\n",
+          //        mbmi->interintra_mode, mbmi->interintra_uv_mode);
+        }
+      }
+#endif
     }
 
     mbmi->uv_mode = DC_PRED;
@@ -876,7 +908,7 @@
 
           leftmv.as_int = left_block_mv(mi, k);
           abovemv.as_int = above_block_mv(mi, k, mis);
-          if (mbmi->second_ref_frame) {
+          if (mbmi->second_ref_frame > 0) {
             second_leftmv.as_int = left_block_second_mv(mi, k);
             second_abovemv.as_int = above_block_second_mv(mi, k, mis);
           }
@@ -894,7 +926,7 @@
               blockmv.as_mv.row += best_mv.as_mv.row;
               blockmv.as_mv.col += best_mv.as_mv.col;
 
-              if (mbmi->second_ref_frame) {
+              if (mbmi->second_ref_frame > 0) {
                 read_nmv(bc, &secondmv.as_mv, &best_mv_second.as_mv, nmvc);
                 read_nmv_fp(bc, &secondmv.as_mv, &best_mv_second.as_mv, nmvc,
                             xd->allow_high_precision_mv);
@@ -909,7 +941,7 @@
               break;
             case LEFT4X4:
               blockmv.as_int = leftmv.as_int;
-              if (mbmi->second_ref_frame)
+              if (mbmi->second_ref_frame > 0)
                 secondmv.as_int = second_leftmv.as_int;
 #ifdef VPX_MODE_COUNT
               vp9_mv_cont_count[mv_contz][0]++;
@@ -917,7 +949,7 @@
               break;
             case ABOVE4X4:
               blockmv.as_int = abovemv.as_int;
-              if (mbmi->second_ref_frame)
+              if (mbmi->second_ref_frame > 0)
                 secondmv.as_int = second_abovemv.as_int;
 #ifdef VPX_MODE_COUNT
               vp9_mv_cont_count[mv_contz][1]++;
@@ -925,7 +957,7 @@
               break;
             case ZERO4X4:
               blockmv.as_int = 0;
-              if (mbmi->second_ref_frame)
+              if (mbmi->second_ref_frame > 0)
                 secondmv.as_int = 0;
 #ifdef VPX_MODE_COUNT
               vp9_mv_cont_count[mv_contz][2]++;
@@ -940,7 +972,7 @@
                                                      mb_to_right_edge,
                                                      mb_to_top_edge,
                                                      mb_to_bottom_edge);
-          if (mbmi->second_ref_frame) {
+          if (mbmi->second_ref_frame > 0) {
             mbmi->need_to_clamp_mvs |= check_mv_bounds(&secondmv,
                                                        mb_to_left_edge,
                                                        mb_to_right_edge,
@@ -959,7 +991,7 @@
 
             do {
               mi->bmi[ *fill_offset].as_mv.first.as_int = blockmv.as_int;
-              if (mbmi->second_ref_frame)
+              if (mbmi->second_ref_frame > 0)
                 mi->bmi[ *fill_offset].as_mv.second.as_int = secondmv.as_int;
               fill_offset++;
             } while (--fill_count);
@@ -978,7 +1010,7 @@
         /* Clip "next_nearest" so that it does not extend to far out of image */
         clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
                  mb_to_top_edge, mb_to_bottom_edge);
-        if (mbmi->second_ref_frame) {
+        if (mbmi->second_ref_frame > 0) {
           mbmi->mv[1].as_int = nearby_second.as_int;
           clamp_mv(&mbmi->mv[1], mb_to_left_edge, mb_to_right_edge,
                    mb_to_top_edge, mb_to_bottom_edge);
@@ -990,7 +1022,7 @@
         /* Clip "next_nearest" so that it does not extend to far out of image */
         clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
                  mb_to_top_edge, mb_to_bottom_edge);
-        if (mbmi->second_ref_frame) {
+        if (mbmi->second_ref_frame > 0) {
           mbmi->mv[1].as_int = nearest_second.as_int;
           clamp_mv(&mbmi->mv[1], mb_to_left_edge, mb_to_right_edge,
                    mb_to_top_edge, mb_to_bottom_edge);
@@ -999,7 +1031,7 @@
 
       case ZEROMV:
         mv->as_int = 0;
-        if (mbmi->second_ref_frame)
+        if (mbmi->second_ref_frame > 0)
           mbmi->mv[1].as_int = 0;
         break;
 
@@ -1038,7 +1070,7 @@
                                                   mb_to_top_edge,
                                                   mb_to_bottom_edge);
 
-        if (mbmi->second_ref_frame) {
+        if (mbmi->second_ref_frame > 0) {
 #if CONFIG_NEW_MVREF
         {
           int best_index;
--- a/vp9/decoder/decodframe.c
+++ b/vp9/decoder/decodframe.c
@@ -185,20 +185,39 @@
   } else {
 #if CONFIG_SUPERBLOCKS
     if (xd->mode_info_context->mbmi.encoded_as_sb) {
-      vp9_build_inter32x32_predictors_sb(xd, xd->dst.y_buffer,
-                                         xd->dst.u_buffer, xd->dst.v_buffer,
-                                         xd->dst.y_stride, xd->dst.uv_stride);
+      vp9_build_inter32x32_predictors_sb(xd,
+                                         xd->dst.y_buffer,
+                                         xd->dst.u_buffer,
+                                         xd->dst.v_buffer,
+                                         xd->dst.y_stride,
+                                         xd->dst.uv_stride);
     } else {
 #endif
-    vp9_build_1st_inter16x16_predictors_mb(xd, xd->dst.y_buffer,
-                                           xd->dst.u_buffer, xd->dst.v_buffer,
-                                           xd->dst.y_stride, xd->dst.uv_stride);
+    vp9_build_1st_inter16x16_predictors_mb(xd,
+                                           xd->dst.y_buffer,
+                                           xd->dst.u_buffer,
+                                           xd->dst.v_buffer,
+                                           xd->dst.y_stride,
+                                           xd->dst.uv_stride);
 
-    if (xd->mode_info_context->mbmi.second_ref_frame) {
-      vp9_build_2nd_inter16x16_predictors_mb(xd, xd->dst.y_buffer,
-                                             xd->dst.u_buffer, xd->dst.v_buffer,
-                                             xd->dst.y_stride, xd->dst.uv_stride);
+    if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
+      vp9_build_2nd_inter16x16_predictors_mb(xd,
+                                             xd->dst.y_buffer,
+                                             xd->dst.u_buffer,
+                                             xd->dst.v_buffer,
+                                             xd->dst.y_stride,
+                                             xd->dst.uv_stride);
     }
+#if CONFIG_COMP_INTERINTRA_PRED
+    else if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) {
+      vp9_build_interintra_16x16_predictors_mb(xd,
+                                               xd->dst.y_buffer,
+                                               xd->dst.u_buffer,
+                                               xd->dst.v_buffer,
+                                               xd->dst.y_stride,
+                                               xd->dst.uv_stride);
+    }
+#endif
 #if CONFIG_SUPERBLOCKS
     }
 #endif
@@ -707,7 +726,7 @@
       xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
       xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
 
-      if (xd->mode_info_context->mbmi.second_ref_frame) {
+      if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
         int second_ref_fb_idx;
 
         /* Select the appropriate reference frame for this MB */
@@ -1281,6 +1300,9 @@
     } else {
       pc->mcomp_filter_type = vp9_read_literal(&header_bc, 2);
     }
+#if CONFIG_COMP_INTERINTRA_PRED
+    pc->use_interintra = vp9_read_bit(&header_bc);
+#endif
     /* To enable choice of different interploation filters */
     vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc);
   }
@@ -1323,6 +1345,9 @@
   vp9_copy(pbi->common.fc.pre_i8x8_mode_prob, pbi->common.fc.i8x8_mode_prob);
   vp9_copy(pbi->common.fc.pre_sub_mv_ref_prob, pbi->common.fc.sub_mv_ref_prob);
   vp9_copy(pbi->common.fc.pre_mbsplit_prob, pbi->common.fc.mbsplit_prob);
+#if CONFIG_COMP_INTERINTRA_PRED
+  pbi->common.fc.pre_interintra_prob = pbi->common.fc.interintra_prob;
+#endif
   pbi->common.fc.pre_nmvc = pbi->common.fc.nmvc;
   vp9_zero(pbi->common.fc.coef_counts);
   vp9_zero(pbi->common.fc.hybrid_coef_counts);
@@ -1339,6 +1364,9 @@
   vp9_zero(pbi->common.fc.NMVcount);
   vp9_zero(pbi->common.fc.mv_ref_ct);
   vp9_zero(pbi->common.fc.mv_ref_ct_a);
+#if CONFIG_COMP_INTERINTRA_PRED
+  vp9_zero(pbi->common.fc.interintra_counts);
+#endif
 
   read_coef_probs(pbi, &header_bc);
 
--- a/vp9/encoder/bitstream.c
+++ b/vp9/encoder/bitstream.c
@@ -338,6 +338,21 @@
   return bestsavings;
 }
 
+static void vp9_cond_prob_update(vp9_writer *bc, vp9_prob *oldp, vp9_prob upd,
+                                 unsigned int *ct) {
+  vp9_prob newp;
+  int savings;
+  newp = get_binary_prob(ct[0], ct[1]);
+  savings = prob_update_savings(ct, *oldp, newp, upd);
+  if (savings > 0) {
+    vp9_write(bc, 1, upd);
+    vp9_write_literal(bc, newp, 8);
+    *oldp = newp;
+  } else {
+    vp9_write(bc, 0, upd);
+  }
+}
+
 static void pack_mb_tokens(vp9_writer* const bc,
                            TOKENEXTRA **tp,
                            const TOKENEXTRA *const stop) {
@@ -975,7 +990,7 @@
             }
           }
 
-          if (mi->second_ref_frame &&
+          if (mi->second_ref_frame > 0 &&
               (mode == NEWMV || mode == SPLITMV)) {
             int_mv n1, n2;
 
@@ -986,9 +1001,30 @@
           // does the feature use compound prediction or not
           // (if not specified at the frame/segment level)
           if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) {
-            vp9_write(bc, mi->second_ref_frame != INTRA_FRAME,
+            vp9_write(bc, mi->second_ref_frame > INTRA_FRAME,
                       vp9_get_pred_prob(pc, xd, PRED_COMP));
           }
+#if CONFIG_COMP_INTERINTRA_PRED
+          if (cpi->common.use_interintra &&
+              mode >= NEARESTMV && mode < SPLITMV &&
+              mi->second_ref_frame <= INTRA_FRAME) {
+            vp9_write(bc, mi->second_ref_frame == INTRA_FRAME,
+                      pc->fc.interintra_prob);
+            // if (!cpi->dummy_packing)
+            //   printf("-- %d (%d)\n", mi->second_ref_frame == INTRA_FRAME,
+            //          pc->fc.interintra_prob);
+            if (mi->second_ref_frame == INTRA_FRAME) {
+              // if (!cpi->dummy_packing)
+              //   printf("** %d %d\n", mi->interintra_mode,
+                       // mi->interintra_uv_mode);
+              write_ymode(bc, mi->interintra_mode, pc->fc.ymode_prob);
+#if SEPARATE_INTERINTRA_UV
+              write_uv_mode(bc, mi->interintra_uv_mode,
+                            pc->fc.uv_mode_prob[mi->interintra_mode]);
+#endif
+            }
+          }
+#endif
 
           {
             switch (mode) { /* new, split require MVs */
@@ -1024,7 +1060,7 @@
                           (const nmv_context*) nmvc,
                           xd->allow_high_precision_mv);
 
-                if (mi->second_ref_frame) {
+                if (mi->second_ref_frame > 0) {
 #if CONFIG_NEW_MVREF
                   unsigned int best_index;
                   sec_ref_frame = mi->second_ref_frame;
@@ -1095,7 +1131,7 @@
                               (const nmv_context*) nmvc,
                               xd->allow_high_precision_mv);
 
-                    if (mi->second_ref_frame) {
+                    if (mi->second_ref_frame > 0) {
                       write_nmv(bc,
                                 &cpi->mb.partition_info->bmi[j].second_mv.as_mv,
                                 &best_second_mv,
@@ -2021,6 +2057,15 @@
     vp9_write_bit(&header_bc, (pc->mcomp_filter_type == SWITCHABLE));
     if (pc->mcomp_filter_type != SWITCHABLE)
       vp9_write_literal(&header_bc, (pc->mcomp_filter_type), 2);
+#if CONFIG_COMP_INTERINTRA_PRED
+    //  printf("Counts: %d %d\n", cpi->interintra_count[0],
+    //         cpi->interintra_count[1]);
+    if (!cpi->dummy_packing && pc->use_interintra)
+      pc->use_interintra = (cpi->interintra_count[1] > 0);
+    vp9_write_bit(&header_bc, pc->use_interintra);
+    if (!pc->use_interintra)
+      vp9_zero(cpi->interintra_count);
+#endif
   }
 
   vp9_write_bit(&header_bc, pc->refresh_entropy_probs);
@@ -2050,6 +2095,9 @@
   vp9_copy(cpi->common.fc.pre_mbsplit_prob, cpi->common.fc.mbsplit_prob);
   vp9_copy(cpi->common.fc.pre_i8x8_mode_prob, cpi->common.fc.i8x8_mode_prob);
   cpi->common.fc.pre_nmvc = cpi->common.fc.nmvc;
+#if CONFIG_COMP_INTERINTRA_PRED
+  cpi->common.fc.pre_interintra_prob = cpi->common.fc.interintra_prob;
+#endif
   vp9_zero(cpi->sub_mv_ref_count);
   vp9_zero(cpi->mbsplit_count);
   vp9_zero(cpi->common.fc.mv_ref_ct)
@@ -2094,6 +2142,14 @@
 #endif
     if (pc->mcomp_filter_type == SWITCHABLE)
       update_switchable_interp_probs(cpi, &header_bc);
+#if CONFIG_COMP_INTERINTRA_PRED
+    if (pc->use_interintra) {
+      vp9_cond_prob_update(&header_bc,
+                           &pc->fc.interintra_prob,
+                           VP9_UPD_INTERINTRA_PROB,
+                           cpi->interintra_count);
+    }
+#endif
 
     vp9_write_literal(&header_bc, pc->prob_intra_coded, 8);
     vp9_write_literal(&header_bc, pc->prob_last_coded, 8);
@@ -2116,7 +2172,6 @@
         }
       }
     }
-
     update_mbintra_mode_probs(cpi, &header_bc);
 
     vp9_write_nmv_probs(cpi, xd->allow_high_precision_mv, &header_bc);
--- a/vp9/encoder/encodeframe.c
+++ b/vp9/encoder/encodeframe.c
@@ -578,6 +578,20 @@
       mbmi->best_second_mv.as_int = best_second_mv.as_int;
       vp9_update_nmv_count(cpi, x, &best_mv, &best_second_mv);
     }
+#if CONFIG_COMP_INTERINTRA_PRED
+    if (mbmi->mode >= NEARESTMV && mbmi->mode < SPLITMV &&
+        mbmi->second_ref_frame <= INTRA_FRAME) {
+      if (mbmi->second_ref_frame == INTRA_FRAME) {
+        ++cpi->interintra_count[1];
+        ++cpi->ymode_count[mbmi->interintra_mode];
+#if SEPARATE_INTERINTRA_UV
+        ++cpi->y_uv_mode_count[mbmi->interintra_mode][mbmi->interintra_uv_mode];
+#endif
+      } else {
+        ++cpi->interintra_count[0];
+      }
+    }
+#endif
 
     cpi->prediction_error += ctx->distortion;
     cpi->intra_error += ctx->intra_error;
@@ -1114,7 +1128,7 @@
 
         pred_context = vp9_get_pred_context(cm, xd, PRED_COMP);
 
-        if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME)
+        if (xd->mode_info_context->mbmi.second_ref_frame <= INTRA_FRAME)
           cpi->single_pred_count[pred_context]++;
         else
           cpi->comp_pred_count[pred_context]++;
@@ -1393,6 +1407,10 @@
   vp9_zero(cpi->sb_ymode_count)
   cpi->sb_count = 0;
 #endif
+#if CONFIG_COMP_INTERINTRA_PRED
+  vp9_zero(cpi->interintra_count);
+  vp9_zero(cpi->interintra_select_count);
+#endif
 
   vpx_memset(cm->above_context, 0,
              sizeof(ENTROPY_CONTEXT_PLANES) * cm->mb_cols);
@@ -2219,7 +2237,7 @@
     xd->pre.u_buffer = cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
     xd->pre.v_buffer = cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
 
-    if (mbmi->second_ref_frame) {
+    if (mbmi->second_ref_frame > 0) {
       int second_ref_fb_idx;
 
       if (mbmi->second_ref_frame == LAST_FRAME)
@@ -2406,7 +2424,7 @@
     xd->pre.u_buffer = cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
     xd->pre.v_buffer = cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
 
-    if (xd->mode_info_context->mbmi.second_ref_frame) {
+    if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
       int second_ref_fb_idx;
 
       if (xd->mode_info_context->mbmi.second_ref_frame == LAST_FRAME)
--- a/vp9/encoder/encodemv.c
+++ b/vp9/encoder/encodemv.c
@@ -610,7 +610,7 @@
           mv.col = (x->partition_info->bmi[i].mv.as_mv.col
                     - best_ref_mv->as_mv.col);
           vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount, 1);
-          if (x->e_mbd.mode_info_context->mbmi.second_ref_frame) {
+          if (x->e_mbd.mode_info_context->mbmi.second_ref_frame > 0) {
             mv.row = (x->partition_info->bmi[i].second_mv.as_mv.row
                       - second_best_ref_mv->as_mv.row);
             mv.col = (x->partition_info->bmi[i].second_mv.as_mv.col
@@ -624,7 +624,7 @@
           mv.col = (x->partition_info->bmi[i].mv.as_mv.col
                     - best_ref_mv->as_mv.col);
           vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount, 0);
-          if (x->e_mbd.mode_info_context->mbmi.second_ref_frame) {
+          if (x->e_mbd.mode_info_context->mbmi.second_ref_frame > 0) {
             mv.row = (x->partition_info->bmi[i].second_mv.as_mv.row
                       - second_best_ref_mv->as_mv.row);
             mv.col = (x->partition_info->bmi[i].second_mv.as_mv.col
@@ -640,7 +640,7 @@
       mv.row = (mbmi->mv[0].as_mv.row - best_ref_mv->as_mv.row);
       mv.col = (mbmi->mv[0].as_mv.col - best_ref_mv->as_mv.col);
       vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount, 1);
-      if (mbmi->second_ref_frame) {
+      if (mbmi->second_ref_frame > 0) {
         mv.row = (mbmi->mv[1].as_mv.row - second_best_ref_mv->as_mv.row);
         mv.col = (mbmi->mv[1].as_mv.col - second_best_ref_mv->as_mv.col);
         vp9_increment_nmv(&mv, &second_best_ref_mv->as_mv, &cpi->NMVcount, 1);
@@ -649,7 +649,7 @@
       mv.row = (mbmi->mv[0].as_mv.row - best_ref_mv->as_mv.row);
       mv.col = (mbmi->mv[0].as_mv.col - best_ref_mv->as_mv.col);
       vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount, 0);
-      if (mbmi->second_ref_frame) {
+      if (mbmi->second_ref_frame > 0) {
         mv.row = (mbmi->mv[1].as_mv.row - second_best_ref_mv->as_mv.row);
         mv.col = (mbmi->mv[1].as_mv.col - second_best_ref_mv->as_mv.col);
         vp9_increment_nmv(&mv, &second_best_ref_mv->as_mv, &cpi->NMVcount, 0);
--- a/vp9/encoder/onyx_if.c
+++ b/vp9/encoder/onyx_if.c
@@ -224,6 +224,7 @@
 
   }
 }
+
 static void set_mvcost(MACROBLOCK *mb) {
   if (mb->e_mbd.allow_high_precision_mv) {
     mb->mvcost = mb->nmvcost_hp;
@@ -788,6 +789,21 @@
       sf->thresh_mult[THR_COMP_SPLITGA  ] = 5000;
       sf->thresh_mult[THR_COMP_SPLITLG  ] = 5000;
 
+#if CONFIG_COMP_INTERINTRA_PRED
+      sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARL   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEWL    ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARG   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEWG    ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARA   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEWA    ] = 0;
+#endif
+
       sf->first_step = 0;
       sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
       sf->search_best_filter = SEARCH_BEST_FILTER;
@@ -912,6 +928,20 @@
       sf->thresh_mult[THR_COMP_SPLITLA  ] = 1700;
       sf->thresh_mult[THR_COMP_SPLITGA  ] = 4500;
       sf->thresh_mult[THR_COMP_SPLITLG  ] = 4500;
+#if CONFIG_COMP_INTERINTRA_PRED
+      sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARL   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEWL    ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARG   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEWG    ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEARA   ] = 0;
+      sf->thresh_mult[THR_COMP_INTERINTRA_NEWA    ] = 0;
+#endif
 
       if (Speed > 0) {
         /* Disable coefficient optimization above speed 0 */
@@ -1002,6 +1032,20 @@
         sf->thresh_mult[THR_COMP_NEWLG    ] = 2000;
         sf->thresh_mult[THR_COMP_NEWLA    ] = 2000;
         sf->thresh_mult[THR_COMP_NEWGA    ] = 2000;
+#if CONFIG_COMP_INTERINTRA_PRED
+        sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARL   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEWL    ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARG   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEWG    ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARA   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEWA    ] = 0;
+#endif
       }
 
       if (Speed > 2) {
@@ -1077,6 +1121,20 @@
         sf->thresh_mult[THR_COMP_NEWLG    ] = 2500;
         sf->thresh_mult[THR_COMP_NEWLA    ] = 2500;
         sf->thresh_mult[THR_COMP_NEWGA    ] = 2500;
+#if CONFIG_COMP_INTERINTRA_PRED
+        sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARL   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEWL    ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARG   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEWG    ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEARA   ] = 0;
+        sf->thresh_mult[THR_COMP_INTERINTRA_NEWA    ] = 0;
+#endif
 
         sf->improved_dct = 0;
 
@@ -1116,6 +1174,12 @@
     sf->thresh_mult[THR_NEARG_FILT    ] = INT_MAX;
     sf->thresh_mult[THR_NEWG_FILT     ] = INT_MAX;
 #endif
+#if CONFIG_COMP_INTERINTRA_PRED
+    sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG   ] = INT_MAX;
+    sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = INT_MAX;
+    sf->thresh_mult[THR_COMP_INTERINTRA_NEARG   ] = INT_MAX;
+    sf->thresh_mult[THR_COMP_INTERINTRA_NEWG    ] = INT_MAX;
+#endif
     sf->thresh_mult[THR_SPLITG   ] = INT_MAX;
   }
 
@@ -1130,6 +1194,12 @@
     sf->thresh_mult[THR_NEARA_FILT    ] = INT_MAX;
     sf->thresh_mult[THR_NEWA_FILT     ] = INT_MAX;
 #endif
+#if CONFIG_COMP_INTERINTRA_PRED
+    sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA   ] = INT_MAX;
+    sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = INT_MAX;
+    sf->thresh_mult[THR_COMP_INTERINTRA_NEARA   ] = INT_MAX;
+    sf->thresh_mult[THR_COMP_INTERINTRA_NEWA    ] = INT_MAX;
+#endif
     sf->thresh_mult[THR_SPLITA   ] = INT_MAX;
   }
 
@@ -1156,6 +1226,14 @@
     sf->thresh_mult[THR_COMP_NEWGA    ] = INT_MAX;
     sf->thresh_mult[THR_COMP_SPLITGA  ] = INT_MAX;
   }
+#if CONFIG_COMP_INTERINTRA_PRED
+  if ((cpi->ref_frame_flags & VP9_LAST_FLAG) != VP9_LAST_FLAG) {
+    sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL   ] = INT_MAX;
+    sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = INT_MAX;
+    sf->thresh_mult[THR_COMP_INTERINTRA_NEARL   ] = INT_MAX;
+    sf->thresh_mult[THR_COMP_INTERINTRA_NEWL    ] = INT_MAX;
+  }
+#endif
 
   // Slow quant, dct and trellis not worthwhile for first pass
   // so make sure they are always turned off.
@@ -2850,6 +2928,19 @@
   */
 }
 #endif
+#if CONFIG_COMP_INTERINTRA_PRED
+static void select_interintra_mode(VP9_COMP *cpi) {
+  static const double threshold = 0.01;
+  VP9_COMMON *cm = &cpi->common;
+  // FIXME(debargha): Make this RD based
+  int sum = cpi->interintra_select_count[1] + cpi->interintra_select_count[0];
+  if (sum) {
+    double fraction = (double) cpi->interintra_select_count[1] / sum;
+    // printf("fraction: %f\n", fraction);
+    cm->use_interintra = (fraction > threshold);
+  }
+}
+#endif
 
 static void encode_frame_to_data_rate
 (
@@ -3144,6 +3235,12 @@
     set_mvcost(&cpi->mb);
   }
 
+#if CONFIG_COMP_INTERINTRA_PRED
+  if (cm->current_video_frame == 0) {
+    cm->use_interintra = 1;
+  }
+#endif
+
 #if CONFIG_POSTPROC
 
   if (cpi->oxcf.noise_sensitivity > 0) {
@@ -3634,6 +3731,9 @@
     vp9_copy(cpi->common.fc.i8x8_mode_counts, cpi->i8x8_mode_count);
     vp9_copy(cpi->common.fc.sub_mv_ref_counts, cpi->sub_mv_ref_count);
     vp9_copy(cpi->common.fc.mbsplit_counts, cpi->mbsplit_count);
+#if CONFIG_COMP_INTERINTRA_PRED
+    vp9_copy(cpi->common.fc.interintra_counts, cpi->interintra_count);
+#endif
     vp9_adapt_mode_probs(&cpi->common);
 
     cpi->common.fc.NMVcount = cpi->NMVcount;
@@ -3644,6 +3744,10 @@
     vp9_adapt_nmv_probs(&cpi->common, cpi->mb.e_mbd.allow_high_precision_mv);
     vp9_update_mode_context(&cpi->common);
   }
+#if CONFIG_COMP_INTERINTRA_PRED
+  if (cm->frame_type != KEY_FRAME)
+    select_interintra_mode(cpi);
+#endif
 
   /* Move storing frame_type out of the above loop since it is also
    * needed in motion search besides loopfilter */
--- a/vp9/encoder/onyx_int.h
+++ b/vp9/encoder/onyx_int.h
@@ -43,9 +43,17 @@
 #define ARF_DECAY_THRESH 12
 
 #if CONFIG_PRED_FILTER
+#if CONFIG_COMP_INTERINTRA_PRED
+#define MAX_MODES 66
+#else
 #define MAX_MODES 54
+#endif
 #else  // CONFIG_PRED_FILTER
+#if CONFIG_COMP_INTERINTRA_PRED
+#define MAX_MODES 54
+#else
 #define MAX_MODES 42
+#endif
 #endif  // CONFIG_PRED_FILTER
 
 #define MIN_THRESHMULT  32
@@ -111,6 +119,9 @@
 
   vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
                                  [VP9_SWITCHABLE_FILTERS - 1];
+#if CONFIG_COMP_INTERINTRA_PRED
+  vp9_prob interintra_prob;
+#endif
 
   int mv_ref_ct[6][4][2];
   int mode_context[6][4];
@@ -238,6 +249,22 @@
   THR_COMP_SPLITLG,
   THR_COMP_SPLITLA,
   THR_COMP_SPLITGA,
+#if CONFIG_COMP_INTERINTRA_PRED
+  THR_COMP_INTERINTRA_ZEROL,
+  THR_COMP_INTERINTRA_NEARESTL,
+  THR_COMP_INTERINTRA_NEARL,
+  THR_COMP_INTERINTRA_NEWL,
+
+  THR_COMP_INTERINTRA_ZEROG,
+  THR_COMP_INTERINTRA_NEARESTG,
+  THR_COMP_INTERINTRA_NEARG,
+  THR_COMP_INTERINTRA_NEWG,
+
+  THR_COMP_INTERINTRA_ZEROA,
+  THR_COMP_INTERINTRA_NEARESTA,
+  THR_COMP_INTERINTRA_NEARA,
+  THR_COMP_INTERINTRA_NEWA,
+#endif
 }
 THR_MODES;
 #else
@@ -296,7 +323,23 @@
 
   THR_COMP_SPLITLG,
   THR_COMP_SPLITLA,
-  THR_COMP_SPLITGA
+  THR_COMP_SPLITGA,
+#if CONFIG_COMP_INTERINTRA_PRED
+  THR_COMP_INTERINTRA_ZEROL,
+  THR_COMP_INTERINTRA_NEARESTL,
+  THR_COMP_INTERINTRA_NEARL,
+  THR_COMP_INTERINTRA_NEWL,
+
+  THR_COMP_INTERINTRA_ZEROG,
+  THR_COMP_INTERINTRA_NEARESTG,
+  THR_COMP_INTERINTRA_NEARG,
+  THR_COMP_INTERINTRA_NEWG,
+
+  THR_COMP_INTERINTRA_ZEROA,
+  THR_COMP_INTERINTRA_NEARESTA,
+  THR_COMP_INTERINTRA_NEARA,
+  THR_COMP_INTERINTRA_NEWA,
+#endif
 }
 THR_MODES;
 #endif
@@ -539,6 +582,10 @@
   int sub_mv_ref_count[SUBMVREF_COUNT][VP9_SUBMVREFS];
   int mbsplit_count[VP9_NUMMBSPLITS];
   int y_uv_mode_count[VP9_YMODES][VP9_UV_MODES];
+#if CONFIG_COMP_INTERINTRA_PRED
+  int interintra_count[2];
+  int interintra_select_count[2];
+#endif
 
   nmv_context_counts NMVcount;
 
@@ -751,7 +798,6 @@
 #endif
   unsigned int switchable_interp_count[VP9_SWITCHABLE_FILTERS + 1]
                                       [VP9_SWITCHABLE_FILTERS];
-
 #if CONFIG_NEW_MVREF
   unsigned int best_ref_index_counts[MAX_REF_FRAMES][MAX_MV_REFS];
 #endif
--- a/vp9/encoder/ratectrl.c
+++ b/vp9/encoder/ratectrl.c
@@ -175,6 +175,9 @@
   vp9_copy(cc->coef_probs_16x16, cm->fc.coef_probs_16x16);
   vp9_copy(cc->hybrid_coef_probs_16x16, cm->fc.hybrid_coef_probs_16x16);
   vp9_copy(cc->switchable_interp_prob, cm->fc.switchable_interp_prob);
+#if CONFIG_COMP_INTERINTRA_PRED
+  cc->interintra_prob = cm->fc.interintra_prob;
+#endif
 }
 
 void vp9_restore_coding_context(VP9_COMP *cpi) {
@@ -231,6 +234,9 @@
   vp9_copy(cm->fc.coef_probs_16x16, cc->coef_probs_16x16);
   vp9_copy(cm->fc.hybrid_coef_probs_16x16, cc->hybrid_coef_probs_16x16);
   vp9_copy(cm->fc.switchable_interp_prob, cc->switchable_interp_prob);
+#if CONFIG_COMP_INTERINTRA_PRED
+  cm->fc.interintra_prob = cc->interintra_prob;
+#endif
 }
 
 
--- a/vp9/encoder/rdopt.c
+++ b/vp9/encoder/rdopt.c
@@ -78,54 +78,54 @@
 
 #if CONFIG_PRED_FILTER
 const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
-  {ZEROMV,    LAST_FRAME,   0,  0},
-  {ZEROMV,    LAST_FRAME,   0,  1},
-  {DC_PRED,   INTRA_FRAME,  0,  0},
+  {ZEROMV,    LAST_FRAME,   NONE,  0},
+  {ZEROMV,    LAST_FRAME,   NONE,  1},
+  {DC_PRED,   INTRA_FRAME,  NONE,  0},
 
-  {NEARESTMV, LAST_FRAME,   0,  0},
-  {NEARESTMV, LAST_FRAME,   0,  1},
-  {NEARMV,    LAST_FRAME,   0,  0},
-  {NEARMV,    LAST_FRAME,   0,  1},
+  {NEARESTMV, LAST_FRAME,   NONE,  0},
+  {NEARESTMV, LAST_FRAME,   NONE,  1},
+  {NEARMV,    LAST_FRAME,   NONE,  0},
+  {NEARMV,    LAST_FRAME,   NONE,  1},
 
-  {ZEROMV,    GOLDEN_FRAME, 0,  0},
-  {ZEROMV,    GOLDEN_FRAME, 0,  1},
-  {NEARESTMV, GOLDEN_FRAME, 0,  0},
-  {NEARESTMV, GOLDEN_FRAME, 0,  1},
+  {ZEROMV,    GOLDEN_FRAME, NONE,  0},
+  {ZEROMV,    GOLDEN_FRAME, NONE,  1},
+  {NEARESTMV, GOLDEN_FRAME, NONE,  0},
+  {NEARESTMV, GOLDEN_FRAME, NONE,  1},
 
-  {ZEROMV,    ALTREF_FRAME, 0,  0},
-  {ZEROMV,    ALTREF_FRAME, 0,  1},
-  {NEARESTMV, ALTREF_FRAME, 0,  0},
-  {NEARESTMV, ALTREF_FRAME, 0,  1},
+  {ZEROMV,    ALTREF_FRAME, NONE,  0},
+  {ZEROMV,    ALTREF_FRAME, NONE,  1},
+  {NEARESTMV, ALTREF_FRAME, NONE,  0},
+  {NEARESTMV, ALTREF_FRAME, NONE,  1},
 
-  {NEARMV,    GOLDEN_FRAME, 0,  0},
-  {NEARMV,    GOLDEN_FRAME, 0,  1},
-  {NEARMV,    ALTREF_FRAME, 0,  0},
-  {NEARMV,    ALTREF_FRAME, 0,  1},
+  {NEARMV,    GOLDEN_FRAME, NONE,  0},
+  {NEARMV,    GOLDEN_FRAME, NONE,  1},
+  {NEARMV,    ALTREF_FRAME, NONE,  0},
+  {NEARMV,    ALTREF_FRAME, NONE,  1},
 
-  {V_PRED,    INTRA_FRAME,  0,  0},
-  {H_PRED,    INTRA_FRAME,  0,  0},
-  {D45_PRED,  INTRA_FRAME,  0,  0},
-  {D135_PRED, INTRA_FRAME,  0,  0},
-  {D117_PRED, INTRA_FRAME,  0,  0},
-  {D153_PRED, INTRA_FRAME,  0,  0},
-  {D27_PRED,  INTRA_FRAME,  0,  0},
-  {D63_PRED,  INTRA_FRAME,  0,  0},
+  {V_PRED,    INTRA_FRAME,  NONE,  0},
+  {H_PRED,    INTRA_FRAME,  NONE,  0},
+  {D45_PRED,  INTRA_FRAME,  NONE,  0},
+  {D135_PRED, INTRA_FRAME,  NONE,  0},
+  {D117_PRED, INTRA_FRAME,  NONE,  0},
+  {D153_PRED, INTRA_FRAME,  NONE,  0},
+  {D27_PRED,  INTRA_FRAME,  NONE,  0},
+  {D63_PRED,  INTRA_FRAME,  NONE,  0},
 
-  {TM_PRED,   INTRA_FRAME,  0,  0},
+  {TM_PRED,   INTRA_FRAME,  NONE,  0},
 
-  {NEWMV,     LAST_FRAME,   0,  0},
-  {NEWMV,     LAST_FRAME,   0,  1},
-  {NEWMV,     GOLDEN_FRAME, 0,  0},
-  {NEWMV,     GOLDEN_FRAME, 0,  1},
-  {NEWMV,     ALTREF_FRAME, 0,  0},
-  {NEWMV,     ALTREF_FRAME, 0,  1},
+  {NEWMV,     LAST_FRAME,   NONE,  0},
+  {NEWMV,     LAST_FRAME,   NONE,  1},
+  {NEWMV,     GOLDEN_FRAME, NONE,  0},
+  {NEWMV,     GOLDEN_FRAME, NONE,  1},
+  {NEWMV,     ALTREF_FRAME, NONE,  0},
+  {NEWMV,     ALTREF_FRAME, NONE,  1},
 
-  {SPLITMV,   LAST_FRAME,   0,  0},
-  {SPLITMV,   GOLDEN_FRAME, 0,  0},
-  {SPLITMV,   ALTREF_FRAME, 0,  0},
+  {SPLITMV,   LAST_FRAME,   NONE,  0},
+  {SPLITMV,   GOLDEN_FRAME, NONE,  0},
+  {SPLITMV,   ALTREF_FRAME, NONE,  0},
 
-  {B_PRED,    INTRA_FRAME,  0,  0},
-  {I8X8_PRED, INTRA_FRAME,  0,  0},
+  {B_PRED,    INTRA_FRAME,  NONE,  0},
+  {I8X8_PRED, INTRA_FRAME,  NONE,  0},
 
   /* compound prediction modes */
   {ZEROMV,    LAST_FRAME,   GOLDEN_FRAME, 0},
@@ -146,46 +146,64 @@
 
   {SPLITMV,   LAST_FRAME,   GOLDEN_FRAME, 0},
   {SPLITMV,   ALTREF_FRAME, LAST_FRAME,   0},
-  {SPLITMV,   GOLDEN_FRAME, ALTREF_FRAME, 0}
+  {SPLITMV,   GOLDEN_FRAME, ALTREF_FRAME, 0},
+
+#if CONFIG_COMP_INTERINTRA_PRED
+  /* compound inter-intra prediction */
+  {ZEROMV,    LAST_FRAME,   INTRA_FRAME, 0},
+  {NEARESTMV, LAST_FRAME,   INTRA_FRAME, 0},
+  {NEARMV,    LAST_FRAME,   INTRA_FRAME, 0},
+  {NEWMV,     LAST_FRAME,   INTRA_FRAME, 0},
+
+  {ZEROMV,    GOLDEN_FRAME,   INTRA_FRAME, 0},
+  {NEARESTMV, GOLDEN_FRAME,   INTRA_FRAME, 0},
+  {NEARMV,    GOLDEN_FRAME,   INTRA_FRAME, 0},
+  {NEWMV,     GOLDEN_FRAME,   INTRA_FRAME, 0},
+
+  {ZEROMV,    ALTREF_FRAME,   INTRA_FRAME, 0},
+  {NEARESTMV, ALTREF_FRAME,   INTRA_FRAME, 0},
+  {NEARMV,    ALTREF_FRAME,   INTRA_FRAME, 0},
+  {NEWMV,     ALTREF_FRAME,   INTRA_FRAME, 0},
+#endif
 };
 #else
 const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
-  {ZEROMV,    LAST_FRAME,   0},
-  {DC_PRED,   INTRA_FRAME,  0},
+  {ZEROMV,    LAST_FRAME,   NONE},
+  {DC_PRED,   INTRA_FRAME,  NONE},
 
-  {NEARESTMV, LAST_FRAME,   0},
-  {NEARMV,    LAST_FRAME,   0},
+  {NEARESTMV, LAST_FRAME,   NONE},
+  {NEARMV,    LAST_FRAME,   NONE},
 
-  {ZEROMV,    GOLDEN_FRAME, 0},
-  {NEARESTMV, GOLDEN_FRAME, 0},
+  {ZEROMV,    GOLDEN_FRAME, NONE},
+  {NEARESTMV, GOLDEN_FRAME, NONE},
 
-  {ZEROMV,    ALTREF_FRAME, 0},
-  {NEARESTMV, ALTREF_FRAME, 0},
+  {ZEROMV,    ALTREF_FRAME, NONE},
+  {NEARESTMV, ALTREF_FRAME, NONE},
 
-  {NEARMV,    GOLDEN_FRAME, 0},
-  {NEARMV,    ALTREF_FRAME, 0},
+  {NEARMV,    GOLDEN_FRAME, NONE},
+  {NEARMV,    ALTREF_FRAME, NONE},
 
-  {V_PRED,    INTRA_FRAME,  0},
-  {H_PRED,    INTRA_FRAME,  0},
-  {D45_PRED,  INTRA_FRAME,  0},
-  {D135_PRED, INTRA_FRAME,  0},
-  {D117_PRED, INTRA_FRAME,  0},
-  {D153_PRED, INTRA_FRAME,  0},
-  {D27_PRED,  INTRA_FRAME,  0},
-  {D63_PRED,  INTRA_FRAME,  0},
+  {V_PRED,    INTRA_FRAME,  NONE},
+  {H_PRED,    INTRA_FRAME,  NONE},
+  {D45_PRED,  INTRA_FRAME,  NONE},
+  {D135_PRED, INTRA_FRAME,  NONE},
+  {D117_PRED, INTRA_FRAME,  NONE},
+  {D153_PRED, INTRA_FRAME,  NONE},
+  {D27_PRED,  INTRA_FRAME,  NONE},
+  {D63_PRED,  INTRA_FRAME,  NONE},
 
-  {TM_PRED,   INTRA_FRAME,  0},
+  {TM_PRED,   INTRA_FRAME,  NONE},
 
-  {NEWMV,     LAST_FRAME,   0},
-  {NEWMV,     GOLDEN_FRAME, 0},
-  {NEWMV,     ALTREF_FRAME, 0},
+  {NEWMV,     LAST_FRAME,   NONE},
+  {NEWMV,     GOLDEN_FRAME, NONE},
+  {NEWMV,     ALTREF_FRAME, NONE},
 
-  {SPLITMV,   LAST_FRAME,   0},
-  {SPLITMV,   GOLDEN_FRAME, 0},
-  {SPLITMV,   ALTREF_FRAME, 0},
+  {SPLITMV,   LAST_FRAME,   NONE},
+  {SPLITMV,   GOLDEN_FRAME, NONE},
+  {SPLITMV,   ALTREF_FRAME, NONE},
 
-  {B_PRED,    INTRA_FRAME,  0},
-  {I8X8_PRED, INTRA_FRAME,  0},
+  {B_PRED,    INTRA_FRAME,  NONE},
+  {I8X8_PRED, INTRA_FRAME,  NONE},
 
   /* compound prediction modes */
   {ZEROMV,    LAST_FRAME,   GOLDEN_FRAME},
@@ -206,7 +224,25 @@
 
   {SPLITMV,   LAST_FRAME,   GOLDEN_FRAME},
   {SPLITMV,   ALTREF_FRAME, LAST_FRAME  },
-  {SPLITMV,   GOLDEN_FRAME, ALTREF_FRAME}
+  {SPLITMV,   GOLDEN_FRAME, ALTREF_FRAME},
+
+#if CONFIG_COMP_INTERINTRA_PRED
+  /* compound inter-intra prediction */
+  {ZEROMV,    LAST_FRAME,   INTRA_FRAME},
+  {NEARESTMV, LAST_FRAME,   INTRA_FRAME},
+  {NEARMV,    LAST_FRAME,   INTRA_FRAME},
+  {NEWMV,     LAST_FRAME,   INTRA_FRAME},
+
+  {ZEROMV,    GOLDEN_FRAME,   INTRA_FRAME},
+  {NEARESTMV, GOLDEN_FRAME,   INTRA_FRAME},
+  {NEARMV,    GOLDEN_FRAME,   INTRA_FRAME},
+  {NEWMV,     GOLDEN_FRAME,   INTRA_FRAME},
+
+  {ZEROMV,    ALTREF_FRAME,   INTRA_FRAME},
+  {NEARESTMV, ALTREF_FRAME,   INTRA_FRAME},
+  {NEARMV,    ALTREF_FRAME,   INTRA_FRAME},
+  {NEWMV,     ALTREF_FRAME,   INTRA_FRAME},
+#endif
 };
 #endif
 
@@ -1960,7 +1996,7 @@
       // is when we are on a new label  (jbb May 08, 2007)
       switch (m = this_mode) {
         case NEW4X4 :
-          if (mbmi->second_ref_frame) {
+          if (mbmi->second_ref_frame > 0) {
             this_mv->as_int = seg_mvs[mbmi->ref_frame - 1].as_int;
             this_second_mv->as_int =
               seg_mvs[mbmi->second_ref_frame - 1].as_int;
@@ -1968,7 +2004,7 @@
 
           thismvcost  = vp9_mv_bit_cost(this_mv, best_ref_mv, mvjcost, mvcost,
                                         102, xd->allow_high_precision_mv);
-          if (mbmi->second_ref_frame) {
+          if (mbmi->second_ref_frame > 0) {
             thismvcost += vp9_mv_bit_cost(this_second_mv, second_best_ref_mv,
                                           mvjcost, mvcost, 102,
                                           xd->allow_high_precision_mv);
@@ -1976,17 +2012,17 @@
           break;
         case LEFT4X4:
           this_mv->as_int = col ? d[-1].bmi.as_mv.first.as_int : left_block_mv(mic, i);
-          if (mbmi->second_ref_frame)
+          if (mbmi->second_ref_frame > 0)
             this_second_mv->as_int = col ? d[-1].bmi.as_mv.second.as_int : left_block_second_mv(mic, i);
           break;
         case ABOVE4X4:
           this_mv->as_int = row ? d[-4].bmi.as_mv.first.as_int : above_block_mv(mic, i, mis);
-          if (mbmi->second_ref_frame)
+          if (mbmi->second_ref_frame > 0)
             this_second_mv->as_int = row ? d[-4].bmi.as_mv.second.as_int : above_block_second_mv(mic, i, mis);
           break;
         case ZERO4X4:
           this_mv->as_int = 0;
-          if (mbmi->second_ref_frame)
+          if (mbmi->second_ref_frame > 0)
             this_second_mv->as_int = 0;
           break;
         default:
@@ -1999,12 +2035,12 @@
         left_second_mv.as_int = 0;
         left_mv.as_int = col ? d[-1].bmi.as_mv.first.as_int :
                          left_block_mv(mic, i);
-        if (mbmi->second_ref_frame)
+        if (mbmi->second_ref_frame > 0)
           left_second_mv.as_int = col ? d[-1].bmi.as_mv.second.as_int :
                                   left_block_second_mv(mic, i);
 
         if (left_mv.as_int == this_mv->as_int &&
-            (!mbmi->second_ref_frame ||
+            (mbmi->second_ref_frame <= 0 ||
              left_second_mv.as_int == this_second_mv->as_int))
           m = LEFT4X4;
       }
@@ -2018,12 +2054,12 @@
     }
 
     d->bmi.as_mv.first.as_int = this_mv->as_int;
-    if (mbmi->second_ref_frame)
+    if (mbmi->second_ref_frame > 0)
       d->bmi.as_mv.second.as_int = this_second_mv->as_int;
 
     x->partition_info->bmi[i].mode = m;
     x->partition_info->bmi[i].mv.as_int = this_mv->as_int;
-    if (mbmi->second_ref_frame)
+    if (mbmi->second_ref_frame > 0)
       x->partition_info->bmi[i].second_mv.as_int = this_second_mv->as_int;
   }
 
@@ -2051,7 +2087,7 @@
       int thisdistortion;
 
       vp9_build_inter_predictors_b(bd, 16, xd->subpixel_predict);
-      if (xd->mode_info_context->mbmi.second_ref_frame)
+      if (xd->mode_info_context->mbmi.second_ref_frame > 0)
         vp9_build_2nd_inter_predictors_b(bd, 16, xd->subpixel_predict_avg);
       vp9_subtract_b(be, bd, 16);
       x->vp9_short_fdct4x4(be->src_diff, be->coeff, 32);
@@ -2101,7 +2137,7 @@
       int thisdistortion;
 
       vp9_build_inter_predictors4b(xd, bd, 16);
-      if (xd->mode_info_context->mbmi.second_ref_frame)
+      if (xd->mode_info_context->mbmi.second_ref_frame > 0)
         vp9_build_2nd_inter_predictors4b(xd, bd, 16);
       vp9_subtract_4b_c(be, bd, 16);
 
@@ -2282,7 +2318,7 @@
       tl_s = (ENTROPY_CONTEXT *)&t_left_s;
 
       // motion search for newmv (single predictor case only)
-      if (!mbmi->second_ref_frame && this_mode == NEW4X4) {
+      if (mbmi->second_ref_frame <= 0 && this_mode == NEW4X4) {
         int sseshift, n;
         int step_param = 0;
         int further_steps;
@@ -2368,8 +2404,8 @@
           // safe motion search result for use in compound prediction
           seg_mvs[i][mbmi->ref_frame - 1].as_int = mode_mv[NEW4X4].as_int;
         }
-      } /* NEW4X4 */
-      else if (mbmi->second_ref_frame && this_mode == NEW4X4) {
+      } else if (mbmi->second_ref_frame > 0 && this_mode == NEW4X4) {
+        /* NEW4X4 */
         /* motion search not completed? Then skip newmv for this block with
          * comppred */
         if (seg_mvs[i][mbmi->second_ref_frame - 1].as_int == INVALID_MV ||
@@ -2390,7 +2426,7 @@
           ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) {
         continue;
       }
-      if (mbmi->second_ref_frame &&
+      if (mbmi->second_ref_frame > 0 &&
           mv_check_bounds(x, &second_mode_mv[this_mode]))
         continue;
 
@@ -2463,7 +2499,7 @@
     // store everything needed to come back to this!!
     for (i = 0; i < 16; i++) {
       bsi->mvs[i].as_mv = x->partition_info->bmi[i].mv.as_mv;
-      if (mbmi->second_ref_frame)
+      if (mbmi->second_ref_frame > 0)
         bsi->second_mvs[i].as_mv = x->partition_info->bmi[i].second_mv.as_mv;
       bsi->modes[i] = x->partition_info->bmi[i].mode;
       bsi->eobs[i] = best_eobs[i];
@@ -2694,7 +2730,7 @@
     BLOCKD *bd = &x->e_mbd.block[i];
 
     bd->bmi.as_mv.first.as_int = bsi.mvs[i].as_int;
-    if (mbmi->second_ref_frame)
+    if (mbmi->second_ref_frame > 0)
       bd->bmi.as_mv.second.as_int = bsi.second_mvs[i].as_int;
     bd->eob = bsi.eobs[i];
   }
@@ -2718,7 +2754,7 @@
 
     x->partition_info->bmi[i].mode = bsi.modes[j];
     x->partition_info->bmi[i].mv.as_mv = bsi.mvs[j].as_mv;
-    if (mbmi->second_ref_frame)
+    if (mbmi->second_ref_frame > 0)
       x->partition_info->bmi[i].second_mv.as_mv = bsi.second_mvs[j].as_mv;
   }
   /*
@@ -2725,7 +2761,7 @@
    * used to set mbmi->mv.as_int
    */
   x->partition_info->bmi[15].mv.as_int = bsi.mvs[15].as_int;
-  if (mbmi->second_ref_frame)
+  if (mbmi->second_ref_frame > 0)
     x->partition_info->bmi[15].second_mv.as_int = bsi.second_mvs[15].as_int;
 
   return (int)(bsi.segment_rd);
@@ -3165,7 +3201,7 @@
   memcpy(ctx->txfm_rd_diff, txfm_size_diff, sizeof(ctx->txfm_rd_diff));
 }
 
-static void inter_mode_cost(VP9_COMP *cpi, MACROBLOCK *x, int this_mode,
+static void inter_mode_cost(VP9_COMP *cpi, MACROBLOCK *x,
                             int *rate2, int *distortion2, int *rate_y,
                             int *distortion, int* rate_uv, int *distortion_uv,
                             int *skippable, int64_t txfm_cache[NB_TXFM_MODES]) {
@@ -3232,6 +3268,9 @@
                                  int mdcounts[4], int64_t txfm_cache[],
                                  int *rate2, int *distortion, int *skippable,
                                  int *compmode_cost,
+#if CONFIG_COMP_INTERINTRA_PRED
+                                 int *compmode_interintra_cost,
+#endif
                                  int *rate_y, int *distortion_y,
                                  int *rate_uv, int *distortion_uv,
                                  int *mode_excluded, int *disable_skip,
@@ -3243,11 +3282,15 @@
   MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
   BLOCK *b = &x->block[0];
   BLOCKD *d = &xd->block[0];
-  const int is_comp_pred = (mbmi->second_ref_frame != 0);
+  const int is_comp_pred = (mbmi->second_ref_frame > 0);
+#if CONFIG_COMP_INTERINTRA_PRED
+  const int is_comp_interintra_pred = (mbmi->second_ref_frame == INTRA_FRAME);
+#endif
   const int num_refs = is_comp_pred ? 2 : 1;
   const int this_mode = mbmi->mode;
   int i;
-  int refs[2] = { mbmi->ref_frame, mbmi->second_ref_frame };
+  int refs[2] = { mbmi->ref_frame,
+                  (mbmi->second_ref_frame < 0 ? 0 : mbmi->second_ref_frame) };
   int_mv cur_mv[2];
   int_mv mvp;
   int64_t this_rd = 0;
@@ -3368,11 +3411,30 @@
                                 is_comp_pred);
   *rate2 += vp9_cost_mv_ref(cpi, this_mode,
                             mbmi->mb_mode_context[mbmi->ref_frame]);
+#if CONFIG_COMP_INTERINTRA_PRED
+  if (!is_comp_pred) {
+    *compmode_interintra_cost = vp9_cost_bit(cm->fc.interintra_prob,
+                                             is_comp_interintra_pred);
+    if (is_comp_interintra_pred) {
+      *compmode_interintra_cost +=
+          x->mbmode_cost[xd->frame_type][mbmi->interintra_mode];
+#if SEPARATE_INTERINTRA_UV
+      *compmode_interintra_cost +=
+          x->intra_uv_mode_cost[xd->frame_type][mbmi->interintra_uv_mode];
+#endif
+    }
+  }
+#endif
 
   if (block_size == BLOCK_16X16) {
     vp9_build_1st_inter16x16_predictors_mby(xd, xd->predictor, 16, 0);
     if (is_comp_pred)
       vp9_build_2nd_inter16x16_predictors_mby(xd, xd->predictor, 16);
+#if CONFIG_COMP_INTERINTRA_PRED
+    if (is_comp_interintra_pred) {
+      vp9_build_interintra_16x16_predictors_mby(xd, xd->predictor, 16);
+    }
+#endif
   } else {
 #if CONFIG_SUPERBLOCKS
     vp9_build_inter32x32_predictors_sb(xd,
@@ -3440,6 +3502,15 @@
     }
   }
 
+  if (is_comp_pred) {
+    *mode_excluded = (cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY);
+  } else {
+    *mode_excluded = (cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY);
+  }
+#if CONFIG_COMP_INTERINTRA_PRED
+  if (is_comp_interintra_pred && !cm->use_interintra) *mode_excluded = 1;
+#endif
+
   if (!x->skip) {
     if (block_size == BLOCK_16X16) {
       vp9_build_1st_inter16x16_predictors_mbuv(xd, &xd->predictor[256],
@@ -3447,7 +3518,13 @@
       if (is_comp_pred)
         vp9_build_2nd_inter16x16_predictors_mbuv(xd, &xd->predictor[256],
                                                  &xd->predictor[320], 8);
-      inter_mode_cost(cpi, x, this_mode, rate2, distortion,
+#if CONFIG_COMP_INTERINTRA_PRED
+      if (is_comp_interintra_pred) {
+        vp9_build_interintra_16x16_predictors_mbuv(xd, &xd->predictor[256],
+                                                   &xd->predictor[320], 8);
+      }
+#endif
+      inter_mode_cost(cpi, x, rate2, distortion,
                       rate_y, distortion_y, rate_uv, distortion_uv,
                       skippable, txfm_cache);
     } else {
@@ -3469,12 +3546,6 @@
 #endif
     }
   }
-  if (is_comp_pred) {
-    *mode_excluded = (cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY);
-  } else {
-    *mode_excluded = (cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY);
-  }
-
   return this_rd;  // if 0, this will be re-calculated by caller
 }
 
@@ -3503,9 +3574,12 @@
   int64_t best_pred_diff[NB_PREDICTION_TYPES];
   int64_t best_pred_rd[NB_PREDICTION_TYPES];
   int64_t best_rd = INT64_MAX, best_intra_rd = INT64_MAX;
-#if CONFIG_PRED_FILTER
-  int64_t best_overall_rd = INT64_MAX;
+#if CONFIG_COMP_INTERINTRA_PRED
+  int is_best_interintra = 0;
+  int64_t best_intra16_rd = INT64_MAX;
+  int best_intra16_mode = DC_PRED, best_intra16_uv_mode = DC_PRED;
 #endif
+  int64_t best_overall_rd = INT64_MAX;
   int uv_intra_rate, uv_intra_distortion, uv_intra_rate_tokenonly;
   int uv_intra_skippable = 0;
   int uv_intra_rate_8x8 = 0, uv_intra_distortion_8x8 = 0, uv_intra_rate_tokenonly_8x8 = 0;
@@ -3608,6 +3682,9 @@
     int disable_skip = 0, skippable = 0;
     int other_cost = 0;
     int compmode_cost = 0;
+#if CONFIG_COMP_INTERINTRA_PRED
+    int compmode_interintra_cost = 0;
+#endif
     int mode_excluded = 0;
     int64_t txfm_cache[NB_TXFM_MODES] = { 0 };
 
@@ -3645,6 +3722,10 @@
     mbmi->second_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
     mbmi->second_uv_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
 #endif
+#if CONFIG_COMP_INTERINTRA_PRED
+    mbmi->interintra_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
+    mbmi->interintra_uv_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
+#endif
 
     // If the segment reference frame feature is enabled....
     // then do nothing if the current ref frame is not allowed..
@@ -3684,7 +3765,7 @@
       vpx_memcpy(mdcounts, frame_mdcounts[ref], sizeof(mdcounts));
     }
 
-    if (mbmi->second_ref_frame) {
+    if (mbmi->second_ref_frame > 0) {
       int ref = mbmi->second_ref_frame;
 
       xd->second_pre.y_buffer = y_buffer[ref];
@@ -3872,7 +3953,7 @@
     // Split MV. The code is very different from the other inter modes so
     // special case it.
     else if (this_mode == SPLITMV) {
-      const int is_comp_pred = mbmi->second_ref_frame != 0;
+      const int is_comp_pred = mbmi->second_ref_frame > 0;
       int64_t tmp_rd, this_rd_thresh;
       int_mv *second_ref = is_comp_pred ? &second_best_ref_mv : NULL;
 
@@ -3921,10 +4002,25 @@
       mbmi->mode = this_mode;
     }
     else {
+#if CONFIG_COMP_INTERINTRA_PRED
+      if (mbmi->second_ref_frame == INTRA_FRAME) {
+        if (best_intra16_mode == DC_PRED - 1) continue;
+        mbmi->interintra_mode = best_intra16_mode;
+#if SEPARATE_INTERINTRA_UV
+        mbmi->interintra_uv_mode = best_intra16_uv_mode;
+#else
+        mbmi->interintra_uv_mode = best_intra16_mode;
+#endif
+      }
+#endif
       this_rd = handle_inter_mode(cpi, x, BLOCK_16X16,
                                   &saddone, near_sadidx, mdcounts, txfm_cache,
                                   &rate2, &distortion2, &skippable,
-                                  &compmode_cost, &rate_y, &distortion,
+                                  &compmode_cost,
+#if CONFIG_COMP_INTERINTRA_PRED
+                                  &compmode_interintra_cost,
+#endif
+                                  &rate_y, &distortion,
                                   &rate_uv, &distortion_uv,
                                   &mode_excluded, &disable_skip, recon_yoffset,
                                   mode_index, frame_mv, frame_best_ref_mv);
@@ -3932,6 +4028,11 @@
         continue;
     }
 
+#if CONFIG_COMP_INTERINTRA_PRED
+    if (cpi->common.use_interintra)
+      rate2 += compmode_interintra_cost;
+#endif
+
     if (cpi->common.comp_pred_mode == HYBRID_PREDICTION)
       rate2 += compmode_cost;
 
@@ -3996,18 +4097,33 @@
       best_intra_rd = this_rd;
       *returnintra = distortion2;
     }
+#if CONFIG_COMP_INTERINTRA_PRED
+    if ((mbmi->ref_frame == INTRA_FRAME) &&
+        (this_mode >= DC_PRED && this_mode <= TM_PRED) &&
+        (this_rd < best_intra16_rd)) {
+      best_intra16_rd = this_rd;
+      best_intra16_mode = this_mode;
+      best_intra16_uv_mode = (mbmi->txfm_size != TX_4X4 ?
+                              uv_intra_mode_8x8 : uv_intra_mode);
+    }
+#endif
 
+
     if (!disable_skip && mbmi->ref_frame == INTRA_FRAME)
       for (i = 0; i < NB_PREDICTION_TYPES; ++i)
         best_pred_rd[i] = MIN(best_pred_rd[i], this_rd);
 
-#if CONFIG_PRED_FILTER
-    // Keep track of the best mode irrespective of prediction filter state
     if (this_rd < best_overall_rd) {
       best_overall_rd = this_rd;
+#if CONFIG_PRED_FILTER
       best_filter_state = mbmi->pred_filter_enabled;
+#endif
+#if CONFIG_COMP_INTERINTRA_PRED
+      is_best_interintra = (mbmi->second_ref_frame == INTRA_FRAME);
+#endif
     }
 
+#if CONFIG_PRED_FILTER
     // Ignore modes where the prediction filter state doesn't
     // match the state signaled at the frame level
     if ((cm->pred_filter_mode == 2) ||
@@ -4017,6 +4133,11 @@
       // Did this mode help.. i.e. is it the new best mode
       if (this_rd < best_rd || x->skip) {
         if (!mode_excluded) {
+          /*
+          if (mbmi->second_ref_frame == INTRA_FRAME) {
+            printf("rd %d best %d bestintra16 %d\n", this_rd, best_rd, best_intra16_rd);
+          }
+          */
           // Note index of best mode so far
           best_mode_index = mode_index;
 
@@ -4087,10 +4208,10 @@
         single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2);
         hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2);
 
-        if (mbmi->second_ref_frame == INTRA_FRAME &&
+        if (mbmi->second_ref_frame <= INTRA_FRAME &&
             single_rd < best_pred_rd[SINGLE_PREDICTION_ONLY]) {
           best_pred_rd[SINGLE_PREDICTION_ONLY] = single_rd;
-        } else if (mbmi->second_ref_frame != INTRA_FRAME &&
+        } else if (mbmi->second_ref_frame > INTRA_FRAME &&
                    single_rd < best_pred_rd[COMP_PREDICTION_ONLY]) {
           best_pred_rd[COMP_PREDICTION_ONLY] = single_rd;
         }
@@ -4128,6 +4249,9 @@
   else
     ++cpi->pred_filter_off_count;
 #endif
+#if CONFIG_COMP_INTERINTRA_PRED
+  ++cpi->interintra_select_count[is_best_interintra];
+#endif
   if (cpi->common.mcomp_filter_type == SWITCHABLE &&
       best_mbmode.mode >= NEARESTMV &&
       best_mbmode.mode <= SPLITMV) {
@@ -4191,7 +4315,7 @@
   if (best_mbmode.mode == SPLITMV) {
     for (i = 0; i < 16; i++)
       xd->mode_info_context->bmi[i].as_mv.first.as_int = best_bmodes[i].as_mv.first.as_int;
-    if (mbmi->second_ref_frame)
+    if (mbmi->second_ref_frame > 0)
       for (i = 0; i < 16; i++)
         xd->mode_info_context->bmi[i].as_mv.second.as_int = best_bmodes[i].as_mv.second.as_int;
 
@@ -4220,10 +4344,12 @@
   }
 
 end:
-  store_coding_context(x, &x->mb_context[xd->mb_index], best_mode_index,
-                       &best_partition, &frame_best_ref_mv[mbmi->ref_frame],
-                       &frame_best_ref_mv[mbmi->second_ref_frame],
-                       best_pred_diff, best_txfm_diff);
+  store_coding_context(
+      x, &x->mb_context[xd->mb_index], best_mode_index, &best_partition,
+      &frame_best_ref_mv[xd->mode_info_context->mbmi.ref_frame],
+      &frame_best_ref_mv[xd->mode_info_context->mbmi.second_ref_frame < 0 ?
+                         0 : xd->mode_info_context->mbmi.second_ref_frame],
+      best_pred_diff, best_txfm_diff);
 }
 
 #if CONFIG_SUPERBLOCKS
@@ -4448,6 +4574,11 @@
   MB_MODE_INFO best_mbmode;
   int mode_index, best_mode_index;
   unsigned int ref_costs[MAX_REF_FRAMES];
+#if CONFIG_COMP_INTERINTRA_PRED
+  int is_best_interintra = 0;
+  int64_t best_intra16_rd = INT64_MAX;
+  int best_intra16_mode = DC_PRED, best_intra16_uv_mode = DC_PRED;
+#endif
 
   x->skip = 0;
   xd->mode_info_context->mbmi.segment_id = segment_id;
@@ -4480,6 +4611,9 @@
     int distortion2 = 0, distortion_y = 0, distortion_uv = 0;
     int skippable;
     int64_t txfm_cache[NB_TXFM_MODES];
+#if CONFIG_COMP_INTERINTRA_PRED
+    int compmode_interintra_cost = 0;
+#endif
 
     // Test best rd so far against threshold for trying this mode.
     if (best_rd <= cpi->rd_threshes[mode_index]) {
@@ -4489,7 +4623,7 @@
     this_mode = vp9_mode_order[mode_index].mode;
     ref_frame = vp9_mode_order[mode_index].ref_frame;
     mbmi->ref_frame = ref_frame;
-    comp_pred = vp9_mode_order[mode_index].second_ref_frame != INTRA_FRAME;
+    comp_pred = vp9_mode_order[mode_index].second_ref_frame > INTRA_FRAME;
     mbmi->mode = this_mode;
     mbmi->uv_mode = DC_PRED;
 #if CONFIG_COMP_INTRA_PRED
@@ -4502,7 +4636,8 @@
 
     // not yet supported or not superblocky
     // TODO(rbultje): support intra coding
-    if (ref_frame == INTRA_FRAME || this_mode == SPLITMV)
+    if (ref_frame == INTRA_FRAME || this_mode == SPLITMV ||
+        vp9_mode_order[mode_index].second_ref_frame == INTRA_FRAME)
       continue;
 
     if (comp_pred) {
@@ -4522,7 +4657,7 @@
       xd->second_pre.v_buffer = v_buffer[second_ref];
       mode_excluded = cm->comp_pred_mode == SINGLE_PREDICTION_ONLY;
     } else {
-      mbmi->second_ref_frame = INTRA_FRAME;
+      mbmi->second_ref_frame = NONE;
       mode_excluded = cm->comp_pred_mode == COMP_PREDICTION_ONLY;
     }
 
@@ -4559,7 +4694,11 @@
     this_rd = handle_inter_mode(cpi, x, BLOCK_32X32,
                                 &saddone, near_sadidx, mdcounts, txfm_cache,
                                 &rate2, &distortion2, &skippable,
-                                &compmode_cost, &rate_y, &distortion_y,
+                                &compmode_cost,
+#if CONFIG_COMP_INTERINTRA_PRED
+                                &compmode_interintra_cost,
+#endif
+                                &rate_y, &distortion_y,
                                 &rate_uv, &distortion_uv,
                                 &mode_excluded, &disable_skip, recon_yoffset,
                                 mode_index, frame_mv, frame_best_ref_mv);
@@ -4691,10 +4830,10 @@
       single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2);
       hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2);
 
-      if (mbmi->second_ref_frame == INTRA_FRAME &&
+      if (mbmi->second_ref_frame <= INTRA_FRAME &&
           single_rd < best_pred_rd[SINGLE_PREDICTION_ONLY]) {
         best_pred_rd[SINGLE_PREDICTION_ONLY] = single_rd;
-      } else if (mbmi->second_ref_frame != INTRA_FRAME &&
+      } else if (mbmi->second_ref_frame > INTRA_FRAME &&
                  single_rd < best_pred_rd[COMP_PREDICTION_ONLY]) {
         best_pred_rd[COMP_PREDICTION_ONLY] = single_rd;
       }
@@ -4746,7 +4885,7 @@
       (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME)) {
     mbmi->mode = ZEROMV;
     mbmi->ref_frame = ALTREF_FRAME;
-    mbmi->second_ref_frame = 0;
+    mbmi->second_ref_frame = INTRA_FRAME;
     mbmi->mv[0].as_int = 0;
     mbmi->uv_mode = DC_PRED;
     mbmi->mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0;
@@ -4783,7 +4922,8 @@
  end:
   store_coding_context(x, &x->sb_context[0], best_mode_index, NULL,
                        &frame_best_ref_mv[mbmi->ref_frame],
-                       &frame_best_ref_mv[mbmi->second_ref_frame],
+                       &frame_best_ref_mv[mbmi->second_ref_frame < 0 ?
+                                          0 : mbmi->second_ref_frame],
                        best_pred_diff, best_txfm_diff);
 
   return best_rd;