Compute strongest Sobel x and y edge component

Change-Id: I731975a3f5e49602a5e370e9aa6fa5b8dc01ce6a
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 87761e9..e96ca16 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -416,6 +416,9 @@
   // detection). For reference, 556 is the value returned for a solid
   // vertical black/white edge.
   uint16_t edge_strength;
+  // The strongest edge strength seen along the x/y axis.
+  uint16_t edge_strength_x;
+  uint16_t edge_strength_y;
 
   // [Saved stat index]
   COMP_RD_STATS comp_rd_stats[MAX_COMP_RD_STATS];
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 50b619f..3423abf 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -510,15 +510,16 @@
       cpi, cm->base_qindex + xd->delta_qindex + cm->y_dc_delta_q);
 }
 
-static uint16_t edge_strength(const struct buf_2d *ref, const BLOCK_SIZE bsize,
-                              const bool high_bd, const int bd) {
+static EdgeInfo edge_info(const struct buf_2d *ref, const BLOCK_SIZE bsize,
+                          const bool high_bd, const int bd) {
   const int width = block_size_wide[bsize];
   const int height = block_size_high[bsize];
   // Implementation requires width to be a multiple of 8. It also requires
   // height to be a multiple of 4, but this is always the case.
   assert(height % 4 == 0);
   if (width % 8 != 0) {
-    return 0;
+    EdgeInfo ei = { .magnitude = 0, .x = 0, .y = 0 };
+    return ei;
   }
   return av1_edge_exists(ref->buf, ref->stride, width, height, high_bd, bd);
 }
@@ -611,9 +612,14 @@
   // should not be used. Use a value that will always succeed in the check.
   if (cpi->sf.disable_wedge_search_edge_thresh == 0) {
     x->edge_strength = UINT16_MAX;
+    x->edge_strength_x = UINT16_MAX;
+    x->edge_strength_y = UINT16_MAX;
   } else {
-    x->edge_strength =
-        edge_strength(&x->plane[0].src, bsize, is_cur_buf_hbd(xd), xd->bd);
+    EdgeInfo ei =
+        edge_info(&x->plane[0].src, bsize, is_cur_buf_hbd(xd), xd->bd);
+    x->edge_strength = ei.magnitude;
+    x->edge_strength_x = ei.x;
+    x->edge_strength_y = ei.y;
   }
   // Save rdmult before it might be changed, so it can be restored later.
   orig_rdmult = x->rdmult;
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 28caad0..f5dfca0 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -13061,12 +13061,14 @@
   }
 }
 
-static uint16_t edge_probability(const uint8_t *input, int w, int h,
+static EdgeInfo edge_probability(const uint8_t *input, int w, int h,
                                  bool high_bd, int bd) {
   // The probability of an edge in the whole image is the same as the highest
   // probability of an edge for any individual pixel. Use Sobel as the metric
   // for finding an edge.
   uint16_t highest = 0;
+  uint16_t highest_x = 0;
+  uint16_t highest_y = 0;
   // Ignore the 1 pixel border around the image for the computation.
   for (int j = 1; j < h - 1; ++j) {
     for (int i = 1; i < w - 1; ++i) {
@@ -13076,18 +13078,22 @@
       int16_t g_y = g.y >> (bd - 8);
       uint16_t magnitude = (uint16_t)sqrt(g_x * g_x + g_y * g_y);
       highest = AOMMAX(highest, magnitude);
+      highest_x = AOMMAX(highest_x, g_x);
+      highest_y = AOMMAX(highest_y, g_y);
     }
   }
-  return highest;
+  EdgeInfo ei = { .magnitude = highest, .x = highest_x, .y = highest_y };
+  return ei;
 }
 
 /* Uses most of the Canny edge detection algorithm to find if there are any
  * edges in the image.
  */
-uint16_t av1_edge_exists(const uint8_t *src, int src_stride, int w, int h,
+EdgeInfo av1_edge_exists(const uint8_t *src, int src_stride, int w, int h,
                          bool high_bd, int bd) {
   if (w < 3 || h < 3) {
-    return 0;
+    EdgeInfo n = { .magnitude = 0, .x = 0, .y = 0 };
+    return n;
   }
   uint8_t *blurred;
   if (high_bd) {
@@ -13100,7 +13106,7 @@
   // want a probability of an edge existing in the buffer, which is determined
   // by the strongest edge in it -- we don't need to eliminate the weaker
   // edges. Use Sobel for the edge detection.
-  uint16_t prob = edge_probability(blurred, w, h, high_bd, bd);
+  EdgeInfo prob = edge_probability(blurred, w, h, high_bd, bd);
   if (high_bd) {
     aom_free(CONVERT_TO_SHORTPTR(blurred));
   } else {
diff --git a/av1/encoder/rdopt.h b/av1/encoder/rdopt.h
index 983d385..0ce931a 100644
--- a/av1/encoder/rdopt.h
+++ b/av1/encoder/rdopt.h
@@ -128,13 +128,21 @@
     struct macroblock *x, int mi_row, int mi_col, struct RD_STATS *rd_cost,
     BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far);
 
+// The best edge strength seen in the block, as well as the best x and y
+// components of edge strength seen.
+typedef struct {
+  uint16_t magnitude;
+  uint16_t x;
+  uint16_t y;
+} EdgeInfo;
+
 /** Returns an integer indicating the strength of the edge.
  * 0 means no edge found, 556 is the strength of a solid black/white edge,
  * and the number may range higher if the signal is even stronger (e.g., on a
  * corner). high_bd is a bool indicating the source should be treated
  * as a 16-bit array. bd is the bit depth.
  */
-uint16_t av1_edge_exists(const uint8_t *src, int src_stride, int w, int h,
+EdgeInfo av1_edge_exists(const uint8_t *src, int src_stride, int w, int h,
                          bool high_bd, int bd);
 
 /** Applies a Gaussian blur with sigma = 1.3. Used by av1_edge_exists and
diff --git a/test/edge_detect_test.cc b/test/edge_detect_test.cc
index 47466cb..77a731f 100644
--- a/test/edge_detect_test.cc
+++ b/test/edge_detect_test.cc
@@ -185,8 +185,9 @@
   const bool high_bd = GET_PARAM(3);
   const int bd = GET_PARAM(4);
 
-  ASSERT_EQ(0, av1_edge_exists(input_, stride_8tap(width), width, height,
-                               high_bd, bd));
+  ASSERT_EQ(
+      0, av1_edge_exists(input_, stride_8tap(width), width, height, high_bd, bd)
+             .magnitude);
 }
 
 INSTANTIATE_TEST_CASE_P(ImageBrightnessTests, EdgeDetectBrightnessTest,
@@ -245,9 +246,11 @@
   free(orig);
   // Value should be between 556 and 560.
   ASSERT_LE(556, av1_edge_exists(padded, stride_8tap(width), width, height,
-                                 high_bd, bd));
+                                 high_bd, bd)
+                     .magnitude);
   ASSERT_GE(560, av1_edge_exists(padded, stride_8tap(width), width, height,
-                                 high_bd, bd));
+                                 high_bd, bd)
+                     .magnitude);
 
   free_pad_8tap(padded, width, high_bd);
 }