]> granicus.if.org Git - libvpx/commitdiff
Use YUV components to build the temporal filter
authorJingning Han <jingning@google.com>
Sat, 11 Aug 2018 00:01:08 +0000 (17:01 -0700)
committerJingning Han <jingning@google.com>
Thu, 16 Aug 2018 21:47:31 +0000 (14:47 -0700)
Use both luma and chroma components simultaneously to estimate the
non-local mean kernel and build the temporal filter. It improves
the compression performance primarily for chroma components. Tested
in speed 0 and vbr mode, the coding gains are:

          Overall PSNR   SSIM     PSNR_U      PSNR_V
low        -0.10%       -0.12%    -0.48%      -0.49%
mid        -0.13%       -0.16%    -0.58%      -0.88%
720p       -0.31%       -0.24%    -0.75%      -0.72%
hd         -0.09%       -0.10%    -0.59%      -0.79%
nefl2k     -0.30%       -0.13%    -0.53%      -0.50%

Change-Id: I24d39997818322b0d69bd9dbeda02c60cd2b2e1b

vp9/encoder/vp9_temporal_filter.c

index c0ecbb7b145d1b9a7dcf8a985f9886ea9e3ddf39..4b28af15ca41ca6c0d3dee89e1c134b96718c17d 100644 (file)
@@ -136,6 +136,11 @@ static void apply_temporal_filter(
       int diff_sse[9] = { 0 };
       int idx, idy, index = 0;
 
+      const int uv_r = i >> ss_y;
+      const int uv_c = j >> ss_x;
+
+      int diff;
+
       for (idy = -1; idy <= 1; ++idy) {
         for (idx = -1; idx <= 1; ++idx) {
           const int row = (int)i + idy;
@@ -156,6 +161,16 @@ static void apply_temporal_filter(
       modifier = 0;
       for (idx = 0; idx < 9; ++idx) modifier += diff_sse[idx];
 
+      diff = u_frame1[uv_r * uv_stride + uv_c] -
+             u_pred[uv_r * uv_buf_stride + uv_c];
+      modifier += diff * diff;
+
+      diff = v_frame1[uv_r * uv_stride + uv_c] -
+             v_pred[uv_r * uv_buf_stride + uv_c];
+      modifier += diff * diff;
+
+      index += 2;
+
       modifier = mod_index(modifier, index, rounding, strength, filter_weight);
 
       y_count[k] += modifier;
@@ -165,9 +180,6 @@ static void apply_temporal_filter(
 
       // Process chroma component
       if (!(i & ss_y) && !(j & ss_x)) {
-        const int uv_r = i >> ss_y;
-        const int uv_c = j >> ss_x;
-
         const int u_pixel_value = u_pred[uv_r * uv_buf_stride + uv_c];
         const int v_pixel_value = v_pred[uv_r * uv_buf_stride + uv_c];
 
@@ -176,6 +188,7 @@ static void apply_temporal_filter(
         int v_diff_sse[9] = { 0 };
         int idx, idy, index = 0;
         int u_mod = 0, v_mod = 0;
+        int y_diff = 0;
 
         for (idy = -1; idy <= 1; ++idy) {
           for (idx = -1; idx <= 1; ++idx) {
@@ -204,6 +217,20 @@ static void apply_temporal_filter(
           v_mod += v_diff_sse[idx];
         }
 
+        for (idy = 0; idy < 1 + ss_y; ++idy) {
+          for (idx = 0; idx < 1 + ss_x; ++idx) {
+            const int row = (uv_r << ss_y) + idy;
+            const int col = (uv_c << ss_x) + idx;
+            const int diff = y_frame1[row * (int)y_stride + col] -
+                             y_pred[row * (int)block_width + col];
+            y_diff += diff * diff;
+            ++index;
+          }
+        }
+
+        u_mod += y_diff;
+        v_mod += y_diff;
+
         u_mod = mod_index(u_mod, index, rounding, strength, filter_weight);
         v_mod = mod_index(v_mod, index, rounding, strength, filter_weight);
 
@@ -517,6 +544,13 @@ void vp9_temporal_filter_iterate_row_c(VP9_COMP *cpi, ThreadData *td,
         // score is lower. If not applying MC default behavior
         // is to weight all MBs equal.
         filter_weight = err < thresh_low ? 2 : err < thresh_high ? 1 : 0;
+
+        switch (abs(frame - alt_ref_index)) {
+          case 1: filter_weight = VPXMIN(filter_weight, 2); break;
+          case 2:
+          case 3: filter_weight = VPXMIN(filter_weight, 1); break;
+          default: break;
+        }
       }
 
       if (filter_weight != 0) {