Add convolve 1d functions

Added convolve 1d functions for 1d-only sub-pixel interpolation, including
av1_convolve_x() function for "subpel_x_q4 == 0" case and av1_convolve_y()
function for "subpel_y_q4 == 0" case. Separated into different cases for
speeding up the codec(especially the decoder). The optimized version will
be added later.

Change-Id: I08fd317d02c786af68270a971bb3b17c94bd52ca
diff --git a/av1/common/av1_rtcd_defs.pl b/av1/common/av1_rtcd_defs.pl
index 5b337be..6201779 100755
--- a/av1/common/av1_rtcd_defs.pl
+++ b/av1/common/av1_rtcd_defs.pl
@@ -573,6 +573,10 @@
   if (aom_config("CONFIG_COMPOUND_ROUND") ne "yes") {
     add_proto qw/void av1_convolve_2d_copy/, "const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst, int dst_stride, int w, int h, InterpFilterParams *filter_params_x, InterpFilterParams *filter_params_y, const int subpel_x_q4, const int subpel_y_q4, ConvolveParams *conv_params";
     specialize qw/av1_convolve_2d_copy sse2/;
+    add_proto qw/void av1_convolve_x/, "const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst, int dst_stride, int w, int h, InterpFilterParams *filter_params_x, InterpFilterParams *filter_params_y, const int subpel_x_q4, const int subpel_y_q4, ConvolveParams *conv_params";
+    specialize qw/av1_convolve_x c/;
+    add_proto qw/void av1_convolve_y/, "const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst, int dst_stride, int w, int h, InterpFilterParams *filter_params_x, InterpFilterParams *filter_params_y, const int subpel_x_q4, const int subpel_y_q4, ConvolveParams *conv_params";
+    specialize qw/av1_convolve_y c/;
   }
 
   add_proto qw/void av1_convolve_2d_scale/, "const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst, int dst_stride, int w, int h, InterpFilterParams *filter_params_x, InterpFilterParams *filter_params_y, const int subpel_x_qn, const int x_step_qn, const int subpel_y_q4, const int y_step_qn, ConvolveParams *conv_params";
diff --git a/av1/common/convolve.c b/av1/common/convolve.c
index b3dd85e..705ebbb 100644
--- a/av1/common/convolve.c
+++ b/av1/common/convolve.c
@@ -623,6 +623,66 @@
   }
 }
 
+void av1_convolve_x_c(const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst,
+                      int dst_stride, int w, int h,
+                      InterpFilterParams *filter_params_x,
+                      InterpFilterParams *filter_params_y,
+                      const int subpel_x_q4, const int subpel_y_q4,
+                      ConvolveParams *conv_params) {
+  int x, y, k;
+  const int fo_vert = filter_params_y->taps / 2 - 1;
+  const int bits = FILTER_BITS - conv_params->round_0 - conv_params->round_1;
+  (void)filter_params_x;
+  (void)subpel_x_q4;
+
+  // vertical filter
+  const int16_t *y_filter = av1_get_interp_filter_subpel_kernel(
+      *filter_params_y, subpel_y_q4 & SUBPEL_MASK);
+  for (y = 0; y < h; ++y) {
+    for (x = 0; x < w; ++x) {
+      CONV_BUF_TYPE res = 0;
+      for (k = 0; k < filter_params_y->taps; ++k) {
+        res += y_filter[k] * src[(y - fo_vert + k) * src_stride + x];
+      }
+      res *= (1 << bits);
+      if (conv_params->do_average)
+        dst[y * dst_stride + x] += res;
+      else
+        dst[y * dst_stride + x] = res;
+    }
+  }
+}
+
+void av1_convolve_y_c(const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst,
+                      int dst_stride, int w, int h,
+                      InterpFilterParams *filter_params_x,
+                      InterpFilterParams *filter_params_y,
+                      const int subpel_x_q4, const int subpel_y_q4,
+                      ConvolveParams *conv_params) {
+  int x, y, k;
+  const int fo_horiz = filter_params_x->taps / 2 - 1;
+  const int bits = FILTER_BITS - conv_params->round_1;
+  (void)filter_params_y;
+  (void)subpel_y_q4;
+
+  // horizontal filter
+  const int16_t *x_filter = av1_get_interp_filter_subpel_kernel(
+      *filter_params_x, subpel_x_q4 & SUBPEL_MASK);
+  for (y = 0; y < h; ++y) {
+    for (x = 0; x < w; ++x) {
+      CONV_BUF_TYPE res = 0;
+      for (k = 0; k < filter_params_x->taps; ++k) {
+        res += x_filter[k] * src[y * src_stride + x - fo_horiz + k];
+      }
+      res = (1 << bits) * ROUND_POWER_OF_TWO(res, conv_params->round_0);
+      if (conv_params->do_average)
+        dst[y * dst_stride + x] += res;
+      else
+        dst[y * dst_stride + x] = res;
+    }
+  }
+}
+
 void av1_convolve_2d_copy_c(const uint8_t *src, int src_stride,
                             CONV_BUF_TYPE *dst, int dst_stride, int w, int h,
                             InterpFilterParams *filter_params_x,
@@ -882,17 +942,21 @@
                       conv_params->dst_stride, w, h, &filter_params_x,
                       &filter_params_y, subpel_x_q4, subpel_y_q4, conv_params);
 #else
+      // Special case convolve functions should produce the same result as
+      // av1_convolve_2d.
       if (subpel_x_q4 == 0 && subpel_y_q4 == 0) {
         av1_convolve_2d_copy(src, src_stride, conv_params->dst,
                              conv_params->dst_stride, w, h, &filter_params_x,
                              &filter_params_y, subpel_x_q4, subpel_y_q4,
                              conv_params);
-      } else if (subpel_x_q4 == 0 || subpel_y_q4 == 0) {
-        // place holder
-        av1_convolve_2d(src, src_stride, conv_params->dst,
-                        conv_params->dst_stride, w, h, &filter_params_x,
-                        &filter_params_y, subpel_x_q4, subpel_y_q4,
-                        conv_params);
+      } else if (subpel_x_q4 == 0) {
+        av1_convolve_x(src, src_stride, conv_params->dst,
+                       conv_params->dst_stride, w, h, &filter_params_x,
+                       &filter_params_y, subpel_x_q4, subpel_y_q4, conv_params);
+      } else if (subpel_y_q4 == 0) {
+        av1_convolve_y(src, src_stride, conv_params->dst,
+                       conv_params->dst_stride, w, h, &filter_params_x,
+                       &filter_params_y, subpel_x_q4, subpel_y_q4, conv_params);
       } else {
         // subpel_x_q4 != 0 && subpel_y_q4 != 0
         av1_convolve_2d(src, src_stride, conv_params->dst,