shithub: libvpx

Download patch

ref: e93f2fdb836f28da36cbe406417b2265279b5813
parent: b24373fec224e1436ab658dda08442c9c85143d6
parent: 2ca24b0075df0623fe44e07ea000e182a1317d33
author: James Bankoski <jimbankoski@google.com>
date: Wed Jul 13 11:31:17 EDT 2016

Merge "postproc - move filling of noise buffer to vpx_dsp."

--- a/test/add_noise_test.cc
+++ b/test/add_noise_test.cc
@@ -13,6 +13,7 @@
 #include "third_party/googletest/src/include/gtest/gtest.h"
 #include "./vpx_dsp_rtcd.h"
 #include "vpx/vpx_integer.h"
+#include "vpx_dsp/postproc.h"
 #include "vpx_mem/vpx_mem.h"
 
 namespace {
@@ -40,50 +41,6 @@
   return sqrt(v);
 }
 
-// TODO(jimbankoski): The following 2 functions are duplicated in each codec.
-// For now the vp9 one has been copied into the test as is. We should normalize
-// these in vpx_dsp and not have 3 copies of these unless there is different
-// noise we add for each codec.
-
-double gaussian(double sigma, double mu, double x) {
-  return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
-         (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
-}
-
-int setup_noise(int size_noise, char *noise) {
-  char char_dist[300];
-  const int ai = 4;
-  const int qi = 24;
-  const double sigma = ai + .5 + .6 * (63 - qi) / 63.0;
-
-  /* set up a lookup table of 256 entries that matches
-   * a gaussian distribution with sigma determined by q.
-   */
-  int next = 0;
-
-  for (int i = -32; i < 32; i++) {
-    int a_i = (int) (0.5 + 256 * gaussian(sigma, 0, i));
-
-    if (a_i) {
-      for (int j = 0; j < a_i; j++) {
-        char_dist[next + j] = (char)(i);
-      }
-
-      next = next + a_i;
-    }
-  }
-
-  for (; next < 256; next++)
-    char_dist[next] = 0;
-
-  for (int i = 0; i < size_noise; i++) {
-    noise[i] = char_dist[rand() & 0xff];  // NOLINT
-  }
-
-  // Returns the most negative value in distribution.
-  return char_dist[0];
-}
-
 TEST_P(AddNoiseTest, CheckNoiseAdded) {
   DECLARE_ALIGNED(16, char, blackclamp[16]);
   DECLARE_ALIGNED(16, char, whiteclamp[16]);
@@ -92,12 +49,12 @@
   const int height = 64;
   const int image_size = width * height;
   char noise[3072];
+  const int clamp = vpx_setup_noise(sizeof(noise), 4.4, noise);
 
-  const int clamp = setup_noise(3072, noise);
   for (int i = 0; i < 16; i++) {
-    blackclamp[i] = -clamp;
-    whiteclamp[i] = -clamp;
-    bothclamp[i] = -2 * clamp;
+    blackclamp[i] = clamp;
+    whiteclamp[i] = clamp;
+    bothclamp[i] = 2 * clamp;
   }
 
   uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
@@ -127,7 +84,7 @@
 
   // Check to make sure don't roll over.
   for (int i = 0; i < image_size; ++i) {
-    EXPECT_GT((int)s[i], 10) << "i = " << i;
+    EXPECT_GT((int)s[i], clamp) << "i = " << i;
   }
 
   // Initialize pixels in the image to 0 and check for roll under.
@@ -138,7 +95,7 @@
 
   // Check to make sure don't roll under.
   for (int i = 0; i < image_size; ++i) {
-    EXPECT_LT((int)s[i], 245) << "i = " << i;
+    EXPECT_LT((int)s[i], 255 - clamp) << "i = " << i;
   }
 
   vpx_free(s);
@@ -153,11 +110,12 @@
   const int image_size = width * height;
   char noise[3072];
 
-  const int clamp = setup_noise(3072, noise);
+  const int clamp = vpx_setup_noise(sizeof(noise), 4.4, noise);
+
   for (int i = 0; i < 16; i++) {
-    blackclamp[i] = -clamp;
-    whiteclamp[i] = -clamp;
-    bothclamp[i] = -2 * clamp;
+    blackclamp[i] = clamp;
+    whiteclamp[i] = clamp;
+    bothclamp[i] = 2 * clamp;
   }
 
   uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
--- a/vp8/common/postproc.c
+++ b/vp8/common/postproc.c
@@ -12,6 +12,7 @@
 #include "vpx_config.h"
 #include "vpx_dsp_rtcd.h"
 #include "vp8_rtcd.h"
+#include "vpx_dsp/postproc.h"
 #include "vpx_scale_rtcd.h"
 #include "vpx_scale/yv12config.h"
 #include "postproc.h"
@@ -202,69 +203,6 @@
     }
 }
 
-static double gaussian(double sigma, double mu, double x)
-{
-    return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
-           (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
-}
-
-static void fillrd(struct postproc_state *state, int q, int a)
-{
-    char char_dist[300];
-
-    double sigma;
-    int i;
-
-    vp8_clear_system_state();
-
-
-    sigma = a + .5 + .6 * (63 - q) / 63.0;
-
-    /* set up a lookup table of 256 entries that matches
-     * a gaussian distribution with sigma determined by q.
-     */
-    {
-        int next, j;
-
-        next = 0;
-
-        for (i = -32; i < 32; i++)
-        {
-            const int v = (int)(.5 + 256 * gaussian(sigma, 0, i));
-
-            if (v)
-            {
-                for (j = 0; j < v; j++)
-                {
-                    char_dist[next+j] = (char) i;
-                }
-
-                next = next + j;
-            }
-
-        }
-
-        for (; next < 256; next++)
-            char_dist[next] = 0;
-
-    }
-
-    for (i = 0; i < 3072; i++)
-    {
-        state->noise[i] = char_dist[rand() & 0xff];
-    }
-
-    for (i = 0; i < 16; i++)
-    {
-        state->blackclamp[i] = -char_dist[0];
-        state->whiteclamp[i] = -char_dist[0];
-        state->bothclamp[i] = -2 * char_dist[0];
-    }
-
-    state->last_q = q;
-    state->last_noise = a;
-}
-
 /* Blend the macro block with a solid colored square.  Leave the
  * edges unblended to give distinction to macro blocks in areas
  * filled with the same color block.
@@ -552,7 +490,22 @@
         if (oci->postproc_state.last_q != q
             || oci->postproc_state.last_noise != noise_level)
         {
-            fillrd(&oci->postproc_state, 63 - q, noise_level);
+            double sigma;
+            int clamp, i;
+            struct postproc_state *ppstate = &oci->postproc_state;
+            vp8_clear_system_state();
+            sigma = noise_level + .5 + .6 * q / 63.0;
+            clamp = vpx_setup_noise(sizeof(ppstate->noise), sigma,
+                                    ppstate->noise);
+            for (i = 0; i < 16; i++)
+            {
+                ppstate->blackclamp[i] = clamp;
+                ppstate->whiteclamp[i] = clamp;
+                ppstate->bothclamp[i] = 2 * clamp;
+            }
+
+            ppstate->last_q = q;
+            ppstate->last_noise = noise_level;
         }
 
         vpx_plane_add_noise
--- a/vp9/common/vp9_postproc.c
+++ b/vp9/common/vp9_postproc.c
@@ -18,6 +18,7 @@
 #include "./vp9_rtcd.h"
 
 #include "vpx_dsp/vpx_dsp_common.h"
+#include "vpx_dsp/postproc.h"
 #include "vpx_ports/mem.h"
 #include "vpx_ports/system_state.h"
 #include "vpx_scale/vpx_scale.h"
@@ -294,59 +295,6 @@
   vp9_deblock(src, dst, q, limits);
 }
 
-static double gaussian(double sigma, double mu, double x) {
-  return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
-         (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
-}
-
-static void fillrd(struct postproc_state *state, int q, int a) {
-  char char_dist[300];
-
-  double sigma;
-  int ai = a, qi = q, i;
-
-  vpx_clear_system_state();
-
-  sigma = ai + .5 + .6 * (63 - qi) / 63.0;
-
-  /* set up a lookup table of 256 entries that matches
-   * a gaussian distribution with sigma determined by q.
-   */
-  {
-    int next, j;
-
-    next = 0;
-
-    for (i = -32; i < 32; i++) {
-      int a_i = (int)(0.5 + 256 * gaussian(sigma, 0, i));
-
-      if (a_i) {
-        for (j = 0; j < a_i; j++) {
-          char_dist[next + j] = (char) i;
-        }
-
-        next = next + j;
-      }
-    }
-
-    for (; next < 256; next++)
-      char_dist[next] = 0;
-  }
-
-  for (i = 0; i < 3072; i++) {
-    state->noise[i] = char_dist[rand() & 0xff];  // NOLINT
-  }
-
-  for (i = 0; i < 16; i++) {
-    state->blackclamp[i] = -char_dist[0];
-    state->whiteclamp[i] = -char_dist[0];
-    state->bothclamp[i] = -2 * char_dist[0];
-  }
-
-  state->last_q = q;
-  state->last_noise = a;
-}
-
 static void swap_mi_and_prev_mi(VP9_COMMON *cm) {
   // Current mip will be the prev_mip for the next frame.
   MODE_INFO *temp = cm->postproc_state.prev_mip;
@@ -469,7 +417,20 @@
     const int noise_level = ppflags->noise_level;
     if (ppstate->last_q != q ||
         ppstate->last_noise != noise_level) {
-      fillrd(ppstate, 63 - q, noise_level);
+      double sigma;
+      int clamp, i;
+      vpx_clear_system_state();
+      sigma = noise_level + .5 + .6 * q / 63.0;
+      clamp = vpx_setup_noise(sizeof(ppstate->noise), sigma,
+                              ppstate->noise);
+
+      for (i = 0; i < 16; i++) {
+        ppstate->blackclamp[i] = clamp;
+        ppstate->whiteclamp[i] = clamp;
+        ppstate->bothclamp[i] = 2 * clamp;
+      }
+      ppstate->last_q = q;
+      ppstate->last_noise = noise_level;
     }
     vpx_plane_add_noise(ppbuf->y_buffer, ppstate->noise, ppstate->blackclamp,
                         ppstate->whiteclamp, ppstate->bothclamp,
--- a/vpx_dsp/add_noise.c
+++ b/vpx_dsp/add_noise.c
@@ -8,6 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <math.h>
 #include <stdlib.h>
 
 #include "./vpx_config.h"
@@ -37,4 +38,38 @@
       pos[j] = v + ref[j];
     }
   }
+}
+
+static double gaussian(double sigma, double mu, double x) {
+  return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
+         (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
+}
+
+int vpx_setup_noise(int size, double sigma, char *noise) {
+  char char_dist[256];
+  int next, i, j;
+
+  next = 0;
+
+  // set up a 256 entry lookup that matches gaussian distribution
+  for (i = -32; i < 32; i++) {
+    int a_i = (int) (0.5 + 256 * gaussian(sigma, 0, i));
+    if (a_i) {
+      for (j = 0; j < a_i; j++) {
+        char_dist[next + j] = (char) (i);
+      }
+      next = next + j;
+    }
+  }
+
+  // Rounding error - might mean we have less than 256.
+  for (; next < 256; next++)
+    char_dist[next] = 0;
+
+  for (i = 0; i < size; i++) {
+    noise[i] = char_dist[rand() & 0xff];  // NOLINT
+  }
+
+  // Returns the highest non 0 value used in distribution.
+  return -char_dist[0];
 }
--- /dev/null
+++ b/vpx_dsp/postproc.h
@@ -1,0 +1,24 @@
+/*
+ *  Copyright (c) 2016 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VPX_DSP_POSTPROC_H_
+#define VPX_DSP_POSTPROC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int vpx_setup_noise(int size, double sigma, char *noise);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // VPX_DSP_POSTPROC_H_
--- a/vpx_dsp/vpx_dsp.mk
+++ b/vpx_dsp/vpx_dsp.mk
@@ -53,6 +53,7 @@
 ifneq ($(filter yes,$(CONFIG_POSTPROC) $(CONFIG_VP9_POSTPROC)),)
 DSP_SRCS-yes += add_noise.c
 DSP_SRCS-yes += deblock.c
+DSP_SRCS-yes += postproc.h
 DSP_SRCS-$(HAVE_MSA) += mips/add_noise_msa.c
 DSP_SRCS-$(HAVE_MSA) += mips/deblock_msa.c
 DSP_SRCS-$(HAVE_SSE2) += x86/add_noise_sse2.asm