Merge "Adding experiment for supertransform" into nextgenv2
diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h
index c4dce60..03e34e0 100644
--- a/vp10/common/blockd.h
+++ b/vp10/common/blockd.h
@@ -89,7 +89,6 @@
   // 1: an ext intra mode is used; 0: otherwise.
   uint8_t use_ext_intra_mode[PLANE_TYPES];
   EXT_INTRA_MODE ext_intra_mode[PLANE_TYPES];
-  uint8_t ext_intra_angle[PLANE_TYPES];
 } EXT_INTRA_MODE_INFO;
 #endif  // CONFIG_EXT_INTRA
 
@@ -124,6 +123,7 @@
 
 #if CONFIG_EXT_INTRA
   EXT_INTRA_MODE_INFO ext_intra_mode_info;
+  int8_t angle_delta[2];
 #endif  // CONFIG_EXT_INTRA
 
   // TODO(slavarnway): Delete and use bmi[3].as_mv[] instead.
@@ -328,14 +328,14 @@
 #endif  // CONFIG_EXT_TX
 
 #if CONFIG_EXT_INTRA
-// 0: use both directional and filter modes; 1: use directional modes only.
-#define DR_ONLY 0
-// 0: use slow exhaustive search; 1: use fast sub-optimal search.
+#define ALLOW_FILTER_INTRA_MODES 1
+#define ANGLE_STEP 3
+#define MAX_ANGLE_DELTAS 3
 #define ANGLE_FAST_SEARCH 1
-// A parameter to adjust early termination in the fast search of angles.
-#define RD_ADJUSTER 1.4
-// Number of different angles that are supported
-#define EXT_INTRA_ANGLES 128
+
+static uint8_t mode_to_angle_map[INTRA_MODES] = {
+    0, 90, 180, 45, 135, 111, 157, 203, 67, 0,
+};
 
 static const TX_TYPE filter_intra_mode_to_tx_type_lookup[FILTER_INTRA_MODES] = {
   DCT_DCT,    // FILTER_DC
@@ -349,13 +349,6 @@
   ADST_DCT,   // FILTER_D63
   ADST_ADST,  // FILTER_TM
 };
-
-// Maps the angle index to the actual prediction angle (in degrees).
-// Angle index is in the range [0, EXT_INTRA_ANGLES); the actual prediction
-// angle is in the range (0, 270).
-static INLINE int prediction_angle_map(int angle_in) {
-  return (10 + 2 * angle_in);
-}
 #endif  // CONFIG_EXT_INTRA
 
 static INLINE TX_TYPE get_tx_type(PLANE_TYPE plane_type,
@@ -363,33 +356,44 @@
                                   int block_idx, TX_SIZE tx_size) {
   const MODE_INFO *const mi = xd->mi[0];
   const MB_MODE_INFO *const mbmi = &mi->mbmi;
-#if CONFIG_EXT_INTRA
-  const int use_ext_intra_mode_info =
-      mbmi->ext_intra_mode_info.use_ext_intra_mode[plane_type];
-  const EXT_INTRA_MODE ext_intra_mode =
-      mbmi->ext_intra_mode_info.ext_intra_mode[plane_type];
 
-  if (!is_inter_block(mbmi) && use_ext_intra_mode_info) {
-    if (!xd->lossless[mbmi->segment_id] && tx_size < TX_32X32
+#if CONFIG_EXT_INTRA
+  if (!is_inter_block(mbmi)) {
+    const int use_ext_intra_mode_info =
+        mbmi->ext_intra_mode_info.use_ext_intra_mode[plane_type];
+    const EXT_INTRA_MODE ext_intra_mode =
+        mbmi->ext_intra_mode_info.ext_intra_mode[plane_type];
+    const PREDICTION_MODE mode = (plane_type == PLANE_TYPE_Y) ?
+        get_y_mode(mi, block_idx) : mbmi->uv_mode;
+
+    if (xd->lossless[mbmi->segment_id] || tx_size >= TX_32X32)
+      return DCT_DCT;
+
 #if CONFIG_EXT_TX
-        && !(mbmi->sb_type >= BLOCK_8X8 && plane_type == PLANE_TYPE_Y)
+    if (mbmi->sb_type >= BLOCK_8X8 && plane_type == PLANE_TYPE_Y)
+      return mbmi->tx_type;
 #endif  // CONFIG_EXT_TX
-    ) {
-      if (ext_intra_mode > FILTER_TM_PRED) {
-        int angle = mbmi->ext_intra_mode_info.ext_intra_angle[plane_type];
-        angle = prediction_angle_map(angle);
-        assert(angle > 0 && angle < 270);
-        if (angle == 135)
-          return ADST_ADST;
-        else if (angle < 45 || angle > 225)
-          return DCT_DCT;
-        else if (angle < 135)
-          return ADST_DCT;
-        else
-          return DCT_ADST;
-      } else {
-        return filter_intra_mode_to_tx_type_lookup[ext_intra_mode];
-      }
+
+    if (use_ext_intra_mode_info)
+      return filter_intra_mode_to_tx_type_lookup[ext_intra_mode];
+
+    if (mode == DC_PRED) {
+      return DCT_DCT;
+    } else if (mode == TM_PRED) {
+      return ADST_ADST;
+    } else {
+      int angle = mode_to_angle_map[mode];
+      if (mbmi->sb_type >= BLOCK_8X8)
+        angle += mbmi->angle_delta[plane_type] * ANGLE_STEP;
+      assert(angle > 0 && angle < 270);
+      if (angle == 135)
+        return ADST_ADST;
+      else if (angle < 45 || angle > 225)
+        return DCT_DCT;
+      else if (angle < 135)
+        return ADST_DCT;
+      else
+        return DCT_ADST;
     }
   }
 #endif  // CONFIG_EXT_INTRA
diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c
index e347c23..ceb55df 100644
--- a/vp10/common/entropymode.c
+++ b/vp10/common/entropymode.c
@@ -1094,7 +1094,7 @@
 #endif
 
 #if CONFIG_EXT_INTRA
-static  const vpx_prob default_ext_intra_probs[2] = {200, 200};
+static  const vpx_prob default_ext_intra_probs[2] = {230, 230};
 #endif  // CONFIG_EXT_INTRA
 
 static void init_mode_probs(FRAME_CONTEXT *fc) {
diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h
index 00eacc5..2b5c948 100644
--- a/vp10/common/entropymode.h
+++ b/vp10/common/entropymode.h
@@ -32,11 +32,6 @@
 #define PALETTE_BLOCK_SIZES (BLOCK_64X64 - BLOCK_8X8 + 1)
 #define PALETTE_Y_MODE_CONTEXTS 3
 
-#if CONFIG_EXT_INTRA
-// Probability that an ext_intra mode is a directional prediction mode
-#define DR_EXT_INTRA_PROB 144
-#endif  // CONFIG_EXT_INTRA
-
 struct VP10Common;
 
 struct tx_probs {
diff --git a/vp10/common/enums.h b/vp10/common/enums.h
index 56e9c90..3f9395e 100644
--- a/vp10/common/enums.h
+++ b/vp10/common/enums.h
@@ -168,7 +168,6 @@
   FILTER_D207_PRED,
   FILTER_D63_PRED,
   FILTER_TM_PRED,
-  EXT_DR_PRED,
   EXT_INTRA_MODES,
 } EXT_INTRA_MODE;
 
diff --git a/vp10/common/reconintra.c b/vp10/common/reconintra.c
index 474edbd..87dc13a 100644
--- a/vp10/common/reconintra.c
+++ b/vp10/common/reconintra.c
@@ -405,32 +405,11 @@
   }
 }
 
-static INLINE void v_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
-                               const uint8_t *above, const uint8_t *left) {
-  int r;
-  (void) left;
-
-  for (r = 0; r < bs; r++) {
-    memcpy(dst, above, bs);
-    dst += stride;
-  }
-}
-
-static INLINE void h_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
-                               const uint8_t *above, const uint8_t *left) {
-  int r;
-  (void) above;
-
-  for (r = 0; r < bs; r++) {
-    memset(dst, left[r], bs);
-    dst += stride;
-  }
-}
-
-static void dr_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
+static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
                          const uint8_t *above, const uint8_t *left, int angle) {
   double t = 0;
   int dx, dy;
+  int bs = 4 << tx_size;
 
   if (angle != 90 && angle != 180)
     t = tan(angle * PI / 180.0);
@@ -448,9 +427,9 @@
     dy = -((int)(256 * t));
     dr_prediction_z3(dst, stride, bs, above, left, dx, dy);
   } else if (angle == 90) {
-    v_predictor(dst, stride, bs, above, left);
+    pred[V_PRED][tx_size](dst, stride, above, left);
   } else if (angle == 180) {
-    h_predictor(dst, stride, bs, above, left);
+    pred[H_PRED][tx_size](dst, stride, above, left);
   }
 }
 
@@ -915,11 +894,7 @@
   int i;
   uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
   uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
-#if CONFIG_MISC_FIXES
-  DECLARE_ALIGNED(16, uint16_t, left_col[32]);
-#else
   DECLARE_ALIGNED(16, uint16_t, left_col[64]);
-#endif
   DECLARE_ALIGNED(16, uint16_t, above_data[64 + 16]);
   uint16_t *above_row = above_data + 16;
   const uint16_t *const_above_row = above_row;
@@ -946,37 +921,38 @@
       &xd->mi[0]->mbmi.ext_intra_mode_info;
   const EXT_INTRA_MODE ext_intra_mode =
       ext_intra_mode_info->ext_intra_mode[plane != 0];
-  const int angle =
-      prediction_angle_map(ext_intra_mode_info->ext_intra_angle[plane != 0]);
+  int p_angle = 0;
+
+  if (mode != DC_PRED && mode != TM_PRED &&
+      xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
+    p_angle = mode_to_angle_map[mode] +
+        xd->mi[0]->mbmi.angle_delta[plane != 0] * ANGLE_STEP;
+#if CONFIG_MISC_FIXES
+    if (p_angle <= 90)
+      need_above = 1, need_left = 0;
+    else if (p_angle < 180)
+      need_above = 1, need_left = 1;
+    else
+      need_above = 0, need_left = 1;
+#else
+    if (p_angle < 90)
+      need_above = 0, need_aboveright = 1, need_left = 0;
+    else if (p_angle == 90)
+      need_above = 1, need_aboveright = 0, need_left = 0;
+    else if (p_angle < 180)
+      need_above = 1, need_aboveright = 0, need_left = 1;
+    else
+      need_above = 0, need_aboveright = 0, need_left = 1;
+#endif  // CONFIG_MISC_FIXES
+  }
 
   if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
     EXT_INTRA_MODE ext_intra_mode =
         ext_intra_mode_info->ext_intra_mode[plane != 0];
-    if (ext_intra_mode <= FILTER_TM_PRED) {
-      need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT;
-      need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE;
-      need_aboveright =
-          ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT;
-    } else {
-      assert(angle > 0 && angle < 270);
-#if CONFIG_MISC_FIXES
-      if (angle <= 90)
-        need_above = 1, need_left = 0;
-      else if (angle < 180)
-        need_above = 1, need_left = 1;
-      else
-        need_above = 0, need_left = 1;
-#else
-      if (angle < 90)
-        need_above = 0, need_aboveright = 1, need_left = 0;
-      else if (angle == 90)
-        need_above = 1, need_aboveright = 0, need_left = 0;
-      else if (angle < 180)
-        need_above = 1, need_aboveright = 0, need_left = 1;
-      else
-        need_above = 0, need_aboveright = 0, need_left = 1;
-#endif  // CONFIG_MISC_FIXES
-    }
+    need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT;
+    need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE;
+    need_aboveright =
+        ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT;
   }
 #endif  // CONFIG_EXT_INTRA
 
@@ -993,10 +969,10 @@
 #if CONFIG_EXT_INTRA
     int need_bottom;
     if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
-      if (ext_intra_mode <= FILTER_TM_PRED)
         need_bottom = 0;
-      else
-        need_bottom = angle > 180;
+    } else if (mode != DC_PRED && mode != TM_PRED &&
+        xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
+        need_bottom = p_angle > 180;
     } else {
       need_bottom = !!(extend_modes[mode] & NEED_BOTTOMLEFT);
     }
@@ -1024,10 +1000,10 @@
 #if CONFIG_EXT_INTRA
     int need_right;
     if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
-      if (ext_intra_mode <= FILTER_TM_PRED)
-        need_right = 1;
-      else
-        need_right = angle < 90;
+      need_right = 1;
+    } else if (mode != DC_PRED && mode != TM_PRED &&
+        xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
+      need_right = p_angle < 90;
     } else {
       need_right = !!(extend_modes[mode] & NEED_ABOVERIGHT);
     }
@@ -1052,7 +1028,9 @@
   (void)need_aboveright;
 #if CONFIG_EXT_INTRA
   if (ext_intra_mode_info->use_ext_intra_mode[plane != 0] ||
-      (extend_modes[mode] & NEED_ABOVELEFT)) {
+      (extend_modes[mode] & NEED_ABOVELEFT) ||
+      (mode != DC_PRED && mode != TM_PRED &&
+        xd->mi[0]->mbmi.sb_type >= BLOCK_8X8)) {
     above_row[-1] = n_top_px > 0 ?
         (n_left_px > 0 ? above_ref[-1] : base + 1) : base - 1;
   }
@@ -1185,13 +1163,15 @@
 
 #if CONFIG_EXT_INTRA
   if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
-    if (ext_intra_mode <= FILTER_TM_PRED)
-      highbd_filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs,
-                                                     const_above_row, left_col,
-                                                     bd);
-    else
-      highbd_dr_predictor(dst, dst_stride, bs, const_above_row, left_col,
-                          angle, bd);
+    highbd_filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs,
+        const_above_row, left_col, bd);
+    return;
+  }
+
+  if (mode != DC_PRED && mode != TM_PRED &&
+      xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
+    highbd_dr_predictor(dst, dst_stride, bs, const_above_row, left_col,
+                        p_angle, bd);
     return;
   }
 #endif  // CONFIG_EXT_INTRA
@@ -1247,37 +1227,39 @@
       &xd->mi[0]->mbmi.ext_intra_mode_info;
   const EXT_INTRA_MODE ext_intra_mode =
       ext_intra_mode_info->ext_intra_mode[plane != 0];
-  const int angle =
-      prediction_angle_map(ext_intra_mode_info->ext_intra_angle[plane != 0]);
+  int p_angle = 0;
+
+  if (mode != DC_PRED && mode != TM_PRED &&
+      xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
+    p_angle = mode_to_angle_map[mode] +
+        xd->mi[0]->mbmi.angle_delta[plane != 0] * ANGLE_STEP;
+
+#if CONFIG_MISC_FIXES
+    if (p_angle <= 90)
+      need_above = 1, need_left = 0;
+    else if (p_angle < 180)
+      need_above = 1, need_left = 1;
+    else
+      need_above = 0, need_left = 1;
+#else
+    if (p_angle < 90)
+      need_above = 0, need_aboveright = 1, need_left = 0;
+    else if (p_angle == 90)
+      need_above = 1, need_aboveright = 0, need_left = 0;
+    else if (p_angle < 180)
+      need_above = 1, need_aboveright = 0, need_left = 1;
+    else
+      need_above = 0, need_aboveright = 0, need_left = 1;
+#endif  // CONFIG_MISC_FIXES
+  }
 
   if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
     EXT_INTRA_MODE ext_intra_mode =
         ext_intra_mode_info->ext_intra_mode[plane != 0];
-    if (ext_intra_mode <= FILTER_TM_PRED) {
-      need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT;
-      need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE;
-      need_aboveright =
-          ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT;
-    } else {
-      assert(angle > 0 && angle < 270);
-#if CONFIG_MISC_FIXES
-      if (angle <= 90)
-        need_above = 1, need_left = 0;
-      else if (angle < 180)
-        need_above = 1, need_left = 1;
-      else
-        need_above = 0, need_left = 1;
-#else
-      if (angle < 90)
-        need_above = 0, need_aboveright = 1, need_left = 0;
-      else if (angle == 90)
-        need_above = 1, need_aboveright = 0, need_left = 0;
-      else if (angle < 180)
-        need_above = 1, need_aboveright = 0, need_left = 1;
-      else
-        need_above = 0, need_aboveright = 0, need_left = 1;
-#endif  // CONFIG_MISC_FIXES
-    }
+    need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT;
+    need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE;
+    need_aboveright =
+        ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT;
   }
 #endif  // CONFIG_EXT_INTRA
 
@@ -1318,10 +1300,10 @@
 #if CONFIG_EXT_INTRA
     int need_bottom;
     if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
-      if (ext_intra_mode <= FILTER_TM_PRED)
-        need_bottom = 0;
-      else
-        need_bottom = angle > 180;
+      need_bottom = 0;
+    } else if (mode != DC_PRED && mode != TM_PRED &&
+        xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
+      need_bottom = p_angle > 180;
     } else {
       need_bottom = !!(extend_modes[mode] & NEED_BOTTOMLEFT);
     }
@@ -1373,10 +1355,10 @@
 #if CONFIG_EXT_INTRA
     int need_right;
     if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
-      if (ext_intra_mode <= FILTER_TM_PRED)
-        need_right = 1;
-      else
-        need_right = angle < 90;
+      need_right = 1;
+    } else if (mode != DC_PRED && mode != TM_PRED &&
+        xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
+      need_right = p_angle < 90;
     } else {
       need_right = !!(extend_modes[mode] & NEED_ABOVERIGHT);
     }
@@ -1428,7 +1410,9 @@
   (void)need_aboveright;
 #if CONFIG_EXT_INTRA
   if (ext_intra_mode_info->use_ext_intra_mode[plane != 0] ||
-      (extend_modes[mode] & NEED_ABOVELEFT)) {
+      (extend_modes[mode] & NEED_ABOVELEFT) ||
+      (mode != DC_PRED && mode != TM_PRED &&
+          xd->mi[0]->mbmi.sb_type >= BLOCK_8X8)) {
     above_row[-1] = n_top_px > 0 ? (n_left_px > 0 ? above_ref[-1] : 129) : 127;
   }
 #else
@@ -1486,11 +1470,14 @@
 
 #if CONFIG_EXT_INTRA
   if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
-    if (ext_intra_mode <= FILTER_TM_PRED)
-      filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs,
-                                              const_above_row, left_col);
-    else
-      dr_predictor(dst, dst_stride, bs, const_above_row, left_col, angle);
+    filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs,
+        const_above_row, left_col);
+    return;
+  }
+
+  if (mode != DC_PRED && mode != TM_PRED &&
+      xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
+    dr_predictor(dst, dst_stride, tx_size, const_above_row, left_col, p_angle);
     return;
   }
 #endif  // CONFIG_EXT_INTRA
@@ -1510,10 +1497,10 @@
 }
 
 void vp10_predict_intra_block(const MACROBLOCKD *xd, int bwl_in, int bhl_in,
-                             TX_SIZE tx_size, PREDICTION_MODE mode,
-                             const uint8_t *ref, int ref_stride,
-                             uint8_t *dst, int dst_stride,
-                             int aoff, int loff, int plane) {
+                              TX_SIZE tx_size, PREDICTION_MODE mode,
+                              const uint8_t *ref, int ref_stride,
+                              uint8_t *dst, int dst_stride,
+                              int aoff, int loff, int plane) {
   const int txw = (1 << tx_size);
   const int have_top = loff || xd->up_available;
   const int have_left = aoff || xd->left_available;
diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c
index cc0f3f0..a8868d4 100644
--- a/vp10/decoder/decodemv.c
+++ b/vp10/decoder/decodemv.c
@@ -346,18 +346,16 @@
   MODE_INFO *const mi = xd->mi[0];
   MB_MODE_INFO *const mbmi = &mi->mbmi;
   FRAME_COUNTS *counts = xd->counts;
+
+#if !ALLOW_FILTER_INTRA_MODES
+  return;
+#endif
   if (mbmi->mode == DC_PRED) {
     mbmi->ext_intra_mode_info.use_ext_intra_mode[0] =
         vpx_read(r, cm->fc->ext_intra_probs[0]);
     if (mbmi->ext_intra_mode_info.use_ext_intra_mode[0]) {
-      if (DR_ONLY ? 1 : vpx_read(r, DR_EXT_INTRA_PROB)) {
-        mbmi->ext_intra_mode_info.ext_intra_mode[0] = EXT_DR_PRED;
-        mbmi->ext_intra_mode_info.ext_intra_angle[0] =
-            read_uniform(r, EXT_INTRA_ANGLES);
-      } else {
-        mbmi->ext_intra_mode_info.ext_intra_mode[0] =
-            read_uniform(r, FILTER_INTRA_MODES);
-      }
+      mbmi->ext_intra_mode_info.ext_intra_mode[0] =
+          read_uniform(r, FILTER_INTRA_MODES);
     }
     if (counts)
       ++counts->ext_intra[0][mbmi->ext_intra_mode_info.use_ext_intra_mode[0]];
@@ -366,14 +364,8 @@
     mbmi->ext_intra_mode_info.use_ext_intra_mode[1] =
         vpx_read(r, cm->fc->ext_intra_probs[1]);
     if (mbmi->ext_intra_mode_info.use_ext_intra_mode[1]) {
-      if (DR_ONLY ? 1 : vpx_read(r, DR_EXT_INTRA_PROB)) {
-        mbmi->ext_intra_mode_info.ext_intra_mode[1] = EXT_DR_PRED;
-        mbmi->ext_intra_mode_info.ext_intra_angle[1] =
-            read_uniform(r, EXT_INTRA_ANGLES);
-      } else {
-        mbmi->ext_intra_mode_info.ext_intra_mode[1] =
-            read_uniform(r, FILTER_INTRA_MODES);
-      }
+      mbmi->ext_intra_mode_info.ext_intra_mode[1] =
+          read_uniform(r, FILTER_INTRA_MODES);
     }
     if (counts)
       ++counts->ext_intra[1][mbmi->ext_intra_mode_info.use_ext_intra_mode[1]];
@@ -426,9 +418,20 @@
     default:
       mbmi->mode = read_intra_mode(r,
           get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
+#if CONFIG_EXT_INTRA
+      if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
+        mbmi->angle_delta[0] =
+            read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS;
+#endif  // CONFIG_EXT_INTRA
   }
 
   mbmi->uv_mode = read_intra_mode_uv(cm, xd, r, mbmi->mode);
+#if CONFIG_EXT_INTRA
+  if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED &&
+      bsize >= BLOCK_8X8)
+    mbmi->angle_delta[1] =
+        read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS;
+#endif
 
   mbmi->palette_mode_info.palette_size[0] = 0;
   mbmi->palette_mode_info.palette_size[1] = 0;
@@ -591,8 +594,6 @@
                                       cm->fc->switchable_interp_prob[ctx]);
   if (counts)
     ++counts->switchable_interp[ctx][type];
-  // printf("%d/%d -> %d, %d\n", cm->current_video_frame, cm->show_frame,
-  //        xd->mi[0]->mbmi.sb_type, xd->mi[0]->mbmi.interp_filter);
   return type;
 }
 
@@ -626,9 +627,22 @@
       break;
     default:
       mbmi->mode = read_intra_mode_y(cm, xd, r, size_group_lookup[bsize]);
+#if CONFIG_EXT_INTRA
+      mbmi->angle_delta[0] = 0;
+      if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
+        mbmi->angle_delta[0] =
+            read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS;
+#endif  // CONFIG_EXT_INTRA
   }
 
   mbmi->uv_mode = read_intra_mode_uv(cm, xd, r, mbmi->mode);
+#if CONFIG_EXT_INTRA
+  if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED &&
+      bsize >= BLOCK_8X8)
+    mbmi->angle_delta[1] =
+        read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS;
+#endif  // CONFIG_EXT_INTRA
+
   mbmi->palette_mode_info.palette_size[0] = 0;
   mbmi->palette_mode_info.palette_size[1] = 0;
 #if CONFIG_EXT_INTRA
diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index beb3414..a7b1f24 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -520,19 +520,15 @@
 static void write_ext_intra_mode_info(const VP10_COMMON *const cm,
                                       const MB_MODE_INFO *const mbmi,
                                       vpx_writer *w) {
+#if !ALLOW_FILTER_INTRA_MODES
+  return;
+#endif
   if (mbmi->mode == DC_PRED) {
     vpx_write(w, mbmi->ext_intra_mode_info.use_ext_intra_mode[0],
               cm->fc->ext_intra_probs[0]);
     if (mbmi->ext_intra_mode_info.use_ext_intra_mode[0]) {
       EXT_INTRA_MODE mode = mbmi->ext_intra_mode_info.ext_intra_mode[0];
-      int dr_mode = mode > FILTER_TM_PRED;
-      if (!DR_ONLY)
-        vpx_write(w, dr_mode, DR_EXT_INTRA_PROB);
-      if (dr_mode)
-        write_uniform(w, EXT_INTRA_ANGLES,
-                      mbmi->ext_intra_mode_info.ext_intra_angle[0]);
-      else
-        write_uniform(w, FILTER_INTRA_MODES, mode);
+      write_uniform(w, FILTER_INTRA_MODES, mode);
     }
   }
   if (mbmi->uv_mode == DC_PRED) {
@@ -540,14 +536,7 @@
               cm->fc->ext_intra_probs[1]);
     if (mbmi->ext_intra_mode_info.use_ext_intra_mode[1]) {
       EXT_INTRA_MODE mode = mbmi->ext_intra_mode_info.ext_intra_mode[1];
-      int dr_mode = mode > FILTER_TM_PRED;
-      if (!DR_ONLY)
-        vpx_write(w, dr_mode, DR_EXT_INTRA_PROB);
-      if (dr_mode)
-        write_uniform(w, EXT_INTRA_ANGLES,
-                      mbmi->ext_intra_mode_info.ext_intra_angle[1]);
-      else
-        write_uniform(w, FILTER_INTRA_MODES, mode);
+      write_uniform(w, FILTER_INTRA_MODES, mode);
     }
   }
 }
@@ -644,6 +633,12 @@
   if (!is_inter) {
     if (bsize >= BLOCK_8X8) {
       write_intra_mode(w, mode, cm->fc->y_mode_prob[size_group_lookup[bsize]]);
+#if CONFIG_EXT_INTRA
+      if (mode != DC_PRED && mode != TM_PRED) {
+        write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1,
+                      MAX_ANGLE_DELTAS + mbmi->angle_delta[0]);
+      }
+#endif  // CONFIG_EXT_INTRA
     } else {
       int idx, idy;
       const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
@@ -657,6 +652,11 @@
     }
     write_intra_mode(w, mbmi->uv_mode, cm->fc->uv_mode_prob[mode]);
 #if CONFIG_EXT_INTRA
+    if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED &&
+        bsize >= BLOCK_8X8)
+      write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1,
+                    MAX_ANGLE_DELTAS + mbmi->angle_delta[1]);
+
     if (bsize >= BLOCK_8X8)
       write_ext_intra_mode_info(cm, mbmi, w);
 #endif  // CONFIG_EXT_INTRA
@@ -782,6 +782,11 @@
   if (bsize >= BLOCK_8X8) {
     write_intra_mode(w, mbmi->mode,
                      get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
+#if CONFIG_EXT_INTRA
+    if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
+      write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1,
+                    MAX_ANGLE_DELTAS + mbmi->angle_delta[0]);
+#endif  // CONFIG_EXT_INTRA
   } else {
     const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
     const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
@@ -797,6 +802,12 @@
   }
 
   write_intra_mode(w, mbmi->uv_mode, cm->fc->uv_mode_prob[mbmi->mode]);
+#if CONFIG_EXT_INTRA
+  if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED &&
+      bsize >= BLOCK_8X8)
+    write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1,
+                  MAX_ANGLE_DELTAS + mbmi->angle_delta[1]);
+#endif  // CONFIG_EXT_INTRA
 
   if (bsize >= BLOCK_8X8 && cm->allow_screen_content_tools &&
       mbmi->mode == DC_PRED)
diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c
index dc56563..5c447b2 100644
--- a/vp10/encoder/rdopt.c
+++ b/vp10/encoder/rdopt.c
@@ -1507,10 +1507,7 @@
   MB_MODE_INFO *mbmi = &mic->mbmi;
   int this_rate, this_rate_tokenonly, s;
   int ext_intra_selected_flag = 0;
-  int i, step, delta, angle, best_angle, best_angle_dir;
-  int deltas[3] = {25, 5, 1};
-  int branches[3] = {2, 2, 2};
-  int64_t this_distortion, this_rd, best_angle_rd = INT64_MAX;
+  int64_t this_distortion, this_rd;
   EXT_INTRA_MODE mode;
   TX_SIZE best_tx_size = TX_4X4;
   EXT_INTRA_MODE_INFO ext_intra_mode_info;
@@ -1522,123 +1519,30 @@
   mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = 1;
   mbmi->mode = DC_PRED;
 
-  if (!DR_ONLY) {
-    for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
-      mbmi->ext_intra_mode_info.ext_intra_mode[0] = mode;
-      super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
-                      &s, NULL, bsize, *best_rd);
-      if (this_rate_tokenonly == INT_MAX)
-        continue;
+  for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
+    mbmi->ext_intra_mode_info.ext_intra_mode[0] = mode;
+    super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
+                    &s, NULL, bsize, *best_rd);
+    if (this_rate_tokenonly == INT_MAX)
+      continue;
 
-      this_rate = this_rate_tokenonly +
-          vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) +
-          vp10_cost_bit(DR_EXT_INTRA_PROB, 0) +
-          write_uniform_cost(FILTER_INTRA_MODES, mode) + mode_cost;
-      this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+    this_rate = this_rate_tokenonly +
+        vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) +
+        write_uniform_cost(FILTER_INTRA_MODES, mode) + mode_cost;
+    this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
 
-      if (this_rd < *best_rd) {
-        *best_rd            = this_rd;
-        best_tx_size        = mic->mbmi.tx_size;
-        ext_intra_mode_info = mbmi->ext_intra_mode_info;
+    if (this_rd < *best_rd) {
+      *best_rd            = this_rd;
+      best_tx_size        = mic->mbmi.tx_size;
+      ext_intra_mode_info = mbmi->ext_intra_mode_info;
 #if CONFIG_EXT_TX
-        best_tx_type        = mic->mbmi.tx_type;
+      best_tx_type        = mic->mbmi.tx_type;
 #endif  // CONFIG_EXT_TX
-        *rate               = this_rate;
-        *rate_tokenonly     = this_rate_tokenonly;
-        *distortion         = this_distortion;
-        *skippable          = s;
-        ext_intra_selected_flag = 1;
-      }
-    }
-  }
-
-  mbmi->ext_intra_mode_info.ext_intra_mode[0] = EXT_DR_PRED;
-  if (ANGLE_FAST_SEARCH) {
-    best_angle = EXT_INTRA_ANGLES / 2;
-    for (step = 0; step < 3; ++step) {
-      delta = deltas[step];
-      for (i = -branches[step]; i <= branches[step]; ++i) {
-        int64_t rd_thresh;
-        if (i == 0 && step != 0)
-          continue;
-        angle = best_angle + i * delta;
-        if (angle < 0)
-          angle = 0;
-        if (angle >= EXT_INTRA_ANGLES)
-          angle = EXT_INTRA_ANGLES - 1;
-        if (angle == best_angle && step != 0)
-          continue;
-        mbmi->ext_intra_mode_info.ext_intra_angle[0] = angle;
-        if (*best_rd == INT64_MAX)
-          rd_thresh = best_angle_rd;
-        else
-          rd_thresh = VPXMIN(best_angle_rd, *best_rd * RD_ADJUSTER);
-        super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
-                        &s, NULL, bsize, rd_thresh);
-        if (this_rate_tokenonly == INT_MAX)
-          continue;
-        this_rate = this_rate_tokenonly +
-            vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) +
-            (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) +
-            write_uniform_cost(EXT_INTRA_ANGLES, angle) + mode_cost;
-        this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
-        if (this_rd < *best_rd) {
-          *best_rd            = this_rd;
-          best_tx_size        = mic->mbmi.tx_size;
-          ext_intra_mode_info = mbmi->ext_intra_mode_info;
-#if CONFIG_EXT_TX
-          best_tx_type        = mic->mbmi.tx_type;
-#endif  // CONFIG_EXT_TX
-          *rate               = this_rate;
-          *rate_tokenonly     = this_rate_tokenonly;
-          *distortion         = this_distortion;
-          *skippable          = s;
-          ext_intra_selected_flag = 1;
-        }
-        if (this_rd < best_angle_rd) {
-          best_angle_rd = this_rd;
-          best_angle_dir = i;
-        }
-      }
-
-      best_angle += best_angle_dir * delta;
-      if (best_angle < 0)
-        best_angle = 0;
-      if (best_angle >= EXT_INTRA_ANGLES)
-        best_angle = EXT_INTRA_ANGLES - 1;
-      if (*best_rd < best_angle_rd / RD_ADJUSTER)
-        break;
-    }
-  } else {
-    for (angle = 0; angle < EXT_INTRA_ANGLES; ++angle) {
-      mbmi->ext_intra_mode_info.ext_intra_angle[0] = angle;
-      if (prediction_angle_map(angle) == 90 ||
-          prediction_angle_map(angle) == 180)
-        continue;
-      super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
-                      &s, NULL, bsize, *best_rd);
-      if (this_rate_tokenonly == INT_MAX)
-        continue;
-
-      this_rate = this_rate_tokenonly +
-          vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) +
-          (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) +
-          write_uniform_cost(EXT_INTRA_ANGLES, angle) + mode_cost;
-      this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
-
-      if (this_rd < *best_rd) {
-        *best_rd            = this_rd;
-        best_tx_size        = mic->mbmi.tx_size;
-        ext_intra_mode_info = mbmi->ext_intra_mode_info;
-#if CONFIG_EXT_TX
-        best_tx_type        = mic->mbmi.tx_type;
-#endif  // CONFIG_EXT_TX
-        *rate               = this_rate;
-        *rate_tokenonly     = this_rate_tokenonly;
-        *distortion         = this_distortion;
-        *skippable          = s;
-        ext_intra_selected_flag = 1;
-      }
+      *rate               = this_rate;
+      *rate_tokenonly     = this_rate_tokenonly;
+      *distortion         = this_distortion;
+      *skippable          = s;
+      ext_intra_selected_flag = 1;
     }
   }
 
@@ -1649,8 +1553,6 @@
         ext_intra_mode_info.use_ext_intra_mode[0];
     mbmi->ext_intra_mode_info.ext_intra_mode[0] =
         ext_intra_mode_info.ext_intra_mode[0];
-    mbmi->ext_intra_mode_info.ext_intra_angle[0] =
-        ext_intra_mode_info.ext_intra_angle[0];
 #if CONFIG_EXT_TX
     mbmi->tx_type = best_tx_type;
 #endif  // CONFIG_EXT_TX
@@ -1659,6 +1561,132 @@
     return 0;
   }
 }
+
+static int64_t rd_pick_intra_angle_sby(VP10_COMP *cpi, MACROBLOCK *x,
+                                       int *rate, int *rate_tokenonly,
+                                       int64_t *distortion, int *skippable,
+                                       BLOCK_SIZE bsize, int rate_overhead,
+                                       int64_t best_rd) {
+  MACROBLOCKD *const xd = &x->e_mbd;
+  MODE_INFO *const mic = xd->mi[0];
+  MB_MODE_INFO *mbmi = &mic->mbmi;
+  int this_rate, this_rate_tokenonly, s;
+  int angle_delta, best_angle_delta = 0;
+  const double rd_adjust = 1.2;
+  int64_t this_distortion, this_rd, sse_dummy;
+  TX_SIZE best_tx_size = mic->mbmi.tx_size;
+#if CONFIG_EXT_TX
+  TX_TYPE best_tx_type = mbmi->tx_type;
+#endif  // CONFIG_EXT_TX
+
+  if (ANGLE_FAST_SEARCH) {
+    int deltas_level1[3] = {0, -2, 2};
+    int deltas_level2[3][2] = {
+        {-1, 1}, {-3, -1}, {1, 3},
+    };
+    const int level1 = 3, level2 = 2;
+    int i, j, best_i = -1;
+
+    for (i = 0; i < level1; ++i) {
+      mic->mbmi.angle_delta[0] = deltas_level1[i];
+      super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
+                      &s, NULL, bsize,
+                      (i == 0 && best_rd < INT64_MAX) ? best_rd * rd_adjust :
+                          best_rd);
+      if (this_rate_tokenonly == INT_MAX) {
+        if (i == 0)
+          break;
+        else
+          continue;
+      }
+      this_rate = this_rate_tokenonly + rate_overhead;
+      this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+      if (i == 0 && best_rd < INT64_MAX && this_rd > best_rd * rd_adjust)
+        break;
+      if (this_rd < best_rd) {
+        best_i              = i;
+        best_rd             = this_rd;
+        best_angle_delta    = mbmi->angle_delta[0];
+        best_tx_size        = mbmi->tx_size;
+#if CONFIG_EXT_TX
+        best_tx_type        = mbmi->tx_type;
+#endif  // CONFIG_EXT_TX
+        *rate               = this_rate;
+        *rate_tokenonly     = this_rate_tokenonly;
+        *distortion         = this_distortion;
+        *skippable          = s;
+      }
+    }
+
+    if (best_i >= 0) {
+      for (j = 0; j < level2; ++j) {
+        mic->mbmi.angle_delta[0] = deltas_level2[best_i][j];
+        super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
+                        &s, NULL, bsize, best_rd);
+        if (this_rate_tokenonly == INT_MAX)
+          continue;
+        this_rate = this_rate_tokenonly + rate_overhead;
+        this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+        if (this_rd < best_rd) {
+          best_rd             = this_rd;
+          best_angle_delta    = mbmi->angle_delta[0];
+          best_tx_size        = mbmi->tx_size;
+#if CONFIG_EXT_TX
+          best_tx_type        = mbmi->tx_type;
+#endif  // CONFIG_EXT_TX
+          *rate               = this_rate;
+          *rate_tokenonly     = this_rate_tokenonly;
+          *distortion         = this_distortion;
+          *skippable          = s;
+        }
+      }
+    }
+  } else {
+    for (angle_delta = -MAX_ANGLE_DELTAS; angle_delta <= MAX_ANGLE_DELTAS;
+        ++angle_delta) {
+      mic->mbmi.angle_delta[0] = angle_delta;
+
+      super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
+                      &s, NULL, bsize, best_rd);
+      if (this_rate_tokenonly == INT_MAX)
+        continue;
+
+      this_rate = this_rate_tokenonly + rate_overhead;
+      this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+
+      if (this_rd < best_rd) {
+        best_rd             = this_rd;
+        best_angle_delta    = mbmi->angle_delta[0];
+        best_tx_size        = mbmi->tx_size;
+#if CONFIG_EXT_TX
+        best_tx_type        = mbmi->tx_type;
+#endif  // CONFIG_EXT_TX
+        *rate               = this_rate;
+        *rate_tokenonly     = this_rate_tokenonly;
+        *distortion         = this_distortion;
+        *skippable          = s;
+      }
+    }
+  }
+
+  mbmi->tx_size = best_tx_size;
+  mbmi->angle_delta[0] = best_angle_delta;
+#if CONFIG_EXT_TX
+  mbmi->tx_type = best_tx_type;
+#endif  // CONFIG_EXT_TX
+
+  if (*rate_tokenonly < INT_MAX) {
+    txfm_rd_in_plane(x,
+#if CONFIG_VAR_TX
+                     cpi,
+#endif
+                     &this_rate_tokenonly, &this_distortion, &s,
+                     &sse_dummy, INT64_MAX, 0, bsize, mbmi->tx_size,
+                     cpi->sf.use_fast_coef_costing);
+  }
+
+  return best_rd;
+}
 #endif  // CONFIG_EXT_INTRA
 
 // This function is used only for intra_only frames
@@ -1676,6 +1704,7 @@
   TX_SIZE best_tx = TX_4X4;
 #if CONFIG_EXT_INTRA
   EXT_INTRA_MODE_INFO ext_intra_mode_info;
+  int is_directional_mode, rate_overhead, best_angle_delta = 0;
 #endif  // CONFIG_EXT_INTRA
 #if CONFIG_EXT_TX
   TX_TYPE best_tx_type = DCT_DCT;
@@ -1696,6 +1725,7 @@
 #if CONFIG_EXT_INTRA
   ext_intra_mode_info.use_ext_intra_mode[0] = 0;
   mic->mbmi.ext_intra_mode_info.use_ext_intra_mode[0] = 0;
+  mic->mbmi.angle_delta[0] = 0;
 #endif  // CONFIG_EXT_INTRA
   memset(x->skip_txfm, SKIP_TXFM_NONE, sizeof(x->skip_txfm));
   palette_mode_info.palette_size[0] = 0;
@@ -1708,9 +1738,24 @@
   /* Y Search for intra prediction mode */
   for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
     mic->mbmi.mode = mode;
-
+#if CONFIG_EXT_INTRA
+    is_directional_mode = (mode != DC_PRED && mode != TM_PRED);
+    if (is_directional_mode) {
+    rate_overhead = bmode_costs[mode] +
+        write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1, 0);
+    this_rate_tokenonly = INT_MAX;
+    this_rd =
+        rd_pick_intra_angle_sby(cpi, x, &this_rate, &this_rate_tokenonly,
+                                &this_distortion, &s, bsize, rate_overhead,
+                                best_rd);
+    } else {
+      mic->mbmi.angle_delta[0] = 0;
+      super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
+                      &s, NULL, bsize, best_rd);
+    }
+#endif  // CONFIG_EXT_INTRA
     super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
-        &s, NULL, bsize, best_rd);
+                    &s, NULL, bsize, best_rd);
 
     if (this_rate_tokenonly == INT_MAX)
       continue;
@@ -1721,8 +1766,12 @@
           vp10_cost_bit(vp10_default_palette_y_mode_prob[bsize - BLOCK_8X8]
                                                          [palette_ctx], 0);
 #if CONFIG_EXT_INTRA
-    if (mode == DC_PRED)
+    if (mode == DC_PRED && ALLOW_FILTER_INTRA_MODES)
       this_rate += vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 0);
+    if (is_directional_mode)
+      this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1,
+                                      MAX_ANGLE_DELTAS +
+                                      mic->mbmi.angle_delta[0]);
 #endif  // CONFIG_EXT_INTRA
     this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
 
@@ -1730,6 +1779,9 @@
       mode_selected   = mode;
       best_rd         = this_rd;
       best_tx         = mic->mbmi.tx_size;
+#if CONFIG_EXT_INTRA
+      best_angle_delta = mic->mbmi.angle_delta[0];
+#endif  // CONFIG_EXT_INTRA
 #if CONFIG_EXT_TX
       best_tx_type    = mic->mbmi.tx_type;
 #endif  // CONFIG_EXT_TX
@@ -1746,7 +1798,7 @@
                               &best_tx, &mode_selected, &best_rd);
 
 #if CONFIG_EXT_INTRA
-  if (!palette_mode_info.palette_size[0] > 0) {
+  if (!palette_mode_info.palette_size[0] > 0 && ALLOW_FILTER_INTRA_MODES) {
     if (rd_pick_ext_intra_sby(cpi, x, rate, rate_tokenonly, distortion,
                               skippable, bsize, bmode_costs[DC_PRED],
                               &best_rd)) {
@@ -1764,13 +1816,14 @@
   if (ext_intra_mode_info.use_ext_intra_mode[0]) {
     mic->mbmi.ext_intra_mode_info.ext_intra_mode[0] =
         ext_intra_mode_info.ext_intra_mode[0];
-    mic->mbmi.ext_intra_mode_info.ext_intra_angle[0] =
-        ext_intra_mode_info.ext_intra_angle[0];
   }
 #endif  // CONFIG_EXT_INTRA
 
   mic->mbmi.mode = mode_selected;
   mic->mbmi.tx_size = best_tx;
+#if CONFIG_EXT_INTRA
+  mic->mbmi.angle_delta[0] = best_angle_delta;
+#endif  // CONFIG_EXT_INTRA
 #if CONFIG_EXT_TX
   mic->mbmi.tx_type = best_tx_type;
 #endif  // CONFIG_EXT_TX
@@ -2468,127 +2521,38 @@
   MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
   int ext_intra_selected_flag = 0;
   int this_rate_tokenonly, this_rate, s;
-  int64_t this_distortion, this_sse, this_rd, best_angle_rd = INT64_MAX;
+  int64_t this_distortion, this_sse, this_rd;
   EXT_INTRA_MODE mode;
-  int i, step, delta, angle, best_angle, best_angle_dir;
-  int deltas[3] = {25, 5, 1};
-  int branches[3] = {2, 2, 2};
   EXT_INTRA_MODE_INFO ext_intra_mode_info;
 
   vp10_zero(ext_intra_mode_info);
   mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 1;
   mbmi->uv_mode = DC_PRED;
 
-  if (!DR_ONLY) {
-    for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
-      mbmi->ext_intra_mode_info.ext_intra_mode[1] = mode;
-      if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
-                            &this_distortion, &s, &this_sse, bsize, *best_rd))
-        continue;
+  for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
+    mbmi->ext_intra_mode_info.ext_intra_mode[1] = mode;
+    if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
+                          &this_distortion, &s, &this_sse, bsize, *best_rd))
+      continue;
 
-      this_rate = this_rate_tokenonly +
-          vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) +
-          vp10_cost_bit(DR_EXT_INTRA_PROB, 0) +
-          cpi->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] +
-          write_uniform_cost(FILTER_INTRA_MODES, mode);
-      this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
-      if (this_rd < *best_rd) {
-        *best_rd        = this_rd;
-        *rate           = this_rate;
-        *rate_tokenonly = this_rate_tokenonly;
-        *distortion     = this_distortion;
-        *skippable      = s;
-        ext_intra_mode_info = mbmi->ext_intra_mode_info;
-        ext_intra_selected_flag = 1;
-        if (!x->select_tx_size)
-          swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE);
-      }
+    this_rate = this_rate_tokenonly +
+        vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) +
+        cpi->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] +
+        write_uniform_cost(FILTER_INTRA_MODES, mode);
+    this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+    if (this_rd < *best_rd) {
+      *best_rd        = this_rd;
+      *rate           = this_rate;
+      *rate_tokenonly = this_rate_tokenonly;
+      *distortion     = this_distortion;
+      *skippable      = s;
+      ext_intra_mode_info = mbmi->ext_intra_mode_info;
+      ext_intra_selected_flag = 1;
+      if (!x->select_tx_size)
+        swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE);
     }
   }
 
-  mbmi->ext_intra_mode_info.ext_intra_mode[1] = EXT_DR_PRED;
-  if (ANGLE_FAST_SEARCH) {
-    best_angle = EXT_INTRA_ANGLES / 2;
-    for (step = 0; step < 3; ++step) {
-      delta = deltas[step];
-      for (i = -branches[step]; i <= branches[step]; ++i) {
-        int64_t rd_thresh;
-        if (i == 0 && step != 0)
-          continue;
-        angle = best_angle + i * delta;
-        if (angle < 0)
-          angle = 0;
-        if (angle >= EXT_INTRA_ANGLES)
-          angle = EXT_INTRA_ANGLES - 1;
-        if (angle == best_angle && step != 0)
-          continue;
-        mbmi->ext_intra_mode_info.ext_intra_angle[1] = angle;
-        if (*best_rd == INT64_MAX)
-          rd_thresh = best_angle_rd;
-        else
-          rd_thresh = VPXMIN(best_angle_rd, *best_rd * RD_ADJUSTER);
-        if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, &this_distortion,
-                              &s, &this_sse, bsize, rd_thresh))
-          continue;
-        this_rate = this_rate_tokenonly +
-            vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) +
-            (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) +
-            cpi->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] +
-            write_uniform_cost(EXT_INTRA_ANGLES, angle);
-        this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
-        if (this_rd < *best_rd) {
-          *best_rd        = this_rd;
-          *rate           = this_rate;
-          *rate_tokenonly = this_rate_tokenonly;
-          *distortion     = this_distortion;
-          *skippable      = s;
-          ext_intra_mode_info = mbmi->ext_intra_mode_info;
-          ext_intra_selected_flag = 1;
-          if (!x->select_tx_size)
-            swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE);
-        }
-        if (this_rd < best_angle_rd) {
-          best_angle_rd = this_rd;
-          best_angle_dir = i;
-        }
-      }
-      best_angle += best_angle_dir * delta;
-      if (best_angle < 0)
-        best_angle = 0;
-      if (best_angle >= EXT_INTRA_ANGLES)
-        best_angle = EXT_INTRA_ANGLES - 1;
-      if (*best_rd < best_angle_rd / RD_ADJUSTER)
-        break;
-    }
-  } else {
-    for (angle = 0; angle < EXT_INTRA_ANGLES; ++angle) {
-      mbmi->ext_intra_mode_info.ext_intra_angle[1] = angle;
-      if (prediction_angle_map(angle) == 90 ||
-          prediction_angle_map(angle) == 180)
-        continue;
-      if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
-                            &this_distortion, &s, &this_sse, bsize, *best_rd))
-        continue;
-
-      this_rate = this_rate_tokenonly +
-          vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) +
-          (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) +
-          cpi->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] +
-          write_uniform_cost(EXT_INTRA_ANGLES, angle);
-      this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
-      if (this_rd < *best_rd) {
-        *best_rd        = this_rd;
-        *rate           = this_rate;
-        *rate_tokenonly = this_rate_tokenonly;
-        *distortion     = this_distortion;
-        *skippable      = s;
-        ext_intra_mode_info = mbmi->ext_intra_mode_info;
-        ext_intra_selected_flag = 1;
-        if (!x->select_tx_size)
-          swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE);
-      }
-    }
-  }
 
   if (ext_intra_selected_flag) {
     mbmi->uv_mode = DC_PRED;
@@ -2596,14 +2560,105 @@
         ext_intra_mode_info.use_ext_intra_mode[1];
     mbmi->ext_intra_mode_info.ext_intra_mode[1] =
         ext_intra_mode_info.ext_intra_mode[1];
-    mbmi->ext_intra_mode_info.ext_intra_angle[1] =
-        ext_intra_mode_info.ext_intra_angle[1];
-
     return 1;
   } else {
     return 0;
   }
 }
+
+static int rd_pick_intra_angle_sbuv(VP10_COMP *cpi, MACROBLOCK *x,
+                                    PICK_MODE_CONTEXT *ctx,
+                                    int *rate, int *rate_tokenonly,
+                                    int64_t *distortion, int *skippable,
+                                    BLOCK_SIZE bsize, int rate_overhead,
+                                    int64_t best_rd) {
+  MACROBLOCKD *const xd = &x->e_mbd;
+  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+  int this_rate_tokenonly, this_rate, s;
+  int64_t this_distortion, this_sse, this_rd;
+  int angle_delta, best_angle_delta = 0;
+  const double rd_adjust = 1.2;
+
+  (void)ctx;
+  *rate_tokenonly = INT_MAX;
+  if (ANGLE_FAST_SEARCH) {
+    int deltas_level1[3] = {0, -2, 2};
+    int deltas_level2[3][2] = {
+        {-1, 1}, {-3, -1}, {1, 3},
+    };
+    const int level1 = 3, level2 = 2;
+    int i, j, best_i = -1;
+
+    for (i = 0; i < level1; ++i) {
+      mbmi->angle_delta[1] = deltas_level1[i];
+      if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
+                            &this_distortion, &s, &this_sse, bsize,
+                            (i == 0 && best_rd < INT64_MAX) ?
+                                best_rd * rd_adjust : best_rd)) {
+        if (i == 0)
+          break;
+        else
+          continue;
+      }
+      this_rate = this_rate_tokenonly + rate_overhead;
+      this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+      if (i == 0 && best_rd < INT64_MAX && this_rd > best_rd * rd_adjust)
+        break;
+      if (this_rd < best_rd) {
+        best_i           = i;
+        best_rd          = this_rd;
+        best_angle_delta = mbmi->angle_delta[1];
+        *rate            = this_rate;
+        *rate_tokenonly  = this_rate_tokenonly;
+        *distortion      = this_distortion;
+        *skippable       = s;
+      }
+    }
+
+    if (best_i >= 0) {
+      for (j = 0; j < level2; ++j) {
+        mbmi->angle_delta[1] = deltas_level2[best_i][j];
+        if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
+                              &this_distortion, &s, &this_sse, bsize, best_rd))
+          continue;
+        this_rate = this_rate_tokenonly + rate_overhead;
+        this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+        if (this_rd < best_rd) {
+          best_rd          = this_rd;
+          best_angle_delta = mbmi->angle_delta[1];
+          *rate            = this_rate;
+          *rate_tokenonly  = this_rate_tokenonly;
+          *distortion      = this_distortion;
+          *skippable       = s;
+        }
+      }
+    }
+  } else {
+    for (angle_delta = -MAX_ANGLE_DELTAS; angle_delta <= MAX_ANGLE_DELTAS;
+        ++angle_delta) {
+      mbmi->angle_delta[1] = angle_delta;
+      if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
+                            &this_distortion, &s, &this_sse, bsize, best_rd))
+        continue;
+      this_rate = this_rate_tokenonly + rate_overhead;
+      this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+      if (this_rd < best_rd) {
+        best_rd          = this_rd;
+        best_angle_delta = mbmi->angle_delta[1];
+        *rate            = this_rate;
+        *rate_tokenonly  = this_rate_tokenonly;
+        *distortion      = this_distortion;
+        *skippable       = s;
+      }
+    }
+  }
+
+  mbmi->angle_delta[1] = best_angle_delta;
+  if (*rate_tokenonly != INT_MAX)
+    super_block_uvrd(cpi, x, &this_rate_tokenonly,
+                     &this_distortion, &s, &this_sse, bsize, INT_MAX);
+  return *rate_tokenonly != INT_MAX;
+}
 #endif  // CONFIG_EXT_INTRA
 
 static int64_t rd_pick_intra_sbuv_mode(VP10_COMP *cpi, MACROBLOCK *x,
@@ -2619,6 +2674,7 @@
   int this_rate_tokenonly, this_rate, s;
   int64_t this_distortion, this_sse;
 #if CONFIG_EXT_INTRA
+  int is_directional_mode, rate_overhead, best_angle_delta = 0;
   EXT_INTRA_MODE_INFO ext_intra_mode_info;
 
   ext_intra_mode_info.use_ext_intra_mode[1] = 0;
@@ -2631,20 +2687,44 @@
       continue;
 
     mbmi->uv_mode = mode;
-
+#if CONFIG_EXT_INTRA
+    is_directional_mode = (mode != DC_PRED && mode != TM_PRED);
+    rate_overhead = cpi->intra_uv_mode_cost[mbmi->mode][mode] +
+        write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1, 0);
+    mbmi->angle_delta[1] = 0;
+    if (mbmi->sb_type >= BLOCK_8X8 && is_directional_mode) {
+      if (!rd_pick_intra_angle_sbuv(cpi, x, ctx, &this_rate,
+                                    &this_rate_tokenonly, &this_distortion, &s,
+                                    bsize, rate_overhead, best_rd))
+        continue;
+    } else {
+      if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
+                            &this_distortion, &s, &this_sse, bsize, best_rd))
+        continue;
+    }
+    this_rate = this_rate_tokenonly +
+        cpi->intra_uv_mode_cost[mbmi->mode][mode];
+    if (mbmi->sb_type >= BLOCK_8X8 && is_directional_mode)
+      this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1,
+                                      MAX_ANGLE_DELTAS +
+                                      mbmi->angle_delta[1]);
+    if (mode == DC_PRED && 0)
+      this_rate += vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 0);
+#else
     if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
                           &this_distortion, &s, &this_sse, bsize, best_rd))
       continue;
     this_rate = this_rate_tokenonly +
         cpi->intra_uv_mode_cost[xd->mi[0]->mbmi.mode][mode];
-#if CONFIG_EXT_INTRA
-    if (mode == DC_PRED)
-      this_rate += vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 0);
 #endif  // CONFIG_EXT_INTRA
+
     this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
 
     if (this_rd < best_rd) {
       mode_selected   = mode;
+#if CONFIG_EXT_INTRA
+      best_angle_delta = mbmi->angle_delta[1];
+#endif  // CONFIG_EXT_INTRA
       best_rd         = this_rd;
       *rate           = this_rate;
       *rate_tokenonly = this_rate_tokenonly;
@@ -2656,7 +2736,7 @@
   }
 
 #if CONFIG_EXT_INTRA
-  if (mbmi->sb_type >= BLOCK_8X8) {
+  if (mbmi->sb_type >= BLOCK_8X8 && ALLOW_FILTER_INTRA_MODES) {
     if (rd_pick_ext_intra_sbuv(cpi, x, ctx, rate, rate_tokenonly, distortion,
                                skippable, bsize, &best_rd)) {
       mode_selected   = mbmi->uv_mode;
@@ -2669,6 +2749,7 @@
   if (ext_intra_mode_info.use_ext_intra_mode[1])
     mbmi->ext_intra_mode_info.ext_intra_mode[1] =
         ext_intra_mode_info.ext_intra_mode[1];
+  mbmi->angle_delta[1] = best_angle_delta;
 #endif  // CONFIG_EXT_INTRA
   mbmi->uv_mode = mode_selected;
   return best_rd;
@@ -4478,6 +4559,9 @@
   PREDICTION_MODE mode_uv[TX_SIZES];
 #if CONFIG_EXT_INTRA
   EXT_INTRA_MODE_INFO ext_intra_mode_info_uv[TX_SIZES];
+  int8_t uv_angle_delta[TX_SIZES];
+  int is_directional_mode;
+  int rate_overhead, rate_dummy;
 #endif  // CONFIG_EXT_INTRA
   const int intra_cost_penalty = vp10_get_intra_cost_penalty(
       cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth);
@@ -4762,17 +4846,31 @@
       TX_SIZE uv_tx;
       struct macroblockd_plane *const pd = &xd->plane[1];
       memset(x->skip_txfm, 0, sizeof(x->skip_txfm));
-      super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable,
-                      NULL, bsize, best_rd);
+
 #if CONFIG_EXT_INTRA
+      is_directional_mode = (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED);
+      if (is_directional_mode) {
+        rate_overhead = write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1, 0) +
+            cpi->mbmode_cost[mbmi->mode];
+        rate_y = INT_MAX;
+        this_rd =
+            rd_pick_intra_angle_sby(cpi, x, &rate_dummy, &rate_y, &distortion_y,
+                                    &skippable, bsize, rate_overhead, best_rd);
+      } else {
+        mbmi->angle_delta[0] = 0;
+        super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable,
+                        NULL, bsize, best_rd);
+      }
+
       // TODO(huisu): ext-intra is turned off in lossless mode for now to
       // avoid a unit test failure
-      if (mbmi->mode == DC_PRED && !xd->lossless[mbmi->segment_id]) {
+      if (mbmi->mode == DC_PRED && !xd->lossless[mbmi->segment_id] &&
+          ALLOW_FILTER_INTRA_MODES) {
         MB_MODE_INFO mbmi_copy = *mbmi;
-        int rate_dummy;
 
         if (rate_y != INT_MAX) {
-          int this_rate = rate_y + cpi->mbmode_cost[mbmi->mode] +
+          int this_rate = rate_y +
+              cpi->mbmode_cost[mbmi->mode] +
               vp10_cost_bit(cm->fc->ext_intra_probs[0], 0);
           this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, distortion_y);
         } else {
@@ -4784,7 +4882,11 @@
                                    cpi->mbmode_cost[mbmi->mode], &this_rd))
           *mbmi = mbmi_copy;
       }
+#else
+      super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable,
+                      NULL, bsize, best_rd);
 #endif  // CONFIG_EXT_INTRA
+
       if (rate_y == INT_MAX)
         continue;
       uv_tx = get_uv_tx_size_impl(mbmi->tx_size, bsize, pd->subsampling_x,
@@ -4795,6 +4897,7 @@
                              &dist_uv[uv_tx], &skip_uv[uv_tx], &mode_uv[uv_tx]);
 #if CONFIG_EXT_INTRA
         ext_intra_mode_info_uv[uv_tx] = mbmi->ext_intra_mode_info;
+        uv_angle_delta[uv_tx] = mbmi->angle_delta[1];
 #endif  // CONFIG_EXT_INTRA
       }
 
@@ -4803,32 +4906,29 @@
       skippable = skippable && skip_uv[uv_tx];
       mbmi->uv_mode = mode_uv[uv_tx];
 #if CONFIG_EXT_INTRA
+      mbmi->angle_delta[1] = uv_angle_delta[uv_tx];
       mbmi->ext_intra_mode_info.use_ext_intra_mode[1] =
           ext_intra_mode_info_uv[uv_tx].use_ext_intra_mode[1];
       if (ext_intra_mode_info_uv[uv_tx].use_ext_intra_mode[1]) {
         mbmi->ext_intra_mode_info.ext_intra_mode[1] =
             ext_intra_mode_info_uv[uv_tx].ext_intra_mode[1];
-        mbmi->ext_intra_mode_info.ext_intra_angle[1] =
-            ext_intra_mode_info_uv[uv_tx].ext_intra_angle[1];
       }
 #endif  // CONFIG_EXT_INTRA
 
       rate2 = rate_y + cpi->mbmode_cost[mbmi->mode] + rate_uv_intra[uv_tx];
 #if CONFIG_EXT_INTRA
-      if (mbmi->mode == DC_PRED) {
+      if (is_directional_mode)
+        rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1,
+                                    MAX_ANGLE_DELTAS +
+                                    mbmi->angle_delta[0]);
+
+      if (mbmi->mode == DC_PRED && ALLOW_FILTER_INTRA_MODES) {
         rate2 += vp10_cost_bit(cm->fc->ext_intra_probs[0],
                                mbmi->ext_intra_mode_info.use_ext_intra_mode[0]);
         if (mbmi->ext_intra_mode_info.use_ext_intra_mode[0]) {
           EXT_INTRA_MODE ext_intra_mode =
               mbmi->ext_intra_mode_info.ext_intra_mode[0];
-          int angle = mbmi->ext_intra_mode_info.ext_intra_angle[0];
-          if (!DR_ONLY)
-              rate2 += vp10_cost_bit(DR_EXT_INTRA_PROB,
-                                     ext_intra_mode > FILTER_TM_PRED);
-          if (ext_intra_mode > FILTER_TM_PRED)
-            rate2 += write_uniform_cost(EXT_INTRA_ANGLES, angle);
-          else
-            rate2 += write_uniform_cost(FILTER_INTRA_MODES, ext_intra_mode);
+          rate2 += write_uniform_cost(FILTER_INTRA_MODES, ext_intra_mode);
         }
       }
 #endif  // CONFIG_EXT_INTRA