]> granicus.if.org Git - libvpx/commitdiff
Recursive extrapolation filter
authorYue Chen <yuec@google.com>
Tue, 13 Aug 2013 17:44:34 +0000 (10:44 -0700)
committerYue Chen <yuec@google.com>
Wed, 14 Aug 2013 22:59:11 +0000 (15:59 -0700)
The recursive intra filter is implemented. 6 extrapolation intra
filters are added as extra modes for 4x4 and 8x8 blocks.
Signaling bits are added at the block level to indicate if a normal
intra mode is switched to recursive intra filter mode. They are
entropy coded by maintaining a backward adaptive probability table
showing the usage of recursive filters at different block-sizes and
different intra modes.

Bit-rate reduction: +0.458% (derf)

Change-Id: I1b8e00405ea1494002ca40de1db52c51259012c4

15 files changed:
configure
vp9/common/vp9_blockd.h
vp9/common/vp9_entropymode.c
vp9/common/vp9_onyxc_int.h
vp9/common/vp9_reconintra.c
vp9/common/vp9_reconintra.h
vp9/decoder/vp9_decodemv.c
vp9/decoder/vp9_decodframe.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_encodeframe.c
vp9/encoder/vp9_encodemb.c
vp9/encoder/vp9_mbgraph.c
vp9/encoder/vp9_onyx_int.h
vp9/encoder/vp9_ratectrl.c
vp9/encoder/vp9_rdopt.c

index b84b3cd9f4bc489bdf4ecdc793192413665b1795..517ce26913efaca515e2c0de94170909d307252d 100755 (executable)
--- a/configure
+++ b/configure
@@ -251,6 +251,7 @@ EXPERIMENT_LIST="
     non420
     alpha
     interintra
+    filterintra
 "
 CONFIG_LIST="
     external_build
index 10d12794a2aee591cd722df3f1b1178954bb2a4c..716638da36d6e9c2acd7053b271cb81836400b2d 100644 (file)
@@ -89,6 +89,15 @@ static INLINE int is_inter_mode(MB_PREDICTION_MODE mode) {
   return mode >= NEARESTMV && mode <= NEWMV;
 }
 
+#if CONFIG_FILTERINTRA
+static INLINE int is_filter_allowed(MB_PREDICTION_MODE mode) {
+  return mode != DC_PRED &&
+         mode != D45_PRED &&
+         mode != D27_PRED &&
+         mode != D63_PRED;
+}
+#endif
+
 #define VP9_INTRA_MODES (TM_PRED + 1)
 
 #define VP9_INTER_MODES (1 + NEWMV - NEARESTMV)
@@ -160,6 +169,9 @@ typedef struct {
   MB_PREDICTION_MODE mode, uv_mode;
 #if CONFIG_INTERINTRA
   MB_PREDICTION_MODE interintra_mode, interintra_uv_mode;
+#endif
+#if CONFIG_FILTERINTRA
+  int filterbit, uv_filterbit;
 #endif
   MV_REFERENCE_FRAME ref_frame[2];
   TX_SIZE txfm_size;
@@ -187,6 +199,9 @@ typedef struct {
 
 typedef struct {
   MB_MODE_INFO mbmi;
+#if CONFIG_FILTERINTRA
+  int b_filter_info[4];
+#endif
   union b_mode_info bmi[4];
 } MODE_INFO;
 
index fb30e018cbcaf5a07832524a2872fb79ad1d8b22..b989d34e5c2b7df3f747408efd352faff935b6aa 100644 (file)
@@ -214,6 +214,16 @@ const vp9_prob vp9_kf_y_mode_prob[VP9_INTRA_MODES]
   }
 };
 
+#if CONFIG_FILTERINTRA
+const vp9_prob vp9_default_filterintra_prob[TX_SIZES][VP9_INTRA_MODES] = {
+  // DC   V    H    D45  D135 D117 D153 D27  D63  TM
+    {160, 160, 160, 160, 160, 160, 160, 160, 160, 160},  // TX_4X4
+    {180, 180, 180, 180, 180, 180, 180, 180, 180, 180},  // TX_8X8
+    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200},  // TX_16X16
+    {220, 220, 220, 220, 220, 220, 220, 220, 220, 220},  // TX_32X32
+};
+#endif
+
 static const vp9_prob default_inter_mode_probs[INTER_MODE_CONTEXTS]
                                               [VP9_INTER_MODES - 1] = {
   {2,       173,   34},  // 0 = both zero mv
@@ -339,6 +349,9 @@ void vp9_init_mbmode_probs(VP9_COMMON *cm) {
 #if CONFIG_INTERINTRA
   cm->fc.interintra_prob = VP9_DEF_INTERINTRA_PROB;
 #endif
+#if CONFIG_FILTERINTRA
+  vp9_copy(cm->fc.filterintra_prob, vp9_default_filterintra_prob);
+#endif
 }
 
 const vp9_tree_index vp9_switchable_interp_tree[VP9_SWITCHABLE_FILTERS*2-2] = {
@@ -467,6 +480,12 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) {
                                      counts->interintra);
   }
 #endif
+#if CONFIG_FILTERINTRA
+  for (i = 0; i < TX_SIZES; ++i)
+    for (j = 0; j < VP9_INTRA_MODES; ++j)
+      fc->filterintra_prob[i][j] = update_ct2(pre_fc->filterintra_prob[i][j],
+                                              counts->filterintra[i][j]);
+#endif
 }
 
 static void set_default_lf_deltas(struct loopfilter *lf) {
index cd9183570f14cfc1ea69e235f776f594c9e0f070..171ce9827c20e5eb995c160e5201f93734c1382e 100644 (file)
@@ -56,6 +56,9 @@ typedef struct frame_contexts {
 #if CONFIG_INTERINTRA
   vp9_prob interintra_prob;
 #endif
+#if CONFIG_FILTERINTRA
+  vp9_prob filterintra_prob[TX_SIZES][VP9_INTRA_MODES];
+#endif
 } FRAME_CONTEXT;
 
 typedef struct {
@@ -78,6 +81,9 @@ typedef struct {
 #if CONFIG_INTERINTRA
   unsigned int interintra[2];
 #endif
+#if CONFIG_FILTERINTRA
+  unsigned int filterintra[TX_SIZES][VP9_INTRA_MODES][2];
+#endif
 } FRAME_COUNTS;
 
 
index 059d9fc18317b4f88746d047597150981d854970..32857a378ff2f042bb6a42468efa2d204f591495 100644 (file)
@@ -401,11 +401,110 @@ static void build_intra_predictors(uint8_t *src, int src_stride,
   }
 }
 
+#if CONFIG_FILTERINTRA
+static void filter_intra_predictors(uint8_t *ypred_ptr, int y_stride, int bs,
+                                    uint8_t *yabove_row, uint8_t *yleft_col,
+                                    int mode) {
+  static const int prec_bits = 10;
+  static const int round_val = 511;
+  static const int taps[10][3] = {
+      {438 , 660, -352},  // DC
+      {1014, 565, -559},  // V
+      {312, 1017, -312},  // H
+      {0, 0, 0},          // D45
+      {478, 483, 153},    // D135
+      {699, 470, -122},   // D117
+      {356, 707, 35},     // D153
+      {0, 0, 0},          // D27
+      {0, 0, 0},          // D63
+      {877, 896, -812}    // TM
+      };
+  int k, r, c;
+  int pred[17][17];
+  int mean, ipred;
+  const int c1 = taps[mode][0];
+  const int c2 = taps[mode][1];
+  const int c3 = taps[mode][2];
+
+  k = 0;
+  mean = 0;
+  while (k < bs) {
+    mean = mean + (int)yleft_col[r];
+    mean = mean + (int)yabove_row[c];
+    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 < bs + 1; c++)
+    pred[0][c] = (int)yabove_row[c - 1] - mean;
+
+  for (r = 1; r < bs + 1; r++)
+    for (c = 1; c < bs + 1; c++) {
+      ipred = c1 * pred[r - 1][c] + c2 * pred[r][c - 1]
+              + c3 * 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(uint8_t *src, int src_stride,
+                                          uint8_t *pred_ptr, int stride,
+                                          MB_PREDICTION_MODE mode, TX_SIZE txsz,
+                                          int up_available, int left_available,
+                                          int right_available) {
+  int i;
+  DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
+  DECLARE_ALIGNED_ARRAY(16, uint8_t, yabove_data, 128 + 16);
+  uint8_t *above_row = yabove_data + 16;
+  const int bs = 4 << txsz;
+
+  if (left_available) {
+    for (i = 0; i < bs; i++)
+      left_col[i] = src[i * src_stride - 1];
+  } else {
+    vpx_memset(left_col, 129, bs);
+  }
+
+  if (up_available) {
+    uint8_t *above_ptr = src - src_stride;
+    if (bs == 4 && right_available && left_available) {
+      above_row = above_ptr;
+    } else {
+      vpx_memcpy(above_row, above_ptr, bs);
+      if (bs == 4 && right_available)
+        vpx_memcpy(above_row + bs, above_ptr + bs, bs);
+      else
+        vpx_memset(above_row + bs, above_row[bs - 1], bs);
+      above_row[-1] = left_available ? above_ptr[-1] : 129;
+    }
+  } else {
+    vpx_memset(above_row, 127, bs * 2);
+    above_row[-1] = 127;
+  }
+
+  filter_intra_predictors(pred_ptr, stride, bs, above_row, left_col, mode);
+}
+#endif
+
 void vp9_predict_intra_block(MACROBLOCKD *xd,
                             int block_idx,
                             int bwl_in,
                             TX_SIZE tx_size,
                             int mode,
+#if CONFIG_FILTERINTRA
+                            int filterbit,
+#endif
                             uint8_t *reference, int ref_stride,
                             uint8_t *predictor, int pre_stride) {
   const int bwl = bwl_in - tx_size;
@@ -413,14 +512,30 @@ void vp9_predict_intra_block(MACROBLOCKD *xd,
   const int have_top = (block_idx >> bwl) || xd->up_available;
   const int have_left = (block_idx & wmask) || xd->left_available;
   const int have_right = ((block_idx & wmask) != wmask);
+#if CONFIG_FILTERINTRA
+  int filterflag = is_filter_allowed(mode) && (tx_size <= TX_8X8) && filterbit;
+#endif
 
   assert(bwl >= 0);
+#if CONFIG_FILTERINTRA
+  if (!filterflag) {
+#endif
   build_intra_predictors(reference, ref_stride,
                          predictor, pre_stride,
                          mode,
                          tx_size,
                          have_top, have_left,
                          have_right);
+#if CONFIG_FILTERINTRA
+  } else {
+    build_filter_intra_predictors(reference, ref_stride,
+                                  predictor, pre_stride,
+                                  mode,
+                                  tx_size,
+                                  have_top, have_left,
+                                  have_right);
+  }
+#endif
 }
 
 #if CONFIG_INTERINTRA
@@ -549,7 +664,7 @@ static void combine_interintra(MB_PREDICTION_MODE mode,
 
 // Break down rectangular intra prediction for joint spatio-temporal prediction
 // into two square intra predictions.
-void build_intra_predictors_for_interintra(uint8_t *src, int src_stride,
+static void build_intra_predictors_for_interintra(uint8_t *src, int src_stride,
                                            uint8_t *pred_ptr, int stride,
                                            MB_PREDICTION_MODE mode,
                                            int bw, int bh,
index 527fff25b35fac456155fc20fb4b559f19fa0386..3ca6e2cc483033f279fdcdc0fc9d59eff77432c9 100644 (file)
@@ -25,7 +25,11 @@ void vp9_predict_intra_block(MACROBLOCKD *xd,
                             int block_idx,
                             int bwl_in,
                             TX_SIZE tx_size,
-                            int mode, uint8_t *ref, int ref_stride,
+                            int mode,
+#if CONFIG_FILTERINTRA
+                            int filterbit,
+#endif
+                            uint8_t *ref, int ref_stride,
                             uint8_t *predictor, int pre_stride);
 #if CONFIG_INTERINTRA
 void vp9_build_interintra_predictors(MACROBLOCKD *xd,
index 26b831a9f15bd2aca031835051a286c057258fde..e0be588ac0c0aa5ec3a4fe58cdef7335989dba0f 100644 (file)
@@ -169,6 +169,13 @@ static void read_intra_frame_mode_info(VP9D_COMP *pbi, MODE_INFO *m,
     const MB_PREDICTION_MODE L = xd->left_available ?
                                   left_block_mode(m, 0) : DC_PRED;
     mbmi->mode = read_intra_mode(r, vp9_kf_y_mode_prob[A][L]);
+#if CONFIG_FILTERINTRA
+    if ((mbmi->txfm_size <= TX_8X8) && is_filter_allowed(mbmi->mode))
+      mbmi->filterbit = vp9_read(r,
+                         cm->fc.filterintra_prob[mbmi->txfm_size][mbmi->mode]);
+    else
+      mbmi->filterbit = 0;
+#endif
   } else {
     // Only 4x4, 4x8, 8x4 blocks
     const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];  // 1 or 2
@@ -188,13 +195,34 @@ static void read_intra_frame_mode_info(VP9D_COMP *pbi, MODE_INFO *m,
           m->bmi[ib + 2].as_mode = b_mode;
         if (num_4x4_w == 2)
           m->bmi[ib + 1].as_mode = b_mode;
+#if CONFIG_FILTERINTRA
+        if (is_filter_allowed(b_mode))
+          m->b_filter_info[ib] = vp9_read(r,
+                                          cm->fc.filterintra_prob[0][b_mode]);
+        else
+          m->b_filter_info[ib] = 0;
+        if (num_4x4_h == 2)
+          m->b_filter_info[ib + 2] = m->b_filter_info[ib];
+        if (num_4x4_w == 2)
+          m->b_filter_info[ib + 1] = m->b_filter_info[ib];
+#endif
       }
     }
 
     mbmi->mode = m->bmi[3].as_mode;
+#if CONFIG_FILTERINTRA
+    mbmi->filterbit = m->b_filter_info[3];
+#endif
   }
 
   mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]);
+#if CONFIG_FILTERINTRA
+  if ((get_uv_tx_size(mbmi) <= TX_8X8) && 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,
@@ -390,6 +418,15 @@ static void read_intra_block_mode_info(VP9D_COMP *pbi, MODE_INFO *mi,
     const int size_group = size_group_lookup[bsize];
     mbmi->mode = read_intra_mode(r, cm->fc.y_mode_prob[size_group]);
     cm->counts.y_mode[size_group][mbmi->mode]++;
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(mbmi->mode) && (mbmi->txfm_size <= TX_8X8)) {
+      mbmi->filterbit = vp9_read(r,
+                          cm->fc.filterintra_prob[mbmi->txfm_size][mbmi->mode]);
+      cm->counts.filterintra[mbmi->txfm_size][mbmi->mode][mbmi->filterbit]++;
+    } else {
+      mbmi->filterbit = 0;
+    }
+#endif
   } else {
      // Only 4x4, 4x8, 8x4 blocks
      const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];  // 1 or 2
@@ -407,13 +444,40 @@ static void read_intra_block_mode_info(VP9D_COMP *pbi, MODE_INFO *mi,
            mi->bmi[ib + 2].as_mode = b_mode;
          if (num_4x4_w == 2)
            mi->bmi[ib + 1].as_mode = b_mode;
+#if CONFIG_FILTERINTRA
+         if (is_filter_allowed(b_mode)) {
+           mi->b_filter_info[ib] = vp9_read(r,
+                                            cm->fc.filterintra_prob[0][b_mode]);
+           cm->counts.filterintra[0][b_mode][mi->b_filter_info[ib]]++;
+         } else {
+           mi->b_filter_info[ib] = 0;
+         }
+
+         if (num_4x4_h == 2)
+           mi->b_filter_info[ib + 2] = mi->b_filter_info[ib];
+         if (num_4x4_w == 2)
+           mi->b_filter_info[ib + 1] = mi->b_filter_info[ib];
+#endif
       }
     }
     mbmi->mode = mi->bmi[3].as_mode;
+#if CONFIG_FILTERINTRA
+    mbmi->filterbit = mi->b_filter_info[3];
+#endif
   }
 
   mbmi->uv_mode = read_intra_mode(r, cm->fc.uv_mode_prob[mbmi->mode]);
   cm->counts.uv_mode[mbmi->mode][mbmi->uv_mode]++;
+#if CONFIG_FILTERINTRA
+  if (is_filter_allowed(mbmi->uv_mode) && (get_uv_tx_size(mbmi) <= TX_8X8)) {
+    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 int read_is_inter_block(VP9D_COMP *pbi, int segment_id, vp9_reader *r) {
index 13e5fc82129b940a4f0ad1809ef319790a56b568..e9d6f74d4a1ace284d586440f1e962d07fba94e8 100644 (file)
@@ -140,12 +140,22 @@ static void decode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
   const int tx_ib = raster_block >> tx_size;
   const int mode = plane == 0 ? mi->mbmi.mode
                               : mi->mbmi.uv_mode;
+#if CONFIG_FILTERINTRA
+  int fbit = 0;
+#endif
 
   if (plane == 0 && mi->mbmi.sb_type < BLOCK_8X8) {
     assert(bsize == BLOCK_8X8);
     b_mode = mi->bmi[raster_block].as_mode;
+#if CONFIG_FILTERINTRA
+    fbit = mi->b_filter_info[raster_block];
+#endif
   } else {
     b_mode = mode;
+#if CONFIG_FILTERINTRA
+    if (tx_size <= TX_8X8)
+      fbit = plane == 0? mi->mbmi.filterbit: mi->mbmi.uv_filterbit;
+#endif
   }
 
   if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0)
@@ -153,6 +163,9 @@ static void decode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
 
   plane_b_size = b_width_log2(bsize) - pd->subsampling_x;
   vp9_predict_intra_block(xd, tx_ib, plane_b_size, tx_size, b_mode,
+#if CONFIG_FILTERINTRA
+                          fbit,
+#endif
                           dst, pd->dst.stride,
                           dst, pd->dst.stride);
 
index b379838c9a1d0d48ce1a541aa0b2252e8f6c6918..27821ff258a447d4aef2b5ed6ae09f7028f4392a 100644 (file)
@@ -447,6 +447,12 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc) {
 
     if (bsize >= BLOCK_8X8) {
       write_intra_mode(bc, mode, pc->fc.y_mode_prob[size_group_lookup[bsize]]);
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mode) && (mi->txfm_size <= TX_8X8)) {
+        vp9_write(bc, mi->filterbit,
+                  pc->fc.filterintra_prob[mi->txfm_size][mode]);
+      }
+#endif
     } else {
       int idx, idy;
       const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
@@ -455,10 +461,22 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc) {
         for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
           const MB_PREDICTION_MODE bm = m->bmi[idy * 2 + idx].as_mode;
           write_intra_mode(bc, bm, pc->fc.y_mode_prob[0]);
+#if CONFIG_FILTERINTRA
+          if (is_filter_allowed(bm)) {
+            vp9_write(bc, m->b_filter_info[idy * 2 + idx],
+                      pc->fc.filterintra_prob[0][bm]);
+          }
+#endif
         }
       }
     }
     write_intra_mode(bc, mi->uv_mode, pc->fc.uv_mode_prob[mode]);
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(mi->uv_mode) && (get_uv_tx_size(mi) <= TX_8X8)) {
+      vp9_write(bc, mi->uv_filterbit,
+                pc->fc.filterintra_prob[get_uv_tx_size(mi)][mi->uv_mode]);
+    }
+#endif
   } else {
     vp9_prob *mv_ref_p;
     encode_ref_frame(cpi, bc);
@@ -570,6 +588,11 @@ static void write_mb_modes_kf(const VP9_COMP *cpi, MODE_INFO *m,
     const MB_PREDICTION_MODE L = xd->left_available ?
                                  left_block_mode(m, 0) : DC_PRED;
     write_intra_mode(bc, ym, vp9_kf_y_mode_prob[A][L]);
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(ym) && (m->mbmi.txfm_size <= TX_8X8))
+      vp9_write(bc, m->mbmi.filterbit,
+                c->fc.filterintra_prob[m->mbmi.txfm_size][ym]);
+#endif
   } else {
     int idx, idy;
     const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[m->mbmi.sb_type];
@@ -585,11 +608,21 @@ static void write_mb_modes_kf(const VP9_COMP *cpi, MODE_INFO *m,
         ++intra_mode_stats[A][L][bm];
 #endif
         write_intra_mode(bc, bm, vp9_kf_y_mode_prob[A][L]);
+#if CONFIG_FILTERINTRA
+        if (is_filter_allowed(bm))
+          vp9_write(bc, m->b_filter_info[i], c->fc.filterintra_prob[0][bm]);
+#endif
       }
     }
   }
 
   write_intra_mode(bc, m->mbmi.uv_mode, vp9_kf_uv_mode_prob[ym]);
+#if CONFIG_FILTERINTRA
+  if (is_filter_allowed(m->mbmi.uv_mode) &&
+      (get_uv_tx_size(&(m->mbmi)) <= TX_8X8))
+    vp9_write(bc, m->mbmi.uv_filterbit,
+           c->fc.filterintra_prob[get_uv_tx_size(&(m->mbmi))][m->mbmi.uv_mode]);
+#endif
 }
 
 static void write_modes_b(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc,
index 63ff00d9915eda89e9bd955bb95c1bf11de5ccef..32d6b0d62ba2846dde1444dbbc837b36a61235eb 100644 (file)
@@ -2009,6 +2009,10 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) {
 
   xd->mode_info_context->mbmi.mode = DC_PRED;
   xd->mode_info_context->mbmi.uv_mode = DC_PRED;
+#if CONFIG_FILTERINTRA
+  xd->mode_info_context->mbmi.filterbit = 0;
+  xd->mode_info_context->mbmi.uv_filterbit = 0;
+#endif
 
   vp9_zero(cpi->y_mode_count)
   vp9_zero(cpi->y_uv_mode_count)
@@ -2024,6 +2028,9 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) {
   vp9_zero(cpi->interintra_count);
   vp9_zero(cpi->interintra_select_count);
 #endif
+#if CONFIG_FILTERINTRA
+  vp9_zero(cm->counts.filterintra);
+#endif
 
   // Note: this memset assumes above_context[0], [1] and [2]
   // are allocated as part of the same buffer.
@@ -2515,13 +2522,30 @@ static void sum_intra_stats(VP9_COMP *cpi, MACROBLOCK *x) {
   const MACROBLOCKD *xd = &x->e_mbd;
   const MB_PREDICTION_MODE m = xd->mode_info_context->mbmi.mode;
   const MB_PREDICTION_MODE uvm = xd->mode_info_context->mbmi.uv_mode;
+#if CONFIG_FILTERINTRA
+  const int uv_fbit = xd->mode_info_context->mbmi.uv_filterbit;
+  int fbit = xd->mode_info_context->mbmi.filterbit;
+#endif
 
   ++cpi->y_uv_mode_count[m][uvm];
+#if CONFIG_FILTERINTRA
+  if (is_filter_allowed(uvm) &&
+      (get_uv_tx_size(&(xd->mode_info_context->mbmi)) <= TX_8X8))
+    ++cpi->common.counts.filterintra
+                         [get_uv_tx_size(&(xd->mode_info_context->mbmi))]
+                         [uvm][uv_fbit];
+#endif
   if (xd->mode_info_context->mbmi.sb_type >= BLOCK_8X8) {
     const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type;
     const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
     const int bsl = MIN(bwl, bhl);
     ++cpi->y_mode_count[MIN(bsl, 3)][m];
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(m) &&
+        (xd->mode_info_context->mbmi.txfm_size <= TX_8X8))
+      ++cpi->common.counts.filterintra[xd->mode_info_context->mbmi.txfm_size]
+                                       [m][fbit];
+#endif
   } else {
     int idx, idy;
     int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[
@@ -2532,6 +2556,12 @@ static void sum_intra_stats(VP9_COMP *cpi, MACROBLOCK *x) {
       for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
         int m = xd->mode_info_context->bmi[idy * 2 + idx].as_mode;
         ++cpi->y_mode_count[0][m];
+#if CONFIG_FILTERINTRA
+        if (is_filter_allowed(m)) {
+          fbit = xd->mode_info_context->b_filter_info[idy * 2 + idx];
+          ++cpi->common.counts.filterintra[0][m][fbit];
+        }
+#endif
       }
     }
   }
index 40b0a4e5a2be601a1c15026e6b013ab36994bd8d..5a23b0beb717fad69cffe38fe074fce1e62d3f8e 100644 (file)
@@ -640,6 +640,9 @@ void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
   const int16_t *scan, *iscan;
   TX_TYPE tx_type;
   MB_PREDICTION_MODE mode;
+#if CONFIG_FILTERINTRA
+  int fbit = 0;
+#endif
   const int bwl = b_width_log2(bsize) - pd->subsampling_x, bw = 1 << bwl;
   const int twl = bwl - tx_size, twmask = (1 << twl) - 1;
   int xoff, yoff;
@@ -660,6 +663,9 @@ void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
       scan = vp9_default_scan_32x32;
       iscan = vp9_default_iscan_32x32;
       mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
+#if CONFIG_FILTERINTRA
+      fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
       block >>= 6;
       xoff = 32 * (block & twmask);
       yoff = 32 * (block >> twl);
@@ -667,6 +673,9 @@ void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
       src = p->src.buf + yoff * p->src.stride + xoff;
       src_diff = p->src_diff + 4 * bw * yoff + xoff;
       vp9_predict_intra_block(xd, block, bwl, TX_32X32, mode,
+#if CONFIG_FILTERINTRA
+                              fbit,
+#endif
                               dst, pd->dst.stride, dst, pd->dst.stride);
       vp9_subtract_block(32, 32, src_diff, bw * 4,
                          src, p->src.stride, dst, pd->dst.stride);
@@ -685,6 +694,9 @@ void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
       scan = get_scan_16x16(tx_type);
       iscan = get_iscan_16x16(tx_type);
       mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
+#if CONFIG_FILTERINTRA
+      fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
       block >>= 4;
       xoff = 16 * (block & twmask);
       yoff = 16 * (block >> twl);
@@ -692,6 +704,9 @@ void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
       src = p->src.buf + yoff * p->src.stride + xoff;
       src_diff = p->src_diff + 4 * bw * yoff + xoff;
       vp9_predict_intra_block(xd, block, bwl, TX_16X16, mode,
+#if CONFIG_FILTERINTRA
+                              fbit,
+#endif
                               dst, pd->dst.stride, dst, pd->dst.stride);
       vp9_subtract_block(16, 16, src_diff, bw * 4,
                          src, p->src.stride, dst, pd->dst.stride);
@@ -714,6 +729,9 @@ void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
       scan = get_scan_8x8(tx_type);
       iscan = get_iscan_8x8(tx_type);
       mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
+#if CONFIG_FILTERINTRA
+      fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
       block >>= 2;
       xoff = 8 * (block & twmask);
       yoff = 8 * (block >> twl);
@@ -721,6 +739,9 @@ void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
       src = p->src.buf + yoff * p->src.stride + xoff;
       src_diff = p->src_diff + 4 * bw * yoff + xoff;
       vp9_predict_intra_block(xd, block, bwl, TX_8X8, mode,
+#if CONFIG_FILTERINTRA
+                              fbit,
+#endif
                               dst, pd->dst.stride, dst, pd->dst.stride);
       vp9_subtract_block(8, 8, src_diff, bw * 4,
                          src, p->src.stride, dst, pd->dst.stride);
@@ -747,12 +768,22 @@ void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
       else
         mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
 
+#if CONFIG_FILTERINTRA
+      if (mbmi->sb_type < BLOCK_8X8 && plane == 0)
+        fbit = xd->mode_info_context->b_filter_info[block];
+      else
+        fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
+
       xoff = 4 * (block & twmask);
       yoff = 4 * (block >> twl);
       dst = pd->dst.buf + yoff * pd->dst.stride + xoff;
       src = p->src.buf + yoff * p->src.stride + xoff;
       src_diff = p->src_diff + 4 * bw * yoff + xoff;
       vp9_predict_intra_block(xd, block, bwl, TX_4X4, mode,
+#if CONFIG_FILTERINTRA
+                              fbit,
+#endif
                               dst, pd->dst.stride, dst, pd->dst.stride);
       vp9_subtract_block(4, 4, src_diff, bw * 4,
                          src, p->src.stride, dst, pd->dst.stride);
index 314e195d251ee8cfb000ed38599e2e3447eed753..b8d801695705297847628a4fed1d7d373230a421 100644 (file)
@@ -146,7 +146,13 @@ static int find_best_16x16_intra(VP9_COMP *cpi,
     unsigned int err;
 
     xd->mode_info_context->mbmi.mode = mode;
+#if CONFIG_FILTERINTRA
+    xd->mode_info_context->mbmi.filterbit = 0;
+#endif
     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);
     err = vp9_sad16x16(x->plane[0].src.buf, x->plane[0].src.stride,
index d8282de0929d50255ee0a924ef51506e512f5a25..9f948f2e65a13fdced723e53dd8e8cd82c4556f7 100644 (file)
@@ -99,6 +99,9 @@ typedef struct {
 #if CONFIG_INTERINTRA
   vp9_prob interintra_prob;
 #endif
+#if CONFIG_FILTERINTRA
+  vp9_prob filterintra_prob[TX_SIZES][VP9_INTRA_MODES];
+#endif
 } CODING_CONTEXT;
 
 typedef struct {
index dece23b66b49f0710f67ac24e303ea448b5136b0..c6e5b2ddeffe33d473aa47f9718ce1295b59c46d 100644 (file)
@@ -109,6 +109,9 @@ void vp9_save_coding_context(VP9_COMP *cpi) {
 #if CONFIG_INTERINTRA
   cc->interintra_prob = cm->fc.interintra_prob;
 #endif
+#if CONFIG_FILTERINTRA
+  vp9_copy(cc->filterintra_prob, cm->fc.filterintra_prob);
+#endif
 }
 
 void vp9_restore_coding_context(VP9_COMP *cpi) {
@@ -151,6 +154,9 @@ void vp9_restore_coding_context(VP9_COMP *cpi) {
 #if CONFIG_INTERINTRA
   cm->fc.interintra_prob = cc->interintra_prob;
 #endif
+#if CONFIG_FILTERINTRA
+  vp9_copy(cm->fc.filterintra_prob, cc->filterintra_prob);
+#endif
 }
 
 void vp9_setup_key_frame(VP9_COMP *cpi) {
index 1994360a46a40147729e6a110a73e0c3607dc0a6..c6b6443e3fc81cb2bfa293e38fec83dea5aaabc1 100644 (file)
@@ -1155,6 +1155,9 @@ static int conditional_skipintra(MB_PREDICTION_MODE mode,
 
 static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
                                      MB_PREDICTION_MODE *best_mode,
+#if CONFIG_FILTERINTRA
+                                     int *best_fbit,
+#endif
                                      int *bmode_costs,
                                      ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l,
                                      int *bestrate, int *bestratey,
@@ -1182,6 +1185,9 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
   const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
   const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
   int idx, idy, block;
+#if CONFIG_FILTERINTRA
+  int mode_ext, fbit;
+#endif
   uint8_t best_dst[8 * 8];
 
   assert(ib < 4);
@@ -1190,6 +1196,7 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
   vpx_memcpy(tl, l, sizeof(tl));
   xd->mode_info_context->mbmi.txfm_size = TX_4X4;
 
+#if !CONFIG_FILTERINTRA
   for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
     int64_t this_rd;
     int ratey = 0;
@@ -1201,6 +1208,20 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
     }
 
     rate = bmode_costs[mode];
+#else
+  for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; ++mode_ext) {
+    int64_t this_rd;
+    int ratey = 0;
+
+    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
     distortion = 0;
 
     vpx_memcpy(tempa, ta, sizeof(ta));
@@ -1215,11 +1236,17 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
 
         block = ib + idy * 2 + idx;
         xd->mode_info_context->bmi[block].as_mode = mode;
+#if CONFIG_FILTERINTRA
+        xd->mode_info_context->b_filter_info[block] = fbit;
+#endif
         src_diff = raster_block_offset_int16(xd, BLOCK_8X8, 0, block,
                                              p->src_diff);
         coeff = BLOCK_OFFSET(x->plane[0].coeff, block, 16);
         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);
@@ -1264,6 +1291,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)
@@ -1314,6 +1344,9 @@ static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP * const cpi,
     for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
       const int mis = xd->mode_info_stride;
       MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+#if CONFIG_FILTERINTRA
+      int UNINITIALIZED_IS_SAFE(best_fbit);
+#endif
       int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(ry);
       int64_t UNINITIALIZED_IS_SAFE(d), this_rd;
       i = idy * 2 + idx;
@@ -1326,7 +1359,11 @@ static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP * const cpi,
         bmode_costs  = mb->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);
@@ -1343,6 +1380,13 @@ static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP * const cpi,
         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;
@@ -1353,6 +1397,9 @@ static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP * const cpi,
   *rate_y = tot_rate_y;
   *distortion = total_distortion;
   xd->mode_info_context->mbmi.mode = mic->bmi[3].as_mode;
+#if CONFIG_FILTERINTRA
+  xd->mode_info_context->mbmi.filterbit = mic->b_filter_info[3];
+#endif
 
   return RDCOST(mb->rdmult, mb->rddiv, cost, total_distortion);
 }
@@ -1371,16 +1418,31 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
   TX_SIZE UNINITIALIZED_IS_SAFE(best_tx);
   int i;
   int *bmode_costs = x->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 *const mic = xd->mode_info_context;
     const int mis = xd->mode_info_stride;
+#else
+  for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; mode_ext++) {
+    int64_t local_tx_cache[TX_MODES];
+    MODE_INFO *const mic = xd->mode_info_context;
+    const int mis = xd->mode_info_stride;
+
+    fbit = mode_ext & 1;
+    mode = mode_ext >> 1;
+    if (fbit && !is_filter_allowed(mode))
+      continue;
+#endif
 
     if (cpi->common.frame_type == KEY_FRAME) {
       const MB_PREDICTION_MODE A = above_block_mode(mic, 0, mis);
@@ -1390,6 +1452,9 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
       bmode_costs = x->y_mode_costs[A][L];
     }
     x->e_mbd.mode_info_context->mbmi.mode = mode;
+#if CONFIG_FILTERINTRA
+    x->e_mbd.mode_info_context->mbmi.filterbit = fbit;
+#endif
 
     super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, &s, NULL,
                     bsize, local_tx_cache, best_rd);
@@ -1398,10 +1463,20 @@ 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) &&
+        (xd->mode_info_context->mbmi.txfm_size <= TX_8X8))
+      this_rate += vp9_cost_bit(cpi->common.fc.filterintra_prob
+                                [xd->mode_info_context->mbmi.txfm_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         = x->e_mbd.mode_info_context->mbmi.txfm_size;
       *rate           = this_rate;
@@ -1422,6 +1497,9 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
   }
 
   x->e_mbd.mode_info_context->mbmi.mode = mode_selected;
+#if CONFIG_FILTERINTRA
+  x->e_mbd.mode_info_context->mbmi.filterbit = fbit_selected;
+#endif
   x->e_mbd.mode_info_context->mbmi.txfm_size = best_tx;
 
   return best_rd;
@@ -1472,16 +1550,40 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
   MB_PREDICTION_MODE last_mode = bsize <= BLOCK_8X8 ?
               TM_PRED : cpi->sf.last_chroma_intra_mode;
 
+#if CONFIG_FILTERINTRA
+  int mode_ext, fbit = 0, fbit_selected = 0;
+  for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * last_mode + 1; mode_ext++) {
+    mode = mode_ext >> 1;
+    fbit = mode_ext & 1;
+
+    if (fbit && !is_filter_allowed(mode))
+      continue;
+    if (fbit && is_filter_allowed(mode) &&
+        (get_uv_tx_size(&(x->e_mbd.mode_info_context->mbmi)) != TX_4X4))
+      continue;
+
+    x->e_mbd.mode_info_context->mbmi.uv_filterbit = fbit;
+#else
   for (mode = DC_PRED; mode <= last_mode; mode++) {
+#endif
     x->e_mbd.mode_info_context->mbmi.uv_mode = mode;
     super_block_uvrd(&cpi->common, x, &this_rate_tokenonly,
                      &this_distortion, &s, NULL, bsize);
     this_rate = this_rate_tokenonly +
                 x->intra_uv_mode_cost[cpi->common.frame_type][mode];
+#if CONFIG_FILTERINTRA
+    if (is_filter_allowed(mode) &&
+        (get_uv_tx_size(&(x->e_mbd.mode_info_context->mbmi)) <= TX_8X8))
+      this_rate += vp9_cost_bit(cpi->common.fc.filterintra_prob
+             [get_uv_tx_size(&(x->e_mbd.mode_info_context->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;
@@ -1491,6 +1593,9 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
   }
 
   x->e_mbd.mode_info_context->mbmi.uv_mode = mode_selected;
+#if CONFIG_FILTERINTRA
+  x->e_mbd.mode_info_context->mbmi.uv_filterbit = fbit_selected;
+#endif
 
   return best_rd;
 }
@@ -3286,6 +3391,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];
   MB_PREDICTION_MODE mode_uv[TX_SIZES];
+#if CONFIG_FILTERINTRA
+  int fbit_uv[TX_SIZES];
+#endif
   struct scale_factors scale_factor[4];
   unsigned int ref_frame_mask = 0;
   unsigned int mode_mask = 0;
@@ -3598,12 +3706,18 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
                              &rate_uv_tokenonly[TX_4X4],
                              &dist_uv[TX_4X4], &skip_uv[TX_4X4],
                              &mode_uv[TX_4X4]);
+#if CONFIG_FILTERINTRA
+        fbit_uv[TX_4X4] = mbmi->uv_filterbit;
+#endif
       }
       rate2 += rate_uv_intra[TX_4X4];
       rate_uv = rate_uv_tokenonly[TX_4X4];
       distortion2 += dist_uv[TX_4X4];
       distortion_uv = dist_uv[TX_4X4];
       mbmi->uv_mode = mode_uv[TX_4X4];
+#if CONFIG_FILTERINTRA
+      mbmi->uv_filterbit = fbit_uv[TX_4X4];
+#endif
       tx_cache[ONLY_4X4] = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
       for (i = 0; i < TX_MODES; ++i)
         tx_cache[i] = tx_cache[ONLY_4X4];
@@ -3630,9 +3744,39 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
         if (conditional_skipintra(mbmi->mode, best_intra_mode))
             continue;
       }
+#if CONFIG_FILTERINTRA
+      mbmi->filterbit = 0;
+#endif
       super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, NULL,
                       bsize, tx_cache, best_rd);
 
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mbmi->mode)) {
+        int temp_txfm_size, skippable_fil, rate_y_fil = 0;
+        int64_t distortion_y_fil = 0;
+        int64_t tx_cache_fil[TX_MODES];
+        int rate0, rate1;
+        temp_txfm_size = mbmi->txfm_size;
+        mbmi->filterbit = 1;
+        super_block_yrd(cpi, x, &rate_y_fil, &distortion_y_fil, &skippable_fil,
+                        NULL, bsize, tx_cache_fil, best_rd);
+        rate0 = vp9_cost_bit(
+                        cm->fc.filterintra_prob[temp_txfm_size][mbmi->mode], 0);
+        rate1 = vp9_cost_bit(
+                       cm->fc.filterintra_prob[mbmi->txfm_size][mbmi->mode], 1);
+        if (RDCOST(x->rdmult, x->rddiv, rate_y + rate0, distortion_y) <=
+            RDCOST(x->rdmult, x->rddiv, rate_y_fil + rate1, distortion_y_fil)) {
+          mbmi->txfm_size = temp_txfm_size;
+          mbmi->filterbit = 0;
+        } else {
+          rate_y = rate_y_fil;
+          distortion_y = distortion_y_fil;
+          skippable = skippable_fil;
+          vpx_memcpy(tx_cache, tx_cache_fil, TX_MODES * sizeof(int64_t));
+        }
+      }
+#endif
+
       if (rate_y == INT_MAX)
         continue;
 
@@ -3642,14 +3786,25 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
                              &rate_uv_tokenonly[uv_tx],
                              &dist_uv[uv_tx], &skip_uv[uv_tx],
                              &mode_uv[uv_tx]);
+#if CONFIG_FILTERINTRA
+        fbit_uv[uv_tx] = mbmi->uv_filterbit;
+#endif
       }
 
       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 + x->mbmode_cost[mbmi->mode] + rate_uv_intra[uv_tx];
+#if CONFIG_FILTERINTRA
+      if (is_filter_allowed(mbmi->mode) && mbmi->txfm_size <= TX_8X8)
+        rate2 += vp9_cost_bit(
+         cm->fc.filterintra_prob[mbmi->txfm_size][mbmi->mode], mbmi->filterbit);
+#endif
       if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
         rate2 += intra_cost_penalty;
       distortion2 = distortion_y + distortion_uv;