pvq: use int beta in od_pow
authorTristan Matthews <tmatth@videolan.org>
Fri, 19 Aug 2016 17:30:53 +0000 (10:30 -0700)
committerTristan Matthews <tmatth@videolan.org>
Tue, 23 Aug 2016 20:22:45 +0000 (16:22 -0400)
Note that the gains on objective1-fast are on wikipedia_420.y4m, which
regressed on 8b42d91e983cb3742bb7e4794f374385adfc3820.

objective1-fast:
PSNR YCbCr:     -0.22%     -0.18%     -0.63%
   PSNRHVS:     -0.20%
      SSIM:     -0.22%
    MSSSIM:     -0.22%
 CIEDE2000:     -0.20%

subset1:
PSNR YCbCr:      0.00%      0.01%     -0.00%
   PSNRHVS:     -0.00%
      SSIM:      0.01%
    MSSSIM:      0.01%
 CIEDE2000:      0.00%

src/pvq.c
src/pvq.h

index 10b58d9..4a74ed3 100644 (file)
--- a/src/pvq.c
+++ b/src/pvq.c
@@ -638,13 +638,12 @@ static int16_t od_log2(int16_t x)
    + OD_MULT16_16_Q15(x, 1515)))))))));
 }
 
-static int32_t od_pow(int32_t x, double beta)
+static int32_t od_pow(int32_t x, od_val16 beta)
 {
   int16_t t;
   int xshift;
   int log2_x;
-  /*FIXME: this is double for now due to multiplication by 1/beta.*/
-  double logr;
+  od_val32 logr;
   /*FIXME: this conditional is to avoid doing log2(0).*/
   if (x == 0)
     return 0;
@@ -655,8 +654,8 @@ static int32_t od_pow(int32_t x, double beta)
   /*log2(g/OD_COMPAND_SCALE) = log2(x) - OD_COMPAND_SHIFT in
      Q(OD_LOG2_OUTSHIFT).*/
   logr = od_log2(t) + (log2_x - OD_COMPAND_SHIFT)*OD_LOG2_OUTSCALE;
-  logr = beta*logr;
-  return od_exp2(OD_ROUND32(logr));
+  logr = OD_MULT16_32_QBETA(beta, logr);
+  return od_exp2(logr);
 }
 #endif
 
@@ -678,7 +677,8 @@ static od_val32 od_gain_compand(od_val32 g, int q0, od_val16 beta) {
   if (beta == OD_BETA(1)) return (OD_CGAIN_SCALE*g + (q0 >> 1))/q0;
   else {
     int32_t expr;
-    expr = od_pow(g, 1./(beta*OD_BETA_SCALE_1));
+    /*FIXME: This is 1/beta in Q(BETA_SHIFT), should use od_rcp() instead.*/
+    expr = od_pow(g, OD_ROUND16((1 << (2*OD_BETA_SHIFT))/(double)beta));
     expr <<= OD_CGAIN_SHIFT + OD_COMPAND_SHIFT - OD_EXP2_OUTSHIFT;
     return (expr + (q0 >> 1))/q0;
   }
@@ -766,7 +766,7 @@ od_val32 od_gain_expand(od_val32 cg0, int q0, od_val16 beta) {
     int32_t expr;
     int32_t cg;
     cg = OD_SHR_ROUND(cg0*q0, OD_CGAIN_SHIFT);
-    expr = od_pow(cg, beta*OD_BETA_SCALE_1);
+    expr = od_pow(cg, beta);
     /*Expanded gain must be in Q(OD_COMPAND_SHIFT), hence the subtraction by
        OD_COMPAND_SHIFT.*/
     return OD_SHR_ROUND(expr, OD_EXP2_OUTSHIFT - OD_COMPAND_SHIFT);
index 61aad01..805abca 100644 (file)
--- a/src/pvq.h
+++ b/src/pvq.h
@@ -80,6 +80,9 @@ extern const uint16_t LAPLACE_OFFSET[];
 #define OD_TRIG_SCALE (32768)
 #define OD_BETA_SHIFT (12)
 #define OD_BETA_SCALE_1 (1./(1 << OD_BETA_SHIFT))
+/*Multiplies 16-bit a by 32-bit b and keeps bits [16:64-OD_BETA_SHIFT-1].*/
+#define OD_MULT16_32_QBETA(a, b) \
+ ((int16_t)(a)*(int64_t)(int32_t)(b) >> OD_BETA_SHIFT)
 #define OD_CGAIN_SHIFT (8)
 #define OD_CGAIN_SCALE (1 << OD_CGAIN_SHIFT)
 #else