Handle allocation failure in sgr SIMD functions

In this CL, thread-specific 'error_info' is passed to the low level
functions of selfguided restoration module to service the  allocation
failure of local buffer in av1_selfguided_restoration_avx2()
and av1_selfguided_restoration_sse4_1().

Bug: aomedia:3276
Change-Id: I37dabdc2f0181ab5de0c5075c0f9791b15bb1c8e
diff --git a/av1/common/arm/selfguided_neon.c b/av1/common/arm/selfguided_neon.c
index 8966080..1d3a3cc 100644
--- a/av1/common/arm/selfguided_neon.c
+++ b/av1/common/arm/selfguided_neon.c
@@ -1449,11 +1449,11 @@
   return 0;
 }
 
-void av1_apply_selfguided_restoration_neon(const uint8_t *dat8, int width,
-                                           int height, int stride, int eps,
-                                           const int *xqd, uint8_t *dst8,
-                                           int dst_stride, int32_t *tmpbuf,
-                                           int bit_depth, int highbd) {
+int av1_apply_selfguided_restoration_neon(const uint8_t *dat8, int width,
+                                          int height, int stride, int eps,
+                                          const int *xqd, uint8_t *dst8,
+                                          int dst_stride, int32_t *tmpbuf,
+                                          int bit_depth, int highbd) {
   int32_t *flt0 = tmpbuf;
   int32_t *flt1 = flt0 + RESTORATION_UNITPELS_MAX;
   assert(width * height <= RESTORATION_UNITPELS_MAX);
@@ -1591,4 +1591,5 @@
       h--;
     } while (h > 0);
   }
+  return 0;
 }
diff --git a/av1/common/av1_rtcd_defs.pl b/av1/common/av1_rtcd_defs.pl
index bd2acda..38e1da9 100644
--- a/av1/common/av1_rtcd_defs.pl
+++ b/av1/common/av1_rtcd_defs.pl
@@ -548,7 +548,7 @@
 specialize qw/av1_warp_affine sse4_1 avx2 neon neon_i8mm sve/;
 
 # LOOP_RESTORATION functions
-add_proto qw/void av1_apply_selfguided_restoration/, "const uint8_t *dat, int width, int height, int stride, int eps, const int *xqd, uint8_t *dst, int dst_stride, int32_t *tmpbuf, int bit_depth, int highbd";
+add_proto qw/int av1_apply_selfguided_restoration/, "const uint8_t *dat, int width, int height, int stride, int eps, const int *xqd, uint8_t *dst, int dst_stride, int32_t *tmpbuf, int bit_depth, int highbd";
 specialize qw/av1_apply_selfguided_restoration sse4_1 avx2 neon/;
 
 add_proto qw/int av1_selfguided_restoration/, "const uint8_t *dgd8, int width, int height,
diff --git a/av1/common/restoration.c b/av1/common/restoration.c
index c0a207f..a26f329 100644
--- a/av1/common/restoration.c
+++ b/av1/common/restoration.c
@@ -384,9 +384,11 @@
                                  int stripe_width, int stripe_height,
                                  int procunit_width, const uint8_t *src,
                                  int src_stride, uint8_t *dst, int dst_stride,
-                                 int32_t *tmpbuf, int bit_depth) {
+                                 int32_t *tmpbuf, int bit_depth,
+                                 struct aom_internal_error_info *error_info) {
   (void)tmpbuf;
   (void)bit_depth;
+  (void)error_info;
   assert(bit_depth == 8);
   const WienerConvolveParams conv_params = get_conv_params_wiener(8);
 
@@ -852,19 +854,18 @@
   return 0;
 }
 
-void av1_apply_selfguided_restoration_c(const uint8_t *dat8, int width,
-                                        int height, int stride, int eps,
-                                        const int *xqd, uint8_t *dst8,
-                                        int dst_stride, int32_t *tmpbuf,
-                                        int bit_depth, int highbd) {
+int av1_apply_selfguided_restoration_c(const uint8_t *dat8, int width,
+                                       int height, int stride, int eps,
+                                       const int *xqd, uint8_t *dst8,
+                                       int dst_stride, int32_t *tmpbuf,
+                                       int bit_depth, int highbd) {
   int32_t *flt0 = tmpbuf;
   int32_t *flt1 = flt0 + RESTORATION_UNITPELS_MAX;
   assert(width * height <= RESTORATION_UNITPELS_MAX);
 
   const int ret = av1_selfguided_restoration_c(
       dat8, width, height, stride, flt0, flt1, width, eps, bit_depth, highbd);
-  (void)ret;
-  assert(!ret);
+  if (ret != 0) return ret;
   const sgr_params_type *const params = &av1_sgr_params[eps];
   int xq[2];
   av1_decode_xq(xqd, xq, params);
@@ -891,32 +892,39 @@
         *dst8ij = (uint8_t)out;
     }
   }
+  return 0;
 }
 
 static void sgrproj_filter_stripe(const RestorationUnitInfo *rui,
                                   int stripe_width, int stripe_height,
                                   int procunit_width, const uint8_t *src,
                                   int src_stride, uint8_t *dst, int dst_stride,
-                                  int32_t *tmpbuf, int bit_depth) {
+                                  int32_t *tmpbuf, int bit_depth,
+                                  struct aom_internal_error_info *error_info) {
   (void)bit_depth;
   assert(bit_depth == 8);
 
   for (int j = 0; j < stripe_width; j += procunit_width) {
     int w = AOMMIN(procunit_width, stripe_width - j);
-    av1_apply_selfguided_restoration(
-        src + j, w, stripe_height, src_stride, rui->sgrproj_info.ep,
-        rui->sgrproj_info.xqd, dst + j, dst_stride, tmpbuf, bit_depth, 0);
+    if (av1_apply_selfguided_restoration(
+            src + j, w, stripe_height, src_stride, rui->sgrproj_info.ep,
+            rui->sgrproj_info.xqd, dst + j, dst_stride, tmpbuf, bit_depth,
+            0) != 0) {
+      aom_internal_error(
+          error_info, AOM_CODEC_MEM_ERROR,
+          "Error allocating buffer in av1_apply_selfguided_restoration");
+    }
   }
 }
 
 #if CONFIG_AV1_HIGHBITDEPTH
-static void wiener_filter_stripe_highbd(const RestorationUnitInfo *rui,
-                                        int stripe_width, int stripe_height,
-                                        int procunit_width, const uint8_t *src8,
-                                        int src_stride, uint8_t *dst8,
-                                        int dst_stride, int32_t *tmpbuf,
-                                        int bit_depth) {
+static void wiener_filter_stripe_highbd(
+    const RestorationUnitInfo *rui, int stripe_width, int stripe_height,
+    int procunit_width, const uint8_t *src8, int src_stride, uint8_t *dst8,
+    int dst_stride, int32_t *tmpbuf, int bit_depth,
+    struct aom_internal_error_info *error_info) {
   (void)tmpbuf;
+  (void)error_info;
   const WienerConvolveParams conv_params = get_conv_params_wiener(bit_depth);
 
   for (int j = 0; j < stripe_width; j += procunit_width) {
@@ -930,17 +938,21 @@
   }
 }
 
-static void sgrproj_filter_stripe_highbd(const RestorationUnitInfo *rui,
-                                         int stripe_width, int stripe_height,
-                                         int procunit_width,
-                                         const uint8_t *src8, int src_stride,
-                                         uint8_t *dst8, int dst_stride,
-                                         int32_t *tmpbuf, int bit_depth) {
+static void sgrproj_filter_stripe_highbd(
+    const RestorationUnitInfo *rui, int stripe_width, int stripe_height,
+    int procunit_width, const uint8_t *src8, int src_stride, uint8_t *dst8,
+    int dst_stride, int32_t *tmpbuf, int bit_depth,
+    struct aom_internal_error_info *error_info) {
   for (int j = 0; j < stripe_width; j += procunit_width) {
     int w = AOMMIN(procunit_width, stripe_width - j);
-    av1_apply_selfguided_restoration(
-        src8 + j, w, stripe_height, src_stride, rui->sgrproj_info.ep,
-        rui->sgrproj_info.xqd, dst8 + j, dst_stride, tmpbuf, bit_depth, 1);
+    if (av1_apply_selfguided_restoration(
+            src8 + j, w, stripe_height, src_stride, rui->sgrproj_info.ep,
+            rui->sgrproj_info.xqd, dst8 + j, dst_stride, tmpbuf, bit_depth,
+            1) != 0) {
+      aom_internal_error(
+          error_info, AOM_CODEC_MEM_ERROR,
+          "Error allocating buffer in av1_apply_selfguided_restoration");
+    }
   }
 }
 #endif  // CONFIG_AV1_HIGHBITDEPTH
@@ -949,7 +961,8 @@
                                   int stripe_width, int stripe_height,
                                   int procunit_width, const uint8_t *src,
                                   int src_stride, uint8_t *dst, int dst_stride,
-                                  int32_t *tmpbuf, int bit_depth);
+                                  int32_t *tmpbuf, int bit_depth,
+                                  struct aom_internal_error_info *error_info);
 
 #if CONFIG_AV1_HIGHBITDEPTH
 #define NUM_STRIPE_FILTERS 4
@@ -965,14 +978,12 @@
 #endif  // CONFIG_AV1_HIGHBITDEPTH
 
 // Filter one restoration unit
-void av1_loop_restoration_filter_unit(const RestorationTileLimits *limits,
-                                      const RestorationUnitInfo *rui,
-                                      const RestorationStripeBoundaries *rsb,
-                                      RestorationLineBuffers *rlbs, int plane_w,
-                                      int plane_h, int ss_x, int ss_y,
-                                      int highbd, int bit_depth, uint8_t *data8,
-                                      int stride, uint8_t *dst8, int dst_stride,
-                                      int32_t *tmpbuf, int optimized_lr) {
+void av1_loop_restoration_filter_unit(
+    const RestorationTileLimits *limits, const RestorationUnitInfo *rui,
+    const RestorationStripeBoundaries *rsb, RestorationLineBuffers *rlbs,
+    int plane_w, int plane_h, int ss_x, int ss_y, int highbd, int bit_depth,
+    uint8_t *data8, int stride, uint8_t *dst8, int dst_stride, int32_t *tmpbuf,
+    int optimized_lr, struct aom_internal_error_info *error_info) {
   RestorationType unit_rtype = rui->restoration_type;
 
   int unit_h = limits->v_end - limits->v_start;
@@ -1024,7 +1035,8 @@
                                      copy_below, optimized_lr);
 
     stripe_filter(rui, unit_w, h, procunit_width, data8_tl + i * stride, stride,
-                  dst8_tl + i * dst_stride, dst_stride, tmpbuf, bit_depth);
+                  dst8_tl + i * dst_stride, dst_stride, tmpbuf, bit_depth,
+                  error_info);
 
     restore_processing_stripe_boundary(&remaining_stripes, rlbs, highbd, h,
                                        data8, stride, copy_above, copy_below,
@@ -1036,7 +1048,8 @@
 
 static void filter_frame_on_unit(const RestorationTileLimits *limits,
                                  int rest_unit_idx, void *priv, int32_t *tmpbuf,
-                                 RestorationLineBuffers *rlbs) {
+                                 RestorationLineBuffers *rlbs,
+                                 struct aom_internal_error_info *error_info) {
   FilterFrameCtxt *ctxt = (FilterFrameCtxt *)priv;
   const RestorationInfo *rsi = ctxt->rsi;
 
@@ -1044,7 +1057,7 @@
       limits, &rsi->unit_info[rest_unit_idx], &rsi->boundaries, rlbs,
       ctxt->plane_w, ctxt->plane_h, ctxt->ss_x, ctxt->ss_y, ctxt->highbd,
       ctxt->bit_depth, ctxt->data8, ctxt->data_stride, ctxt->dst8,
-      ctxt->dst_stride, tmpbuf, rsi->optimized_lr);
+      ctxt->dst_stride, tmpbuf, rsi->optimized_lr, error_info);
 }
 
 void av1_loop_restoration_filter_frame_init(AV1LrStruct *lr_ctxt,
@@ -1155,9 +1168,6 @@
     int32_t *tmpbuf, RestorationLineBuffers *rlbs, sync_read_fn_t on_sync_read,
     sync_write_fn_t on_sync_write, struct AV1LrSyncData *const lr_sync,
     struct aom_internal_error_info *error_info) {
-  // TODO(aomedia:3276): Pass error_info to the low-level functions as required
-  // in future to handle error propagation.
-  (void)error_info;
   const int ext_size = unit_size * 3 / 2;
   int x0 = 0, j = 0;
   while (x0 < plane_w) {
@@ -1190,7 +1200,7 @@
     }
 #endif
 
-    on_rest_unit(limits, unit_idx, priv, tmpbuf, rlbs);
+    on_rest_unit(limits, unit_idx, priv, tmpbuf, rlbs, error_info);
 
     on_sync_write(lr_sync, row_number, j, hnum_rest_units, plane);
 
diff --git a/av1/common/restoration.h b/av1/common/restoration.h
index 5f0e1e0..d5da81d 100644
--- a/av1/common/restoration.h
+++ b/av1/common/restoration.h
@@ -318,7 +318,8 @@
 typedef void (*rest_unit_visitor_t)(const RestorationTileLimits *limits,
                                     int rest_unit_idx, void *priv,
                                     int32_t *tmpbuf,
-                                    RestorationLineBuffers *rlbs);
+                                    RestorationLineBuffers *rlbs,
+                                    struct aom_internal_error_info *error_info);
 
 typedef struct FilterFrameCtxt {
   const RestorationInfo *rsi;
@@ -357,47 +358,47 @@
  * This function applies the loop restoration filter to a single
  * loop restoration unit.
  *
- * \param[in]  limits        Limits of the unit
- * \param[in]  rui           The parameters to use for this unit and its
- *                           coefficients
- * \param[in]  rsb           Deblocked pixels to use for stripe boundaries
- * \param[in]  rlbs          Space to use as a scratch buffer
- * \param[in]  ss_x          Horizontal subsampling for plane
- * \param[in]  ss_y          Vertical subsampling for plane
- * \param[in]  plane_w       Width of the current plane
- * \param[in]  plane_h       Height of the current plane
- * \param[in]  highbd        Whether high bitdepth pipeline is used
- * \param[in]  bit_depth     Bit-depth of the video
- * \param[in]  data8         Frame data (pointing at the top-left corner of
- *                           the frame, not the restoration unit).
- * \param[in]  stride        Stride of \c data8
- * \param[out] dst8          Buffer where the results will be written. Like
- *                           \c data8, \c dst8 should point at the top-left
- *                           corner of the frame
- * \param[in]  dst_stride    Stride of \c dst8
- * \param[in]  tmpbuf        Scratch buffer used by the sgrproj filter which
- *                           should be at least SGRPROJ_TMPBUF_SIZE big.
- * \param[in]  optimized_lr  Whether to use fast optimized Loop Restoration
+ * \param[in]       limits        Limits of the unit
+ * \param[in]       rui           The parameters to use for this unit and its
+ *                                coefficients
+ * \param[in]       rsb           Deblocked pixels to use for stripe boundaries
+ * \param[in]       rlbs          Space to use as a scratch buffer
+ * \param[in]       ss_x          Horizontal subsampling for plane
+ * \param[in]       ss_y          Vertical subsampling for plane
+ * \param[in]       plane_w       Width of the current plane
+ * \param[in]       plane_h       Height of the current plane
+ * \param[in]       highbd        Whether high bitdepth pipeline is used
+ * \param[in]       bit_depth     Bit-depth of the video
+ * \param[in]       data8         Frame data (pointing at the top-left corner of
+ *                                the frame, not the restoration unit).
+ * \param[in]       stride        Stride of \c data8
+ * \param[out]      dst8          Buffer where the results will be written. Like
+ *                                \c data8, \c dst8 should point at the top-left
+ *                                corner of the frame
+ * \param[in]       dst_stride    Stride of \c dst8
+ * \param[in]       tmpbuf        Scratch buffer used by the sgrproj filter
+ *                                which should be at least SGRPROJ_TMPBUF_SIZE
+ *                                big.
+ * \param[in]       optimized_lr  Whether to use fast optimized Loop Restoration
+ * \param[in,out]   error_info    Error info for reporting errors
  *
  * \remark Nothing is returned. Instead, the filtered unit is output in
  * \c dst8 at the proper restoration unit offset.
  */
-void av1_loop_restoration_filter_unit(const RestorationTileLimits *limits,
-                                      const RestorationUnitInfo *rui,
-                                      const RestorationStripeBoundaries *rsb,
-                                      RestorationLineBuffers *rlbs, int plane_w,
-                                      int plane_h, int ss_x, int ss_y,
-                                      int highbd, int bit_depth, uint8_t *data8,
-                                      int stride, uint8_t *dst8, int dst_stride,
-                                      int32_t *tmpbuf, int optimized_lr);
+void av1_loop_restoration_filter_unit(
+    const RestorationTileLimits *limits, const RestorationUnitInfo *rui,
+    const RestorationStripeBoundaries *rsb, RestorationLineBuffers *rlbs,
+    int plane_w, int plane_h, int ss_x, int ss_y, int highbd, int bit_depth,
+    uint8_t *data8, int stride, uint8_t *dst8, int dst_stride, int32_t *tmpbuf,
+    int optimized_lr, struct aom_internal_error_info *error_info);
 
 /*!\brief Function for applying loop restoration filter to a frame
  *
  * \ingroup in_loop_restoration
  * This function applies the loop restoration filter to a frame.
  *
- * \param[in, out]  frame         Compressed frame buffer
- * \param[in, out]  cm            Pointer to top level common structure
+ * \param[in,out]   frame         Compressed frame buffer
+ * \param[in,out]   cm            Pointer to top level common structure
  * \param[in]       optimized_lr  Whether to use fast optimized Loop Restoration
  * \param[in]       lr_ctxt       Loop restoration context
  *
diff --git a/av1/common/x86/selfguided_avx2.c b/av1/common/x86/selfguided_avx2.c
index 4ab35e8..5ab6c46 100644
--- a/av1/common/x86/selfguided_avx2.c
+++ b/av1/common/x86/selfguided_avx2.c
@@ -630,18 +630,17 @@
   return 0;
 }
 
-void av1_apply_selfguided_restoration_avx2(const uint8_t *dat8, int width,
-                                           int height, int stride, int eps,
-                                           const int *xqd, uint8_t *dst8,
-                                           int dst_stride, int32_t *tmpbuf,
-                                           int bit_depth, int highbd) {
+int av1_apply_selfguided_restoration_avx2(const uint8_t *dat8, int width,
+                                          int height, int stride, int eps,
+                                          const int *xqd, uint8_t *dst8,
+                                          int dst_stride, int32_t *tmpbuf,
+                                          int bit_depth, int highbd) {
   int32_t *flt0 = tmpbuf;
   int32_t *flt1 = flt0 + RESTORATION_UNITPELS_MAX;
   assert(width * height <= RESTORATION_UNITPELS_MAX);
   const int ret = av1_selfguided_restoration_avx2(
       dat8, width, height, stride, flt0, flt1, width, eps, bit_depth, highbd);
-  (void)ret;
-  assert(!ret);
+  if (ret != 0) return ret;
   const sgr_params_type *const params = &av1_sgr_params[eps];
   int xq[2];
   av1_decode_xq(xqd, xq, params);
@@ -721,4 +720,5 @@
       }
     }
   }
+  return 0;
 }
diff --git a/av1/common/x86/selfguided_sse4.c b/av1/common/x86/selfguided_sse4.c
index 948bbfb..ac850f5 100644
--- a/av1/common/x86/selfguided_sse4.c
+++ b/av1/common/x86/selfguided_sse4.c
@@ -582,18 +582,17 @@
   return 0;
 }
 
-void av1_apply_selfguided_restoration_sse4_1(const uint8_t *dat8, int width,
-                                             int height, int stride, int eps,
-                                             const int *xqd, uint8_t *dst8,
-                                             int dst_stride, int32_t *tmpbuf,
-                                             int bit_depth, int highbd) {
+int av1_apply_selfguided_restoration_sse4_1(const uint8_t *dat8, int width,
+                                            int height, int stride, int eps,
+                                            const int *xqd, uint8_t *dst8,
+                                            int dst_stride, int32_t *tmpbuf,
+                                            int bit_depth, int highbd) {
   int32_t *flt0 = tmpbuf;
   int32_t *flt1 = flt0 + RESTORATION_UNITPELS_MAX;
   assert(width * height <= RESTORATION_UNITPELS_MAX);
   const int ret = av1_selfguided_restoration_sse4_1(
       dat8, width, height, stride, flt0, flt1, width, eps, bit_depth, highbd);
-  (void)ret;
-  assert(!ret);
+  if (ret != 0) return ret;
   const sgr_params_type *const params = &av1_sgr_params[eps];
   int xq[2];
   av1_decode_xq(xqd, xq, params);
@@ -659,4 +658,5 @@
       }
     }
   }
+  return 0;
 }
diff --git a/av1/encoder/pickrst.c b/av1/encoder/pickrst.c
index cf7633b..6429064 100644
--- a/av1/encoder/pickrst.c
+++ b/av1/encoder/pickrst.c
@@ -220,7 +220,7 @@
       is_uv && cm->seq_params->subsampling_x,
       is_uv && cm->seq_params->subsampling_y, highbd, bit_depth,
       fts->buffers[plane], fts->strides[is_uv], rsc->dst->buffers[plane],
-      rsc->dst->strides[is_uv], cm->rst_tmpbuf, optimized_lr);
+      rsc->dst->strides[is_uv], cm->rst_tmpbuf, optimized_lr, cm->error);
 
   return sse_restoration_unit(limits, rsc->src, rsc->dst, plane, highbd);
 }
@@ -754,7 +754,8 @@
                                  int width, int height, int dat_stride,
                                  int use_highbd, int bit_depth, int pu_width,
                                  int pu_height, int32_t *flt0, int32_t *flt1,
-                                 int flt_stride) {
+                                 int flt_stride,
+                                 struct aom_internal_error_info *error_info) {
   for (int i = 0; i < height; i += pu_height) {
     const int h = AOMMIN(pu_height, height - i);
     int32_t *flt0_row = flt0 + i * flt_stride;
@@ -764,11 +765,13 @@
     // Iterate over the stripe in blocks of width pu_width
     for (int j = 0; j < width; j += pu_width) {
       const int w = AOMMIN(pu_width, width - j);
-      const int ret = av1_selfguided_restoration(
-          dat8_row + j, w, h, dat_stride, flt0_row + j, flt1_row + j,
-          flt_stride, sgr_params_idx, bit_depth, use_highbd);
-      (void)ret;
-      assert(!ret);
+      if (av1_selfguided_restoration(
+              dat8_row + j, w, h, dat_stride, flt0_row + j, flt1_row + j,
+              flt_stride, sgr_params_idx, bit_depth, use_highbd) != 0) {
+        aom_internal_error(
+            error_info, AOM_CODEC_MEM_ERROR,
+            "Error allocating buffer in av1_selfguided_restoration");
+      }
     }
   }
 }
@@ -778,10 +781,11 @@
     const int dat_stride, const uint8_t *src8, const int src_stride,
     const int use_highbitdepth, const int bit_depth, const int pu_width,
     const int pu_height, const int ep, int32_t *flt0, int32_t *flt1,
-    const int flt_stride, int *exqd, int64_t *err) {
+    const int flt_stride, int *exqd, int64_t *err,
+    struct aom_internal_error_info *error_info) {
   int exq[2];
   apply_sgr(ep, dat8, width, height, dat_stride, use_highbitdepth, bit_depth,
-            pu_width, pu_height, flt0, flt1, flt_stride);
+            pu_width, pu_height, flt0, flt1, flt_stride, error_info);
   const sgr_params_type *const params = &av1_sgr_params[ep];
   get_proj_subspace(src8, width, height, src_stride, dat8, dat_stride,
                     use_highbitdepth, flt0, flt_stride, flt1, flt_stride, exq,
@@ -806,7 +810,8 @@
 static SgrprojInfo search_selfguided_restoration(
     const uint8_t *dat8, int width, int height, int dat_stride,
     const uint8_t *src8, int src_stride, int use_highbitdepth, int bit_depth,
-    int pu_width, int pu_height, int32_t *rstbuf, int enable_sgr_ep_pruning) {
+    int pu_width, int pu_height, int32_t *rstbuf, int enable_sgr_ep_pruning,
+    struct aom_internal_error_info *error_info) {
   int32_t *flt0 = rstbuf;
   int32_t *flt1 = flt0 + RESTORATION_UNITPELS_MAX;
   int ep, idx, bestep = 0;
@@ -822,7 +827,7 @@
       int64_t err;
       compute_sgrproj_err(dat8, width, height, dat_stride, src8, src_stride,
                           use_highbitdepth, bit_depth, pu_width, pu_height, ep,
-                          flt0, flt1, flt_stride, exqd, &err);
+                          flt0, flt1, flt_stride, exqd, &err, error_info);
       get_best_error(&besterr, err, exqd, bestxqd, &bestep, ep);
     }
   } else {
@@ -832,7 +837,7 @@
       int64_t err;
       compute_sgrproj_err(dat8, width, height, dat_stride, src8, src_stride,
                           use_highbitdepth, bit_depth, pu_width, pu_height, ep,
-                          flt0, flt1, flt_stride, exqd, &err);
+                          flt0, flt1, flt_stride, exqd, &err, error_info);
       get_best_error(&besterr, err, exqd, bestxqd, &bestep, ep);
     }
     // evaluate left and right ep of winner in seed ep
@@ -843,7 +848,7 @@
       int64_t err;
       compute_sgrproj_err(dat8, width, height, dat_stride, src8, src_stride,
                           use_highbitdepth, bit_depth, pu_width, pu_height, ep,
-                          flt0, flt1, flt_stride, exqd, &err);
+                          flt0, flt1, flt_stride, exqd, &err, error_info);
       get_best_error(&besterr, err, exqd, bestxqd, &bestep, ep);
     }
     // evaluate last two group
@@ -852,7 +857,7 @@
       int64_t err;
       compute_sgrproj_err(dat8, width, height, dat_stride, src8, src_stride,
                           use_highbitdepth, bit_depth, pu_width, pu_height, ep,
-                          flt0, flt1, flt_stride, exqd, &err);
+                          flt0, flt1, flt_stride, exqd, &err, error_info);
       get_best_error(&besterr, err, exqd, bestxqd, &bestep, ep);
     }
   }
@@ -881,10 +886,10 @@
   return bits;
 }
 
-static AOM_INLINE void search_sgrproj(const RestorationTileLimits *limits,
-                                      int rest_unit_idx, void *priv,
-                                      int32_t *tmpbuf,
-                                      RestorationLineBuffers *rlbs) {
+static AOM_INLINE void search_sgrproj(
+    const RestorationTileLimits *limits, int rest_unit_idx, void *priv,
+    int32_t *tmpbuf, RestorationLineBuffers *rlbs,
+    struct aom_internal_error_info *error_info) {
   (void)rlbs;
   RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
   RestUnitSearchInfo *rusi = &rsc->rusi[rest_unit_idx];
@@ -919,7 +924,7 @@
       dgd_start, limits->h_end - limits->h_start,
       limits->v_end - limits->v_start, rsc->dgd_stride, src_start,
       rsc->src_stride, highbd, bit_depth, procunit_width, procunit_height,
-      tmpbuf, rsc->lpf_sf->enable_sgr_ep_pruning);
+      tmpbuf, rsc->lpf_sf->enable_sgr_ep_pruning, error_info);
 
   RestorationUnitInfo rui;
   rui.restoration_type = RESTORE_SGRPROJ;
@@ -1578,12 +1583,13 @@
   return err;
 }
 
-static AOM_INLINE void search_wiener(const RestorationTileLimits *limits,
-                                     int rest_unit_idx, void *priv,
-                                     int32_t *tmpbuf,
-                                     RestorationLineBuffers *rlbs) {
+static AOM_INLINE void search_wiener(
+    const RestorationTileLimits *limits, int rest_unit_idx, void *priv,
+    int32_t *tmpbuf, RestorationLineBuffers *rlbs,
+    struct aom_internal_error_info *error_info) {
   (void)tmpbuf;
   (void)rlbs;
+  (void)error_info;
   RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
   RestUnitSearchInfo *rusi = &rsc->rusi[rest_unit_idx];
 
@@ -1722,13 +1728,14 @@
   if (cost_wiener < cost_none) rsc->ref_wiener = rusi->wiener;
 }
 
-static AOM_INLINE void search_norestore(const RestorationTileLimits *limits,
-                                        int rest_unit_idx, void *priv,
-                                        int32_t *tmpbuf,
-                                        RestorationLineBuffers *rlbs) {
+static AOM_INLINE void search_norestore(
+    const RestorationTileLimits *limits, int rest_unit_idx, void *priv,
+    int32_t *tmpbuf, RestorationLineBuffers *rlbs,
+    struct aom_internal_error_info *error_info) {
   (void)rest_unit_idx;
   (void)tmpbuf;
   (void)rlbs;
+  (void)error_info;
 
   RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
 
@@ -1739,13 +1746,14 @@
   rsc->total_sse[RESTORE_NONE] += rsc->sse[RESTORE_NONE];
 }
 
-static AOM_INLINE void search_switchable(const RestorationTileLimits *limits,
-                                         int rest_unit_idx, void *priv,
-                                         int32_t *tmpbuf,
-                                         RestorationLineBuffers *rlbs) {
+static AOM_INLINE void search_switchable(
+    const RestorationTileLimits *limits, int rest_unit_idx, void *priv,
+    int32_t *tmpbuf, RestorationLineBuffers *rlbs,
+    struct aom_internal_error_info *error_info) {
   (void)limits;
   (void)tmpbuf;
   (void)rlbs;
+  (void)error_info;
   RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
   RestUnitSearchInfo *rusi = &rsc->rusi[rest_unit_idx];
 
@@ -1910,7 +1918,8 @@
               for (RestorationType r = RESTORE_NONE; r < num_rtypes; r++) {
                 if (disable_lr_filter[r]) continue;
 
-                funs[r](&limits, unit_idx, rsc, rsc->cm->rst_tmpbuf, NULL);
+                funs[r](&limits, unit_idx, rsc, rsc->cm->rst_tmpbuf, NULL,
+                        cm->error);
               }
             }
           }
diff --git a/test/selfguided_filter_test.cc b/test/selfguided_filter_test.cc
index 17c8aa6..3dd513b 100644
--- a/test/selfguided_filter_test.cc
+++ b/test/selfguided_filter_test.cc
@@ -30,9 +30,9 @@
 using std::make_tuple;
 using std::tuple;
 
-typedef void (*SgrFunc)(const uint8_t *dat8, int width, int height, int stride,
-                        int eps, const int *xqd, uint8_t *dst8, int dst_stride,
-                        int32_t *tmpbuf, int bit_depth, int highbd);
+typedef int (*SgrFunc)(const uint8_t *dat8, int width, int height, int stride,
+                       int eps, const int *xqd, uint8_t *dst8, int dst_stride,
+                       int32_t *tmpbuf, int bit_depth, int highbd);
 
 // Test parameter list:
 //  <tst_fun_>
@@ -89,9 +89,10 @@
           int h = AOMMIN(pu_height, height - k);
           uint8_t *input_p = input + k * stride + j;
           uint8_t *output_p = output + k * out_stride + j;
-          av1_apply_selfguided_restoration_c(input_p, w, h, stride, eps, xqd,
-                                             output_p, out_stride, tmpbuf, 8,
-                                             0);
+          const int ret_c = av1_apply_selfguided_restoration_c(
+              input_p, w, h, stride, eps, xqd, output_p, out_stride, tmpbuf, 8,
+              0);
+          ASSERT_EQ(ret_c, 0);
         }
     }
     aom_usec_timer_mark(&ref_timer);
@@ -106,8 +107,9 @@
           int h = AOMMIN(pu_height, height - k);
           uint8_t *input_p = input + k * stride + j;
           uint8_t *output_p = output + k * out_stride + j;
-          tst_fun_(input_p, w, h, stride, eps, xqd, output_p, out_stride,
-                   tmpbuf, 8, 0);
+          const int ret_tst = tst_fun_(input_p, w, h, stride, eps, xqd,
+                                       output_p, out_stride, tmpbuf, 8, 0);
+          ASSERT_EQ(ret_tst, 0);
         }
     }
     aom_usec_timer_mark(&tst_timer);
@@ -179,11 +181,13 @@
           uint8_t *input_p = input + k * stride + j;
           uint8_t *output_p = output + k * out_stride + j;
           uint8_t *output2_p = output2 + k * out_stride + j;
-          tst_fun_(input_p, w, h, stride, eps, xqd, output_p, out_stride,
-                   tmpbuf, 8, 0);
-          av1_apply_selfguided_restoration_c(input_p, w, h, stride, eps, xqd,
-                                             output2_p, out_stride, tmpbuf, 8,
-                                             0);
+          const int ret_tst = tst_fun_(input_p, w, h, stride, eps, xqd,
+                                       output_p, out_stride, tmpbuf, 8, 0);
+          ASSERT_EQ(ret_tst, 0);
+          const int ret_c = av1_apply_selfguided_restoration_c(
+              input_p, w, h, stride, eps, xqd, output2_p, out_stride, tmpbuf, 8,
+              0);
+          ASSERT_EQ(ret_c, 0);
         }
 
       for (j = 0; j < test_h; ++j)