Ext-intra modification/tuning

For ext-intra direcation intra modes:

1. Use neighbor block modes to modify edge filtering strength
   Coding gain (lowres/midres/hdres):
     (8 keyframes)
     PSNR: -0.19 -0.22 -0.10
     SSIM: -0.29 -0.27 -0.13

2. Use context-based cdf to code angle_delta syntax
     (8 keyframes)
     PSNR: -0.20 -0.24 -0.27
     SSIM: -0.29 -0.33 -0.37

3. Filter corner sample:
     (8 keyframes)
     PSNR: -0.01 -0.02 -0.05
     SSIM: -0.03 -0.04 -0.05

Combined Bd-rate improvement for 8 keyframes
     PSNR: -0.40 -0.47 -0.40
     SSIM: -0.57 -0.60 -0.51

Change-Id: Id47ac17b6bf91cd810b70cacfc5b457341f417f3
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index b484a6a..99a166e 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -1049,19 +1049,33 @@
 #endif  // CONFIG_FILTER_INTRA
 
 #if CONFIG_EXT_INTRA
-static void write_intra_angle_info(const MACROBLOCKD *xd, aom_writer *w) {
+static void write_intra_angle_info(const MACROBLOCKD *xd,
+                                   FRAME_CONTEXT *const ec_ctx, aom_writer *w) {
   const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
   const BLOCK_SIZE bsize = mbmi->sb_type;
   if (!av1_use_angle_delta(bsize)) return;
 
   if (av1_is_directional_mode(mbmi->mode, bsize)) {
+#if CONFIG_EXT_INTRA_MOD
+    aom_write_symbol(w, mbmi->angle_delta[0] + MAX_ANGLE_DELTA,
+                     ec_ctx->angle_delta_cdf[mbmi->mode - V_PRED],
+                     2 * MAX_ANGLE_DELTA + 1);
+#else
+    (void)ec_ctx;
     write_uniform(w, 2 * MAX_ANGLE_DELTA + 1,
                   MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
+#endif  // CONFIG_EXT_INTRA_MOD
   }
 
   if (av1_is_directional_mode(get_uv_mode(mbmi->uv_mode), bsize)) {
+#if CONFIG_EXT_INTRA_MOD
+    aom_write_symbol(w, mbmi->angle_delta[1] + MAX_ANGLE_DELTA,
+                     ec_ctx->angle_delta_cdf[mbmi->uv_mode - V_PRED],
+                     2 * MAX_ANGLE_DELTA + 1);
+#else
     write_uniform(w, 2 * MAX_ANGLE_DELTA + 1,
                   MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
+#endif
   }
 }
 #endif  // CONFIG_EXT_INTRA
@@ -1594,7 +1608,7 @@
     }
 
 #if CONFIG_EXT_INTRA
-    write_intra_angle_info(xd, w);
+    write_intra_angle_info(xd, ec_ctx, w);
 #endif  // CONFIG_EXT_INTRA
     if (av1_allow_palette(cm->allow_screen_content_tools, bsize))
       write_palette_mode_info(cm, xd, mi, w);
@@ -1933,7 +1947,7 @@
   }
 
 #if CONFIG_EXT_INTRA
-  write_intra_angle_info(xd, w);
+  write_intra_angle_info(xd, ec_ctx, w);
 #endif  // CONFIG_EXT_INTRA
   if (av1_allow_palette(cm->allow_screen_content_tools, bsize))
     write_palette_mode_info(cm, xd, mi, w);
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 049fa83..fd0e58e 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -284,6 +284,9 @@
   int intra_tx_type_costs[EXT_TX_SIZES][TX_TYPES][TX_TYPES];
   int inter_tx_type_costs[EXT_TX_SIZES][TX_TYPES];
 #endif  // CONFIG_EXT_TX
+#if CONFIG_EXT_INTRA && CONFIG_EXT_INTRA_MOD
+  int angle_delta_cost[DIRECTIONAL_MODES][2 * MAX_ANGLE_DELTA + 1];
+#endif  // CONFIG_EXT_INTRA && CONFIG_EXT_INTRA_MOD
 #if CONFIG_LOOP_RESTORATION
   int switchable_restore_cost[RESTORE_SWITCHABLE_TYPES];
   int wiener_restore_cost[2];
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index c8bae01..b866250 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -4265,10 +4265,32 @@
                FILTER_INTRA_MODES);
   }
 #endif  // CONFIG_FILTER_INTRA
+#if CONFIG_EXT_INTRA && CONFIG_EXT_INTRA_MOD
+  if (av1_is_directional_mode(mbmi->mode, bsize) &&
+      av1_use_angle_delta(bsize)) {
+#if CONFIG_ENTROPY_STATS
+    ++counts->angle_delta[mbmi->mode - V_PRED]
+                         [mbmi->angle_delta[0] + MAX_ANGLE_DELTA];
+#endif
+    update_cdf(fc->angle_delta_cdf[mbmi->mode - V_PRED],
+               mbmi->angle_delta[0] + MAX_ANGLE_DELTA, 2 * MAX_ANGLE_DELTA + 1);
+  }
+#endif  // CONFIG_EXT_INTRA && CONFIG_EXT_INTRA_MOD
 
   if (!is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
                            xd->plane[1].subsampling_y))
     return;
+#if CONFIG_EXT_INTRA && CONFIG_EXT_INTRA_MOD
+  if (av1_is_directional_mode(mbmi->uv_mode, bsize) &&
+      av1_use_angle_delta(bsize)) {
+#if CONFIG_ENTROPY_STATS
+    ++counts->angle_delta[mbmi->uv_mode - V_PRED]
+                         [mbmi->angle_delta[1] + MAX_ANGLE_DELTA];
+#endif
+    update_cdf(fc->angle_delta_cdf[mbmi->uv_mode - V_PRED],
+               mbmi->angle_delta[1] + MAX_ANGLE_DELTA, 2 * MAX_ANGLE_DELTA + 1);
+  }
+#endif  // CONFIG_EXT_INTRA && CONFIG_EXT_INTRA_MOD
 #if CONFIG_ENTROPY_STATS
   ++counts->uv_mode[y_mode][uv_mode];
 #endif  // CONFIG_ENTROPY_STATS
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index 9987467..5ecd86a 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -293,6 +293,12 @@
                              av1_ext_tx_inv);
   }
 #endif  // CONFIG_EXT_TX
+#if CONFIG_EXT_INTRA && CONFIG_EXT_INTRA_MOD
+  for (i = 0; i < DIRECTIONAL_MODES; ++i) {
+    av1_cost_tokens_from_cdf(x->angle_delta_cost[i], fc->angle_delta_cdf[i],
+                             NULL);
+  }
+#endif  // CONFIG_EXT_INTRA && CONFIG_EXT_INTRA_MOD
 #if CONFIG_LOOP_RESTORATION
   av1_cost_tokens_from_cdf(x->switchable_restore_cost,
                            fc->switchable_restore_cdf, NULL);
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index c9c766a..90cb82d 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -3024,8 +3024,13 @@
 #if CONFIG_EXT_INTRA
   if (av1_is_directional_mode(mbmi->mode, bsize) &&
       av1_use_angle_delta(bsize)) {
+#if CONFIG_EXT_INTRA_MOD
+    mode_cost += x->angle_delta_cost[mbmi->mode - V_PRED]
+                                    [MAX_ANGLE_DELTA + mbmi->angle_delta[0]];
+#else
     mode_cost += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
                                     MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
+#endif  // CONFIG_EXT_INTRA_MOD
   }
 #endif  // CONFIG_EXT_INTRA
 #if CONFIG_FILTER_INTRA
@@ -3373,8 +3378,13 @@
   if (tokenonly_rd_stats.rate == INT_MAX) return INT64_MAX;
 
   this_rate = tokenonly_rd_stats.rate + mode_cost +
+#if CONFIG_EXT_INTRA_MOD
+              x->angle_delta_cost[mbmi->mode - V_PRED]
+                                 [max_angle_delta + mbmi->angle_delta[0]];
+#else
               write_uniform_cost(2 * max_angle_delta + 1,
                                  mbmi->angle_delta[0] + max_angle_delta);
+#endif  // CONFIG_EXT_INTRA_MOD
   this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
 
   if (this_rd < *best_rd) {
@@ -3748,8 +3758,14 @@
 #if CONFIG_EXT_INTRA
     if (is_directional_mode) {
       if (av1_use_angle_delta(bsize)) {
+#if CONFIG_EXT_INTRA_MOD
+        this_rate +=
+            x->angle_delta_cost[mbmi->mode - V_PRED]
+                               [MAX_ANGLE_DELTA + mbmi->angle_delta[0]];
+#else
         this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
                                         MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
+#endif  // CONFIG_EXT_INTRA_MOD
       }
     }
 #endif  // CONFIG_EXT_INTRA
@@ -5294,6 +5310,10 @@
   if (!super_block_uvrd(cpi, x, &tokenonly_rd_stats, bsize, best_rd_in))
     return INT64_MAX;
   this_rate = tokenonly_rd_stats.rate + rate_overhead;
+#if CONFIG_EXT_INTRA_MOD
+  this_rate += x->angle_delta_cost[mbmi->uv_mode - V_PRED]
+                                  [mbmi->angle_delta[1] + MAX_ANGLE_DELTA];
+#endif  // CONFIG_EXT_INTRA_MOD
   this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
   if (this_rd < *best_rd) {
     *best_rd = this_rd;
@@ -5505,7 +5525,11 @@
     mbmi->angle_delta[1] = 0;
     if (is_directional_mode && av1_use_angle_delta(mbmi->sb_type)) {
       const int rate_overhead = x->intra_uv_mode_cost[mbmi->mode][mode] +
+#if CONFIG_EXT_INTRA_MOD
+                                0;
+#else
                                 write_uniform_cost(2 * MAX_ANGLE_DELTA + 1, 0);
+#endif  // CONFIG_EXT_INTRA_MOD
       if (!rd_pick_intra_angle_sbuv(cpi, x, bsize, rate_overhead, best_rd,
                                     &this_rate, &tokenonly_rd_stats))
         continue;
@@ -5530,8 +5554,13 @@
 #endif
 #if CONFIG_EXT_INTRA
     if (is_directional_mode && av1_use_angle_delta(mbmi->sb_type)) {
+#if CONFIG_EXT_INTRA_MOD
+      this_rate += x->angle_delta_cost[mode - V_PRED]
+                                      [mbmi->angle_delta[1] + MAX_ANGLE_DELTA];
+#else
       this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
                                       MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
+#endif  // CONFIG_EXT_INTRA_MOD
     }
 #endif  // CONFIG_EXT_INTRA
 
@@ -10125,14 +10154,24 @@
 #if CONFIG_EXT_INTRA
       if (is_directional_mode) {
         if (av1_use_angle_delta(bsize)) {
+#if CONFIG_EXT_INTRA_MOD
+          rate2 += x->angle_delta_cost[mbmi->mode - V_PRED]
+                                      [mbmi->angle_delta[0] + MAX_ANGLE_DELTA];
+#else
           rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
                                       MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
+#endif  // CONFIG_EXT_INTRA_MOD
         }
       }
       if (av1_is_directional_mode(get_uv_mode(mbmi->uv_mode), bsize) &&
           av1_use_angle_delta(bsize)) {
+#if CONFIG_EXT_INTRA_MOD
+        rate2 += x->angle_delta_cost[mbmi->uv_mode - V_PRED]
+                                    [mbmi->angle_delta[1] + MAX_ANGLE_DELTA];
+#else
         rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
                                     MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
+#endif  // CONFIG_EXT_INTRA_MOD
       }
 #endif  // CONFIG_EXT_INTRA
 #if CONFIG_FILTER_INTRA