]> granicus.if.org Git - libvpx/commitdiff
Migrating old experiments into new playground branch and speedup
authorYue Chen <yuec@google.com>
Fri, 20 Jun 2014 00:09:47 +0000 (17:09 -0700)
committerYue Chen <yuec@google.com>
Thu, 26 Jun 2014 21:22:53 +0000 (14:22 -0700)
The old interintra experiment is slow (speed is 0.2x original codec
at speed 0).
We use best inter mode to skip some reference frame and NEWMV
search when searching best joint mode.
Quality drop: ~0.1% derf. Speed: 0.36x head.

Change-Id: If10453448284f86c14a0a41f20aeaf9ac838fa32

27 files changed:
configure
vp9/common/vp9_blockd.h
vp9/common/vp9_entropymode.c
vp9/common/vp9_entropymode.h
vp9/common/vp9_enums.h
vp9/common/vp9_onyxc_int.h
vp9/common/vp9_reconinter.c
vp9/common/vp9_reconinter.h
vp9/common/vp9_reconintra.c
vp9/common/vp9_reconintra.h
vp9/common/vp9_rtcd_defs.pl
vp9/decoder/vp9_decodeframe.c
vp9/decoder/vp9_decodemv.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_encodeframe.c
vp9/encoder/vp9_encodemb.c
vp9/encoder/vp9_encoder.c
vp9/encoder/vp9_encoder.h
vp9/encoder/vp9_mbgraph.c
vp9/encoder/vp9_mcomp.c
vp9/encoder/vp9_mcomp.h
vp9/encoder/vp9_pickmode.c
vp9/encoder/vp9_rdopt.c
vp9/encoder/vp9_rdopt.h
vp9/encoder/vp9_sad.c
vp9/encoder/vp9_variance.c
vp9/encoder/vp9_variance.h

index 9a7de73b181197126abf65a3664bf2a9500913d4..fe370a5c0e1dcc7c6844ec2cec8d31b15aa445fe 100755 (executable)
--- a/configure
+++ b/configure
@@ -273,6 +273,11 @@ EXPERIMENT_LIST="
     multiple_arf
     spatial_svc
     denoising
+    masked_interinter
+    interintra
+    masked_interintra
+    filterintra
+    ext_tx
 "
 CONFIG_LIST="
     external_build
index 9088b0bde2885eaf90a97b3230a84a11ee987d30..3636ac5c87deaf2118ecb0e6533510fa6793abf8 100644 (file)
@@ -118,11 +118,75 @@ static INLINE int mi_width_log2(BLOCK_SIZE sb_type) {
   return mi_width_log2_lookup[sb_type];
 }
 
+#if CONFIG_MASKED_INTERINTER
+#define MASK_BITS_SML   3
+#define MASK_BITS_MED   4
+#define MASK_BITS_BIG   5
+#define MASK_NONE      -1
+
+static inline int get_mask_bits(BLOCK_SIZE sb_type) {
+  if (sb_type < BLOCK_8X8)
+    return 0;
+  if (sb_type <= BLOCK_8X8)
+    return MASK_BITS_SML;
+  else if (sb_type <= BLOCK_32X32)
+    return MASK_BITS_MED;
+  else
+    return MASK_BITS_BIG;
+}
+#endif
+
+#if CONFIG_INTERINTRA
+static INLINE TX_SIZE intra_size_log2_for_interintra(int bs) {
+  switch (bs) {
+    case 4:
+      return TX_4X4;
+      break;
+    case 8:
+      return TX_8X8;
+      break;
+    case 16:
+      return TX_16X16;
+      break;
+    case 32:
+      return TX_32X32;
+      break;
+    default:
+      return TX_32X32;
+      break;
+  }
+}
+
+static INLINE int is_interintra_allowed(BLOCK_SIZE sb_type) {
+  return ((sb_type >= BLOCK_8X8) && (sb_type < BLOCK_64X64));
+}
+
+#if CONFIG_MASKED_INTERINTRA
+#define MASK_BITS_SML_INTERINTRA   3
+#define MASK_BITS_MED_INTERINTRA   4
+#define MASK_BITS_BIG_INTERINTRA   5
+#define MASK_NONE_INTERINTRA      -1
+static INLINE int get_mask_bits_interintra(BLOCK_SIZE sb_type) {
+  if (sb_type == BLOCK_4X4)
+     return 0;
+  if (sb_type <= BLOCK_8X8)
+    return MASK_BITS_SML_INTERINTRA;
+  else if (sb_type <= BLOCK_32X32)
+    return MASK_BITS_MED_INTERINTRA;
+  else
+    return MASK_BITS_BIG_INTERINTRA;
+}
+#endif
+#endif
+
 // This structure now relates to 8x8 block regions.
 typedef struct {
   // Common for both INTER and INTRA blocks
   BLOCK_SIZE sb_type;
   PREDICTION_MODE mode;
+#if CONFIG_FILTERINTRA
+  int filterbit, uv_filterbit;
+#endif
   TX_SIZE tx_size;
   uint8_t skip;
   uint8_t segment_id;
@@ -137,10 +201,30 @@ typedef struct {
   int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
   uint8_t mode_context[MAX_REF_FRAMES];
   INTERP_FILTER interp_filter;
+
+#if CONFIG_EXT_TX
+  EXT_TX_TYPE ext_txfrm;
+#endif
+
+#if CONFIG_MASKED_INTERINTER
+  int use_masked_interinter;
+  int mask_index;
+#endif
+#if CONFIG_INTERINTRA
+  PREDICTION_MODE interintra_mode, interintra_uv_mode;
+#if CONFIG_MASKED_INTERINTRA
+  int interintra_mask_index;
+  int interintra_uv_mask_index;
+  int use_masked_interintra;
+#endif
+#endif
 } MB_MODE_INFO;
 
 typedef struct {
   MB_MODE_INFO mbmi;
+#if CONFIG_FILTERINTRA
+  int b_filter_info[4];
+#endif
   b_mode_info bmi[4];
 } MODE_INFO;
 
@@ -149,6 +233,16 @@ static INLINE PREDICTION_MODE get_y_mode(const MODE_INFO *mi, int block) {
                                       : mi->mbmi.mode;
 }
 
+#if CONFIG_FILTERINTRA
+static INLINE int is_filter_allowed(PREDICTION_MODE mode) {
+  return 1;
+}
+
+static INLINE int is_filter_enabled(TX_SIZE txsize) {
+  return (txsize <= TX_32X32);
+}
+#endif
+
 static INLINE int is_inter_block(const MB_MODE_INFO *mbmi) {
   return mbmi->ref_frame[0] > INTRA_FRAME;
 }
@@ -253,8 +347,20 @@ static INLINE TX_TYPE get_tx_type(PLANE_TYPE plane_type,
                                   const MACROBLOCKD *xd) {
   const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
 
+#if !CONFIG_EXT_TX
   if (plane_type != PLANE_TYPE_Y || is_inter_block(mbmi))
     return DCT_DCT;
+#else
+  if (plane_type != PLANE_TYPE_Y)
+      return DCT_DCT;
+
+  if (is_inter_block(mbmi)) {
+    if (mbmi->ext_txfrm == NORM || mbmi->tx_size >= TX_32X32)
+      return DCT_DCT;
+    else
+      return ADST_ADST;
+  }
+#endif
   return intra_mode_to_tx_type_lookup[mbmi->mode];
 }
 
@@ -262,8 +368,20 @@ static INLINE TX_TYPE get_tx_type_4x4(PLANE_TYPE plane_type,
                                       const MACROBLOCKD *xd, int ib) {
   const MODE_INFO *const mi = xd->mi[0];
 
+#if !CONFIG_EXT_TX
   if (plane_type != PLANE_TYPE_Y || xd->lossless || is_inter_block(&mi->mbmi))
     return DCT_DCT;
+#else
+  if (plane_type != PLANE_TYPE_Y || xd->lossless)
+      return DCT_DCT;
+
+  if (is_inter_block(&mi->mbmi)) {
+    if (mi->mbmi.ext_txfrm == NORM)
+      return DCT_DCT;
+    else
+      return ADST_ADST;
+  }
+#endif
 
   return intra_mode_to_tx_type_lookup[get_y_mode(mi, ib)];
 }
index 5b00b0082a135b4dd508d571a2f3567a0cc81caa..b52be94ed4a01722ead1f15d86b3f0e2db82d552 100644 (file)
 #include "vp9/common/vp9_onyxc_int.h"
 #include "vp9/common/vp9_seg_common.h"
 
+#if CONFIG_MASKED_INTERINTER
+static const vp9_prob default_masked_interinter_prob[BLOCK_SIZES] = {
+    192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
+};
+#endif
+
+#if CONFIG_INTERINTRA
+static const vp9_prob default_interintra_prob[BLOCK_SIZES] = {
+  192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
+};
+#if CONFIG_MASKED_INTERINTRA
+static const vp9_prob default_masked_interintra_prob[BLOCK_SIZES] = {
+  192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
+};
+#endif
+#endif
+
+#if CONFIG_FILTERINTRA
+const vp9_prob default_filterintra_prob[TX_SIZES][INTRA_MODES] = {
+  // DC     V      H    D45   D135   D117   D153   D207    D63     TM
+  {153,   171,   147,   150,   129,   101,   100,   153,   132,   111},
+  {171,   173,   185,   131,    70,    53,    70,   148,   127,   114},
+  {175,   203,   213,    86,    45,    71,    41,   150,   125,   154},
+  {235,   230,   154,   202,   154,   205,    37,   128,     0,   202}
+};
+#endif
+
+#if CONFIG_EXT_TX
+const vp9_prob default_ext_tx_prob = 178;  // 0.6 = 153, 0.7 = 178, 0.8 = 204
+#endif
+
 const vp9_prob vp9_kf_y_mode_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1] = {
   {  // above = dc
     { 137,  30,  42, 148, 151, 207,  70,  52,  91 },  // left = dc
@@ -326,6 +357,21 @@ void vp9_init_mode_probs(FRAME_CONTEXT *fc) {
   fc->tx_probs = default_tx_probs;
   vp9_copy(fc->skip_probs, default_skip_probs);
   vp9_copy(fc->inter_mode_probs, default_inter_mode_probs);
+#if CONFIG_MASKED_INTERINTER
+  vp9_copy(fc->masked_interinter_prob, default_masked_interinter_prob);
+#endif
+#if CONFIG_INTERINTRA
+  vp9_copy(fc->interintra_prob, default_interintra_prob);
+#if CONFIG_MASKED_INTERINTRA
+  vp9_copy(fc->masked_interintra_prob, default_masked_interintra_prob);
+#endif
+#endif
+#if CONFIG_FILTERINTRA
+  vp9_copy(fc->filterintra_prob, default_filterintra_prob);
+#endif
+#if CONFIG_EXT_TX
+  fc->ext_tx_prob = default_ext_tx_prob;
+#endif
 }
 
 const vp9_tree_index vp9_switchable_interp_tree
@@ -416,6 +462,48 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) {
 
   for (i = 0; i < SKIP_CONTEXTS; ++i)
     fc->skip_probs[i] = adapt_prob(pre_fc->skip_probs[i], counts->skip[i]);
+
+#if CONFIG_MASKED_INTERINTER
+  if (cm->use_masked_interinter) {
+    for (i = 0; i < BLOCK_SIZES; ++i) {
+      if (get_mask_bits(i))
+        fc->masked_interinter_prob[i] = adapt_prob
+                                      (pre_fc->masked_interinter_prob[i],
+                                       counts->masked_interinter[i]);
+    }
+  }
+#endif
+
+#if CONFIG_INTERINTRA
+  if (cm->use_interintra) {
+    for (i = 0; i < BLOCK_SIZES; ++i) {
+      if (is_interintra_allowed(i))
+        fc->interintra_prob[i] = adapt_prob(pre_fc->interintra_prob[i],
+                                            counts->interintra[i]);
+    }
+#if CONFIG_MASKED_INTERINTRA
+    if (cm->use_masked_interintra) {
+      for (i = 0; i < BLOCK_SIZES; ++i) {
+        if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
+          fc->masked_interintra_prob[i] = adapt_prob(
+                                          pre_fc->masked_interintra_prob[i],
+                                          counts->masked_interintra[i]);
+      }
+    }
+#endif
+  }
+#endif
+
+#if CONFIG_FILTERINTRA
+  for (i = 0; i < TX_SIZES; ++i)
+    for (j = 0; j < INTRA_MODES; ++j)
+      fc->filterintra_prob[i][j] = adapt_prob(pre_fc->filterintra_prob[i][j],
+                                   counts->filterintra[i][j]);
+#endif
+
+#if CONFIG_EXT_TX
+  fc->ext_tx_prob = adapt_prob(pre_fc->ext_tx_prob, counts->ext_tx);
+#endif
 }
 
 static void set_default_lf_deltas(struct loopfilter *lf) {
index 533757bef031b7075ed1f3d1f97f229533135d10..b8b0d4b84c381950bfe60aa842a46f3701547cf2 100644 (file)
@@ -52,6 +52,21 @@ typedef struct frame_contexts {
   struct tx_probs tx_probs;
   vp9_prob skip_probs[SKIP_CONTEXTS];
   nmv_context nmvc;
+#if CONFIG_MASKED_INTERINTER
+  vp9_prob masked_interinter_prob[BLOCK_SIZES];
+#endif
+#if CONFIG_INTERINTRA
+  vp9_prob interintra_prob[BLOCK_SIZES];
+#if CONFIG_MASKED_INTERINTRA
+  vp9_prob masked_interintra_prob[BLOCK_SIZES];
+#endif
+#endif
+#if CONFIG_FILTERINTRA
+  vp9_prob filterintra_prob[TX_SIZES][INTRA_MODES];
+#endif
+#if CONFIG_EXT_TX
+  vp9_prob ext_tx_prob;
+#endif
 } FRAME_CONTEXT;
 
 typedef struct {
@@ -71,6 +86,21 @@ typedef struct {
   struct tx_counts tx;
   unsigned int skip[SKIP_CONTEXTS][2];
   nmv_context_counts mv;
+#if CONFIG_MASKED_INTERINTER
+  unsigned int masked_interinter[BLOCK_SIZES][2];
+#endif
+#if CONFIG_INTERINTRA
+  unsigned int interintra[BLOCK_SIZES][2];
+#if CONFIG_MASKED_INTERINTRA
+  unsigned int masked_interintra[BLOCK_SIZES][2];
+#endif
+#endif
+#if CONFIG_FILTERINTRA
+  unsigned int filterintra[TX_SIZES][INTRA_MODES][2];
+#endif
+#if CONFIG_EXT_TX
+  unsigned int ext_tx[2];
+#endif
 } FRAME_COUNTS;
 
 extern const vp9_prob vp9_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1];
index 068284faa90521c271f5eb1b859996d436a2965c..7a83880ba71be1ec66e535e04fa6d71e8cdbebf1 100644 (file)
@@ -100,6 +100,14 @@ typedef enum {
   TX_TYPES = 4
 } TX_TYPE;
 
+#if CONFIG_EXT_TX
+typedef enum {
+  NORM   = 0,
+  ALT = 1,
+  EXT_TX_TYPES = 2
+} EXT_TX_TYPE;
+#endif
+
 typedef enum {
   UNKNOWN    = 0,
   BT_601     = 1,  // YUV
index e1753a11b9c2c454322fe47430fd26046824ae0a..69bb83d8226b9523f2c1528528d5e177b58ba113 100644 (file)
@@ -212,6 +212,16 @@ typedef struct VP9Common {
 
   PARTITION_CONTEXT *above_seg_context;
   ENTROPY_CONTEXT *above_context;
+
+#if CONFIG_MASKED_INTERINTER
+  int use_masked_interinter;
+#endif
+#if CONFIG_INTERINTRA
+  int use_interintra;
+#if CONFIG_MASKED_INTERINTRA
+  int use_masked_interintra;
+#endif
+#endif
 } VP9_COMMON;
 
 static INLINE YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
index edc36d7805e7cc16bc2e9ebc5d2c02861ca5d593..e2b8768c3532bca70ede3ab12d4be475c66069a9 100644 (file)
@@ -139,6 +139,302 @@ MV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd, const MV *src_mv,
   return clamped_mv;
 }
 
+#if CONFIG_MASKED_INTERINTER
+#define MASK_WEIGHT_BITS 6
+
+static int get_masked_weight(int m) {
+  #define SMOOTHER_LEN  32
+  static const uint8_t smoothfn[2 * SMOOTHER_LEN + 1] = {
+      0,  0,  0,  0,  0,  0,  0,  0,
+      0,  0,  0,  0,  0,  1,  1,  1,
+      1,  1,  2,  2,  3,  4,  5,  6,
+      8,  9, 12, 14, 17, 21, 24, 28,
+      32,
+      36, 40, 43, 47, 50, 52, 55, 56,
+      58, 59, 60, 61, 62, 62, 63, 63,
+      63, 63, 63, 64, 64, 64, 64, 64,
+      64, 64, 64, 64, 64, 64, 64, 64,
+  };
+  if (m < -SMOOTHER_LEN)
+    return 0;
+  else if (m > SMOOTHER_LEN)
+    return (1 << MASK_WEIGHT_BITS);
+  else
+    return smoothfn[m + SMOOTHER_LEN];
+}
+
+static int get_hard_mask(int m) {
+  return m > 0;
+}
+
+// Equation of line: f(x, y) = a[0]*(x - a[2]*w/4) + a[1]*(y - a[3]*h/4) = 0
+// The soft mask is obtained by computing f(x, y) and then calling
+// get_masked_weight(f(x, y)).
+static const int mask_params_sml[1 << MASK_BITS_SML][4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+};
+
+static const int mask_params_med_hgtw[1 << MASK_BITS_MED][4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-1,  2, 2, 1},
+  { 1, -2, 2, 1},
+  {-1,  2, 2, 3},
+  { 1, -2, 2, 3},
+  { 1,  2, 2, 1},
+  {-1, -2, 2, 1},
+  { 1,  2, 2, 3},
+  {-1, -2, 2, 3},
+};
+
+static const int mask_params_med_hltw[1 << MASK_BITS_MED][4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-2,  1, 1, 2},
+  { 2, -1, 1, 2},
+  {-2,  1, 3, 2},
+  { 2, -1, 3, 2},
+  { 2,  1, 1, 2},
+  {-2, -1, 1, 2},
+  { 2,  1, 3, 2},
+  {-2, -1, 3, 2},
+};
+
+static const int mask_params_med_heqw[1 << MASK_BITS_MED][4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  { 0,  2, 0, 1},
+  { 0, -2, 0, 1},
+  { 0,  2, 0, 3},
+  { 0, -2, 0, 3},
+  { 2,  0, 1, 0},
+  {-2,  0, 1, 0},
+  { 2,  0, 3, 0},
+  {-2,  0, 3, 0},
+};
+
+static const int mask_params_big_hgtw[1 << MASK_BITS_BIG][4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-1,  2, 2, 1},
+  { 1, -2, 2, 1},
+  {-1,  2, 2, 3},
+  { 1, -2, 2, 3},
+  { 1,  2, 2, 1},
+  {-1, -2, 2, 1},
+  { 1,  2, 2, 3},
+  {-1, -2, 2, 3},
+
+  {-2,  1, 1, 2},
+  { 2, -1, 1, 2},
+  {-2,  1, 3, 2},
+  { 2, -1, 3, 2},
+  { 2,  1, 1, 2},
+  {-2, -1, 1, 2},
+  { 2,  1, 3, 2},
+  {-2, -1, 3, 2},
+
+  { 0,  2, 0, 1},
+  { 0, -2, 0, 1},
+  { 0,  2, 0, 2},
+  { 0, -2, 0, 2},
+  { 0,  2, 0, 3},
+  { 0, -2, 0, 3},
+  { 2,  0, 2, 0},
+  {-2,  0, 2, 0},
+};
+
+static const int mask_params_big_hltw[1 << MASK_BITS_BIG][4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-1,  2, 2, 1},
+  { 1, -2, 2, 1},
+  {-1,  2, 2, 3},
+  { 1, -2, 2, 3},
+  { 1,  2, 2, 1},
+  {-1, -2, 2, 1},
+  { 1,  2, 2, 3},
+  {-1, -2, 2, 3},
+
+  {-2,  1, 1, 2},
+  { 2, -1, 1, 2},
+  {-2,  1, 3, 2},
+  { 2, -1, 3, 2},
+  { 2,  1, 1, 2},
+  {-2, -1, 1, 2},
+  { 2,  1, 3, 2},
+  {-2, -1, 3, 2},
+
+  { 0,  2, 0, 2},
+  { 0, -2, 0, 2},
+  { 2,  0, 1, 0},
+  {-2,  0, 1, 0},
+  { 2,  0, 2, 0},
+  {-2,  0, 2, 0},
+  { 2,  0, 3, 0},
+  {-2,  0, 3, 0},
+};
+
+static const int mask_params_big_heqw[1 << MASK_BITS_BIG][4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-1,  2, 2, 1},
+  { 1, -2, 2, 1},
+  {-1,  2, 2, 3},
+  { 1, -2, 2, 3},
+  { 1,  2, 2, 1},
+  {-1, -2, 2, 1},
+  { 1,  2, 2, 3},
+  {-1, -2, 2, 3},
+
+  {-2,  1, 1, 2},
+  { 2, -1, 1, 2},
+  {-2,  1, 3, 2},
+  { 2, -1, 3, 2},
+  { 2,  1, 1, 2},
+  {-2, -1, 1, 2},
+  { 2,  1, 3, 2},
+  {-2, -1, 3, 2},
+
+  { 0,  2, 0, 1},
+  { 0, -2, 0, 1},
+  { 0,  2, 0, 3},
+  { 0, -2, 0, 3},
+  { 2,  0, 1, 0},
+  {-2,  0, 1, 0},
+  { 2,  0, 3, 0},
+  {-2,  0, 3, 0},
+};
+
+static const int *get_mask_params(int mask_index,
+                                  BLOCK_SIZE sb_type,
+                                  int h, int w) {
+  const int *a;
+  const int mask_bits = get_mask_bits(sb_type);
+
+  if (mask_index == MASK_NONE)
+    return NULL;
+
+  if (mask_bits == MASK_BITS_SML) {
+    a = mask_params_sml[mask_index];
+  } else if (mask_bits == MASK_BITS_MED) {
+    if (h > w)
+      a = mask_params_med_hgtw[mask_index];
+    else if (h < w)
+      a = mask_params_med_hltw[mask_index];
+    else
+      a = mask_params_med_heqw[mask_index];
+  } else if (mask_bits == MASK_BITS_BIG) {
+    if (h > w)
+      a = mask_params_big_hgtw[mask_index];
+    else if (h < w)
+      a = mask_params_big_hltw[mask_index];
+    else
+      a = mask_params_big_heqw[mask_index];
+  } else {
+    assert(0);
+  }
+  return a;
+}
+
+void vp9_generate_masked_weight(int mask_index,
+                                BLOCK_SIZE sb_type,
+                                int h, int w,
+                                uint8_t *mask, int stride) {
+  int i, j;
+  const int *a = get_mask_params(mask_index, sb_type, h, w);
+  if (!a) return;
+  for (i = 0; i < h; ++i)
+    for (j = 0; j < w; ++j) {
+      int x = (j - (a[2] * w) / 4);
+      int y = (i - (a[3] * h) / 4);
+      int m = a[0] * x + a[1] * y;
+      mask[i * stride + j] = get_masked_weight(m);
+    }
+}
+
+void vp9_generate_hard_mask(int mask_index, BLOCK_SIZE sb_type,
+                            int h, int w, uint8_t *mask, int stride) {
+  int i, j;
+  const int *a = get_mask_params(mask_index, sb_type, h, w);
+  if (!a) return;
+  for (i = 0; i < h; ++i)
+    for (j = 0; j < w; ++j) {
+      int x = (j - (a[2] * w) / 4);
+      int y = (i - (a[3] * h) / 4);
+      int m = a[0] * x + a[1] * y;
+      mask[i * stride + j] = get_hard_mask(m);
+    }
+}
+
+static void build_masked_compound(uint8_t *dst, int dst_stride,
+                                  uint8_t *dst2, int dst2_stride,
+                                  int mask_index, BLOCK_SIZE sb_type,
+                                  int h, int w) {
+  int i, j;
+  uint8_t mask[4096];
+  vp9_generate_masked_weight(mask_index, sb_type, h, w, mask, 64);
+  for (i = 0; i < h; ++i)
+    for (j = 0; j < w; ++j) {
+      int m = mask[i * 64 + j];
+      dst[i * dst_stride + j] =  (dst[i * dst_stride + j] * m +
+                                  dst2[i * dst2_stride + j] *
+                                  ((1 << MASK_WEIGHT_BITS) - m) +
+                                  (1 << (MASK_WEIGHT_BITS - 1))) >>
+                                 MASK_WEIGHT_BITS;
+    }
+}
+#endif
+
 static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
                                    int bw, int bh,
                                    int x, int y, int w, int h,
@@ -193,8 +489,21 @@ static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
     pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride
            + (scaled_mv.col >> SUBPEL_BITS);
 
+#if CONFIG_MASKED_INTERINTER
+    if (ref && get_mask_bits(mi->mbmi.sb_type)
+        && mi->mbmi.use_masked_interinter) {
+      uint8_t tmp_dst[4096];
+      inter_predictor(pre, pre_buf->stride, tmp_dst, 64,
+                     subpel_x, subpel_y, sf, w, h, 0, kernel, xs, ys);
+      build_masked_compound(dst, dst_buf->stride, tmp_dst, 64,
+                            mi->mbmi.mask_index, mi->mbmi.sb_type, h, w);
+    } else {
+#endif
     inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
                     subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys);
+#if CONFIG_MASKED_INTERINTER
+    }
+#endif
   }
 }
 
@@ -229,16 +538,39 @@ static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize,
 void vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
                                     BLOCK_SIZE bsize) {
   build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0);
+#if CONFIG_INTERINTRA
+  if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
+      is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
+    vp9_build_interintra_predictors_sby(xd, xd->plane[0].dst.buf,
+                                        xd->plane[0].dst.stride, bsize);
+#endif
 }
 void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
                                      BLOCK_SIZE bsize) {
   build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1,
                                     MAX_MB_PLANE - 1);
+#if CONFIG_INTERINTRA
+  if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
+      is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
+    vp9_build_interintra_predictors_sbuv(xd, xd->plane[1].dst.buf,
+                                         xd->plane[2].dst.buf,
+                                         xd->plane[1].dst.stride,
+                                         xd->plane[2].dst.stride, bsize);
+#endif
 }
 void vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
                                    BLOCK_SIZE bsize) {
   build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0,
                                     MAX_MB_PLANE - 1);
+#if CONFIG_INTERINTRA
+  if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
+      is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
+    vp9_build_interintra_predictors(xd, xd->plane[0].dst.buf,
+                                    xd->plane[1].dst.buf, xd->plane[2].dst.buf,
+                                    xd->plane[0].dst.stride,
+                                    xd->plane[1].dst.stride,
+                                    xd->plane[2].dst.stride, bsize);
+#endif
 }
 
 // TODO(jingning): This function serves as a placeholder for decoder prediction
@@ -377,8 +709,21 @@ static void dec_build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
       }
     }
 
+#if CONFIG_MASKED_INTERINTER
+    if (ref && get_mask_bits(mi->mbmi.sb_type)
+        && mi->mbmi.use_masked_interinter) {
+      uint8_t tmp_dst[4096];
+      inter_predictor(buf_ptr, buf_stride, tmp_dst, 64,
+                     subpel_x, subpel_y, sf, w, h, 0, kernel, xs, ys);
+      build_masked_compound(dst, dst_buf->stride, tmp_dst, 64,
+                            mi->mbmi.mask_index, mi->mbmi.sb_type, h, w);
+    } else {
+#endif
     inter_predictor(buf_ptr, buf_stride, dst, dst_buf->stride, subpel_x,
                     subpel_y, sf, w, h, ref, kernel, xs, ys);
+#if CONFIG_MASKED_INTERINTER
+    }
+#endif
   }
 }
 
@@ -407,6 +752,15 @@ void vp9_dec_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
                                  0, 0, bw, bh, mi_x, mi_y);
     }
   }
+#if CONFIG_INTERINTRA
+  if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
+      is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
+    vp9_build_interintra_predictors(xd, xd->plane[0].dst.buf,
+                                    xd->plane[1].dst.buf, xd->plane[2].dst.buf,
+                                    xd->plane[0].dst.stride,
+                                    xd->plane[1].dst.stride,
+                                    xd->plane[2].dst.stride, bsize);
+#endif
 }
 
 void vp9_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE],
index 58c596ee87f0452127e29df6156959f8f0407393..34733c7ae98a52a9d7c926bf9191158f43fb3fbb 100644 (file)
@@ -65,6 +65,13 @@ void vp9_setup_pre_planes(MACROBLOCKD *xd, int idx,
                           const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
                           const struct scale_factors *sf);
 
+#if CONFIG_MASKED_INTERINTER
+void vp9_generate_masked_weight(int mask_index, BLOCK_SIZE sb_type,
+                              int h, int w, uint8_t *mask, int stride);
+void vp9_generate_hard_mask(int mask_index, BLOCK_SIZE sb_type,
+                          int h, int w, uint8_t *mask, int stride);
+#endif
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
index 403e105908e384b9b678b14b23d7b86d0d29371f..fa0f100b294297ba360f0249718cdae2a1e5d35a 100644 (file)
@@ -444,8 +444,227 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref,
   }
 }
 
+#if CONFIG_FILTERINTRA
+static void filter_intra_predictors_4tap(uint8_t *ypred_ptr, int y_stride,
+                                         int bs,
+                                         const uint8_t *yabove_row,
+                                         const uint8_t *yleft_col,
+                                         int mode) {
+  static const int prec_bits = 10;
+  static const int round_val = 511;
+
+  int k, r, c;
+  int pred[33][33];
+  int mean, ipred;
+
+  int taps4_4[10][4] = {
+      {735, 881, -537, -54},
+      {1005, 519, -488, -11},
+      {383, 990, -343, -6},
+      {442, 805, -542, 319},
+      {658, 616, -133, -116},
+      {875, 442, -141, -151},
+      {386, 741, -23, -80},
+      {390, 1027, -446, 51},
+      {679, 606, -523, 262},
+      {903, 922, -778, -23}
+  };
+  int taps4_8[10][4] = {
+      {648, 803, -444, 16},
+      {972, 620, -576, 7},
+      {561, 967, -499, -5},
+      {585, 762, -468, 144},
+      {596, 619, -182, -9},
+      {895, 459, -176, -153},
+      {557, 722, -126, -129},
+      {601, 839, -523, 105},
+      {562, 709, -499, 251},
+      {803, 872, -695, 43}
+  };
+  int taps4_16[10][4] = {
+      {423, 728, -347, 111},
+      {963, 685, -665, 23},
+      {281, 1024, -480, 216},
+      {640, 596, -437, 78},
+      {429, 669, -259, 99},
+      {740, 646, -415, 23},
+      {568, 771, -346, 40},
+      {404, 833, -486, 209},
+      {398, 712, -423, 307},
+      {939, 935, -887, 17}
+  };
+  int taps4_32[10][4] = {
+      {477, 737, -393, 150},
+      {881, 630, -546, 67},
+      {506, 984, -443, -20},
+      {114, 459, -270, 528},
+      {433, 528, 14, 3},
+      {837, 470, -301, -30},
+      {181, 777, 89, -107},
+      {-29, 716, -232, 259},
+      {589, 646, -495, 255},
+      {740, 884, -728, 77}
+  };
+
+  const int c1 = (bs >= 32) ? taps4_32[mode][0] : ((bs >= 16) ?
+      taps4_16[mode][0] : ((bs >= 8) ? taps4_8[mode][0] : taps4_4[mode][0]));
+  const int c2 = (bs >= 32) ? taps4_32[mode][1] : ((bs >= 16) ?
+      taps4_16[mode][1] : ((bs >= 8) ? taps4_8[mode][1] : taps4_4[mode][1]));
+  const int c3 = (bs >= 32) ? taps4_32[mode][2] : ((bs >= 16) ?
+      taps4_16[mode][2] : ((bs >= 8) ? taps4_8[mode][2] : taps4_4[mode][2]));
+  const int c4 = (bs >= 32) ? taps4_32[mode][3] : ((bs >= 16) ?
+      taps4_16[mode][3] : ((bs >= 8) ? taps4_8[mode][3] : taps4_4[mode][3]));
+
+  k = 0;
+  mean = 0;
+  while (k < bs) {
+    mean = mean + (int)yleft_col[k];
+    mean = mean + (int)yabove_row[k];
+    k++;
+  }
+  mean = (mean + bs) / (2 * bs);
+
+  for (r = 0; r < bs; r++)
+    pred[r + 1][0] = (int)yleft_col[r] - mean;
+
+  for (c = 0; c < 2 * bs + 1; c++)
+    pred[0][c] = (int)yabove_row[c - 1] - mean;
+
+  for (r = 1; r < bs + 1; r++)
+    for (c = 1; c < 2 * bs + 1 - r; c++) {
+      ipred = c1 * pred[r - 1][c] + c2 * pred[r][c - 1]
+                    + c3 * pred[r - 1][c - 1] + c4 * pred[r - 1][c + 1];
+      pred[r][c] = ipred < 0 ? -((-ipred + round_val) >> prec_bits) :
+                               ((ipred + round_val) >> prec_bits);
+    }
+
+  for (r = 0; r < bs; r++) {
+    for (c = 0; c < bs; c++) {
+      ipred = pred[r + 1][c + 1] + mean;
+      ypred_ptr[c] = clip_pixel(ipred);
+    }
+    ypred_ptr += y_stride;
+  }
+}
+
+static void build_filter_intra_predictors(const MACROBLOCKD *xd,
+                                          const uint8_t *ref, int ref_stride,
+                                          uint8_t *dst, int dst_stride,
+                                          PREDICTION_MODE mode, TX_SIZE tx_size,
+                                          int up_available, int left_available,
+                                          int right_available, int x, int y,
+                                          int plane) {
+  int i;
+  DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
+  DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
+  uint8_t *above_row = above_data + 16;
+  const uint8_t *const_above_row = above_row;
+  const int bs = 4 << tx_size;
+  int frame_width, frame_height;
+  int x0, y0;
+  const struct macroblockd_plane *const pd = &xd->plane[plane];
+
+  // Get current frame pointer, width and height.
+  if (plane == 0) {
+    frame_width = xd->cur_buf->y_width;
+    frame_height = xd->cur_buf->y_height;
+  } else {
+    frame_width = xd->cur_buf->uv_width;
+    frame_height = xd->cur_buf->uv_height;
+  }
+
+  // Get block position in current frame.
+  x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
+  y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
+
+  vpx_memset(left_col, 129, 64);
+
+  // left
+  if (left_available) {
+    if (xd->mb_to_bottom_edge < 0) {
+      /* slower path if the block needs border extension */
+      if (y0 + bs <= frame_height) {
+        for (i = 0; i < bs; ++i)
+          left_col[i] = ref[i * ref_stride - 1];
+      } else {
+        const int extend_bottom = frame_height - y0;
+        for (i = 0; i < extend_bottom; ++i)
+          left_col[i] = ref[i * ref_stride - 1];
+        for (; i < bs; ++i)
+          left_col[i] = ref[(extend_bottom - 1) * ref_stride - 1];
+      }
+    } else {
+      /* faster path if the block does not need extension */
+      for (i = 0; i < bs; ++i)
+        left_col[i] = ref[i * ref_stride - 1];
+    }
+  }
+
+  // TODO(hkuang) do not extend 2*bs pixels for all modes.
+  // above
+  if (up_available) {
+    const uint8_t *above_ref = ref - ref_stride;
+    if (xd->mb_to_right_edge < 0) {
+      /* slower path if the block needs border extension */
+      if (x0 + 2 * bs <= frame_width) {
+        if (right_available && bs == 4) {
+          vpx_memcpy(above_row, above_ref, 2 * bs);
+        } else {
+          vpx_memcpy(above_row, above_ref, bs);
+          vpx_memset(above_row + bs, above_row[bs - 1], bs);
+        }
+      } else if (x0 + bs <= frame_width) {
+        const int r = frame_width - x0;
+        if (right_available && bs == 4) {
+          vpx_memcpy(above_row, above_ref, r);
+          vpx_memset(above_row + r, above_row[r - 1],
+                     x0 + 2 * bs - frame_width);
+        } else {
+          vpx_memcpy(above_row, above_ref, bs);
+          vpx_memset(above_row + bs, above_row[bs - 1], bs);
+        }
+      } else if (x0 <= frame_width) {
+        const int r = frame_width - x0;
+        if (right_available && bs == 4) {
+          vpx_memcpy(above_row, above_ref, r);
+          vpx_memset(above_row + r, above_row[r - 1],
+                     x0 + 2 * bs - frame_width);
+        } else {
+          vpx_memcpy(above_row, above_ref, r);
+          vpx_memset(above_row + r, above_row[r - 1],
+                     x0 + 2 * bs - frame_width);
+        }
+      }
+      above_row[-1] = left_available ? above_ref[-1] : 129;
+    } else {
+      /* faster path if the block does not need extension */
+      if (bs == 4 && right_available && left_available) {
+        const_above_row = above_ref;
+      } else {
+        vpx_memcpy(above_row, above_ref, bs);
+        if (bs == 4 && right_available)
+          vpx_memcpy(above_row + bs, above_ref + bs, bs);
+        else
+          vpx_memset(above_row + bs, above_row[bs - 1], bs);
+        above_row[-1] = left_available ? above_ref[-1] : 129;
+      }
+    }
+  } else {
+    vpx_memset(above_row, 127, bs * 2);
+    above_row[-1] = 127;
+  }
+
+  // predict
+  filter_intra_predictors_4tap(dst, dst_stride, bs, const_above_row, left_col,
+                               mode);
+}
+#endif
+
 void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
                              TX_SIZE tx_size, PREDICTION_MODE mode,
+#if CONFIG_FILTERINTRA
+                             int filterbit,
+#endif
                              const uint8_t *ref, int ref_stride,
                              uint8_t *dst, int dst_stride,
                              int aoff, int loff, int plane) {
@@ -456,8 +675,708 @@ void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
   const int have_right = ((block_idx & wmask) != wmask);
   const int x = aoff * 4;
   const int y = loff * 4;
+#if CONFIG_FILTERINTRA
+  const int filterflag = is_filter_allowed(mode) && is_filter_enabled(tx_size)
+                         && filterbit;
+#endif
 
   assert(bwl >= 0);
+#if CONFIG_FILTERINTRA
+  if (!filterflag) {
+#endif
   build_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode, tx_size,
                          have_top, have_left, have_right, x, y, plane);
+#if CONFIG_FILTERINTRA
+  } else {
+    build_filter_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode,
+                        tx_size, have_top, have_left, have_right, x, y, plane);
+  }
+#endif
+}
+
+#if CONFIG_INTERINTRA
+#if CONFIG_MASKED_INTERINTRA
+#define MASK_WEIGHT_BITS_INTERINTRA 6
+
+static int get_masked_weight_interintra(int m) {
+  #define SMOOTHER_LEN_INTERINTRA  32
+  static const uint8_t smoothfn[2 * SMOOTHER_LEN_INTERINTRA + 1] = {
+      0,  0,  0,  0,  0,  0,  0,  0,
+      0,  0,  0,  0,  0,  1,  1,  1,
+      1,  1,  2,  2,  3,  4,  5,  6,
+      8,  9, 12, 14, 17, 21, 24, 28,
+      32,
+      36, 40, 43, 47, 50, 52, 55, 56,
+      58, 59, 60, 61, 62, 62, 63, 63,
+      63, 63, 63, 64, 64, 64, 64, 64,
+      64, 64, 64, 64, 64, 64, 64, 64,
+  };
+  if (m < -SMOOTHER_LEN_INTERINTRA)
+    return 0;
+  else if (m > SMOOTHER_LEN_INTERINTRA)
+    return (1 << MASK_WEIGHT_BITS_INTERINTRA);
+  else
+    return smoothfn[m + SMOOTHER_LEN_INTERINTRA];
+}
+
+static int get_hard_mask_interintra(int m) {
+  return m > 0;
+}
+
+// Equation of line: f(x, y) = a[0]*(x - a[2]*w/4) + a[1]*(y - a[3]*h/4) = 0
+// The soft mask is obtained by computing f(x, y) and then calling
+// get_masked_weight(f(x, y)).
+static const int mask_params_sml_interintra[1 << MASK_BITS_SML_INTERINTRA]
+                                            [4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+};
+
+static const int mask_params_med_hgtw_interintra[1 << MASK_BITS_MED_INTERINTRA]
+                                                 [4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-1,  2, 2, 1},
+  { 1, -2, 2, 1},
+  {-1,  2, 2, 3},
+  { 1, -2, 2, 3},
+  { 1,  2, 2, 1},
+  {-1, -2, 2, 1},
+  { 1,  2, 2, 3},
+  {-1, -2, 2, 3},
+};
+
+static const int mask_params_med_hltw_interintra[1 << MASK_BITS_MED_INTERINTRA]
+                                                 [4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-2,  1, 1, 2},
+  { 2, -1, 1, 2},
+  {-2,  1, 3, 2},
+  { 2, -1, 3, 2},
+  { 2,  1, 1, 2},
+  {-2, -1, 1, 2},
+  { 2,  1, 3, 2},
+  {-2, -1, 3, 2},
+};
+
+static const int mask_params_med_heqw_interintra[1 << MASK_BITS_MED_INTERINTRA]
+                                                 [4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  { 0,  2, 0, 1},
+  { 0, -2, 0, 1},
+  { 0,  2, 0, 3},
+  { 0, -2, 0, 3},
+  { 2,  0, 1, 0},
+  {-2,  0, 1, 0},
+  { 2,  0, 3, 0},
+  {-2,  0, 3, 0},
+};
+
+static const int mask_params_big_hgtw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
+                                                 [4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-1,  2, 2, 1},
+  { 1, -2, 2, 1},
+  {-1,  2, 2, 3},
+  { 1, -2, 2, 3},
+  { 1,  2, 2, 1},
+  {-1, -2, 2, 1},
+  { 1,  2, 2, 3},
+  {-1, -2, 2, 3},
+
+  {-2,  1, 1, 2},
+  { 2, -1, 1, 2},
+  {-2,  1, 3, 2},
+  { 2, -1, 3, 2},
+  { 2,  1, 1, 2},
+  {-2, -1, 1, 2},
+  { 2,  1, 3, 2},
+  {-2, -1, 3, 2},
+
+  { 0,  2, 0, 1},
+  { 0, -2, 0, 1},
+  { 0,  2, 0, 2},
+  { 0, -2, 0, 2},
+  { 0,  2, 0, 3},
+  { 0, -2, 0, 3},
+  { 2,  0, 2, 0},
+  {-2,  0, 2, 0},
+};
+
+static const int mask_params_big_hltw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
+                                                 [4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-1,  2, 2, 1},
+  { 1, -2, 2, 1},
+  {-1,  2, 2, 3},
+  { 1, -2, 2, 3},
+  { 1,  2, 2, 1},
+  {-1, -2, 2, 1},
+  { 1,  2, 2, 3},
+  {-1, -2, 2, 3},
+
+  {-2,  1, 1, 2},
+  { 2, -1, 1, 2},
+  {-2,  1, 3, 2},
+  { 2, -1, 3, 2},
+  { 2,  1, 1, 2},
+  {-2, -1, 1, 2},
+  { 2,  1, 3, 2},
+  {-2, -1, 3, 2},
+
+  { 0,  2, 0, 2},
+  { 0, -2, 0, 2},
+  { 2,  0, 1, 0},
+  {-2,  0, 1, 0},
+  { 2,  0, 2, 0},
+  {-2,  0, 2, 0},
+  { 2,  0, 3, 0},
+  {-2,  0, 3, 0},
+};
+
+static const int mask_params_big_heqw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
+                                                 [4] = {
+  {-1,  2, 2, 2},
+  { 1, -2, 2, 2},
+  {-2,  1, 2, 2},
+  { 2, -1, 2, 2},
+  { 2,  1, 2, 2},
+  {-2, -1, 2, 2},
+  { 1,  2, 2, 2},
+  {-1, -2, 2, 2},
+
+  {-1,  2, 2, 1},
+  { 1, -2, 2, 1},
+  {-1,  2, 2, 3},
+  { 1, -2, 2, 3},
+  { 1,  2, 2, 1},
+  {-1, -2, 2, 1},
+  { 1,  2, 2, 3},
+  {-1, -2, 2, 3},
+
+  {-2,  1, 1, 2},
+  { 2, -1, 1, 2},
+  {-2,  1, 3, 2},
+  { 2, -1, 3, 2},
+  { 2,  1, 1, 2},
+  {-2, -1, 1, 2},
+  { 2,  1, 3, 2},
+  {-2, -1, 3, 2},
+
+  { 0,  2, 0, 1},
+  { 0, -2, 0, 1},
+  { 0,  2, 0, 3},
+  { 0, -2, 0, 3},
+  { 2,  0, 1, 0},
+  {-2,  0, 1, 0},
+  { 2,  0, 3, 0},
+  {-2,  0, 3, 0},
+};
+
+static const int *get_mask_params_interintra(int mask_index,
+                                             BLOCK_SIZE sb_type,
+                                             int h, int w) {
+  const int *a;
+  const int mask_bits = get_mask_bits_interintra(sb_type);
+
+  if (mask_index == MASK_NONE_INTERINTRA)
+    return NULL;
+
+  if (mask_bits == MASK_BITS_SML_INTERINTRA) {
+    a = mask_params_sml_interintra[mask_index];
+  } else if (mask_bits == MASK_BITS_MED_INTERINTRA) {
+    if (h > w)
+      a = mask_params_med_hgtw_interintra[mask_index];
+    else if (h < w)
+      a = mask_params_med_hltw_interintra[mask_index];
+    else
+      a = mask_params_med_heqw_interintra[mask_index];
+  } else if (mask_bits == MASK_BITS_BIG_INTERINTRA) {
+    if (h > w)
+      a = mask_params_big_hgtw_interintra[mask_index];
+    else if (h < w)
+      a = mask_params_big_hltw_interintra[mask_index];
+    else
+      a = mask_params_big_heqw_interintra[mask_index];
+  } else {
+    assert(0);
+  }
+  return a;
+}
+
+void vp9_generate_masked_weight_interintra(int mask_index,
+                                           BLOCK_SIZE sb_type,
+                                           int h, int w,
+                                           uint8_t *mask, int stride) {
+  int i, j;
+  const int *a = get_mask_params_interintra(mask_index, sb_type, h, w);
+  if (!a) return;
+  for (i = 0; i < h; ++i)
+    for (j = 0; j < w; ++j) {
+      int x = (j - (a[2] * w) / 4);
+      int y = (i - (a[3] * h) / 4);
+      int m = a[0] * x + a[1] * y;
+      mask[i * stride + j] = get_masked_weight_interintra(m);
+    }
+}
+
+void vp9_generate_hard_mask_interintra(int mask_index, BLOCK_SIZE sb_type,
+                            int h, int w, uint8_t *mask, int stride) {
+  int i, j;
+  const int *a = get_mask_params_interintra(mask_index, sb_type, h, w);
+  if (!a) return;
+  for (i = 0; i < h; ++i)
+    for (j = 0; j < w; ++j) {
+      int x = (j - (a[2] * w) / 4);
+      int y = (i - (a[3] * h) / 4);
+      int m = a[0] * x + a[1] * y;
+      mask[i * stride + j] = get_hard_mask_interintra(m);
+    }
+}
+#endif
+
+static void combine_interintra(PREDICTION_MODE mode,
+#if CONFIG_MASKED_INTERINTRA
+                               int use_masked_interintra,
+                               int mask_index,
+                               BLOCK_SIZE bsize,
+#endif
+                               uint8_t *comppred,
+                               int compstride,
+                               uint8_t *interpred,
+                               int interstride,
+                               uint8_t *intrapred,
+                               int intrastride,
+                               int bw, int bh) {
+  static const int scale_bits = 8;
+  static const int scale_max = 256;
+  static const int scale_round = 127;
+  static const int weights1d[64] = {
+      128, 125, 122, 119, 116, 114, 111, 109,
+      107, 105, 103, 101,  99,  97,  96,  94,
+       93,  91,  90,  89,  88,  86,  85,  84,
+       83,  82,  81,  81,  80,  79,  78,  78,
+       77,  76,  76,  75,  75,  74,  74,  73,
+       73,  72,  72,  71,  71,  71,  70,  70,
+       70,  70,  69,  69,  69,  69,  68,  68,
+       68,  68,  68,  67,  67,  67,  67,  67,
+  };
+
+  int size = MAX(bw, bh);
+  int size_scale = (size >= 64 ? 1 :
+                    size == 32 ? 2 :
+                    size == 16 ? 4 :
+                    size == 8  ? 8 : 16);
+  int i, j;
+
+#if CONFIG_MASKED_INTERINTRA
+  if (use_masked_interintra && get_mask_bits_interintra(bsize)) {
+    uint8_t mask[4096];
+    vp9_generate_masked_weight_interintra(mask_index, bsize, bh, bw, mask, bw);
+    for (i = 0; i < bh; ++i) {
+      for (j = 0; j < bw; ++j) {
+        int m = mask[i * bw + j];
+        comppred[i * compstride + j] =
+            (intrapred[i * intrastride + j] * m +
+            interpred[i * interstride + j] *
+            ((1 << MASK_WEIGHT_BITS_INTERINTRA) - m) +
+            (1 << (MASK_WEIGHT_BITS_INTERINTRA - 1))) >>
+            MASK_WEIGHT_BITS_INTERINTRA;
+      }
+    }
+    return;
+  }
+#endif
+
+  switch (mode) {
+    case V_PRED:
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
+          int scale = weights1d[i * size_scale];
+            comppred[i * compstride + j] =
+              ((scale_max - scale) * interpred[i * interstride + j] +
+               scale * intrapred[i * intrastride + j] + scale_round)
+               >> scale_bits;
+        }
+      }
+     break;
+
+    case H_PRED:
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
+          int scale = weights1d[j * size_scale];
+            comppred[i * compstride + j] =
+              ((scale_max - scale) * interpred[i * interstride + j] +
+               scale * intrapred[i * intrastride + j] + scale_round)
+               >> scale_bits;
+        }
+      }
+     break;
+
+    case D63_PRED:
+    case D117_PRED:
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
+          int scale = (weights1d[i * size_scale] * 3 +
+                       weights1d[j * size_scale]) >> 2;
+            comppred[i * compstride + j] =
+              ((scale_max - scale) * interpred[i * interstride + j] +
+                  scale * intrapred[i * intrastride + j] + scale_round)
+                  >> scale_bits;
+        }
+      }
+     break;
+
+    case D207_PRED:
+    case D153_PRED:
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
+          int scale = (weights1d[j * size_scale] * 3 +
+                       weights1d[i * size_scale]) >> 2;
+            comppred[i * compstride + j] =
+              ((scale_max - scale) * interpred[i * interstride + j] +
+                  scale * intrapred[i * intrastride + j] + scale_round)
+                  >> scale_bits;
+        }
+      }
+     break;
+
+    case D135_PRED:
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
+          int scale = weights1d[(i < j ? i : j) * size_scale];
+            comppred[i * compstride + j] =
+              ((scale_max - scale) * interpred[i * interstride + j] +
+                  scale * intrapred[i * intrastride + j] + scale_round)
+                  >> scale_bits;
+        }
+      }
+     break;
+
+    case D45_PRED:
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
+          int scale = (weights1d[i * size_scale] +
+                       weights1d[j * size_scale]) >> 1;
+            comppred[i * compstride + j] =
+              ((scale_max - scale) * interpred[i * interstride + j] +
+                  scale * intrapred[i * intrastride + j] + scale_round)
+                  >> scale_bits;
+        }
+      }
+     break;
+
+    case TM_PRED:
+    case DC_PRED:
+    default:
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
+            comppred[i * compstride + j] = (interpred[i * interstride + j] +
+                intrapred[i * intrastride + j]) >> 1;
+        }
+      }
+      break;
+  }
+}
+
+
+static void build_intra_predictors_for_2nd_block_interintra
+                                  (const MACROBLOCKD *xd, const uint8_t *ref,
+                                   int ref_stride, uint8_t *dst, int dst_stride,
+                                   PREDICTION_MODE mode, TX_SIZE tx_size,
+                                   int up_available, int left_available,
+                                   int right_available, int bwltbh,
+                                   int x, int y, int plane) {
+  int i;
+  DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
+  DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
+  uint8_t *above_row = above_data + 16;
+  const uint8_t *const_above_row = above_row;
+  const int bs = 4 << tx_size;
+  int frame_width, frame_height;
+  int x0, y0;
+  const struct macroblockd_plane *const pd = &xd->plane[plane];
+  const uint8_t *ref_fi;
+  int ref_stride_fi;
+
+  // 127 127 127 .. 127 127 127 127 127 127
+  // 129  A   B  ..  Y   Z
+  // 129  C   D  ..  W   X
+  // 129  E   F  ..  U   V
+  // 129  G   H  ..  S   T   T   T   T   T
+  // ..
+
+  once(init_intra_pred_fn_ptrs);
+
+  // Get current frame pointer, width and height.
+  if (plane == 0) {
+    frame_width = xd->cur_buf->y_width;
+    frame_height = xd->cur_buf->y_height;
+  } else {
+    frame_width = xd->cur_buf->uv_width;
+    frame_height = xd->cur_buf->uv_height;
+  }
+
+  // Get block position in current frame.
+  x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
+  y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
+
+  vpx_memset(left_col, 129, 64);
+
+  // left
+  if (left_available) {
+    if (bwltbh) {
+      ref_fi = ref;
+      ref_stride_fi = ref_stride;
+    } else {
+      ref_fi = dst;
+      ref_stride_fi = dst_stride;
+    }
+    if (xd->mb_to_bottom_edge < 0) {
+      /* slower path if the block needs border extension */
+      if (y0 + bs <= frame_height) {
+        for (i = 0; i < bs; ++i)
+          left_col[i] = ref_fi[i * ref_stride_fi - 1];
+      } else {
+        const int extend_bottom = frame_height - y0;
+        assert(extend_bottom >= 0);
+        for (i = 0; i < extend_bottom; ++i)
+          left_col[i] = ref_fi[i * ref_stride_fi - 1];
+        for (; i < bs; ++i)
+          left_col[i] = ref_fi[(extend_bottom - 1) * ref_stride_fi - 1];
+      }
+    } else {
+      /* faster path if the block does not need extension */
+      for (i = 0; i < bs; ++i)
+        left_col[i] = ref_fi[i * ref_stride_fi - 1];
+    }
+  }
+
+  // TODO(hkuang) do not extend 2*bs pixels for all modes.
+  // above
+  if (up_available) {
+    const uint8_t *above_ref;
+    if (bwltbh) {
+      ref_fi = dst;
+      ref_stride_fi = dst_stride;
+      above_row[-1] = left_available ? ref[-ref_stride-1] : 129;
+    } else {
+      ref_fi = ref;
+      ref_stride_fi = ref_stride;
+      above_row[-1] = ref[-ref_stride-1];
+    }
+    above_ref = ref_fi - ref_stride_fi;
+    if (xd->mb_to_right_edge < 0) {
+      /* slower path if the block needs border extension */
+      if (x0 + 2 * bs <= frame_width) {
+        if (right_available && bs == 4) {
+          vpx_memcpy(above_row, above_ref, 2 * bs);
+        } else {
+          vpx_memcpy(above_row, above_ref, bs);
+          vpx_memset(above_row + bs, above_row[bs - 1], bs);
+        }
+      } else if (x0 + bs <= frame_width) {
+        const int r = frame_width - x0;
+        if (right_available && bs == 4) {
+          vpx_memcpy(above_row, above_ref, r);
+          vpx_memset(above_row + r, above_row[r - 1],
+                     x0 + 2 * bs - frame_width);
+        } else {
+          vpx_memcpy(above_row, above_ref, bs);
+          vpx_memset(above_row + bs, above_row[bs - 1], bs);
+        }
+      } else if (x0 <= frame_width) {
+        const int r = frame_width - x0;
+        assert(r >= 0);
+        if (right_available && bs == 4) {
+          vpx_memcpy(above_row, above_ref, r);
+          vpx_memset(above_row + r, above_row[r - 1],
+                     x0 + 2 * bs - frame_width);
+        } else {
+          vpx_memcpy(above_row, above_ref, r);
+          vpx_memset(above_row + r, above_row[r - 1],
+                     x0 + 2 * bs - frame_width);
+        }
+      }
+    } else {
+      /* faster path if the block does not need extension */
+      if (bs == 4 && right_available && left_available) {
+        const_above_row = above_ref;
+      } else {
+        vpx_memcpy(above_row, above_ref, bs);
+        if (bs == 4 && right_available)
+          vpx_memcpy(above_row + bs, above_ref + bs, bs);
+        else
+          vpx_memset(above_row + bs, above_row[bs - 1], bs);
+      }
+    }
+  } else {
+    vpx_memset(above_row, 127, bs * 2);
+    above_row[-1] = 127;
+  }
+
+  // predict
+  if (mode == DC_PRED) {
+    dc_pred[left_available][up_available][tx_size](dst, dst_stride,
+                                                   const_above_row, left_col);
+  } else {
+    pred[mode][tx_size](dst, dst_stride, const_above_row, left_col);
+  }
+}
+
+// Break down rectangular intra prediction for joint spatio-temporal prediction
+// into two square intra predictions.
+static void build_intra_predictors_for_interintra(MACROBLOCKD *xd,
+                                           uint8_t *src, int src_stride,
+                                           uint8_t *pred_ptr, int stride,
+                                           PREDICTION_MODE mode,
+                                           int bw, int bh,
+                                           int up_available, int left_available,
+                                           int right_available, int plane) {
+  if (bw == bh) {
+    build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
+                           mode, intra_size_log2_for_interintra(bw),
+                           up_available, left_available, right_available,
+                           0, 0, plane);
+  } else if (bw < bh) {
+    uint8_t *src_bottom = src + bw * src_stride;
+    uint8_t *pred_ptr_bottom = pred_ptr + bw * stride;
+    build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
+                           mode, intra_size_log2_for_interintra(bw),
+                           up_available, left_available, right_available,
+                           0, 0, plane);
+    build_intra_predictors_for_2nd_block_interintra(xd, src_bottom, src_stride,
+                           pred_ptr_bottom, stride,
+                           mode, intra_size_log2_for_interintra(bw),
+                           up_available, left_available, 0, 1,
+                           0, bw, plane);
+  } else {
+    uint8_t *src_right = src + bh;
+    uint8_t *pred_ptr_right = pred_ptr + bh;
+    build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
+                           mode, intra_size_log2_for_interintra(bh),
+                           up_available, left_available, 1,
+                           0, 0, plane);
+    build_intra_predictors_for_2nd_block_interintra(xd, src_right, src_stride,
+                           pred_ptr_right, stride,
+                           mode, intra_size_log2_for_interintra(bh),
+                           up_available, left_available, right_available, 0,
+                           bh, 0, plane);
+  }
+}
+
+void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
+                                         uint8_t *ypred,
+                                         int ystride,
+                                         BLOCK_SIZE bsize) {
+  int bw = 4 << b_width_log2(bsize);
+  int bh = 4 << b_height_log2(bsize);
+  uint8_t intrapredictor[4096];
+  build_intra_predictors_for_interintra(
+      xd, xd->plane[0].dst.buf, xd->plane[0].dst.stride,
+      intrapredictor, bw,
+      xd->mi[0]->mbmi.interintra_mode, bw, bh,
+      xd->up_available, xd->left_available, 0, 0);
+  combine_interintra(xd->mi[0]->mbmi.interintra_mode,
+#if CONFIG_MASKED_INTERINTRA
+                     xd->mi[0]->mbmi.use_masked_interintra,
+                     xd->mi[0]->mbmi.interintra_mask_index,
+                     bsize,
+#endif
+                     xd->plane[0].dst.buf, xd->plane[0].dst.stride,
+                     ypred, ystride, intrapredictor, bw, bw, bh);
+}
+
+void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
+                                          uint8_t *upred,
+                                          uint8_t *vpred,
+                                          int ustride, int vstride,
+                                          BLOCK_SIZE bsize) {
+  int bwl = b_width_log2(bsize), bw = 2 << bwl;
+  int bhl = b_height_log2(bsize), bh = 2 << bhl;
+  uint8_t uintrapredictor[1024];
+  uint8_t vintrapredictor[1024];
+  build_intra_predictors_for_interintra(
+      xd, xd->plane[1].dst.buf, xd->plane[1].dst.stride,
+      uintrapredictor, bw,
+      xd->mi[0]->mbmi.interintra_uv_mode, bw, bh,
+      xd->up_available, xd->left_available, 0, 1);
+  build_intra_predictors_for_interintra(
+      xd, xd->plane[2].dst.buf, xd->plane[1].dst.stride,
+      vintrapredictor, bw,
+      xd->mi[0]->mbmi.interintra_uv_mode, bw, bh,
+      xd->up_available, xd->left_available, 0, 2);
+  combine_interintra(xd->mi[0]->mbmi.interintra_uv_mode,
+#if CONFIG_MASKED_INTERINTRA
+                     xd->mi[0]->mbmi.use_masked_interintra,
+                     xd->mi[0]->mbmi.interintra_uv_mask_index,
+                     bsize,
+#endif
+                     xd->plane[1].dst.buf, xd->plane[1].dst.stride,
+                     upred, ustride, uintrapredictor, bw, bw, bh);
+  combine_interintra(xd->mi[0]->mbmi.interintra_uv_mode,
+#if CONFIG_MASKED_INTERINTRA
+                     xd->mi[0]->mbmi.use_masked_interintra,
+                     xd->mi[0]->mbmi.interintra_uv_mask_index,
+                     bsize,
+#endif
+                     xd->plane[2].dst.buf, xd->plane[2].dst.stride,
+                     vpred, vstride, vintrapredictor, bw, bw, bh);
+}
+
+void vp9_build_interintra_predictors(MACROBLOCKD *xd,
+                                     uint8_t *ypred,
+                                     uint8_t *upred,
+                                     uint8_t *vpred,
+                                     int ystride, int ustride, int vstride,
+                                     BLOCK_SIZE bsize) {
+  vp9_build_interintra_predictors_sby(xd, ypred, ystride, bsize);
+  vp9_build_interintra_predictors_sbuv(xd, upred, vpred,
+                                       ustride, vstride, bsize);
 }
+#endif
index d09d2a129c0a79c4f71bafccc02d1f269e390aa4..3b87f6fc14309ee2b402922712b5e1f52626597b 100644 (file)
@@ -20,9 +20,37 @@ extern "C" {
 
 void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
                              TX_SIZE tx_size, PREDICTION_MODE mode,
+#if CONFIG_FILTERINTRA
+                             int filterbit,
+#endif
                              const uint8_t *ref, int ref_stride,
                              uint8_t *dst, int dst_stride,
                              int aoff, int loff, int plane);
+#if CONFIG_INTERINTRA
+void vp9_build_interintra_predictors(MACROBLOCKD *xd,
+                                     uint8_t *ypred,
+                                     uint8_t *upred,
+                                     uint8_t *vpred,
+                                     int ystride,
+                                     int ustride,
+                                     int vstride,
+                                     BLOCK_SIZE bsize);
+void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
+                                         uint8_t *ypred,
+                                         int ystride,
+                                         BLOCK_SIZE bsize);
+void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
+                                          uint8_t *upred,
+                                          uint8_t *vpred,
+                                          int ustride, int vstride,
+                                          BLOCK_SIZE bsize);
+#if CONFIG_MASKED_INTERINTRA
+void vp9_generate_masked_weight_interintra(int mask_index,
+                                           BLOCK_SIZE sb_type,
+                                           int h, int w,
+                                           uint8_t *mask, int stride);
+#endif
+#endif
 #ifdef __cplusplus
 }  // extern "C"
 #endif
index 68613ec967dcc11e6c3dd9e7567b867006f74d7f..b668497bbb13cea6fad4434e686cb4d4ce26e7c3 100644 (file)
@@ -506,6 +506,125 @@ specialize qw/vp9_sub_pixel_variance8x8/, "$sse2_x86inc", "$ssse3_x86inc";
 add_proto qw/unsigned int vp9_sub_pixel_avg_variance8x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse, const uint8_t *second_pred";
 specialize qw/vp9_sub_pixel_avg_variance8x8/, "$sse2_x86inc", "$ssse3_x86inc";
 
+if ((vpx_config("CONFIG_MASKED_INTERINTER") eq "yes") || ((vpx_config("CONFIG_INTERINTRA") eq "yes") && (vpx_config("CONFIG_MASKED_INTERINTRA") eq "yes"))) {
+add_proto qw/unsigned int vp9_masked_variance32x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance32x16/;
+
+add_proto qw/unsigned int vp9_masked_variance16x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masdctked_variance16x32/;
+
+add_proto qw/unsigned int vp9_masked_variance64x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance64x32/;
+
+add_proto qw/unsigned int vp9_masked_variance32x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance32x64/;
+
+add_proto qw/unsigned int vp9_masked_variance32x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance32x32/;
+
+add_proto qw/unsigned int vp9_masked_variance64x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance64x64/;
+
+add_proto qw/unsigned int vp9_masked_variance16x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance16x16/;
+
+add_proto qw/unsigned int vp9_masked_variance16x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance16x8/;
+
+add_proto qw/unsigned int vp9_masked_variance8x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance8x16/;
+
+add_proto qw/unsigned int vp9_masked_variance8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance8x8/;
+
+add_proto qw/unsigned int vp9_masked_variance8x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance8x4/;
+
+add_proto qw/unsigned int vp9_masked_variance4x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance4x8/;
+
+add_proto qw/unsigned int vp9_masked_variance4x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance4x4/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance64x64/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance64x64/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x64/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance32x64/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance64x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance64x32/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance32x16/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance16x32/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance32x32/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance16x16/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance8x16/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance16x8/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance8x8/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance8x4/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance4x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance4x8/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance4x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance4x4/;
+
+add_proto qw/unsigned int vp9_masked_sad64x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad64x64/;
+
+add_proto qw/unsigned int vp9_masked_sad32x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad32x64/;
+
+add_proto qw/unsigned int vp9_masked_sad64x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad64x32/;
+
+add_proto qw/unsigned int vp9_masked_sad32x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad32x16/;
+
+add_proto qw/unsigned int vp9_masked_sad16x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad16x32/;
+
+add_proto qw/unsigned int vp9_masked_sad32x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad32x32/;
+
+add_proto qw/unsigned int vp9_masked_sad16x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad16x16/;
+
+add_proto qw/unsigned int vp9_masked_sad16x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad16x8/;
+
+add_proto qw/unsigned int vp9_masked_sad8x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad8x16/;
+
+add_proto qw/unsigned int vp9_masked_sad8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad8x8/;
+
+add_proto qw/unsigned int vp9_masked_sad8x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad8x4/;
+
+add_proto qw/unsigned int vp9_masked_sad4x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad4x8/;
+
+add_proto qw/unsigned int vp9_masked_sad4x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad4x4/;
+}
+
 # TODO(jingning): need to convert 8x4/4x8 functions into mmx/sse form
 add_proto qw/unsigned int vp9_sub_pixel_variance8x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse";
 specialize qw/vp9_sub_pixel_variance8x4/, "$sse2_x86inc", "$ssse3_x86inc";
index 9220a9eecb6f1c95b1a0fcfa38a7964d547b2592..fb14b6822e036251724c0c96992f64b632225e43 100644 (file)
@@ -254,11 +254,24 @@ static void predict_and_reconstruct_intra_block(int plane, int block,
                                             : mi->mbmi.uv_mode;
   int x, y;
   uint8_t *dst;
+#if CONFIG_FILTERINTRA
+  int fbit;
+  if (plane == 0)
+    if (mi->mbmi.sb_type < BLOCK_8X8)
+      fbit = mi->b_filter_info[block];
+    else
+      fbit = is_filter_enabled(tx_size) ? mi->mbmi.filterbit : 0;
+  else
+    fbit = is_filter_enabled(tx_size) ? mi->mbmi.uv_filterbit : 0;
+#endif
   txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x, &y);
   dst = &pd->dst.buf[4 * y * pd->dst.stride + 4 * x];
 
   vp9_predict_intra_block(xd, block >> (tx_size << 1),
                           b_width_log2(plane_bsize), tx_size, mode,
+#if CONFIG_FILTERINTRA
+                          fbit,
+#endif
                           dst, pd->dst.stride, dst, pd->dst.stride,
                           x, y, plane);
 
@@ -1246,6 +1259,53 @@ static int read_compressed_header(VP9Decoder *pbi, const uint8_t *data,
         vp9_diff_update_prob(&r, &fc->partition_prob[j][i]);
 
     read_mv_probs(nmvc, cm->allow_high_precision_mv, &r);
+
+#if CONFIG_EXT_TX
+    vp9_diff_update_prob(&r, &fc->ext_tx_prob);
+#endif
+
+#if CONFIG_MASKED_INTERINTER
+    if (cm->reference_mode != SINGLE_REFERENCE) {
+      cm->use_masked_interinter = vp9_read_bit(&r);
+      if (cm->use_masked_interinter) {
+        for (i = 0; i < BLOCK_SIZES; i++) {
+          if (get_mask_bits(i))
+            vp9_diff_update_prob(&r, &fc->masked_interinter_prob[i]);
+        }
+      }
+    } else {
+      cm->use_masked_interinter = 0;
+    }
+#endif
+
+#if CONFIG_INTERINTRA
+    if (cm->reference_mode != COMPOUND_REFERENCE) {
+      cm->use_interintra = vp9_read_bit(&r);
+      if (cm->use_interintra) {
+        for (i = 0; i < BLOCK_SIZES; i++) {
+          if (is_interintra_allowed(i)) {
+            vp9_diff_update_prob(&r, &fc->interintra_prob[i]);
+          }
+        }
+#if CONFIG_MASKED_INTERINTRA
+        cm->use_masked_interintra = vp9_read_bit(&r);
+        if (cm->use_masked_interintra) {
+          for (i = 0; i < BLOCK_SIZES; i++) {
+            if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
+              vp9_diff_update_prob(&r, &fc->masked_interintra_prob[i]);
+          }
+        }
+      } else {
+        cm->use_masked_interintra = 0;
+#endif
+      }
+    } else {
+      cm->use_interintra = 0;
+#if CONFIG_MASKED_INTERINTRA
+      cm->use_masked_interintra = 0;
+#endif
+    }
+#endif
   }
 
   return vp9_reader_has_error(&r);
@@ -1297,6 +1357,10 @@ static void debug_check_frame_counts(const VP9_COMMON *const cm) {
   assert(!memcmp(&cm->counts.tx, &zero_counts.tx, sizeof(cm->counts.tx)));
   assert(!memcmp(cm->counts.skip, zero_counts.skip, sizeof(cm->counts.skip)));
   assert(!memcmp(&cm->counts.mv, &zero_counts.mv, sizeof(cm->counts.mv)));
+#if CONFIG_EXT_TX
+  assert(!memcmp(cm->counts.ext_tx, zero_counts.ext_tx,
+                 sizeof(cm->counts.ext_tx)));
+#endif
 }
 #endif  // NDEBUG
 
index 1afaee1e3ba7b96e3d488e3809033e5faf024e37..15309d2a0199af08fdafa4a6ceb2c79ae8fcb0aa 100644 (file)
@@ -175,29 +175,85 @@ static void read_intra_frame_mode_info(VP9_COMMON *const cm,
 
   switch (bsize) {
     case BLOCK_4X4:
+#if !CONFIG_FILTERINTRA
       for (i = 0; i < 4; ++i)
+#else
+      for (i = 0; i < 4; ++i) {
+#endif
         mi->bmi[i].as_mode =
             read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, i));
+#if CONFIG_FILTERINTRA
+        if (is_filter_allowed(mi->bmi[i].as_mode))
+          mi->b_filter_info[i] =
+              vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[i].as_mode]);
+        else
+          mi->b_filter_info[i] = 0;
+      }
+      mbmi->filterbit = mi->b_filter_info[3];
+#endif
       mbmi->mode = mi->bmi[3].as_mode;
       break;
     case BLOCK_4X8:
       mi->bmi[0].as_mode = mi->bmi[2].as_mode =
           read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mi->bmi[0].as_mode))
+        mi->b_filter_info[0] = mi->b_filter_info[2] =
+            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
+      else
+        mi->b_filter_info[0] = mi->b_filter_info[2] = 0;
+#endif
       mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
           read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 1));
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mi->bmi[1].as_mode))
+        mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit =
+            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[1].as_mode]);
+      else
+        mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit = 0;
+#endif
       break;
     case BLOCK_8X4:
       mi->bmi[0].as_mode = mi->bmi[1].as_mode =
           read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mi->bmi[0].as_mode))
+        mi->b_filter_info[0] = mi->b_filter_info[1] =
+            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
+      else
+        mi->b_filter_info[0] = mi->b_filter_info[1] = 0;
+#endif
       mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
           read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 2));
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mi->bmi[2].as_mode))
+        mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit =
+            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[2].as_mode]);
+      else
+        mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit = 0;
+#endif
       break;
     default:
       mbmi->mode = read_intra_mode(r,
                                    get_y_mode_probs(mi, above_mi, left_mi, 0));
+#if CONFIG_FILTERINTRA
+      if (is_filter_enabled(mbmi->tx_size) && is_filter_allowed(mbmi->mode))
+        mbmi->filterbit = vp9_read(r,
+                            cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
+      else
+        mbmi->filterbit = 0;
+#endif
   }
 
   mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]);
+#if CONFIG_FILTERINTRA
+  if (is_filter_enabled(get_uv_tx_size(mbmi)) &&
+      is_filter_allowed(mbmi->uv_mode))
+    mbmi->uv_filterbit = vp9_read(r,
+        cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
+  else
+    mbmi->uv_filterbit = 0;
+#endif
 }
 
 static int read_mv_component(vp9_reader *r,
@@ -335,25 +391,97 @@ static void read_intra_block_mode_info(VP9_COMMON *const cm, MODE_INFO *mi,
 
   switch (bsize) {
     case BLOCK_4X4:
+#if !CONFIG_FILTERINTRA
       for (i = 0; i < 4; ++i)
+#else
+      for (i = 0; i < 4; ++i) {
+#endif
         mi->bmi[i].as_mode = read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+        if (is_filter_allowed(mi->bmi[i].as_mode)) {
+          mi->b_filter_info[i] =
+              vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[i].as_mode]);
+          cm->counts.filterintra[0][mi->bmi[i].as_mode]
+                                   [mi->b_filter_info[i]]++;
+        } else {
+          mi->b_filter_info[i] = 0;
+        }
+      }
+      mbmi->filterbit = mi->b_filter_info[3];
+#endif
       mbmi->mode = mi->bmi[3].as_mode;
       break;
     case BLOCK_4X8:
       mi->bmi[0].as_mode = mi->bmi[2].as_mode = read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mi->bmi[0].as_mode)) {
+        mi->b_filter_info[0] = mi->b_filter_info[2] =
+            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
+        cm->counts.filterintra[0][mi->bmi[0].as_mode][mi->b_filter_info[0]]++;
+      } else {
+        mi->b_filter_info[0] = mi->b_filter_info[2] = 0;
+      }
+#endif
       mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
           read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mi->bmi[1].as_mode)) {
+        mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit =
+            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[1].as_mode]);
+        cm->counts.filterintra[0][mi->bmi[1].as_mode][mi->b_filter_info[1]]++;
+      } else {
+        mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit = 0;
+      }
+#endif
       break;
     case BLOCK_8X4:
       mi->bmi[0].as_mode = mi->bmi[1].as_mode = read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mi->bmi[0].as_mode)) {
+        mi->b_filter_info[0] = mi->b_filter_info[1] =
+            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
+        cm->counts.filterintra[0][mi->bmi[0].as_mode][mi->b_filter_info[0]]++;
+      } else {
+        mi->b_filter_info[0] = mi->b_filter_info[1] = 0;
+      }
+#endif
       mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
           read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mi->bmi[2].as_mode)) {
+        mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit =
+            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[2].as_mode]);
+        cm->counts.filterintra[0][mi->bmi[2].as_mode][mi->b_filter_info[2]]++;
+      } else {
+        mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit = 0;
+      }
+#endif
       break;
     default:
       mbmi->mode = read_intra_mode_y(cm, r, size_group_lookup[bsize]);
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size)) {
+        mbmi->filterbit = vp9_read(r,
+            cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
+        cm->counts.filterintra[mbmi->tx_size][mbmi->mode][mbmi->filterbit]++;
+      } else {
+        mbmi->filterbit = 0;
+      }
+#endif
   }
 
   mbmi->uv_mode = read_intra_mode_uv(cm, r, mbmi->mode);
+#if CONFIG_FILTERINTRA
+  if (is_filter_allowed(mbmi->uv_mode) &&
+      is_filter_enabled(get_uv_tx_size(mbmi))) {
+    mbmi->uv_filterbit = vp9_read(r,
+        cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
+    cm->counts.filterintra[get_uv_tx_size(mbmi)]
+                           [mbmi->uv_mode][mbmi->uv_filterbit]++;
+  } else {
+    mbmi->uv_filterbit = 0;
+  }
+#endif
 }
 
 static INLINE int is_mv_valid(const MV *mv) {
@@ -433,6 +561,19 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
   read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame);
   is_compound = has_second_ref(mbmi);
 
+#if CONFIG_EXT_TX
+  if (mbmi->tx_size <= TX_16X16 &&
+      bsize >= BLOCK_8X8 &&
+      !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP) &&
+      !mbmi->skip) {
+    mbmi->ext_txfrm = vp9_read(r, cm->fc.ext_tx_prob);
+    if (!cm->frame_parallel_decoding_mode)
+      ++cm->counts.ext_tx[mbmi->ext_txfrm];
+  } else {
+    mbmi->ext_txfrm = NORM;
+  }
+#endif
+
   for (ref = 0; ref < 1 + is_compound; ++ref) {
     const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
     vp9_find_mv_refs(cm, xd, tile, mi, frame, mbmi->ref_mvs[frame],
@@ -464,6 +605,37 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
                       ? read_switchable_interp_filter(cm, xd, r)
                       : cm->interp_filter;
 
+#if CONFIG_INTERINTRA
+    if ((cm->use_interintra) &&
+        is_interintra_allowed(bsize) &&
+        is_inter_mode(mbmi->mode) &&
+        (mbmi->ref_frame[1] <= INTRA_FRAME)) {
+      mbmi->ref_frame[1] = vp9_read(r, cm->fc.interintra_prob[bsize]) ?
+                           INTRA_FRAME : NONE;
+      cm->counts.interintra[bsize][mbmi->ref_frame[1] == INTRA_FRAME]++;
+#if CONFIG_MASKED_INTERINTRA
+      mbmi->use_masked_interintra = 0;
+#endif
+      if (mbmi->ref_frame[1] == INTRA_FRAME) {
+        mbmi->interintra_mode =
+            read_intra_mode_y(cm, r, size_group_lookup[bsize]);
+        mbmi->interintra_uv_mode = mbmi->interintra_mode;
+#if CONFIG_MASKED_INTERINTRA
+        if (cm->use_masked_interintra && get_mask_bits_interintra(bsize)) {
+          mbmi->use_masked_interintra = vp9_read(r,
+                                          cm->fc.masked_interintra_prob[bsize]);
+          cm->counts.masked_interintra[bsize][mbmi->use_masked_interintra]++;
+          if (mbmi->use_masked_interintra) {
+            mbmi->interintra_mask_index = vp9_read_literal(r,
+                                               get_mask_bits_interintra(bsize));
+            mbmi->interintra_uv_mask_index = mbmi->interintra_mask_index;
+          }
+        }
+#endif
+      }
+    }
+#endif
+
   if (bsize < BLOCK_8X8) {
     const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];  // 1 or 2
     const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];  // 1 or 2
@@ -508,6 +680,21 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
     xd->corrupted |= !assign_mv(cm, mbmi->mode, mbmi->mv, nearestmv,
                                 nearestmv, nearmv, is_compound, allow_hp, r);
   }
+#if CONFIG_MASKED_INTERINTER
+  mbmi->use_masked_interinter = 0;
+  if (cm->use_masked_interinter &&
+      cm->reference_mode != SINGLE_REFERENCE &&
+      is_inter_mode(mbmi->mode) &&
+      get_mask_bits(bsize) &&
+      mbmi->ref_frame[1] > INTRA_FRAME) {
+    mbmi->use_masked_interinter =
+        vp9_read(r, cm->fc.masked_interinter_prob[bsize]);
+    cm->counts.masked_interinter[bsize][mbmi->use_masked_interinter]++;
+    if (mbmi->use_masked_interinter) {
+      mbmi->mask_index = vp9_read_literal(r, get_mask_bits(bsize));
+    }
+  }
+#endif
 }
 
 static void read_inter_frame_mode_info(VP9_COMMON *const cm,
index 1bf826a56f619e864e613afa41632d71c9eaf2b2..cbc12a584317984acd02c14b5f62c087a41a6683 100644 (file)
@@ -266,6 +266,12 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
   if (!is_inter) {
     if (bsize >= BLOCK_8X8) {
       write_intra_mode(w, mode, cm->fc.y_mode_prob[size_group_lookup[bsize]]);
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mode) && is_filter_enabled(mbmi->tx_size)) {
+        vp9_write(w, mbmi->filterbit,
+                  cm->fc.filterintra_prob[mbmi->tx_size][mode]);
+      }
+#endif
     } else {
       int idx, idy;
       const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
@@ -274,15 +280,37 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
         for (idx = 0; idx < 2; idx += num_4x4_w) {
           const PREDICTION_MODE b_mode = mi->bmi[idy * 2 + idx].as_mode;
           write_intra_mode(w, b_mode, cm->fc.y_mode_prob[0]);
+#if CONFIG_FILTERINTRA
+          if (is_filter_allowed(b_mode)) {
+            vp9_write(w, mi->b_filter_info[idy * 2 + idx],
+                      cm->fc.filterintra_prob[0][b_mode]);
+          }
+#endif
         }
       }
     }
     write_intra_mode(w, mbmi->uv_mode, cm->fc.uv_mode_prob[mode]);
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(mbmi->uv_mode) &&
+        is_filter_enabled(get_uv_tx_size(mbmi))) {
+      vp9_write(w, mbmi->uv_filterbit,
+                cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
+    }
+#endif
   } else {
     const int mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]];
     const vp9_prob *const inter_probs = cm->fc.inter_mode_probs[mode_ctx];
     write_ref_frames(cpi, w);
 
+#if CONFIG_EXT_TX
+    if (mbmi->tx_size <= TX_16X16 &&
+        bsize >= BLOCK_8X8 &&
+        !mbmi->skip &&
+        !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
+      vp9_write(w, mbmi->ext_txfrm, cm->fc.ext_tx_prob);
+    }
+#endif
+
     // If segment skip is not enabled code the mode.
     if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)) {
       if (bsize >= BLOCK_8X8) {
@@ -300,6 +328,32 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
       assert(mbmi->interp_filter == cm->interp_filter);
     }
 
+#if CONFIG_INTERINTRA
+    if ((cm->use_interintra) &&
+        cpi->common.reference_mode != COMPOUND_REFERENCE &&
+        is_interintra_allowed(bsize) &&
+        is_inter_mode(mode) &&
+        (mbmi->ref_frame[1] <= INTRA_FRAME)) {
+        vp9_write(w, mbmi->ref_frame[1] == INTRA_FRAME,
+                  cm->fc.interintra_prob[bsize]);
+        if (mbmi->ref_frame[1] == INTRA_FRAME) {
+          write_intra_mode(w, mbmi->interintra_mode,
+                           cm->fc.y_mode_prob[size_group_lookup[bsize]]);
+#if CONFIG_MASKED_INTERINTRA
+        if (get_mask_bits_interintra(bsize) &&
+            cm->use_masked_interintra) {
+          vp9_write(w, mbmi->use_masked_interintra,
+                    cm->fc.masked_interintra_prob[bsize]);
+          if (mbmi->use_masked_interintra) {
+            vp9_write_literal(w, mbmi->interintra_mask_index,
+                              get_mask_bits_interintra(bsize));
+          }
+        }
+#endif
+      }
+    }
+#endif
+
     if (bsize < BLOCK_8X8) {
       const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
       const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
@@ -326,6 +380,18 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
                         allow_hp);
       }
     }
+#if CONFIG_MASKED_INTERINTER
+  if (cm->use_masked_interinter &&
+      cm->reference_mode != SINGLE_REFERENCE &&
+      is_inter_mode(mode) &&
+      get_mask_bits(mbmi->sb_type) &&
+      mbmi->ref_frame[1] > INTRA_FRAME) {
+    vp9_write(w, mbmi->use_masked_interinter,
+              cm->fc.masked_interinter_prob[bsize]);
+    if (mbmi->use_masked_interinter)
+      vp9_write_literal(w, mbmi->mask_index, get_mask_bits(mbmi->sb_type));
+  }
+#endif
   }
 }
 
@@ -350,6 +416,11 @@ static void write_mb_modes_kf(const VP9_COMP *cpi, MODE_INFO **mi_8x8,
 
   if (bsize >= BLOCK_8X8) {
     write_intra_mode(w, mbmi->mode, get_y_mode_probs(mi, above_mi, left_mi, 0));
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size))
+      vp9_write(w, mbmi->filterbit,
+                cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
+#endif
   } else {
     const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
     const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
@@ -360,11 +431,22 @@ static void write_mb_modes_kf(const VP9_COMP *cpi, MODE_INFO **mi_8x8,
         const int block = idy * 2 + idx;
         write_intra_mode(w, mi->bmi[block].as_mode,
                          get_y_mode_probs(mi, above_mi, left_mi, block));
+#if CONFIG_FILTERINTRA
+        if (is_filter_allowed(mi->bmi[block].as_mode))
+          vp9_write(w, mi->b_filter_info[block],
+                    cm->fc.filterintra_prob[0][mi->bmi[block].as_mode]);
+#endif
       }
     }
   }
 
   write_intra_mode(w, mbmi->uv_mode, vp9_kf_uv_mode_prob[mbmi->mode]);
+#if CONFIG_FILTERINTRA
+  if (is_filter_allowed(mbmi->uv_mode) &&
+      is_filter_enabled(get_uv_tx_size(mbmi)))
+    vp9_write(w, mbmi->uv_filterbit,
+              cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
+#endif
 }
 
 static void write_modes_b(VP9_COMP *cpi, const TileInfo *const tile,
@@ -1176,6 +1258,95 @@ static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) {
                        cm->counts.partition[i], PARTITION_TYPES, &header_bc);
 
     vp9_write_nmv_probs(cm, cm->allow_high_precision_mv, &header_bc);
+
+#if CONFIG_EXT_TX
+    vp9_cond_prob_diff_update(&header_bc, &fc->ext_tx_prob, cm->counts.ext_tx);
+#endif
+
+#if CONFIG_MASKED_INTERINTER
+    if (cm->reference_mode != SINGLE_REFERENCE) {
+      if (!cpi->dummy_packing && cm->use_masked_interinter) {
+        cm->use_masked_interinter = 0;
+        for (i = 0; i < BLOCK_SIZES; i++)
+          if (get_mask_bits(i) && (cm->counts.masked_interinter[i][1] > 0)) {
+            cm->use_masked_interinter = 1;
+            break;
+          }
+      }
+      vp9_write_bit(&header_bc, cm->use_masked_interinter);
+      if (cm->use_masked_interinter) {
+        for (i = 0; i < BLOCK_SIZES; i++)
+          if (get_mask_bits(i))
+            vp9_cond_prob_diff_update(&header_bc,
+                                      &fc->masked_interinter_prob[i],
+                                      cm->counts.masked_interinter[i]);
+      } else {
+        vp9_zero(cm->counts.masked_interinter);
+      }
+    } else {
+      if (!cpi->dummy_packing)
+        cm->use_masked_interinter = 0;
+      vp9_zero(cm->counts.masked_interinter);
+    }
+#endif
+
+#if CONFIG_INTERINTRA
+    if (cm->reference_mode != COMPOUND_REFERENCE) {
+      if (!cpi->dummy_packing && cm->use_interintra) {
+        cm->use_interintra = 0;
+        for (i = 0; i < BLOCK_SIZES; i++) {
+          if (is_interintra_allowed(i) && (cm->counts.interintra[i][1] > 0)) {
+            cm->use_interintra = 1;
+            break;
+          }
+        }
+      }
+      vp9_write_bit(&header_bc, cm->use_interintra);
+      if (cm->use_interintra) {
+        for (i = 0; i < BLOCK_SIZES; i++) {
+          if (is_interintra_allowed(i)) {
+            vp9_cond_prob_diff_update(&header_bc,
+                                      &fc->interintra_prob[i],
+                                      cm->counts.interintra[i]);
+          }
+        }
+#if CONFIG_MASKED_INTERINTRA
+        if (!cpi->dummy_packing && cm->use_masked_interintra) {
+          cm->use_masked_interintra = 0;
+          for (i = 0; i < BLOCK_SIZES; i++) {
+            if (is_interintra_allowed(i) && get_mask_bits_interintra(i) &&
+                (cm->counts.masked_interintra[i][1] > 0)) {
+              cm->use_masked_interintra = 1;
+              break;
+            }
+          }
+        }
+        vp9_write_bit(&header_bc, cm->use_masked_interintra);
+        if (cm->use_masked_interintra) {
+          for (i = 0; i < BLOCK_SIZES; i++) {
+            if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
+              vp9_cond_prob_diff_update(&header_bc,
+                                        &fc->masked_interintra_prob[i],
+                                        cm->counts.masked_interintra[i]);
+          }
+        } else {
+          vp9_zero(cm->counts.masked_interintra);
+        }
+#endif
+      } else {
+        vp9_zero(cm->counts.interintra);
+      }
+    } else {
+      if (!cpi->dummy_packing)
+        cm->use_interintra = 0;
+      vp9_zero(cm->counts.interintra);
+#if CONFIG_MASKED_INTERINTRA
+      if (!cpi->dummy_packing)
+        cm->use_masked_interintra = 0;
+      vp9_zero(cm->counts.masked_interintra);
+#endif
+    }
+#endif
   }
 
   vp9_stop_encode(&header_bc);
index b9349a49a5303726e2c02ec38cd8c9c98cd5ae61..da07f9edb922625a177b8f2fcb21818519c79aa3 100644 (file)
@@ -410,6 +410,9 @@ static void choose_partitioning(VP9_COMP *cpi,
     vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col, sf);
 
     xd->mi[0]->mbmi.ref_frame[0] = LAST_FRAME;
+#if CONFIG_INTERINTRA
+    xd->mi[0]->mbmi.ref_frame[1] = NONE;
+#endif
     xd->mi[0]->mbmi.sb_type = BLOCK_64X64;
     vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv,
                           xd->mi[0]->mbmi.ref_mvs[LAST_FRAME],
@@ -630,6 +633,31 @@ static void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
         const int ctx = vp9_get_pred_context_switchable_interp(xd);
         ++cm->counts.switchable_interp[ctx][mbmi->interp_filter];
       }
+#if CONFIG_MASKED_INTERINTER
+      if (cm->use_masked_interinter &&
+          cm->reference_mode != SINGLE_REFERENCE &&
+          get_mask_bits(bsize) &&
+          mbmi->ref_frame[1] > INTRA_FRAME)
+        ++cm->counts.masked_interinter[bsize][mbmi->use_masked_interinter];
+#endif
+
+#if CONFIG_INTERINTRA
+    if (cm->use_interintra &&
+        is_interintra_allowed(bsize) &&
+        is_inter_mode(mbmi->mode) &&
+        (mbmi->ref_frame[1] <= INTRA_FRAME)) {
+      if (mbmi->ref_frame[1] == INTRA_FRAME) {
+        ++cm->counts.y_mode[size_group_lookup[bsize]][mbmi->interintra_mode];
+        ++cm->counts.interintra[bsize][1];
+#if CONFIG_MASKED_INTERINTRA
+        if (cm->use_masked_interintra && get_mask_bits_interintra(bsize))
+          ++cm->counts.masked_interintra[bsize][mbmi->use_masked_interintra];
+#endif
+      } else {
+        ++cm->counts.interintra[bsize][0];
+      }
+    }
+#endif
     }
 
     rd_opt->comp_pred_diff[SINGLE_REFERENCE] += ctx->single_pred_diff;
@@ -2337,6 +2365,16 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) {
              2 * aligned_mi_cols * MAX_MB_PLANE);
   vpx_memset(xd->above_seg_context, 0,
              sizeof(*xd->above_seg_context) * aligned_mi_cols);
+
+#if CONFIG_MASKED_INTERINTER
+  vp9_zero(cpi->masked_interinter_select_counts);
+#endif
+#if CONFIG_INTERINTRA
+  vp9_zero(cpi->interintra_select_count);
+#if CONFIG_MASKED_INTERINTRA
+  vp9_zero(cpi->masked_interintra_select_count);
+#endif
+#endif
 }
 
 static int check_dual_ref_flags(VP9_COMP *cpi) {
@@ -3232,6 +3270,10 @@ static void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi) {
   const PREDICTION_MODE y_mode = mi->mbmi.mode;
   const PREDICTION_MODE uv_mode = mi->mbmi.uv_mode;
   const BLOCK_SIZE bsize = mi->mbmi.sb_type;
+#if CONFIG_FILTERINTRA
+  const int uv_fbit = mi->mbmi.uv_filterbit;
+  int fbit = mi->mbmi.filterbit;
+#endif
 
   if (bsize < BLOCK_8X8) {
     int idx, idy;
@@ -3239,12 +3281,31 @@ static void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi) {
     const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
     for (idy = 0; idy < 2; idy += num_4x4_h)
       for (idx = 0; idx < 2; idx += num_4x4_w)
+#if CONFIG_FILTERINTRA
+      {
+#endif
         ++counts->y_mode[0][mi->bmi[idy * 2 + idx].as_mode];
+#if CONFIG_FILTERINTRA
+        if (is_filter_allowed(mi->bmi[idy * 2 + idx].as_mode)) {
+          fbit = mi->b_filter_info[idy * 2 + idx];
+          ++counts->filterintra[0][mi->bmi[idy * 2 + idx].as_mode][fbit];
+        }
+      }
+#endif
   } else {
     ++counts->y_mode[size_group_lookup[bsize]][y_mode];
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(y_mode) && is_filter_enabled(mi->mbmi.tx_size))
+      ++counts->filterintra[mi->mbmi.tx_size][y_mode][fbit];
+#endif
   }
 
   ++counts->uv_mode[y_mode][uv_mode];
+#if CONFIG_FILTERINTRA
+  if (is_filter_allowed(uv_mode) &&
+      is_filter_enabled(get_uv_tx_size(&(mi->mbmi))))
+    ++counts->filterintra[get_uv_tx_size(&(mi->mbmi))][uv_mode][uv_fbit];
+#endif
 }
 
 static int get_zbin_mode_boost(const MB_MODE_INFO *mbmi, int enabled) {
@@ -3360,5 +3421,15 @@ static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled,
           if (mi_col + x < cm->mi_cols && mi_row + y < cm->mi_rows)
             mi_8x8[mis * y + x]->mbmi.tx_size = tx_size;
     }
+
+#if CONFIG_EXT_TX
+    if (mbmi->tx_size <= TX_16X16 &&
+        is_inter_block(mbmi) &&
+        bsize >= BLOCK_8X8 &&
+        !mbmi->skip &&
+        !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
+      ++cm->counts.ext_tx[mbmi->ext_txfrm];
+    }
+#endif
   }
 }
index 1c00698b5f979d77995b4e27c9c6fca22945ec0e..243b06b5571306d6c5c84c810b6e39ba7efbae23 100644 (file)
@@ -360,6 +360,9 @@ void vp9_xform_quant(MACROBLOCK *x, int plane, int block,
   const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
   int i, j;
   const int16_t *src_diff;
+#if CONFIG_EXT_TX
+  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+#endif
   txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
   src_diff = &p->src_diff[4 * (j * diff_stride + i)];
 
@@ -372,21 +375,45 @@ void vp9_xform_quant(MACROBLOCK *x, int plane, int block,
                            scan_order->iscan);
       break;
     case TX_16X16:
+#if CONFIG_EXT_TX
+      if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
       vp9_fdct16x16(src_diff, coeff, diff_stride);
+#if CONFIG_EXT_TX
+      } else {
+        vp9_fht16x16(src_diff, coeff, diff_stride, ADST_ADST);
+      }
+#endif
       vp9_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round,
                      p->quant, p->quant_shift, qcoeff, dqcoeff,
                      pd->dequant, p->zbin_extra, eob,
                      scan_order->scan, scan_order->iscan);
       break;
     case TX_8X8:
+#if CONFIG_EXT_TX
+      if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
       vp9_fdct8x8(src_diff, coeff, diff_stride);
+#if CONFIG_EXT_TX
+      } else {
+        vp9_fht8x8(src_diff, coeff, diff_stride, ADST_ADST);
+      }
+#endif
       vp9_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round,
                      p->quant, p->quant_shift, qcoeff, dqcoeff,
                      pd->dequant, p->zbin_extra, eob,
                      scan_order->scan, scan_order->iscan);
       break;
     case TX_4X4:
+#if CONFIG_EXT_TX
+      if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
       x->fwd_txm4x4(src_diff, coeff, diff_stride);
+#if CONFIG_EXT_TX
+      } else {
+        vp9_fht4x4(src_diff, coeff, diff_stride, ADST_ADST);
+      }
+#endif
       vp9_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round,
                      p->quant, p->quant_shift, qcoeff, dqcoeff,
                      pd->dequant, p->zbin_extra, eob,
@@ -409,6 +436,9 @@ static void encode_block(int plane, int block, BLOCK_SIZE plane_bsize,
   int i, j;
   uint8_t *dst;
   ENTROPY_CONTEXT *a, *l;
+#if CONFIG_EXT_TX
+  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+#endif
   txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
   dst = &pd->dst.buf[4 * j * pd->dst.stride + 4 * i];
   a = &ctx->ta[plane][i];
@@ -454,16 +484,43 @@ static void encode_block(int plane, int block, BLOCK_SIZE plane_bsize,
       vp9_idct32x32_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
       break;
     case TX_16X16:
+#if CONFIG_EXT_TX
+      if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
       vp9_idct16x16_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
+#if CONFIG_EXT_TX
+      } else {
+        vp9_iht16x16_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
+                         p->eobs[block]);
+      }
+#endif
       break;
     case TX_8X8:
+#if CONFIG_EXT_TX
+      if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
       vp9_idct8x8_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
+#if CONFIG_EXT_TX
+      } else {
+        vp9_iht8x8_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
+                       p->eobs[block]);
+      }
+#endif
       break;
     case TX_4X4:
+#if CONFIG_EXT_TX
+      if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
       // this is like vp9_short_idct4x4 but has a special case around eob<=1
       // which is significant (not just an optimization) for the lossless
       // case.
       x->itxm_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
+#if CONFIG_EXT_TX
+      } else {
+        vp9_iht4x4_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
+                       p->eobs[block]);
+      }
+#endif
       break;
     default:
       assert(0 && "Invalid transform size");
@@ -479,6 +536,10 @@ static void encode_block_pass1(int plane, int block, BLOCK_SIZE plane_bsize,
   int16_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
   int i, j;
   uint8_t *dst;
+#if CONFIG_EXT_TX
+  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+  mbmi->ext_txfrm = NORM;
+#endif
   txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
   dst = &pd->dst.buf[4 * j * pd->dst.stride + 4 * i];
 
@@ -531,6 +592,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
   const scan_order *scan_order;
   TX_TYPE tx_type;
   PREDICTION_MODE mode;
+#if CONFIG_FILTERINTRA
+  int fbit = 0;
+#endif
   const int bwl = b_width_log2(plane_bsize);
   const int diff_stride = 4 * (1 << bwl);
   uint8_t *src, *dst;
@@ -544,11 +608,20 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
   src = &p->src.buf[4 * (j * src_stride + i)];
   src_diff = &p->src_diff[4 * (j * diff_stride + i)];
 
+#if CONFIG_FILTERINTRA
+      if (mbmi->sb_type < BLOCK_8X8 && plane == 0)
+        fbit = xd->mi[0]->b_filter_info[block];
+      else
+        fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
   switch (tx_size) {
     case TX_32X32:
       scan_order = &vp9_default_scan_orders[TX_32X32];
       mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
       vp9_predict_intra_block(xd, block >> 6, bwl, TX_32X32, mode,
+#if CONFIG_FILTERINTRA
+                              fbit,
+#endif
                               x->skip_encode ? src : dst,
                               x->skip_encode ? src_stride : dst_stride,
                               dst, dst_stride, i, j, plane);
@@ -569,6 +642,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
       scan_order = &vp9_scan_orders[TX_16X16][tx_type];
       mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
       vp9_predict_intra_block(xd, block >> 4, bwl, TX_16X16, mode,
+#if CONFIG_FILTERINTRA
+                              fbit,
+#endif
                               x->skip_encode ? src : dst,
                               x->skip_encode ? src_stride : dst_stride,
                               dst, dst_stride, i, j, plane);
@@ -589,6 +665,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
       scan_order = &vp9_scan_orders[TX_8X8][tx_type];
       mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
       vp9_predict_intra_block(xd, block >> 2, bwl, TX_8X8, mode,
+#if CONFIG_FILTERINTRA
+                              fbit,
+#endif
                               x->skip_encode ? src : dst,
                               x->skip_encode ? src_stride : dst_stride,
                               dst, dst_stride, i, j, plane);
@@ -609,6 +688,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
       scan_order = &vp9_scan_orders[TX_4X4][tx_type];
       mode = plane == 0 ? get_y_mode(xd->mi[0], block) : mbmi->uv_mode;
       vp9_predict_intra_block(xd, block, bwl, TX_4X4, mode,
+#if CONFIG_FILTERINTRA
+                              fbit,
+#endif
                               x->skip_encode ? src : dst,
                               x->skip_encode ? src_stride : dst_stride,
                               dst, dst_stride, i, j, plane);
index 6e07f08cfd84bc7424219bbec3b0dadac6170f3e..bd9fd4ea0365ae0e47846cc3a6d6422212f1b3c6 100644 (file)
@@ -985,6 +985,41 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
       vp9_sub_pixel_avg_variance4x4,
       vp9_sad4x4x3, vp9_sad4x4x8, vp9_sad4x4x4d)
 
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+    CONFIG_MASKED_INTERINTER)
+#define MBFP(BT, MSDF, MVF, MSVF) \
+  cpi->fn_ptr[BT].msdf            = MSDF; \
+  cpi->fn_ptr[BT].mvf             = MVF; \
+  cpi->fn_ptr[BT].msvf            = MSVF;
+
+  MBFP(BLOCK_64X64, vp9_masked_sad64x64, vp9_masked_variance64x64,
+       vp9_masked_sub_pixel_variance64x64)
+  MBFP(BLOCK_64X32, vp9_masked_sad64x32, vp9_masked_variance64x32,
+         vp9_masked_sub_pixel_variance64x32)
+  MBFP(BLOCK_32X64, vp9_masked_sad32x64, vp9_masked_variance32x64,
+         vp9_masked_sub_pixel_variance32x64)
+  MBFP(BLOCK_32X32, vp9_masked_sad32x32, vp9_masked_variance32x32,
+       vp9_masked_sub_pixel_variance32x32)
+  MBFP(BLOCK_32X16, vp9_masked_sad32x16, vp9_masked_variance32x16,
+       vp9_masked_sub_pixel_variance32x16)
+  MBFP(BLOCK_16X32, vp9_masked_sad16x32, vp9_masked_variance16x32,
+       vp9_masked_sub_pixel_variance16x32)
+  MBFP(BLOCK_16X16, vp9_masked_sad16x16, vp9_masked_variance16x16,
+         vp9_masked_sub_pixel_variance16x16)
+  MBFP(BLOCK_16X8, vp9_masked_sad16x8, vp9_masked_variance16x8,
+         vp9_masked_sub_pixel_variance16x8)
+  MBFP(BLOCK_8X16, vp9_masked_sad8x16, vp9_masked_variance8x16,
+         vp9_masked_sub_pixel_variance8x16)
+  MBFP(BLOCK_8X8, vp9_masked_sad8x8, vp9_masked_variance8x8,
+       vp9_masked_sub_pixel_variance8x8)
+  MBFP(BLOCK_4X8, vp9_masked_sad4x8, vp9_masked_variance4x8,
+       vp9_masked_sub_pixel_variance4x8)
+  MBFP(BLOCK_8X4, vp9_masked_sad8x4, vp9_masked_variance8x4,
+       vp9_masked_sub_pixel_variance8x4)
+  MBFP(BLOCK_4X4, vp9_masked_sad4x4, vp9_masked_variance4x4,
+       vp9_masked_sub_pixel_variance4x4)
+#endif
+
   cpi->full_search_sad = vp9_full_search_sad;
   cpi->diamond_search_sad = vp9_diamond_search_sad;
   cpi->refining_search_sad = vp9_refining_search_sad;
@@ -1967,6 +2002,45 @@ YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
   }
 }
 
+#if CONFIG_MASKED_INTERINTER
+static void select_masked_interinter_mode(VP9_COMP *cpi) {
+  static const double threshold = 1/128.0;
+  VP9_COMMON *cm = &cpi->common;
+  int sum = cpi->masked_interinter_select_counts[1] +
+      cpi->masked_interinter_select_counts[0];
+  if (sum) {
+    double fraction = (double) cpi->masked_interinter_select_counts[1] / sum;
+    cm->use_masked_interinter = (fraction > threshold);
+  }
+}
+#endif
+
+#if CONFIG_INTERINTRA
+static void select_interintra_mode(VP9_COMP *cpi) {
+  static const double threshold = 0.007;
+  VP9_COMMON *cm = &cpi->common;
+  int sum = cpi->interintra_select_count[1] + cpi->interintra_select_count[0];
+  if (sum) {
+    double fraction = (double)cpi->interintra_select_count[1] / (double)sum;
+    cm->use_interintra = (fraction > threshold);
+  }
+}
+
+#if CONFIG_MASKED_INTERINTRA
+static void select_masked_interintra_mode(VP9_COMP *cpi) {
+  static const double threshold = 1/100.0;
+  VP9_COMMON *cm = &cpi->common;
+  int sum = cpi->masked_interintra_select_count[1] +
+      cpi->masked_interintra_select_count[0];
+  if (sum) {
+    double fraction = (double)cpi->masked_interintra_select_count[1] /
+                      (double)sum;
+    cm->use_masked_interintra = (fraction > threshold);
+  }
+}
+#endif
+#endif
+
 static void encode_frame_to_data_rate(VP9_COMP *cpi,
                                       size_t *size,
                                       uint8_t *dest,
@@ -2120,6 +2194,20 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
     vp9_set_high_precision_mv(cpi, q < HIGH_PRECISION_MV_QTHRESH);
   }
 
+#if CONFIG_MASKED_INTERINTER
+  if (cm->current_video_frame == 0)
+    cm->use_masked_interinter = 0;
+#endif
+
+#if CONFIG_INTERINTRA
+  if (cm->current_video_frame == 0) {
+    cm->use_interintra = 1;
+#if CONFIG_MASKED_INTERINTRA
+    cm->use_masked_interintra = 1;
+#endif
+  }
+#endif
+
   if (cpi->sf.recode_loop == DISALLOW_RECODE) {
     encode_without_recode_loop(cpi, q);
   } else {
@@ -2181,6 +2269,18 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
       vp9_adapt_mode_probs(cm);
       vp9_adapt_mv_probs(cm, cm->allow_high_precision_mv);
     }
+#if CONFIG_MASKED_INTERINTER
+    select_masked_interinter_mode(cpi);
+#endif
+#if CONFIG_INTERINTRA
+    select_interintra_mode(cpi);
+#if CONFIG_MASKED_INTERINTRA
+    if (cpi->common.use_interintra)
+      select_masked_interintra_mode(cpi);
+    else
+      cpi->common.use_masked_interintra = 0;
+#endif
+#endif
   }
 
   if (cpi->refresh_golden_frame == 1)
index 47649a86329cb952efbd99c489bc504eb71e79f3..f70b995463579ade37df501d30bf0f68ea92a75d 100644 (file)
@@ -64,7 +64,6 @@ typedef struct {
   FRAME_CONTEXT fc;
 } CODING_CONTEXT;
 
-
 typedef enum {
   // encode_breakout is disabled.
   ENCODE_BREAKOUT_DISABLED = 0,
@@ -422,6 +421,16 @@ typedef struct VP9_COMP {
 #if CONFIG_DENOISING
   VP9_DENOISER denoiser;
 #endif
+
+#if CONFIG_MASKED_INTERINTER
+  unsigned int masked_interinter_select_counts[2];
+#endif
+#if CONFIG_INTERINTRA
+  unsigned int interintra_select_count[2];
+#if CONFIG_MASKED_INTERINTRA
+  unsigned int masked_interintra_select_count[2];
+#endif
+#endif
 } VP9_COMP;
 
 void vp9_initialize_enc();
index 81069606e9038bd06310920b25b0783d4c4815d4..338445a737a4830cd600d22621999ceef45d71bf 100644 (file)
@@ -64,6 +64,9 @@ static unsigned int do_16x16_motion_iteration(VP9_COMP *cpi,
   xd->mi[0]->mbmi.mode = NEWMV;
   xd->mi[0]->mbmi.mv[0].as_mv = *dst_mv;
 
+#if CONFIG_INTERINTRA
+  xd->mi[0]->mbmi.ref_frame[1] = NONE;
+#endif
   vp9_build_inter_predictors_sby(xd, mb_row, mb_col, BLOCK_16X16);
 
   /* restore UMV window */
@@ -141,6 +144,9 @@ static int find_best_16x16_intra(VP9_COMP *cpi, PREDICTION_MODE *pbest_mode) {
 
     xd->mi[0]->mbmi.mode = mode;
     vp9_predict_intra_block(xd, 0, 2, TX_16X16, mode,
+#if CONFIG_FILTERINTRA
+                            0,
+#endif
                             x->plane[0].src.buf, x->plane[0].src.stride,
                             xd->plane[0].dst.buf, xd->plane[0].dst.stride,
                             0, 0, 0);
index cb45dfae34cb085e3f9e19f9385d8116c0660d2e..3d241307df77ef68c64cd144bebec091f70e50af 100644 (file)
@@ -1640,3 +1640,354 @@ int vp9_full_pixel_search(VP9_COMP *cpi, MACROBLOCK *x,
 
   return var;
 }
+
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+    CONFIG_MASKED_INTERINTER)
+/* returns subpixel variance error function */
+#define DIST(r, c) \
+    vfp->msvf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
+              src_stride, mask, mask_stride, &sse)
+
+/* checks if (r, c) has better score than previous best */
+
+#define MVC(r, c)                                       \
+    (mvcost ?                                           \
+     ((mvjcost[((r) != rr) * 2 + ((c) != rc)] +         \
+       mvcost[0][((r) - rr)] + mvcost[1][((c) - rc)]) * \
+      error_per_bit + 4096) >> 13 : 0)
+
+#define CHECK_BETTER(v, r, c) \
+  if (c >= minc && c <= maxc && r >= minr && r <= maxr) {              \
+    thismse = (DIST(r, c));                                            \
+    if ((v = MVC(r, c) + thismse) < besterr) {                         \
+      besterr = v;                                                     \
+      br = r;                                                          \
+      bc = c;                                                          \
+      *distortion = thismse;                                           \
+      *sse1 = sse;                                                     \
+    }                                                                  \
+  } else {                                                             \
+    v = INT_MAX;                                                       \
+  }
+
+int vp9_find_best_masked_sub_pixel_tree(const MACROBLOCK *x,
+                                        uint8_t *mask, int mask_stride,
+                                        MV *bestmv, const MV *ref_mv,
+                                        int allow_hp,
+                                        int error_per_bit,
+                                        const vp9_variance_fn_ptr_t *vfp,
+                                        int forced_stop,
+                                        int iters_per_step,
+                                        int *mvjcost, int *mvcost[2],
+                                        int *distortion,
+                                        unsigned int *sse1, int is_second) {
+  const uint8_t *const z = x->plane[0].src.buf;
+  const int src_stride = x->plane[0].src.stride;
+  const MACROBLOCKD *xd = &x->e_mbd;
+  unsigned int besterr = INT_MAX;
+  unsigned int sse;
+  unsigned int whichdir;
+  int thismse;
+  unsigned int halfiters = iters_per_step;
+  unsigned int quarteriters = iters_per_step;
+  unsigned int eighthiters = iters_per_step;
+
+  const int y_stride = xd->plane[0].pre[is_second].stride;
+  const int offset = bestmv->row * y_stride + bestmv->col;
+  const uint8_t *const y = xd->plane[0].pre[is_second].buf;
+
+  int rr = ref_mv->row;
+  int rc = ref_mv->col;
+  int br = bestmv->row * 8;
+  int bc = bestmv->col * 8;
+  int hstep = 4;
+  const int minc = MAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
+  const int maxc = MIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
+  const int minr = MAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
+  const int maxr = MIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
+
+  int tr = br;
+  int tc = bc;
+
+  // central mv
+  bestmv->row *= 8;
+  bestmv->col *= 8;
+
+  // calculate central point error
+  besterr = vfp->mvf(y + offset, y_stride, z, src_stride, mask, mask_stride,
+                     sse1);
+  *distortion = besterr;
+  besterr += mv_err_cost(bestmv, ref_mv, mvjcost, mvcost, error_per_bit);
+
+  // 1/2 pel
+  FIRST_LEVEL_CHECKS;
+  if (halfiters > 1) {
+    SECOND_LEVEL_CHECKS;
+  }
+  tr = br;
+  tc = bc;
+
+  // Note forced_stop: 0 - full, 1 - qtr only, 2 - half only
+  if (forced_stop != 2) {
+    hstep >>= 1;
+    FIRST_LEVEL_CHECKS;
+    if (quarteriters > 1) {
+      SECOND_LEVEL_CHECKS;
+    }
+    tr = br;
+    tc = bc;
+  }
+
+  if (allow_hp && vp9_use_mv_hp(ref_mv) && forced_stop == 0) {
+    hstep >>= 1;
+    FIRST_LEVEL_CHECKS;
+    if (eighthiters > 1) {
+      SECOND_LEVEL_CHECKS;
+    }
+    tr = br;
+    tc = bc;
+  }
+  // These lines insure static analysis doesn't warn that
+  // tr and tc aren't used after the above point.
+  (void) tr;
+  (void) tc;
+
+  bestmv->row = br;
+  bestmv->col = bc;
+
+  if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
+      (abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
+    return INT_MAX;
+
+  return besterr;
+}
+
+#undef DIST
+#undef MVC
+#undef CHECK_BETTER
+
+int vp9_get_masked_mvpred_var(const MACROBLOCK *x,
+                              uint8_t *mask, int mask_stride,
+                              const MV *best_mv, const MV *center_mv,
+                              const vp9_variance_fn_ptr_t *vfp,
+                              int use_mvcost, int is_second) {
+  const MACROBLOCKD *const xd = &x->e_mbd;
+  const struct buf_2d *const what = &x->plane[0].src;
+  const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
+  const MV mv = {best_mv->row * 8, best_mv->col * 8};
+  unsigned int unused;
+
+  return vfp->mvf(what->buf, what->stride,
+                  get_buf_from_mv(in_what, best_mv), in_what->stride,
+                  mask, mask_stride, &unused) +
+      (use_mvcost ?  mv_err_cost(&mv, center_mv, x->nmvjointcost,
+                                 x->mvcost, x->errorperbit) : 0);
+}
+
+int vp9_masked_refining_search_sad_c(const MACROBLOCK *x,
+                                     uint8_t *mask, int mask_stride,
+                                     MV *ref_mv, int error_per_bit,
+                                     int search_range,
+                                     const vp9_variance_fn_ptr_t *fn_ptr,
+                                     const MV *center_mv, int is_second) {
+  const MV neighbors[4] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}};
+  const MACROBLOCKD *const xd = &x->e_mbd;
+  const struct buf_2d *const what = &x->plane[0].src;
+  const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
+  const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
+  unsigned int best_sad = fn_ptr->msdf(what->buf, what->stride,
+                                       get_buf_from_mv(in_what, ref_mv),
+                                       in_what->stride, mask, mask_stride) +
+      mvsad_err_cost(x, ref_mv, &fcenter_mv, error_per_bit);
+  int i, j;
+
+  for (i = 0; i < search_range; i++) {
+    int best_site = -1;
+
+    for (j = 0; j < 4; j++) {
+      const MV mv = {ref_mv->row + neighbors[j].row,
+                     ref_mv->col + neighbors[j].col};
+      if (is_mv_in(x, &mv)) {
+        unsigned int sad = fn_ptr->msdf(what->buf, what->stride,
+            get_buf_from_mv(in_what, &mv), in_what->stride, mask, mask_stride);
+        if (sad < best_sad) {
+          sad += mvsad_err_cost(x, &mv, &fcenter_mv, error_per_bit);
+          if (sad < best_sad) {
+            best_sad = sad;
+            best_site = j;
+          }
+        }
+      }
+    }
+
+    if (best_site == -1) {
+      break;
+    } else {
+      ref_mv->row += neighbors[best_site].row;
+      ref_mv->col += neighbors[best_site].col;
+    }
+  }
+  return best_sad;
+}
+
+int vp9_masked_diamond_search_sad_c(const MACROBLOCK *x,
+                             const search_site_config *cfg,
+                             uint8_t *mask, int mask_stride,
+                             MV *ref_mv, MV *best_mv,
+                             int search_param, int sad_per_bit, int *num00,
+                             const vp9_variance_fn_ptr_t *fn_ptr,
+                             const MV *center_mv, int is_second) {
+  const MACROBLOCKD *const xd = &x->e_mbd;
+  const struct buf_2d *const what = &x->plane[0].src;
+  const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
+  // search_param determines the length of the initial step and hence the number
+  // of iterations
+  // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 =
+  // (MAX_FIRST_STEP/4) pel... etc.
+  const search_site *const ss = &cfg->ss[search_param * cfg->searches_per_step];
+  const int tot_steps = (cfg->ss_count / cfg->searches_per_step) - search_param;
+  const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
+  const uint8_t *best_address, *in_what_ref;
+  int best_sad = INT_MAX;
+  int best_site = 0;
+  int last_site = 0;
+  int i, j, step;
+
+  clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
+  in_what_ref = get_buf_from_mv(in_what, ref_mv);
+  best_address = in_what_ref;
+  *num00 = 0;
+  *best_mv = *ref_mv;
+
+  // Check the starting position
+  best_sad = fn_ptr->msdf(what->buf, what->stride,
+                         best_address, in_what->stride,
+                         mask, mask_stride) +
+      mvsad_err_cost(x, best_mv, &fcenter_mv, sad_per_bit);
+
+  i = 1;
+
+  for (step = 0; step < tot_steps; step++) {
+    for (j = 0; j < cfg->searches_per_step; j++) {
+      const MV mv = {best_mv->row + ss[i].mv.row,
+                     best_mv->col + ss[i].mv.col};
+      if (is_mv_in(x, &mv)) {
+       int sad = fn_ptr->msdf(what->buf, what->stride,
+                              best_address + ss[i].offset, in_what->stride,
+                              mask, mask_stride);
+        if (sad < best_sad) {
+          sad += mvsad_err_cost(x, &mv, &fcenter_mv, sad_per_bit);
+          if (sad < best_sad) {
+            best_sad = sad;
+            best_site = i;
+          }
+        }
+      }
+
+      i++;
+    }
+
+    if (best_site != last_site) {
+      best_mv->row += ss[best_site].mv.row;
+      best_mv->col += ss[best_site].mv.col;
+      best_address += ss[best_site].offset;
+      last_site = best_site;
+#if defined(NEW_DIAMOND_SEARCH)
+      while (1) {
+        const MV this_mv = {best_mv->row + ss[best_site].mv.row,
+                            best_mv->col + ss[best_site].mv.col};
+        if (is_mv_in(x, &this_mv)) {
+          int sad = fn_ptr->msdf(what->buf, what->stride,
+                                 best_address + ss[best_site].offset,
+                                 in_what->stride, mask, mask_stride);
+          if (sad < best_sad) {
+            sad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
+            if (sad < best_sad) {
+              best_sad = sad;
+              best_mv->row += ss[best_site].mv.row;
+              best_mv->col += ss[best_site].mv.col;
+              best_address += ss[best_site].offset;
+              continue;
+            }
+          }
+        }
+        break;
+      }
+#endif
+    } else if (best_address == in_what_ref) {
+      (*num00)++;
+    }
+  }
+  return best_sad;
+}
+
+int vp9_masked_full_pixel_diamond(const VP9_COMP *cpi, MACROBLOCK *x,
+                                  uint8_t *mask, int mask_stride,
+                                  MV *mvp_full, int step_param,
+                                  int sadpb, int further_steps, int do_refine,
+                                  const vp9_variance_fn_ptr_t *fn_ptr,
+                                  const MV *ref_mv, MV *dst_mv,
+                                  int is_second) {
+  MV temp_mv;
+  int thissme, n, num00 = 0;
+  int bestsme = vp9_masked_diamond_search_sad_c(x, &cpi->ss_cfg,
+                                                mask, mask_stride,
+                                                mvp_full, &temp_mv,
+                                                step_param, sadpb, &n,
+                                                fn_ptr, ref_mv, is_second);
+  if (bestsme < INT_MAX)
+    bestsme = vp9_get_masked_mvpred_var(x, mask, mask_stride, &temp_mv, ref_mv,
+                                        fn_ptr, 1, is_second);
+  *dst_mv = temp_mv;
+
+  // If there won't be more n-step search, check to see if refining search is
+  // needed.
+  if (n > further_steps)
+    do_refine = 0;
+
+  while (n < further_steps) {
+    ++n;
+
+    if (num00) {
+      num00--;
+    } else {
+      thissme = vp9_masked_diamond_search_sad_c(x, &cpi->ss_cfg,
+                                                mask, mask_stride,
+                                                mvp_full, &temp_mv,
+                                                step_param + n, sadpb, &num00,
+                                                fn_ptr, ref_mv, is_second);
+      if (thissme < INT_MAX)
+        thissme = vp9_get_masked_mvpred_var(x, mask, mask_stride,
+                                            &temp_mv, ref_mv, fn_ptr, 1,
+                                            is_second);
+
+      // check to see if refining search is needed.
+      if (num00 > further_steps - n)
+        do_refine = 0;
+
+      if (thissme < bestsme) {
+        bestsme = thissme;
+        *dst_mv = temp_mv;
+      }
+    }
+  }
+
+  // final 1-away diamond refining search
+  if (do_refine) {
+    const int search_range = 8;
+    MV best_mv = *dst_mv;
+    thissme = vp9_masked_refining_search_sad_c(x, mask, mask_stride,
+                                               &best_mv, sadpb, search_range,
+                                               fn_ptr, ref_mv, is_second);
+    if (thissme < INT_MAX)
+      thissme = vp9_get_masked_mvpred_var(x, mask, mask_stride,
+                                          &best_mv, ref_mv, fn_ptr, 1,
+                                          is_second);
+    if (thissme < bestsme) {
+      bestsme = thissme;
+      *dst_mv = best_mv;
+    }
+  }
+  return bestsme;
+}
+#endif
index 07e410d3c5aa7c75f9e57785f48b4fb941ca267f..ae69db66be1f83d6fcf3e6459c92b8501098e350 100644 (file)
@@ -153,6 +153,29 @@ int vp9_full_pixel_search(struct VP9_COMP *cpi, MACROBLOCK *x,
                           int step_param, int error_per_bit,
                           const MV *ref_mv, MV *tmp_mv,
                           int var_max, int rd);
+
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+    CONFIG_MASKED_INTERINTER)
+int vp9_find_best_masked_sub_pixel_tree(const MACROBLOCK *x,
+                                        uint8_t *mask, int mask_stride,
+                                        MV *bestmv, const MV *ref_mv,
+                                        int allow_hp,
+                                        int error_per_bit,
+                                        const vp9_variance_fn_ptr_t *vfp,
+                                        int forced_stop,
+                                        int iters_per_step,
+                                        int *mvjcost, int *mvcost[2],
+                                        int *distortion,
+                                        unsigned int *sse1, int is_second);
+int vp9_masked_full_pixel_diamond(const struct VP9_COMP *cpi, MACROBLOCK *x,
+                                  uint8_t *mask, int mask_stride,
+                                  MV *mvp_full, int step_param,
+                                  int sadpb, int further_steps, int do_refine,
+                                  const vp9_variance_fn_ptr_t *fn_ptr,
+                                  const MV *ref_mv, MV *dst_mv,
+                                  int is_second);
+#endif
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
index 4c340ea0bf6d4328d5d0a4017eb361e858d40df7..064d5b967f680218117e89835ff4e2acdca83ca1 100644 (file)
@@ -689,6 +689,9 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
         for (i = 0; i < width; i += step) {
           vp9_predict_intra_block(xd, block_idx, b_width_log2(bsize),
                                   mbmi->tx_size, this_mode,
+#if CONFIG_FILTERINTRA
+                                  0,
+#endif
                                   &p->src.buf[4 * (j * dst_stride + i)],
                                   src_stride,
                                   &pd->dst.buf[4 * (j * dst_stride + i)],
@@ -699,7 +702,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
           ++block_idx;
         }
       }
-
       rate = rate2;
       dist = dist2;
 
index 9402d4a4e4a36e4a6342ab116a6f2fa21b417ce7..03b7a2758e19bc764c17f19e76fd4151b2a7a00f 100644 (file)
@@ -117,6 +117,23 @@ static const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
   {D63_PRED,  {INTRA_FRAME,  NONE}},
   {D117_PRED, {INTRA_FRAME,  NONE}},
   {D45_PRED,  {INTRA_FRAME,  NONE}},
+
+#if CONFIG_INTERINTRA
+  {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
 };
 
 static const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
@@ -1059,6 +1076,9 @@ static int conditional_skipintra(PREDICTION_MODE mode,
 
 static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
                                      PREDICTION_MODE *best_mode,
+#if CONFIG_FILTERINTRA
+                                     int *best_fbit,
+#endif
                                      const int *bmode_costs,
                                      ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l,
                                      int *bestrate, int *bestratey,
@@ -1083,6 +1103,9 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
   const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
   int idx, idy;
   uint8_t best_dst[8 * 8];
+#if CONFIG_FILTERINTRA
+  int mode_ext, fbit;
+#endif
 
   assert(ib < 4);
 
@@ -1090,6 +1113,7 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
   vpx_memcpy(tl, l, sizeof(tl));
   xd->mi[0]->mbmi.tx_size = TX_4X4;
 
+#if !CONFIG_FILTERINTRA
   for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
     int64_t this_rd;
     int ratey = 0;
@@ -1105,6 +1129,22 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
       if (conditional_skipintra(mode, *best_mode))
           continue;
     }
+#else
+  for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; ++mode_ext) {
+    int64_t this_rd;
+    int ratey = 0;
+    int64_t distortion = 0;
+    int rate;
+
+    fbit = mode_ext & 1;
+    mode = mode_ext >> 1;
+    if (fbit && !is_filter_allowed(mode))
+      continue;
+
+    rate = bmode_costs[mode];
+    if (is_filter_allowed(mode))
+      rate += vp9_cost_bit(cpi->common.fc.filterintra_prob[0][mode], fbit);
+#endif
 
     vpx_memcpy(tempa, ta, sizeof(ta));
     vpx_memcpy(templ, tl, sizeof(tl));
@@ -1118,8 +1158,14 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
                                                             p->src_diff);
         int16_t *const coeff = BLOCK_OFFSET(x->plane[0].coeff, block);
         xd->mi[0]->bmi[block].as_mode = mode;
+#if CONFIG_FILTERINTRA
+        xd->mi[0]->b_filter_info[block] = fbit;
+#endif
         vp9_predict_intra_block(xd, block, 1,
                                 TX_4X4, mode,
+#if CONFIG_FILTERINTRA
+                                fbit,
+#endif
                                 x->skip_encode ? src : dst,
                                 x->skip_encode ? src_stride : dst_stride,
                                 dst, dst_stride, idx, idy, 0);
@@ -1164,6 +1210,9 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
       *bestdistortion = distortion;
       best_rd = this_rd;
       *best_mode = mode;
+#if CONFIG_FILTERINTRA
+      *best_fbit = fbit;
+#endif
       vpx_memcpy(a, tempa, sizeof(tempa));
       vpx_memcpy(l, templ, sizeof(templ));
       for (idy = 0; idy < num_4x4_blocks_high * 4; ++idy)
@@ -1211,6 +1260,9 @@ static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP *cpi, MACROBLOCK *mb,
   for (idy = 0; idy < 2; idy += num_4x4_blocks_high) {
     for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
       PREDICTION_MODE best_mode = DC_PRED;
+#if CONFIG_FILTERINTRA
+      int best_fbit = 0;
+#endif
       int r = INT_MAX, ry = INT_MAX;
       int64_t d = INT64_MAX, this_rd = INT64_MAX;
       i = idy * 2 + idx;
@@ -1221,7 +1273,11 @@ static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP *cpi, MACROBLOCK *mb,
         bmode_costs  = cpi->y_mode_costs[A][L];
       }
 
-      this_rd = rd_pick_intra4x4block(cpi, mb, i, &best_mode, bmode_costs,
+      this_rd = rd_pick_intra4x4block(cpi, mb, i, &best_mode,
+#if CONFIG_FILTERINTRA
+                                      &best_fbit,
+#endif
+                                      bmode_costs,
                                       t_above + idx, t_left + idy, &r, &ry, &d,
                                       bsize, best_rd - total_rd);
       if (this_rd >= best_rd - total_rd)
@@ -1237,6 +1293,13 @@ static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP *cpi, MACROBLOCK *mb,
         mic->bmi[i + j * 2].as_mode = best_mode;
       for (j = 1; j < num_4x4_blocks_wide; ++j)
         mic->bmi[i + j].as_mode = best_mode;
+#if CONFIG_FILTERINTRA
+      mic->b_filter_info[i] = best_fbit;
+      for (j = 1; j < num_4x4_blocks_high; ++j)
+        mic->b_filter_info[i + j * 2] = best_fbit;
+      for (j = 1; j < num_4x4_blocks_wide; ++j)
+        mic->b_filter_info[i + j] = best_fbit;
+#endif
 
       if (total_rd >= best_rd)
         return INT64_MAX;
@@ -1247,6 +1310,9 @@ static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP *cpi, MACROBLOCK *mb,
   *rate_y = tot_rate_y;
   *distortion = total_distortion;
   mic->mbmi.mode = mic->bmi[3].as_mode;
+#if CONFIG_FILTERINTRA
+  mic->mbmi.filterbit = mic->b_filter_info[3];
+#endif
 
   return RDCOST(mb->rdmult, mb->rddiv, cost, total_distortion);
 }
@@ -1266,17 +1332,31 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
   TX_SIZE best_tx = TX_4X4;
   int i;
   int *bmode_costs = cpi->mbmode_cost;
+#if CONFIG_FILTERINTRA
+    int mode_ext, fbit, fbit_selected = 0;
+#endif
 
   if (cpi->sf.tx_size_search_method == USE_FULL_RD)
     for (i = 0; i < TX_MODES; i++)
       tx_cache[i] = INT64_MAX;
 
   /* Y Search for intra prediction mode */
+#if !CONFIG_FILTERINTRA
   for (mode = DC_PRED; mode <= TM_PRED; mode++) {
     int64_t local_tx_cache[TX_MODES];
     MODE_INFO *above_mi = xd->mi[-xd->mi_stride];
     MODE_INFO *left_mi = xd->left_available ? xd->mi[-1] : NULL;
+#else
+  for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; mode_ext++) {
+    int64_t local_tx_cache[TX_MODES];
+    MODE_INFO *above_mi = xd->mi[-xd->mi_stride];
+    MODE_INFO *left_mi = xd->left_available ? xd->mi[-1] : NULL;
 
+    fbit = mode_ext & 1;
+    mode = mode_ext >> 1;
+    if (fbit && !is_filter_allowed(mode))
+      continue;
+#endif
     if (cpi->common.frame_type == KEY_FRAME) {
       const PREDICTION_MODE A = vp9_above_block_mode(mic, above_mi, 0);
       const PREDICTION_MODE L = vp9_left_block_mode(mic, left_mi, 0);
@@ -1284,6 +1364,9 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
       bmode_costs = cpi->y_mode_costs[A][L];
     }
     mic->mbmi.mode = mode;
+#if CONFIG_FILTERINTRA
+    mic->mbmi.filterbit = fbit;
+#endif
 
     intra_super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
         &s, NULL, bsize, local_tx_cache, best_rd);
@@ -1292,10 +1375,18 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
       continue;
 
     this_rate = this_rate_tokenonly + bmode_costs[mode];
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(mode) && is_filter_enabled(mic->mbmi.tx_size))
+      this_rate += vp9_cost_bit(cpi->common.fc.filterintra_prob
+                                [mic->mbmi.tx_size][mode], fbit);
+#endif
     this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
 
     if (this_rd < best_rd) {
       mode_selected   = mode;
+#if CONFIG_FILTERINTRA
+      fbit_selected   = fbit;
+#endif
       best_rd         = this_rd;
       best_tx         = mic->mbmi.tx_size;
       *rate           = this_rate;
@@ -1316,6 +1407,12 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
   }
 
   mic->mbmi.mode = mode_selected;
+#if CONFIG_FILTERINTRA
+  if (is_filter_enabled(best_tx))
+    mic->mbmi.filterbit = fbit_selected;
+  else
+    mic->mbmi.filterbit = 0;
+#endif
   mic->mbmi.tx_size = best_tx;
 
   return best_rd;
@@ -1379,9 +1476,24 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
   int this_rate_tokenonly, this_rate, s;
   int64_t this_distortion, this_sse;
 
+#if CONFIG_FILTERINTRA
+  int mode_ext, fbit = 0, fbit_selected = 0;
+  for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; mode_ext++) {
+    mode = mode_ext >> 1;
+    fbit = mode_ext & 1;
+
+    if (fbit && !is_filter_allowed(mode))
+      continue;
+    if (fbit &&
+        !is_filter_enabled(get_uv_tx_size(&(x->e_mbd.mi[0]->mbmi))))
+      continue;
+
+    x->e_mbd.mi[0]->mbmi.uv_filterbit = fbit;
+#else
   for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
     if (!(cpi->sf.intra_uv_mode_mask[max_tx_size] & (1 << mode)))
       continue;
+#endif
 
     xd->mi[0]->mbmi.uv_mode = mode;
 
@@ -1391,10 +1503,19 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
       continue;
     this_rate = this_rate_tokenonly +
                 cpi->intra_uv_mode_cost[cpi->common.frame_type][mode];
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(mode) &&
+        is_filter_enabled(get_uv_tx_size(&(x->e_mbd.mi[0]->mbmi))))
+      this_rate += vp9_cost_bit(cpi->common.fc.filterintra_prob
+                   [get_uv_tx_size(&(x->e_mbd.mi[0]->mbmi))][mode], fbit);
+#endif
     this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
 
     if (this_rd < best_rd) {
       mode_selected   = mode;
+#if CONFIG_FILTERINTRA
+      fbit_selected   = fbit;
+#endif
       best_rd         = this_rd;
       *rate           = this_rate;
       *rate_tokenonly = this_rate_tokenonly;
@@ -1406,6 +1527,9 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
   }
 
   xd->mi[0]->mbmi.uv_mode = mode_selected;
+#if CONFIG_FILTERINTRA
+  xd->mi[0]->mbmi.uv_filterbit = fbit_selected;
+#endif
   return best_rd;
 }
 
@@ -1427,6 +1551,9 @@ static void choose_intra_uv_mode(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
                                  BLOCK_SIZE bsize, TX_SIZE max_tx_size,
                                  int *rate_uv, int *rate_uv_tokenonly,
                                  int64_t *dist_uv, int *skip_uv,
+#if CONFIG_FILTERINTRA
+                                 int *fbit_uv,
+#endif
                                  PREDICTION_MODE *mode_uv) {
   MACROBLOCK *const x = &cpi->mb;
 
@@ -1443,6 +1570,9 @@ static void choose_intra_uv_mode(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
                             bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize, max_tx_size);
   }
   *mode_uv = x->e_mbd.mi[0]->mbmi.uv_mode;
+#if CONFIG_FILTERINTRA
+  *fbit_uv = x->e_mbd.mi[0]->mbmi.uv_filterbit;
+#endif
 }
 
 static int cost_mv_ref(const VP9_COMP *cpi, PREDICTION_MODE mode,
@@ -1662,6 +1792,9 @@ static int check_best_zero_mv(
       (this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) &&
       frame_mv[this_mode][ref_frames[0]].as_int == 0 &&
       (ref_frames[1] == NONE ||
+#if CONFIG_INTERINTRA
+       ref_frames[1] == INTRA_FRAME ||
+#endif
        frame_mv[this_mode][ref_frames[1]].as_int == 0)) {
     int rfc = mode_context[ref_frames[0]];
     int c1 = cost_mv_ref(cpi, NEARMV, rfc);
@@ -1674,7 +1807,11 @@ static int check_best_zero_mv(
       if (c2 > c3) return 0;
     } else {
       assert(this_mode == ZEROMV);
-      if (ref_frames[1] == NONE) {
+      if (ref_frames[1] == NONE
+#if CONFIG_INTERINTRA
+          || ref_frames[1] == INTRA_FRAME
+#endif
+          ) {
         if ((c3 >= c2 && frame_mv[NEARESTMV][ref_frames[0]].as_int == 0) ||
             (c3 >= c1 && frame_mv[NEARMV][ref_frames[0]].as_int == 0))
           return 0;
@@ -2558,11 +2695,184 @@ static INLINE void restore_dst_buf(MACROBLOCKD *xd,
   }
 }
 
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA)|| \
+    CONFIG_MASKED_INTERINTER)
+static void do_masked_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
+                                    uint8_t *mask, int mask_stride,
+                                    BLOCK_SIZE bsize,
+                                    int mi_row, int mi_col,
+                                    int_mv *tmp_mv, int *rate_mv,
+                                    int is_second) {
+  MACROBLOCKD *xd = &x->e_mbd;
+  const VP9_COMMON *cm = &cpi->common;
+  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+  struct buf_2d backup_yv12[MAX_MB_PLANE] = {{0, 0}};
+  int bestsme = INT_MAX;
+  int step_param;
+  int sadpb = x->sadperbit16;
+  MV mvp_full;
+  int ref = mbmi->ref_frame[is_second];
+  MV ref_mv = mbmi->ref_mvs[ref][0].as_mv;
+
+  int tmp_col_min = x->mv_col_min;
+  int tmp_col_max = x->mv_col_max;
+  int tmp_row_min = x->mv_row_min;
+  int tmp_row_max = x->mv_row_max;
+
+  const YV12_BUFFER_CONFIG *scaled_ref_frame = vp9_get_scaled_ref_frame(cpi,
+                                                                        ref);
+
+  MV pred_mv[3];
+  pred_mv[0] = mbmi->ref_mvs[ref][0].as_mv;
+  pred_mv[1] = mbmi->ref_mvs[ref][1].as_mv;
+  pred_mv[2] = x->pred_mv[ref];
+
+  if (scaled_ref_frame) {
+    int i;
+    // Swap out the reference frame for a version that's been scaled to
+    // match the resolution of the current frame, allowing the existing
+    // motion search code to be used without additional modifications.
+    for (i = 0; i < MAX_MB_PLANE; i++)
+      backup_yv12[i] = xd->plane[i].pre[is_second];
+
+    vp9_setup_pre_planes(xd, is_second, scaled_ref_frame, mi_row, mi_col, NULL);
+  }
+
+  vp9_set_mv_search_range(x, &ref_mv);
+
+  // Work out the size of the first step in the mv step search.
+  // 0 here is maximum length first step. 1 is MAX >> 1 etc.
+  if (cpi->sf.mv.auto_mv_step_size && cm->show_frame) {
+    // Take wtd average of the step_params based on the last frame's
+    // max mv magnitude and that based on the best ref mvs of the current
+    // block for the given reference.
+    step_param = (vp9_init_search_range(&cpi->sf, x->max_mv_context[ref]) +
+                    cpi->mv_step_param) / 2;
+  } else {
+    step_param = cpi->mv_step_param;
+  }
+
+  if (cpi->sf.adaptive_motion_search && bsize < BLOCK_64X64 &&
+      cm->show_frame) {
+    int boffset = 2 * (b_width_log2(BLOCK_64X64) - MIN(b_height_log2(bsize),
+                                                       b_width_log2(bsize)));
+    step_param = MAX(step_param, boffset);
+  }
+
+  if (cpi->sf.adaptive_motion_search) {
+    int bwl = b_width_log2_lookup[bsize];
+    int bhl = b_height_log2_lookup[bsize];
+    int i;
+    int tlevel = x->pred_mv_sad[ref] >> (bwl + bhl + 4);
+
+    if (tlevel < 5)
+      step_param += 2;
+
+    for (i = LAST_FRAME; i <= ALTREF_FRAME && cm->show_frame; ++i) {
+      if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
+        x->pred_mv[ref].row = 0;
+        x->pred_mv[ref].col = 0;
+        tmp_mv->as_int = INVALID_MV;
+
+        if (scaled_ref_frame) {
+          int i;
+          for (i = 0; i < MAX_MB_PLANE; i++)
+            xd->plane[i].pre[is_second] = backup_yv12[i];
+        }
+        return;
+      }
+    }
+  }
+
+  mvp_full = pred_mv[x->mv_best_ref_index[ref]];
+
+  mvp_full.col >>= 3;
+  mvp_full.row >>= 3;
+
+  bestsme = vp9_masked_full_pixel_diamond(cpi, x, mask, mask_stride,
+                                          &mvp_full, step_param, sadpb,
+                                          cpi->sf.mv.max_step_search_steps - 1
+                                          - step_param, 1,
+                                          &cpi->fn_ptr[bsize],
+                                          &ref_mv, &tmp_mv->as_mv, is_second);
+
+  x->mv_col_min = tmp_col_min;
+  x->mv_col_max = tmp_col_max;
+  x->mv_row_min = tmp_row_min;
+  x->mv_row_max = tmp_row_max;
+
+  if (bestsme < INT_MAX) {
+    int dis;  /* TODO: use dis in distortion calculation later. */
+    vp9_find_best_masked_sub_pixel_tree(x, mask, mask_stride,
+                                        &tmp_mv->as_mv, &ref_mv,
+                                        cm->allow_high_precision_mv,
+                                        x->errorperbit,
+                                        &cpi->fn_ptr[bsize],
+                                        cpi->sf.mv.subpel_force_stop,
+                                        cpi->sf.mv.subpel_iters_per_step,
+                                        x->nmvjointcost, x->mvcost,
+                                        &dis, &x->pred_sse[ref], is_second);
+  }
+  *rate_mv = vp9_mv_bit_cost(&tmp_mv->as_mv, &ref_mv,
+                             x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
+
+  if (cpi->sf.adaptive_motion_search && cm->show_frame)
+    x->pred_mv[ref] = tmp_mv->as_mv;
+
+  if (scaled_ref_frame) {
+    int i;
+    for (i = 0; i < MAX_MB_PLANE; i++)
+      xd->plane[i].pre[is_second] = backup_yv12[i];
+  }
+}
+#endif
+
+#if CONFIG_MASKED_INTERINTER
+static void do_masked_motion_search_indexed(VP9_COMP *cpi, MACROBLOCK *x,
+                                            int mask_index,
+                                            BLOCK_SIZE bsize,
+                                            int *refs,
+                                            int mi_row, int mi_col,
+                                            int_mv *tmp_mv, int *rate_mv) {
+  MACROBLOCKD *xd = &x->e_mbd;
+  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+  BLOCK_SIZE sb_type = mbmi->sb_type;
+  int w = (4 << b_width_log2(sb_type));
+  int h = (4 << b_height_log2(sb_type));
+  int i, j;
+  uint8_t mask[4096];
+  int mask_stride = 64;
+
+  vp9_generate_masked_weight(mask_index, sb_type, h, w,
+                             mask, mask_stride);
+  /*
+  vp9_generate_hard_mask(mask_index, sb_type, h, w,
+                         mask, mask_stride);
+                         */
+
+  do_masked_motion_search(cpi, x, mask, mask_stride, bsize,
+                          mi_row, mi_col, &tmp_mv[0], &rate_mv[0], 0);
+
+  for (i = 0; i < h; ++i)
+    for (j = 0; j < w; ++j)
+      mask[i * mask_stride + j] = 64 - mask[i * mask_stride + j];
+
+  do_masked_motion_search(cpi, x, mask, mask_stride, bsize,
+                          mi_row, mi_col, &tmp_mv[1], &rate_mv[1], 1);
+}
+#endif
+
 static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
                                  BLOCK_SIZE bsize,
                                  int64_t txfm_cache[],
                                  int *rate2, int64_t *distortion,
                                  int *skippable,
+#if CONFIG_MASKED_INTERINTER
+                                 int *compmode_interinter_cost,
+#endif
+#if CONFIG_INTERINTRA
+                                 int *compmode_interintra_cost,
+#endif
                                  int *rate_y, int64_t *distortion_y,
                                  int *rate_uv, int64_t *distortion_uv,
                                  int *mode_excluded, int *disable_skip,
@@ -2570,6 +2880,9 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
                                  int_mv (*mode_mv)[MAX_REF_FRAMES],
                                  int mi_row, int mi_col,
                                  int_mv single_newmv[MAX_REF_FRAMES],
+#if CONFIG_INTERINTRA
+                                 int single_newmv_rate[MAX_REF_FRAMES],
+#endif
                                  int64_t *psse,
                                  const int64_t ref_best_rd) {
   VP9_COMMON *cm = &cpi->common;
@@ -2593,6 +2906,22 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
   uint8_t *orig_dst[MAX_MB_PLANE];
   int orig_dst_stride[MAX_MB_PLANE];
   int rs = 0;
+#if CONFIG_MASKED_INTERINTER || CONFIG_INTERINTRA
+  int rate_mv_tmp = 0;
+#endif
+#if CONFIG_INTERINTRA
+  const int is_comp_interintra_pred = (mbmi->ref_frame[1] == INTRA_FRAME);
+#if CONFIG_MASKED_INTERINTRA
+  mbmi->use_masked_interintra = 0;
+  mbmi->interintra_mask_index = -1;
+  mbmi->interintra_uv_mask_index = -1;
+#endif
+#endif
+#if CONFIG_MASKED_INTERINTER
+  mbmi->use_masked_interinter = 0;
+  mbmi->mask_index = MASK_NONE;
+  *compmode_interinter_cost = 0;
+#endif
 
   if (is_comp_pred) {
     if (frame_mv[refs[0]].as_int == INVALID_MV ||
@@ -2618,18 +2947,35 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
                                    &mbmi->ref_mvs[refs[1]][0].as_mv,
                                    x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
       }
+#if !(CONFIG_MASKED_INTERINTER || CONFIG_INTERINTRA)
       *rate2 += rate_mv;
+#endif
     } else {
       int_mv tmp_mv;
+#if CONFIG_INTERINTRA
+      if (!is_comp_interintra_pred) {
+#endif
       single_motion_search(cpi, x, bsize, mi_row, mi_col,
                            &tmp_mv, &rate_mv);
       if (tmp_mv.as_int == INVALID_MV)
         return INT64_MAX;
+#if !(CONFIG_MASKED_INTERINTER || CONFIG_INTERINTRA)
       *rate2 += rate_mv;
+#endif
       frame_mv[refs[0]].as_int =
           xd->mi[0]->bmi[0].as_mv[0].as_int = tmp_mv.as_int;
       single_newmv[refs[0]].as_int = tmp_mv.as_int;
+#if CONFIG_INTERINTRA
+        single_newmv_rate[refs[0]] = rate_mv;
+      } else {
+        frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
+        rate_mv = single_newmv_rate[refs[0]];
+      }
+#endif
     }
+#if CONFIG_MASKED_INTERINTER || CONFIG_INTERINTRA
+      rate_mv_tmp = rate_mv;
+#endif
   }
 
   for (i = 0; i < num_refs; ++i) {
@@ -2704,6 +3050,10 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
           int64_t dist_sum = 0;
           if ((cm->interp_filter == SWITCHABLE &&
                (!i || best_needs_copy)) ||
+#if CONFIG_INTERINTRA
+              (is_inter_mode(this_mode) && is_comp_interintra_pred &&
+               is_interintra_allowed(mbmi->sb_type)) ||
+#endif
               (cm->interp_filter != SWITCHABLE &&
                (cm->interp_filter == mbmi->interp_filter ||
                 (i == 0 && intpel_mv)))) {
@@ -2755,11 +3105,324 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
       restore_dst_buf(xd, orig_dst, orig_dst_stride);
     }
   }
+
   // Set the appropriate filter
   mbmi->interp_filter = cm->interp_filter != SWITCHABLE ?
       cm->interp_filter : *best_filter;
   rs = cm->interp_filter == SWITCHABLE ? vp9_get_switchable_rate(cpi) : 0;
 
+#if CONFIG_MASKED_INTERINTER
+  if (is_comp_pred && get_mask_bits(bsize)) {
+    int mask_index, best_mask_index = MASK_NONE, rs;
+    int rate_sum;
+    int64_t dist_sum;
+    int64_t best_rd_nomask = INT64_MAX;
+    int64_t best_rd_mask = INT64_MAX;
+    int mask_types;
+    mbmi->use_masked_interinter = 0;
+    rs = vp9_cost_bit(cm->fc.masked_interinter_prob[bsize], 0);
+    vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+    model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+    rd = RDCOST(x->rdmult, x->rddiv, rs + rate_mv_tmp + rate_sum, dist_sum);
+    best_rd_nomask = rd;
+    mbmi->use_masked_interinter = 1;
+    rs = get_mask_bits(bsize) * 256 +
+        vp9_cost_bit(cm->fc.masked_interinter_prob[bsize], 1);
+    mask_types = (1 << get_mask_bits(bsize));
+    if (this_mode == NEWMV) {
+#define USE_MASKED_NEWMV_FAST_SEARCH
+#ifdef USE_MASKED_NEWMV_FAST_SEARCH
+      int_mv tmp_mv[2];
+      int rate_mvs[2], tmp_rate_mv;
+      for (mask_index = 0; mask_index < mask_types; ++mask_index) {
+        mbmi->mask_index = mask_index;
+        vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+        model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+        rd = RDCOST(x->rdmult, x->rddiv, rs + rate_mv_tmp + rate_sum, dist_sum);
+        if (rd < best_rd_mask) {
+          best_mask_index = mask_index;
+          best_rd_mask = rd;
+        }
+      }
+      mbmi->mask_index = best_mask_index;
+      do_masked_motion_search_indexed(cpi, x, mbmi->mask_index, bsize,
+                                      refs, mi_row, mi_col,
+                                      tmp_mv, rate_mvs);
+      tmp_rate_mv = rate_mvs[0] + rate_mvs[1];
+      mbmi->mv[0].as_int = tmp_mv[0].as_int;
+      mbmi->mv[1].as_int = tmp_mv[1].as_int;
+      vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+      model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+      rd = RDCOST(x->rdmult, x->rddiv, rs + tmp_rate_mv + rate_sum, dist_sum);
+      if (rd < best_rd_mask) {
+        best_rd_mask = rd;
+      } else {
+        mbmi->mv[0].as_int = cur_mv[0].as_int;
+        mbmi->mv[1].as_int = cur_mv[1].as_int;
+        tmp_rate_mv = rate_mv_tmp;
+      }
+      if (best_rd_mask < best_rd_nomask) {
+        mbmi->use_masked_interinter = 1;
+        mbmi->mask_index = best_mask_index;
+        if (cm->use_masked_interinter) {
+          xd->mi[0]->bmi[0].as_mv[0].as_int = mbmi->mv[0].as_int;
+          xd->mi[0]->bmi[0].as_mv[1].as_int = mbmi->mv[1].as_int;
+          rate_mv_tmp = tmp_rate_mv;
+        }
+      } else {
+        mbmi->use_masked_interinter = 0;
+        mbmi->mask_index = MASK_NONE;
+        mbmi->mv[0].as_int = cur_mv[0].as_int;
+        mbmi->mv[1].as_int = cur_mv[1].as_int;
+      }
+#else
+      int best_tmp_rate_mv = INT_MAX;
+      int_mv best_tmp_mv[2];
+      best_tmp_mv[0].as_int = 0;
+      best_tmp_mv[1].as_int = 0;
+      for (mask_index = 0; mask_index < mask_types; ++mask_index) {
+        int_mv tmp_mv[2];
+        int rate_mvs[2], tmp_rate_mv;
+        mbmi->mask_index = mask_index;
+        do_masked_motion_search_indexed(cpi, x, mask_index, bsize,
+                                        refs, mi_row, mi_col,
+                                        tmp_mv, rate_mvs);
+        tmp_rate_mv = rate_mvs[0] + rate_mvs[1];
+        mbmi->mv[0].as_int = tmp_mv[0].as_int;
+        mbmi->mv[1].as_int = tmp_mv[1].as_int;
+        vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+        model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+        rd = RDCOST(x->rdmult, x->rddiv, rs + tmp_rate_mv + rate_sum, dist_sum);
+        mbmi->mv[0].as_int = cur_mv[0].as_int;
+        mbmi->mv[1].as_int = cur_mv[1].as_int;
+        if (rd < best_rd_mask) {
+          best_mask_index = mask_index;
+          best_rd_mask = rd;
+          best_tmp_mv[0].as_int = tmp_mv[0].as_int;
+          best_tmp_mv[1].as_int = tmp_mv[1].as_int;
+          best_tmp_rate_mv = tmp_rate_mv;
+        }
+      }
+      if (best_rd_mask < best_rd_nomask) {
+        mbmi->use_masked_compound = 1;
+        mbmi->mask_index = best_mask_index;
+        if (cm->use_masked_compound) {
+          mbmi->mv[0].as_int = best_tmp_mv[0].as_int;
+          mbmi->mv[1].as_int = best_tmp_mv[1].as_int;
+          xd->mode_info_context->bmi[0].as_mv[0].as_int = best_tmp_mv[0].as_int;
+          xd->mode_info_context->bmi[0].as_mv[1].as_int = best_tmp_mv[1].as_int;
+          rate_mv_tmp = best_tmp_rate_mv;
+        }
+      } else {
+        mbmi->use_masked_compound = 0;
+        mbmi->mask_index = MASK_NONE;
+      }
+#endif
+    } else {
+      for (mask_index = 0; mask_index < mask_types; ++mask_index) {
+        mbmi->mask_index = mask_index;
+        vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+        model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+        rd = RDCOST(x->rdmult, x->rddiv, rs + rate_mv_tmp + rate_sum, dist_sum);
+        if (rd < best_rd_mask) {
+          best_mask_index = mask_index;
+          best_rd_mask = rd;
+        }
+      }
+      if (best_rd_mask < best_rd_nomask) {
+        mbmi->use_masked_interinter = 1;
+        mbmi->mask_index = best_mask_index;
+      } else {
+        mbmi->use_masked_interinter = 0;
+        mbmi->mask_index = MASK_NONE;
+      }
+    }
+
+    ++cpi->masked_interinter_select_counts[mbmi->use_masked_interinter];
+
+    if (!cm->use_masked_interinter) {
+      mbmi->use_masked_interinter = 0;
+    }
+    if (ref_best_rd < INT64_MAX &&
+        MIN(best_rd_mask, best_rd_nomask) / 2 > ref_best_rd)
+      return INT64_MAX;
+
+    pred_exists = 0;
+    if (mbmi->use_masked_interinter)
+      *compmode_interinter_cost = get_mask_bits(bsize) * 256 +
+                          vp9_cost_bit(cm->fc.masked_interinter_prob[bsize], 1);
+    else
+      *compmode_interinter_cost = vp9_cost_bit
+                                  (cm->fc.masked_interinter_prob[bsize], 0);
+  }
+#endif  // CONFIG_MASKED_INTERINTER
+
+#if CONFIG_INTERINTRA
+  if ((!is_comp_pred) && is_comp_interintra_pred &&
+      is_interintra_allowed(mbmi->sb_type)) {
+    PREDICTION_MODE interintra_mode, best_interintra_mode = DC_PRED;
+    int64_t best_interintra_rd = INT64_MAX;
+    int rmode, rate_sum;
+    int64_t dist_sum;
+    int j;
+#if CONFIG_MASKED_INTERINTRA
+    int maskbits, mask_types, mask_index, best_mask_index = -1;
+    int64_t best_interintra_rd_nomask, best_interintra_rd_mask = INT64_MAX;
+    int rmask;
+#define MASKED_INTERINTRA_REFINE_SEARCH
+#ifdef MASKED_INTERINTRA_REFINE_SEARCH
+    int bw = 4 << b_width_log2(mbmi->sb_type),
+        bh = 4 << b_height_log2(mbmi->sb_type);
+    uint8_t mask[4096];
+    int_mv tmp_mv;
+    int tmp_rate_mv = 0;
+#endif
+#endif
+    mbmi->ref_frame[1] = NONE;
+    for (j = 0; j < MAX_MB_PLANE; j++) {
+      xd->plane[j].dst.buf = tmp_buf + j * 64 * 64;
+      xd->plane[j].dst.stride = 64;
+    }
+    vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+    restore_dst_buf(xd, orig_dst, orig_dst_stride);
+    mbmi->ref_frame[1] = INTRA_FRAME;
+
+    for (interintra_mode = DC_PRED; interintra_mode <= TM_PRED;
+        ++interintra_mode) {
+      mbmi->interintra_mode = interintra_mode;
+      mbmi->interintra_uv_mode = interintra_mode;
+      rmode = cpi->mbmode_cost[mbmi->interintra_mode];
+      vp9_build_interintra_predictors(xd, tmp_buf, tmp_buf + 64 * 64,
+                                      tmp_buf + 2* 64 * 64, 64, 64, 64, bsize);
+      model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+      rd = RDCOST(x->rdmult, x->rddiv, rmode + rate_sum, dist_sum);
+      if (rd < best_interintra_rd) {
+        best_interintra_rd = rd;
+        best_interintra_mode = interintra_mode;
+      }
+    }
+    mbmi->interintra_mode = best_interintra_mode;
+    mbmi->interintra_uv_mode = best_interintra_mode;
+#if CONFIG_MASKED_INTERINTRA
+    maskbits = get_mask_bits_interintra(bsize);
+    rmode = cpi->mbmode_cost[mbmi->interintra_mode];
+    if (maskbits) {
+      mbmi->use_masked_interintra = 0;
+      vp9_build_interintra_predictors(xd, tmp_buf, tmp_buf + 64 * 64,
+                                      tmp_buf + 2* 64 * 64, 64, 64, 64, bsize);
+      model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+      rmask = vp9_cost_bit(cm->fc.masked_interintra_prob[bsize], 0);
+      rd = RDCOST(x->rdmult, x->rddiv,
+                  rmode + rate_mv_tmp + rmask + rate_sum, dist_sum);
+      best_interintra_rd_nomask = rd;
+
+      mbmi->use_masked_interintra = 1;
+      rmask = maskbits * 256 +
+              vp9_cost_bit(cm->fc.masked_interintra_prob[bsize], 1);
+      mask_types = (1 << maskbits);
+      for (mask_index = 0; mask_index < mask_types; ++mask_index) {
+        mbmi->interintra_mask_index = mask_index;
+        mbmi->interintra_uv_mask_index = mask_index;
+        vp9_build_interintra_predictors(xd, tmp_buf, tmp_buf + 64 * 64,
+                                       tmp_buf + 2* 64 * 64, 64, 64, 64, bsize);
+        model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+        rd = RDCOST(x->rdmult, x->rddiv,
+                    rmode + rate_mv_tmp + rmask + rate_sum, dist_sum);
+        if (rd < best_interintra_rd_mask) {
+          best_interintra_rd_mask = rd;
+          best_mask_index = mask_index;
+        }
+      }
+#ifdef MASKED_INTERINTRA_REFINE_SEARCH
+      // Refine motion vector
+      if (this_mode == NEWMV) {
+        int j;
+        mbmi->interintra_mask_index = best_mask_index;
+        mbmi->interintra_uv_mask_index = best_mask_index;
+        vp9_generate_masked_weight_interintra(best_mask_index, bsize,
+                                              bh, bw, mask, bw);
+        for (i = 0; i < bh; ++i)
+            for (j = 0; j < bw; ++j)
+              mask[i * bw + j] = 64 - mask[i * bw + j];
+        do_masked_motion_search(cpi, x, mask, bw, bsize,
+                                mi_row, mi_col, &tmp_mv, &tmp_rate_mv, 0);
+        mbmi->mv[0].as_int = tmp_mv.as_int;
+        vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+        model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+        rd = RDCOST(x->rdmult, x->rddiv,
+                    rmode + tmp_rate_mv + rmask + rate_sum, dist_sum);
+        if (rd < best_interintra_rd_mask) {
+          best_interintra_rd_mask = rd;
+        } else {
+          tmp_mv.as_int = cur_mv[0].as_int;
+          tmp_rate_mv = rate_mv_tmp;
+        }
+      } else {
+        tmp_mv.as_int = cur_mv[0].as_int;
+        tmp_rate_mv = rate_mv_tmp;
+      }
+      mbmi->mv[0].as_int = tmp_mv.as_int;
+#endif
+      if (best_interintra_rd_mask < best_interintra_rd_nomask) {
+        mbmi->use_masked_interintra = 1;
+        if (cm->use_interintra && cm->use_masked_interintra) {
+          mbmi->interintra_mask_index = best_mask_index;
+          mbmi->interintra_uv_mask_index = best_mask_index;
+#ifdef MASKED_INTERINTRA_REFINE_SEARCH
+          mbmi->mv[0].as_int = tmp_mv.as_int;
+          rate_mv_tmp = tmp_rate_mv;
+#endif
+        } else {
+          mbmi->interintra_mode = best_interintra_mode;
+          mbmi->interintra_uv_mode = best_interintra_mode;
+          mbmi->mv[0].as_int = cur_mv[0].as_int;
+        }
+        best_interintra_rd = best_interintra_rd_mask;
+      } else {
+        mbmi->use_masked_interintra = 0;
+#ifdef MASKED_INTERINTRA_REFINE_SEARCH
+        mbmi->interintra_mode = best_interintra_mode;
+        mbmi->interintra_uv_mode = best_interintra_mode;
+        mbmi->mv[0].as_int = cur_mv[0].as_int;
+#endif
+        best_interintra_rd = best_interintra_rd_nomask;
+      }
+
+      ++cpi->masked_interintra_select_count[mbmi->use_masked_interintra];
+      if (!cm->use_masked_interintra)
+        mbmi->use_masked_interintra = 0;
+    }
+#endif
+    if (ref_best_rd < INT64_MAX &&
+        best_interintra_rd / 2 > ref_best_rd)
+      return INT64_MAX;
+
+    pred_exists = 0;
+  }
+
+  if (!is_comp_pred && is_interintra_allowed(mbmi->sb_type)) {
+    *compmode_interintra_cost = vp9_cost_bit(cm->fc.interintra_prob[bsize],
+                                             is_comp_interintra_pred);
+    if (is_comp_interintra_pred) {
+      *compmode_interintra_cost += cpi->mbmode_cost[mbmi->interintra_mode];
+#if CONFIG_MASKED_INTERINTRA
+      if (get_mask_bits_interintra(bsize) && cm->use_masked_interintra) {
+        *compmode_interintra_cost += vp9_cost_bit(
+                                     cm->fc.masked_interintra_prob[bsize],
+                                     mbmi->use_masked_interintra);
+        if (mbmi->use_masked_interintra) {
+          *compmode_interintra_cost += get_mask_bits_interintra(bsize) * 256;
+        }
+      }
+#endif
+    }
+  }
+#endif
+
+#if CONFIG_INTERINTRA || CONFIG_MASKED_INTERINTER
+  *rate2 += rate_mv_tmp;
+#endif
+
   if (pred_exists) {
     if (best_needs_copy) {
       // again temporarily set the buffers to local memory to prevent a memcpy
@@ -2869,6 +3532,37 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
     int64_t sseuv = INT64_MAX;
     int64_t rdcosty = INT64_MAX;
 
+#if CONFIG_EXT_TX
+    int64_t rdcost_tx;
+    int rate_y_tx;
+    int64_t distortion_y_tx;
+    int dummy;
+    int64_t best_rdcost_tx = INT64_MAX;
+    int best_ext_tx = NORM;
+    double th = 0.97;
+
+    for (i = 0; i < EXT_TX_TYPES; i++) {
+      mbmi->ext_txfrm = i;
+      inter_super_block_yrd(cpi, x, &rate_y_tx, &distortion_y_tx, &dummy, psse,
+                      bsize, txfm_cache, INT64_MAX);
+      assert(rate_y_tx != INT_MAX);
+      if (mbmi->tx_size < TX_32X32)
+        rate_y_tx += vp9_cost_bit(cm->fc.ext_tx_prob, i);
+      assert(rate_y_tx >= 0);
+      rdcost_tx = RDCOST(x->rdmult, x->rddiv, rate_y_tx, distortion_y_tx);
+      rdcost_tx = MIN(rdcost_tx, RDCOST(x->rdmult, x->rddiv, 0, *psse));
+      assert(rdcost_tx >= 0);
+      if (rdcost_tx < best_rdcost_tx * th) {
+        best_ext_tx = i;
+        best_rdcost_tx = rdcost_tx;
+      }
+    }
+    if (mbmi->tx_size == TX_32X32)
+      mbmi->ext_txfrm = NORM;
+    else
+      mbmi->ext_txfrm = best_ext_tx;
+#endif
+
     // Y cost and distortion
     inter_super_block_yrd(cpi, x, rate_y, distortion_y, &skippable_y, psse,
                           bsize, txfm_cache, ref_best_rd);
@@ -2881,6 +3575,10 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
     }
 
     *rate2 += *rate_y;
+#if CONFIG_EXT_TX
+    if (mbmi->tx_size < TX_32X32)
+      *rate2 += vp9_cost_bit(cm->fc.ext_tx_prob, mbmi->ext_txfrm);
+#endif
     *distortion += *distortion_y;
 
     rdcosty = RDCOST(x->rdmult, x->rddiv, *rate2, *distortion);
@@ -3005,6 +3703,9 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
   int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
   struct buf_2d yv12_mb[4][MAX_MB_PLANE];
   int_mv single_newmv[MAX_REF_FRAMES] = { { 0 } };
+#if CONFIG_INTERINTRA
+  int single_newmv_rate[MAX_REF_FRAMES] = { 0 };
+#endif
   static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
                                     VP9_ALT_FLAG };
   int64_t best_rd = best_rd_so_far;
@@ -3027,6 +3728,9 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
   int64_t dist_uv[TX_SIZES];
   int skip_uv[TX_SIZES];
   PREDICTION_MODE mode_uv[TX_SIZES];
+#if CONFIG_FILTERINTRA
+  int fbit_uv[TX_SIZES];
+#endif
   int64_t mode_distortions[MB_MODE_COUNT] = {-1};
   int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
   const int bws = num_8x8_blocks_wide_lookup[bsize] / 2;
@@ -3040,6 +3744,12 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
   const int intra_y_mode_mask =
       cpi->sf.intra_y_mode_mask[max_txsize_lookup[bsize]];
   int inter_mode_mask = cpi->sf.inter_mode_mask[bsize];
+#if CONFIG_INTERINTRA
+  int64_t best_overall_rd = INT64_MAX;
+  int is_best_interintra = 0;
+  int start_skip = 0;
+  int mode_skip_mask_interintra = 0;
+#endif
   vp9_zero(best_mbmode);
   x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
 
@@ -3143,6 +3853,12 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
     int64_t this_rd = INT64_MAX;
     int disable_skip = 0;
     int compmode_cost = 0;
+#if CONFIG_MASKED_INTERINTER
+    int compmode_masked_cost = 0;
+#endif
+#if CONFIG_INTERINTRA
+    int compmode_interintra_cost = 0;
+#endif
     int rate2 = 0, rate_y = 0, rate_uv = 0;
     int64_t distortion2 = 0, distortion_y = 0, distortion_uv = 0;
     int skippable = 0;
@@ -3152,6 +3868,9 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
     int64_t total_sse = INT64_MAX;
     int early_term = 0;
 
+#if CONFIG_INTERINTRA
+    if (mode_index < 30) {
+#endif
     // Look at the reference frame of the best mode so far and set the
     // skip mask to look at a subset of the remaining modes.
     if (mode_index == mode_skip_start && best_mode_index >= 0) {
@@ -3174,6 +3893,54 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
     }
     if (mode_skip_mask & (1 << mode_index))
       continue;
+#if CONFIG_INTERINTRA
+    }
+#define INTERINTRA_SPEEDUP
+#ifdef INTERINTRA_SPEEDUP
+    if (!start_skip && mode_index >= 30) {
+      start_skip = 1;
+      if (best_mode_index >= 0) {
+        if (vp9_mode_order[best_mode_index].ref_frame[1] == NONE) {
+          switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
+            case INTRA_FRAME:
+              break;
+            case LAST_FRAME:
+              if (vp9_mode_order[best_mode_index].mode == NEWMV)
+                mode_skip_mask_interintra |= 0xFF0;
+              else
+                mode_skip_mask_interintra |= 0xFF8;
+              break;
+            case GOLDEN_FRAME:
+              if (vp9_mode_order[best_mode_index].mode == NEWMV)
+                mode_skip_mask_interintra |= 0xF0F;
+              else
+                mode_skip_mask_interintra |= 0xF8F;
+              break;
+            case ALTREF_FRAME:
+              if (vp9_mode_order[best_mode_index].mode == NEWMV)
+                mode_skip_mask_interintra |= 0x0FF;
+              else
+                mode_skip_mask_interintra |= 0x8FF;
+              break;
+            default:
+              break;
+          }
+        } else {
+          switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
+            case LAST_FRAME:
+              mode_skip_mask_interintra |= 0x0F0;
+              break;
+            default:
+              break;
+          }
+        }
+      }
+    }
+    if (mode_skip_mask_interintra & (1 << (mode_index - 30)))
+      continue;
+#endif
+#endif
+
 
     // Test best rd so far against threshold for trying this mode.
     if (rd_less_than_thresh(best_rd, rd_threshes[mode_index],
@@ -3200,6 +3967,10 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
     } else {
       if (ref_frame != INTRA_FRAME)
         mode_excluded = cm->reference_mode == COMPOUND_REFERENCE;
+#if CONFIG_INTERINTRA
+      if (ref_frame > INTRA_FRAME && second_ref_frame == INTRA_FRAME)
+        mode_excluded = mode_excluded? mode_excluded : !cm->use_interintra;
+#endif
     }
 
     if (ref_frame == INTRA_FRAME) {
@@ -3232,6 +4003,11 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
                               inter_mode_mask, this_mode, ref_frames))
         continue;
     }
+#if CONFIG_INTERINTRA
+    if (ref_frame > INTRA_FRAME && second_ref_frame == INTRA_FRAME &&
+        !is_interintra_allowed(bsize))
+      continue;
+#endif
 
     mbmi->mode = this_mode;
     mbmi->uv_mode = DC_PRED;
@@ -3253,12 +4029,56 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
 
     for (i = 0; i < TX_MODES; ++i)
       tx_cache[i] = INT64_MAX;
+#if CONFIG_MASKED_INTERINTER
+    mbmi->use_masked_interinter = 0;
+    mbmi->mask_index = MASK_NONE;
+#endif
+#if CONFIG_INTERINTRA
+    mbmi->interintra_mode = (PREDICTION_MODE)(DC_PRED - 1);
+    mbmi->interintra_uv_mode = (PREDICTION_MODE)(DC_PRED - 1);
+#endif
 
     if (ref_frame == INTRA_FRAME) {
       TX_SIZE uv_tx;
+#if CONFIG_FILTERINTRA
+      mbmi->filterbit = 0;
+#endif
       intra_super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, NULL,
                             bsize, tx_cache, best_rd);
 
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(this_mode) && is_filter_enabled(mbmi->tx_size)) {
+        int rate_y_tmp, rate0, rate1, skippable_tmp;
+        int64_t distortion_y_tmp, tx_cache_tmp[TX_MODES];
+        int tx_size_tmp = mbmi->tx_size;
+        mbmi->filterbit = 0;
+
+        intra_super_block_yrd(cpi, x, &rate_y_tmp, &distortion_y_tmp,
+                              &skippable_tmp, NULL, bsize, tx_cache_tmp,
+                              best_rd);
+
+        if (rate_y == INT_MAX && rate_y_tmp == INT_MAX)
+          continue;
+
+        rate0 = vp9_cost_bit(
+            cm->fc.filterintra_prob[tx_size_tmp][mbmi->mode], 0);
+        rate1 = vp9_cost_bit(
+            cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode], 1);
+
+        if (rate_y_tmp == INT_MAX ||
+            RDCOST(x->rdmult, x->rddiv, rate_y + rate0, distortion_y) <=
+            RDCOST(x->rdmult, x->rddiv, rate_y_tmp + rate1, distortion_y_tmp)) {
+          mbmi->filterbit = 0;
+          mbmi->tx_size = tx_size_tmp;
+        } else {
+          rate_y = rate_y_tmp;
+          distortion_y = distortion_y_tmp;
+          skippable = skippable_tmp;
+          vpx_memcpy(tx_cache, tx_cache_tmp, TX_MODES * sizeof(int64_t));
+        }
+      }
+#endif
+
       if (rate_y == INT_MAX)
         continue;
 
@@ -3266,28 +4086,59 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
       if (rate_uv_intra[uv_tx] == INT_MAX) {
         choose_intra_uv_mode(cpi, ctx, bsize, uv_tx,
                              &rate_uv_intra[uv_tx], &rate_uv_tokenonly[uv_tx],
-                             &dist_uv[uv_tx], &skip_uv[uv_tx], &mode_uv[uv_tx]);
+                             &dist_uv[uv_tx], &skip_uv[uv_tx],
+#if CONFIG_FILTERINTRA
+                             &fbit_uv[uv_tx],
+#endif
+                             &mode_uv[uv_tx]);
       }
 
       rate_uv = rate_uv_tokenonly[uv_tx];
       distortion_uv = dist_uv[uv_tx];
       skippable = skippable && skip_uv[uv_tx];
       mbmi->uv_mode = mode_uv[uv_tx];
+#if CONFIG_FILTERINTRA
+      mbmi->uv_filterbit = fbit_uv[uv_tx];
+#endif
 
       rate2 = rate_y + cpi->mbmode_cost[mbmi->mode] + rate_uv_intra[uv_tx];
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size))
+        rate2 += vp9_cost_bit(
+           cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode], mbmi->filterbit);
+#endif
       if (this_mode != DC_PRED && this_mode != TM_PRED)
         rate2 += intra_cost_penalty;
       distortion2 = distortion_y + distortion_uv;
     } else {
+#if CONFIG_INTERINTRA
+      if (second_ref_frame == INTRA_FRAME) {
+        mbmi->interintra_mode = best_intra_mode;
+        mbmi->interintra_uv_mode = best_intra_mode;
+      }
+#endif
+#if CONFIG_EXT_TX
+      mbmi->ext_txfrm = NORM;
+#endif
       this_rd = handle_inter_mode(cpi, x, bsize,
                                   tx_cache,
                                   &rate2, &distortion2, &skippable,
+#if CONFIG_MASKED_INTERINTER
+                                  &compmode_masked_cost,
+#endif
+#if CONFIG_INTERINTRA
+                                  &compmode_interintra_cost,
+#endif
                                   &rate_y, &distortion_y,
                                   &rate_uv, &distortion_uv,
                                   &mode_excluded, &disable_skip,
                                   &tmp_best_filter, frame_mv,
                                   mi_row, mi_col,
-                                  single_newmv, &total_sse, best_rd);
+                                  single_newmv,
+#if CONFIG_INTERINTRA
+                                  single_newmv_rate,
+#endif
+                                  &total_sse, best_rd);
       if (this_rd == INT64_MAX)
         continue;
 
@@ -3297,6 +4148,17 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
         rate2 += compmode_cost;
     }
 
+#if CONFIG_MASKED_INTERINTER
+    if ((cm->reference_mode == REFERENCE_MODE_SELECT ||
+        cm->reference_mode == COMPOUND_REFERENCE) &&
+        cm->use_masked_interinter && comp_pred)
+      rate2 += compmode_masked_cost;
+#endif
+#if CONFIG_INTERINTRA
+    if (cm->use_interintra)
+      rate2 += compmode_interintra_cost;
+#endif
+
     // Estimate the reference frame signaling cost and add it
     // to the rolling cost variable.
     if (comp_pred) {
@@ -3370,6 +4232,13 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
       mode_distortions[this_mode] = distortion2;
     }
 
+#if CONFIG_INTERINTRA
+    if (this_rd < best_overall_rd) {
+      best_overall_rd = this_rd;
+      is_best_interintra = (second_ref_frame == INTRA_FRAME);
+    }
+#endif
+
     // Did this mode help.. i.e. is it the new best mode
     if (this_rd < best_rd || x->skip) {
       int max_plane = MAX_MB_PLANE;
@@ -3487,6 +4356,11 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
       break;
   }
 
+#if CONFIG_INTERINTRA
+  if (best_mode_index >= 0)
+    ++cpi->interintra_select_count[is_best_interintra];
+#endif
+
   if (best_mode_index < 0 || best_rd >= best_rd_so_far)
     return INT64_MAX;
 
@@ -3696,11 +4570,26 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x,
   int64_t dist_uv;
   int skip_uv;
   PREDICTION_MODE mode_uv = DC_PRED;
+#if CONFIG_FILTERINTRA
+  int fbit_uv = 0;
+#endif
   int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
   int_mv seg_mvs[4][MAX_REF_FRAMES];
   b_mode_info best_bmodes[4];
   int best_skip2 = 0;
   int mode_skip_mask = 0;
+#if CONFIG_MASKED_INTERINTER
+  mbmi->use_masked_interinter = 0;
+  mbmi->mask_index = MASK_NONE;
+#endif
+#if CONFIG_INTERINTRA && CONFIG_MASKED_INTERINTRA
+  mbmi->use_masked_interintra = 0;
+  mbmi->interintra_mask_index = MASK_NONE_INTERINTRA;
+  mbmi->interintra_uv_mask_index = MASK_NONE_INTERINTRA;
+#endif
+#if CONFIG_EXT_TX
+  mbmi->ext_txfrm = NORM;
+#endif
 
   x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
   vpx_memset(x->zcoeff_blk[TX_4X4], 0, 4);
@@ -3873,6 +4762,9 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x,
                              &rate_uv_intra,
                              &rate_uv_tokenonly,
                              &dist_uv, &skip_uv,
+#if CONFIG_FILTERINTRA
+                             &fbit_uv,
+#endif
                              &mode_uv);
       }
       rate2 += rate_uv_intra;
@@ -3880,6 +4772,9 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x,
       distortion2 += dist_uv;
       distortion_uv = dist_uv;
       mbmi->uv_mode = mode_uv;
+#if CONFIG_FILTERINTRA
+      mbmi->uv_filterbit = fbit_uv;
+#endif
     } else {
       int rate;
       int64_t distortion;
@@ -4311,24 +5206,60 @@ void vp9_set_rd_speed_thresholds(VP9_COMP *cpi) {
   rd->thresh_mult[THR_D207_PRED] += 2500;
   rd->thresh_mult[THR_D63_PRED] += 2500;
 
+#if CONFIG_INTERINTRA
+  rd->thresh_mult[THR_COMP_INTERINTRA_ZEROL   ] += 1500;
+  rd->thresh_mult[THR_COMP_INTERINTRA_ZEROG   ] += 1500;
+  rd->thresh_mult[THR_COMP_INTERINTRA_ZEROA   ] += 1500;
+
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] += 1500;
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] += 1500;
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] += 1500;
+
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEARL   ] += 1500;
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEARG   ] += 1500;
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEARA   ] += 1500;
+
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEWL    ] += 2000;
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEWG    ] += 2000;
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEWA    ] += 2000;
+#endif
+
   /* disable frame modes if flags not set */
   if (!(cpi->ref_frame_flags & VP9_LAST_FLAG)) {
     rd->thresh_mult[THR_NEWMV    ] = INT_MAX;
     rd->thresh_mult[THR_NEARESTMV] = INT_MAX;
     rd->thresh_mult[THR_ZEROMV   ] = INT_MAX;
     rd->thresh_mult[THR_NEARMV   ] = INT_MAX;
+#if CONFIG_INTERINTRA
+    rd->thresh_mult[THR_COMP_INTERINTRA_ZEROL   ] = INT_MAX;
+    rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = INT_MAX;
+    rd->thresh_mult[THR_COMP_INTERINTRA_NEARL   ] = INT_MAX;
+    rd->thresh_mult[THR_COMP_INTERINTRA_NEWL    ] = INT_MAX;
+#endif
   }
   if (!(cpi->ref_frame_flags & VP9_GOLD_FLAG)) {
     rd->thresh_mult[THR_NEARESTG ] = INT_MAX;
     rd->thresh_mult[THR_ZEROG    ] = INT_MAX;
     rd->thresh_mult[THR_NEARG    ] = INT_MAX;
     rd->thresh_mult[THR_NEWG     ] = INT_MAX;
+#if CONFIG_INTERINTRA
+    rd->thresh_mult[THR_COMP_INTERINTRA_ZEROG   ] = INT_MAX;
+    rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = INT_MAX;
+    rd->thresh_mult[THR_COMP_INTERINTRA_NEARG   ] = INT_MAX;
+    rd->thresh_mult[THR_COMP_INTERINTRA_NEWG    ] = INT_MAX;
+#endif
   }
   if (!(cpi->ref_frame_flags & VP9_ALT_FLAG)) {
     rd->thresh_mult[THR_NEARESTA ] = INT_MAX;
     rd->thresh_mult[THR_ZEROA    ] = INT_MAX;
     rd->thresh_mult[THR_NEARA    ] = INT_MAX;
     rd->thresh_mult[THR_NEWA     ] = INT_MAX;
+#if CONFIG_INTERINTRA
+    rd->thresh_mult[THR_COMP_INTERINTRA_ZEROA   ] = INT_MAX;
+    rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = INT_MAX;
+    rd->thresh_mult[THR_COMP_INTERINTRA_NEARA   ] = INT_MAX;
+    rd->thresh_mult[THR_COMP_INTERINTRA_NEWA    ] = INT_MAX;
+#endif
   }
 
   if ((cpi->ref_frame_flags & (VP9_LAST_FLAG | VP9_ALT_FLAG)) !=
index 3dfe2d07f2a58a356d3f0f8145c7c9cf670cbec7..4f60f1c716bab5803c85902e57661b9cc86806e6 100644 (file)
@@ -33,7 +33,11 @@ extern "C" {
 
 #define INVALID_MV 0x80008000
 
+#if !CONFIG_INTERINTRA
 #define MAX_MODES 30
+#else
+#define MAX_MODES 42
+#endif
 #define MAX_REFS  6
 
 // This enumerator type needs to be kept aligned with the mode order in
@@ -76,6 +80,23 @@ typedef enum {
   THR_D63_PRED,
   THR_D117_PRED,
   THR_D45_PRED,
+
+#if CONFIG_INTERINTRA
+  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;
 
 typedef enum {
index d06263676fa4b1473bd211e15a70663ffb2ae9e9..94a64ca251af6e7a02647494f199fba3897c252e 100644 (file)
@@ -131,3 +131,47 @@ sadMxN(4, 4)
 sadMxNxK(4, 4, 3)
 sadMxNxK(4, 4, 8)
 sadMxNx4D(4, 4)
+
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+     CONFIG_MASKED_INTERINTER)
+static INLINE unsigned int masked_sad(const uint8_t *a, int a_stride,
+                                      const uint8_t *b, int b_stride,
+                                      const uint8_t *m, int m_stride,
+                                      int width, int height) {
+  int y, x;
+  unsigned int sad = 0;
+
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++)
+      sad += m[x] * abs(a[x] - b[x]);
+
+    a += a_stride;
+    b += b_stride;
+    m += m_stride;
+  }
+  sad = (sad + 31) >> 6;
+
+  return sad;
+}
+
+#define MASKSADMxN(m, n) \
+unsigned int vp9_masked_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
+                                         const uint8_t *ref, int ref_stride, \
+                                         const uint8_t *msk, int msk_stride) { \
+  return masked_sad(src, src_stride, ref, ref_stride, msk, msk_stride, m, n); \
+}
+
+MASKSADMxN(64, 64)
+MASKSADMxN(64, 32)
+MASKSADMxN(32, 64)
+MASKSADMxN(32, 32)
+MASKSADMxN(32, 16)
+MASKSADMxN(16, 32)
+MASKSADMxN(16, 16)
+MASKSADMxN(16, 8)
+MASKSADMxN(8, 16)
+MASKSADMxN(8, 8)
+MASKSADMxN(8, 4)
+MASKSADMxN(4, 8)
+MASKSADMxN(4, 4)
+#endif
index eb5ae2e41c9a9290001728cc740179d098646388..9b02b7fbf37e9a20f223867afbbd79b146ee8e33 100644 (file)
@@ -266,3 +266,98 @@ void vp9_comp_avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
     ref += ref_stride;
   }
 }
+
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+    CONFIG_MASKED_INTERINTER)
+void masked_variance(const uint8_t *a, int  a_stride,
+                     const uint8_t *b, int  b_stride,
+                     const uint8_t *m, int  m_stride,
+                     int  w, int  h, unsigned int *sse, int *sum) {
+  int i, j;
+
+  *sum = 0;
+  *sse = 0;
+
+  for (i = 0; i < h; i++) {
+    for (j = 0; j < w; j++) {
+      const int diff = (a[j] - b[j]) * (m[j]);
+      *sum += diff;
+      *sse += diff * diff;
+    }
+
+    a += a_stride;
+    b += b_stride;
+    m += m_stride;
+  }
+  *sum = (*sum >= 0) ? ((*sum + 31) >> 6) : -((-*sum + 31) >> 6);
+  *sse = (*sse + 2047) >> 12;
+}
+
+#define MASK_VAR(W, H) \
+unsigned int vp9_masked_variance##W##x##H##_c(const uint8_t *a, int a_stride, \
+                                              const uint8_t *b, int b_stride, \
+                                              const uint8_t *m, int m_stride, \
+                                              unsigned int *sse) { \
+  int sum; \
+  masked_variance(a, a_stride, b, b_stride, m, m_stride, W, H, sse, &sum); \
+  return *sse - (((int64_t)sum * sum) / (W * H)); \
+}
+
+#define MASK_SUBPIX_VAR(W, H) \
+unsigned int vp9_masked_sub_pixel_variance##W##x##H##_c( \
+  const uint8_t *src, int  src_stride, \
+  int xoffset, int  yoffset, \
+  const uint8_t *dst, int dst_stride, \
+  const uint8_t *msk, int msk_stride, \
+  unsigned int *sse) { \
+  uint16_t fdata3[(H + 1) * W]; \
+  uint8_t temp2[H * W]; \
+\
+  var_filter_block2d_bil_first_pass(src, fdata3, src_stride, 1, H + 1, W, \
+                                    BILINEAR_FILTERS_2TAP(xoffset)); \
+  var_filter_block2d_bil_second_pass(fdata3, temp2, W, W, H, W, \
+                                     BILINEAR_FILTERS_2TAP(yoffset)); \
+\
+  return vp9_masked_variance##W##x##H##_c(temp2, W, dst, dst_stride, \
+                                          msk, msk_stride, sse); \
+}
+
+MASK_VAR(4, 4)
+MASK_SUBPIX_VAR(4, 4)
+
+MASK_VAR(4, 8)
+MASK_SUBPIX_VAR(4, 8)
+
+MASK_VAR(8, 4)
+MASK_SUBPIX_VAR(8, 4)
+
+MASK_VAR(8, 8)
+MASK_SUBPIX_VAR(8, 8)
+
+MASK_VAR(8, 16)
+MASK_SUBPIX_VAR(8, 16)
+
+MASK_VAR(16, 8)
+MASK_SUBPIX_VAR(16, 8)
+
+MASK_VAR(16, 16)
+MASK_SUBPIX_VAR(16, 16)
+
+MASK_VAR(16, 32)
+MASK_SUBPIX_VAR(16, 32)
+
+MASK_VAR(32, 16)
+MASK_SUBPIX_VAR(32, 16)
+
+MASK_VAR(32, 32)
+MASK_SUBPIX_VAR(32, 32)
+
+MASK_VAR(32, 64)
+MASK_SUBPIX_VAR(32, 64)
+
+MASK_VAR(64, 32)
+MASK_SUBPIX_VAR(64, 32)
+
+MASK_VAR(64, 64)
+MASK_SUBPIX_VAR(64, 64)
+#endif
index 4a194b72cc15da9557162ad81f5799cd5846b3ba..3d4e7b8895b11ac72a91fb3024cb0225e62e7bc3 100644 (file)
@@ -67,6 +67,32 @@ typedef unsigned int (*vp9_subp_avg_variance_fn_t)(const uint8_t *src_ptr,
                                                    unsigned int *sse,
                                                    const uint8_t *second_pred);
 
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+    CONFIG_MASKED_INTERINTER)
+typedef unsigned int(*vp9_masked_sad_fn_t)(const uint8_t *src_ptr,
+                                           int source_stride,
+                                           const uint8_t *ref_ptr,
+                                           int ref_stride,
+                                           const uint8_t *msk_ptr,
+                                           int msk_stride);
+typedef unsigned int (*vp9_masked_variance_fn_t)(const uint8_t *src_ptr,
+                                                 int source_stride,
+                                                 const uint8_t *ref_ptr,
+                                                 int ref_stride,
+                                                 const uint8_t *msk_ptr,
+                                                 int msk_stride,
+                                                 unsigned int *sse);
+typedef unsigned int (*vp9_masked_subpixvariance_fn_t)(const uint8_t *src_ptr,
+                                                       int source_stride,
+                                                       int xoffset,
+                                                       int yoffset,
+                                                       const uint8_t *ref_ptr,
+                                                       int Refstride,
+                                                       const uint8_t *msk_ptr,
+                                                       int msk_stride,
+                                                       unsigned int *sse);
+#endif
+
 typedef struct vp9_variance_vtable {
   vp9_sad_fn_t               sdf;
   vp9_sad_avg_fn_t           sdaf;
@@ -76,6 +102,12 @@ typedef struct vp9_variance_vtable {
   vp9_sad_multi_fn_t         sdx3f;
   vp9_sad_multi_fn_t         sdx8f;
   vp9_sad_multi_d_fn_t       sdx4df;
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+    CONFIG_MASKED_INTERINTER)
+  vp9_masked_sad_fn_t            msdf;
+  vp9_masked_variance_fn_t       mvf;
+  vp9_masked_subpixvariance_fn_t msvf;
+#endif
 } vp9_variance_fn_ptr_t;
 
 void vp9_comp_avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,