pvq_encoder: tune delta_rate for k=1
authorDavid Michael Barr <b@rr-dav.id.au>
Tue, 22 Nov 2016 12:49:54 +0000 (21:49 +0900)
committerDavid Michael Barr <b@rr-dav.id.au>
Thu, 8 Dec 2016 23:37:30 +0000 (13:37 -1000)
Fit to collected rate data from subset3, for k = 1.

daala-master-2016-11-16T13-02-41-114Z -> daala-delta-rate-k1-subset1

   PSNR | PSNR Cb | PSNR Cr | PSNR HVS |   SSIM | MS SSIM | CIEDE 2000
-0.1471 | -0.8594 | -0.7224 |  -0.0740 | 0.0032 |  0.0734 |    -0.3382

master-2017-11-13-4403315 -> daala-delta-rate-k1-o1f

   PSNR | PSNR Cb | PSNR Cr | PSNR HVS |    SSIM | MS SSIM | CIEDE 2000
-0.1484 | -0.6323 | -0.6271 |  -0.1811 | -0.0215 | -0.0829 |    -0.3850

Signed-off-by: David Michael Barr <b@rr-dav.id.au>
src/pvq_encoder.c

index 1440fc2..671f4e2 100644 (file)
@@ -103,6 +103,7 @@ static double pvq_search_rdo_double(const od_val16 *xcoeff, int n, int k,
   double norm_1;
   int rdo_pulses;
   double delta_rate;
+  double accel_rate;
   xx = xy = yy = 0;
   for (j = 0; j < n; j++) {
     x[j] = fabs((float)xcoeff[j]);
@@ -145,6 +146,21 @@ static double pvq_search_rdo_double(const od_val16 *xcoeff, int n, int k,
   /* Rough assumption for now, the last position costs about 3 bits more than
      the first. */
   delta_rate = 3./n;
+  accel_rate = 0.;
+  /* Quadratic fit of rate for a lone pulse.
+     Trained on subset3, like the following pseudocode:
+     rate = od_pvq_rate.where(k=1).group_by(n, pos).mean()
+     polyfit(pos, rate, deg=2, w=sqrt(exp2(-rate))) */
+  if (k == 1) {
+    if (n == 15) {
+      accel_rate = -8./n;
+      delta_rate = 4.5/n - accel_rate;
+    }
+    else if (n == 8) {
+      accel_rate = 5.7/n;
+      delta_rate = 9.3/n - accel_rate;
+    }
+  }
   /* Search one pulse at a time */
   for (; i < k - rdo_pulses; i++) {
     int pos;
@@ -191,7 +207,7 @@ static double pvq_search_rdo_double(const od_val16 *xcoeff, int n, int k,
       /*Calculate rsqrt(yy + 2*ypulse[j] + 1) using an optimized method.*/
       tmp_yy = od_custom_rsqrt_dynamic_table(rsqrt_table, rsqrt_table_size,
        yy, ypulse[j]);
-      tmp_xy = 2*tmp_xy*norm_1*tmp_yy - lambda*j*delta_rate;
+      tmp_xy = 2*tmp_xy*norm_1*tmp_yy - lambda*j*(delta_rate + j*accel_rate);
       if (j == 0 || tmp_xy > best_cost) {
         best_cost = tmp_xy;
         pos = j;