shithub: dav1d

Download patch

ref: 6c27b662f9ab99125294b50257f7a660684e990d
parent: 2c3eaffd2a32c63330b5afb1bf90847a0e0b0472
author: Boyuan Xiao <boyuan.xiao@argondesign.com>
date: Fri Nov 9 08:43:41 EST 2018

Only do intra edge filtering/upsampling if enable_intra_edge set

See section 7.11.2.4 in AV1 spec. Because frame contexts are not
passed into the ipred_z*_c functions the flag is set as a bit inside
the 'angle' function argument.

--- a/src/ipred_prepare.h
+++ b/src/ipred_prepare.h
@@ -83,9 +83,14 @@
                                       enum IntraPredMode mode, int *angle,
                                       int tw, int th, pixel *topleft_out);
 
-// is or'ed with the angle argument into intra predictors to signal that edges
-// are smooth and should use reduced filter strength
-#define ANGLE_SMOOTH_EDGE_FLAG 512
+// These flags are OR'd with the angle argument into intra predictors.
+// ANGLE_USE_EDGE_FILTER_FLAG signals that edges should be convolved
+// with a filter before using them to predict values in a block.
+// ANGLE_SMOOTH_EDGE_FLAG means that edges are smooth and should use
+// reduced filter strength.
+#define ANGLE_USE_EDGE_FILTER_FLAG 1024
+#define ANGLE_SMOOTH_EDGE_FLAG      512
+
 static inline int sm_flag(const BlockContext *const b, const int idx) {
     if (!b->intra[idx]) return 0;
     const enum IntraPredMode m = b->mode[idx];
--- a/src/ipred_tmpl.c
+++ b/src/ipred_tmpl.c
@@ -387,7 +387,8 @@
                        const int width, const int height, int angle,
                        const int max_width, const int max_height)
 {
-    const int is_sm = angle >> 9;
+    const int is_sm = (angle >> 9) & 0x1;
+    const int enable_intra_edge_filter = angle >> 10;
     angle &= 511;
     assert(angle < 90);
     const int dx = dav1d_dr_intra_derivative[angle];
@@ -394,7 +395,8 @@
     pixel top_out[(64 + 64) * 2];
     const pixel *top;
     int max_base_x;
-    const int upsample_above = get_upsample(width + height, 90 - angle, is_sm);
+    const int upsample_above = enable_intra_edge_filter ?
+        get_upsample(width + height, 90 - angle, is_sm) : 0;
     if (upsample_above) {
         upsample_edge(top_out, width + height,
                       &topleft_in[1], -1, width + imin(width, height));
@@ -401,9 +403,8 @@
         top = top_out;
         max_base_x = 2 * (width + height) - 2;
     } else {
-        const int filter_strength =
-            get_filter_strength(width + height, 90 - angle, is_sm);
-
+        const int filter_strength = enable_intra_edge_filter ?
+            get_filter_strength(width + height, 90 - angle, is_sm) : 0;
         if (filter_strength) {
             filter_edge(top_out, width + height, 0, width + height,
                         &topleft_in[1], -1, width + imin(width, height),
@@ -440,13 +441,16 @@
                        const int width, const int height, int angle,
                        const int max_width, const int max_height)
 {
-    const int is_sm = angle >> 9;
+    const int is_sm = (angle >> 9) & 0x1;
+    const int enable_intra_edge_filter = angle >> 10;
     angle &= 511;
     assert(angle > 90 && angle < 180);
     const int dy = dav1d_dr_intra_derivative[angle - 90];
     const int dx = dav1d_dr_intra_derivative[180 - angle];
-    const int upsample_left = get_upsample(width + height, 180 - angle, is_sm);
-    const int upsample_above = get_upsample(width + height, angle - 90, is_sm);
+    const int upsample_left = enable_intra_edge_filter ?
+        get_upsample(width + height, 180 - angle, is_sm) : 0;
+    const int upsample_above = enable_intra_edge_filter ?
+        get_upsample(width + height, angle - 90, is_sm) : 0;
     pixel edge[64 * 2 + 64 * 2 + 1];
     pixel *const topleft = &edge[height * 2];
 
@@ -453,8 +457,8 @@
     if (upsample_above) {
         upsample_edge(topleft, width + 1, topleft_in, 0, width + 1);
     } else {
-        const int filter_strength =
-            get_filter_strength(width + height, angle - 90, is_sm);
+        const int filter_strength = enable_intra_edge_filter ?
+            get_filter_strength(width + height, angle - 90, is_sm) : 0;
 
         if (filter_strength) {
             filter_edge(&topleft[1], width, 0, max_width,
@@ -467,8 +471,8 @@
     if (upsample_left) {
         upsample_edge(edge, height + 1, &topleft_in[-height], 0, height + 1);
     } else {
-        const int filter_strength =
-            get_filter_strength(width + height, 180 - angle, is_sm);
+        const int filter_strength = enable_intra_edge_filter ?
+            get_filter_strength(width + height, 180 - angle, is_sm) : 0;
 
         if (filter_strength) {
             filter_edge(&topleft[-height], height, height - max_height, height,
@@ -514,7 +518,8 @@
                        const int width, const int height, int angle,
                        const int max_width, const int max_height)
 {
-    const int is_sm = angle >> 9;
+    const int is_sm = (angle >> 9) & 0x1;
+    const int enable_intra_edge_filter = angle >> 10;
     angle &= 511;
     assert(angle > 180);
     const int dy = dav1d_dr_intra_derivative[270 - angle];
@@ -521,7 +526,8 @@
     pixel left_out[(64 + 64) * 2];
     const pixel *left;
     int max_base_y;
-    const int upsample_left = get_upsample(width + height, angle - 180, is_sm);
+    const int upsample_left = enable_intra_edge_filter ?
+        get_upsample(width + height, angle - 180, is_sm) : 0;
     if (upsample_left) {
         upsample_edge(left_out, width + height,
                       &topleft_in[-(width + height)],
@@ -529,8 +535,8 @@
         left = &left_out[2 * (width + height) - 2];
         max_base_y = 2 * (width + height) - 2;
     } else {
-        const int filter_strength =
-            get_filter_strength(width + height, angle - 180, is_sm);
+        const int filter_strength = enable_intra_edge_filter ?
+            get_filter_strength(width + height, angle - 180, is_sm) : 0;
 
         if (filter_strength) {
             filter_edge(left_out, width + height, 0, width + height,
--- a/src/recon_tmpl.c
+++ b/src/recon_tmpl.c
@@ -753,6 +753,8 @@
     pixel *const edge = edge_buf + 128;
     const int cbw4 = (bw4 + ss_hor) >> ss_hor, cbh4 = (bh4 + ss_ver) >> ss_ver;
 
+    const int intra_edge_filter_flag = f->seq_hdr.intra_edge_filter << 10;
+
     for (int init_y = 0; init_y < h4; init_y += 16) {
         for (int init_x = 0; init_x < w4; init_x += 16) {
             if (b->pal_sz[0]) {
@@ -775,7 +777,9 @@
                              bw4 * 4, bh4 * 4, "y-pal-pred");
             }
 
-            const int sm_fl = sm_flag(t->a, bx4) | sm_flag(&t->l, by4);
+            const int intra_flags = (sm_flag(t->a, bx4) |
+                                     sm_flag(&t->l, by4) |
+                                     intra_edge_filter_flag);
             const int sb_has_tr = init_x + 16 < w4 ? 1 : init_y ? 0 :
                               intra_edge_flags & EDGE_I444_TOP_HAS_RIGHT;
             const int sb_has_bl = init_x ? 0 : init_y + 16 < h4 ? 1 :
@@ -819,7 +823,7 @@
                                                           t_dim->w, t_dim->h, edge);
                     dsp->ipred.intra_pred[m](dst, f->cur.p.stride[0], edge,
                                              t_dim->w * 4, t_dim->h * 4,
-                                             angle | sm_fl,
+                                             angle | intra_flags,
                                              4 * f->bw - 4 * t->bx,
                                              4 * f->bh - 4 * t->by);
 
@@ -1033,6 +1037,7 @@
                                                               top_sb_edge, uv_mode,
                                                               &angle, uv_t_dim->w,
                                                               uv_t_dim->h, edge);
+                        angle |= intra_edge_filter_flag;
                         dsp->ipred.intra_pred[m](dst, stride, edge,
                                                  uv_t_dim->w * 4,
                                                  uv_t_dim->h * 4,