shithub: libvpx

Download patch

ref: 8487a68baf32fc86af55c39cc7fd06c3444523d5
parent: 2b307b38e3d77555c6da3a65573d781c0a991a5b
author: Paul Wilkins <paulwilkins@google.com>
date: Fri Dec 2 09:57:21 EST 2011

Further work on extended Q range.

Fixed some further QIndex related issues and replaced some tables
(eg zbin and rounding)

Also Added function (currently disabled by default) to populate the
main AC and DC quantizer tables. Using the original AC range the
resulting computed DC values give behavior broadly comparable
on the DERF set. That is not to say that the equations will hold good
over a more extended range. The purpose of this code is to make it
easier to experiment with further alterations to the Q range and distribution
of Q values plus the relative weights given to AC and DC.

The function find_fp_qindex() ensures that changes to the Q tables
are reflected in the value passed in to the first pass code.

Slight experimental adjustment to static segment Q offset.

Change-Id: I36186267d55dfc2a3d565d0cff7218ef300d1cd5

--- a/vp8/common/quant_common.c
+++ b/vp8/common/quant_common.c
@@ -37,7 +37,7 @@
     213,  217,  221,  225,  229,  234,  239,  245,  249,  254,  259,  264,  269,  274,  279,  284,
 };
 #else
-static const int dc_qlookup[QINDEX_RANGE] =
+static int dc_qlookup[QINDEX_RANGE] =
 {
       4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,
      20,   22,   24,   26,   28,   30,   32,   34,   36,   38,   40,   38,   40,   42,   44,   47,
@@ -49,7 +49,7 @@
     464,  483,  496,  507,  520,  529,  540,  551,  570,  585,  604,  624,  645,  667,  692,  718,
 
 };
-static const int ac_qlookup[QINDEX_RANGE] =
+static int ac_qlookup[QINDEX_RANGE] =
 {
     4,    5,    6,    7,    8,    9,    10,   11,   12,   13,   14,   15,   16,   17,   18,   19,
     20,   22,   24,   26,   28,   30,   32,   34,   36,   38,   40,   42,   44,   46,   48,   51,
@@ -62,6 +62,40 @@
 };
 #endif
 
+#if CONFIG_EXTEND_QRANGE
+#define ACDC_MIN 4
+void vp8_init_quant_tables()
+{
+    int i;
+    int current_val = 4;
+    int last_val = 4;
+    int ac_val;
+    int dc_max;
+
+    // Not active by default for now.
+    return;
+
+    for ( i = 0; i < QINDEX_RANGE; i++ )
+    {
+        ac_qlookup[i] = current_val;
+        current_val = (int)((double)current_val * 1.042);
+        if ( current_val == last_val )
+            current_val++;
+        last_val = current_val;
+
+        ac_val = ac_qlookup[i];
+        dc_max = (int)(((double)ac_val * 0.75) + 0.5);
+        dc_qlookup[i] = (0.000000305 * ac_val * ac_val * ac_val) +
+                        (-0.00065 * ac_val * ac_val) +
+                        (0.9 * ac_val) + 0.5;
+        if ( dc_qlookup[i] > dc_max )
+            dc_qlookup[i] = dc_max;
+        if ( dc_qlookup[i] < ACDC_MIN )
+            dc_qlookup[i] = ACDC_MIN;
+    }
+}
+#endif
+
 int vp8_dc_quant(int QIndex, int Delta)
 {
     int retval;
@@ -140,7 +174,9 @@
     if (retval < 8)
         retval = 8;
 #else
-    retval = ac_qlookup[ QIndex ];
+    retval = (ac_qlookup[ QIndex ] * 775) / 1000;
+    if (retval < 4)
+        retval = 4;
 #endif
     return retval;
 }
--- a/vp8/common/quant_common.h
+++ b/vp8/common/quant_common.h
@@ -13,6 +13,9 @@
 #include "blockd.h"
 #include "onyxc_int.h"
 
+#if CONFIG_EXTEND_QRANGE
+extern void vp8_init_quant_tables();
+#endif
 extern int vp8_ac_yquant(int QIndex);
 extern int vp8_dc_quant(int QIndex, int Delta);
 extern int vp8_dc2quant(int QIndex, int Delta);
--- a/vp8/decoder/onyxd_if.c
+++ b/vp8/decoder/onyxd_if.c
@@ -123,6 +123,9 @@
     if (!init_done)
     {
         vp8_initialize_common();
+#if CONFIG_EXTEND_QRANGE
+        vp8_init_quant_tables();
+#endif
         vp8_scale_machine_specific_config();
         init_done = 1;
     }
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -195,6 +195,8 @@
         if ( minqtarget <= vp8_convert_qindex_to_q(i) )
             return i;
     }
+    if ( i == QINDEX_RANGE )
+        return QINDEX_RANGE-1;
 }
 void init_minq_luts()
 {
@@ -251,9 +253,11 @@
         vp8_initialize_common();
         //vp8_dmachine_specific_config();
         vp8_tokenize_initialize();
+#if CONFIG_EXTEND_QRANGE
+        vp8_init_quant_tables();
+#endif
         vp8_init_me_luts();
         init_minq_luts();
-
         init_done = 1;
     }
 }
@@ -467,7 +471,7 @@
             xd->update_mb_segmentation_map = 1;
             xd->update_mb_segmentation_data = 1;
 
-            set_segdata( xd, 1, SEG_LVL_ALT_Q, -(2+(cpi->ni_av_qi >> 3)) );
+            set_segdata( xd, 1, SEG_LVL_ALT_Q, -(3+(cpi->ni_av_qi >> 3)) );
             set_segdata( xd, 1, SEG_LVL_ALT_LF, -2 );
 
             enable_segfeature(xd, 1, SEG_LVL_ALT_Q);
@@ -3281,13 +3285,31 @@
     return code_key_frame;
 
 }
-#if !CONFIG_EXTEND_QRANGE
+
+/*#if !CONFIG_EXTEND_QRANGE
 #define FIRSTPASS_QINDEX 26
 #else
 #define FIRSTPASS_QINDEX 49
-#endif
+#endif*/
 
+int find_fp_qindex()
+{
+    int i;
 
+    for ( i = 0; i < QINDEX_RANGE; i++ )
+    {
+        if ( vp8_convert_qindex_to_q(i) >= 30.0 )
+        {
+            break;
+        }
+    }
+
+    if ( i == QINDEX_RANGE )
+        i--;
+
+    return i;
+}
+
 #if !(CONFIG_REALTIME_ONLY)
 static void Pass1Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
 {
@@ -3294,7 +3316,9 @@
     (void) size;
     (void) dest;
     (void) frame_flags;
-    vp8_set_quantizer(cpi, FIRSTPASS_QINDEX);
+
+
+    vp8_set_quantizer(cpi, find_fp_qindex());
 
     scale_and_extend_source(cpi->un_scaled_source, cpi);
     vp8_first_pass(cpi);
--- a/vp8/encoder/quantize.c
+++ b/vp8/encoder/quantize.c
@@ -934,94 +934,6 @@
 }
 
 
-static const int qrounding_factors[129] =
-{
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48
-};
-
-
-static const int qzbin_factors[129] =
-{
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80
-};
-
-
-static const int qrounding_factors_y2[129] =
-{
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48, 48, 48, 48, 48, 48, 48, 48,
-    48
-};
-
-
-static const int qzbin_factors_y2[129] =
-{
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    84, 84, 84, 84, 84, 84, 84, 84,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80,
-    80
-};
-
-
 #define EXACT_QUANT
 #ifdef EXACT_QUANT
 static void invert_quant(int improved_quant, short *quant,
@@ -1054,6 +966,13 @@
 
     int zbin_boost[16] = {0, 0, 8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 44, 44};
 
+    int qrounding_factor = 48;
+#if CONFIG_EXTEND_QRANGE
+    int qzbin_factor = (vp8_dc_quant(Q,0) < 148) ? 84 : 80;
+#else
+    int qzbin_factor = (vp8_dc_quant(Q,0) < 37) ? 84: 80;
+#endif
+
     for (Q = 0; Q < QINDEX_RANGE; Q++)
     {
         // dc values
@@ -1061,8 +980,8 @@
         cpi->Y1quant_fast[Q][0] = (1 << 16) / quant_val;
         invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + 0,
                      cpi->Y1quant_shift[Q] + 0, quant_val);
-        cpi->Y1zbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
-        cpi->Y1round[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->Y1zbin[Q][0] = ((qzbin_factor * quant_val) + 64) >> 7;
+        cpi->Y1round[Q][0] = (qrounding_factor * quant_val) >> 7;
         cpi->common.Y1dequant[Q][0] = quant_val;
         cpi->zrun_zbin_boost_y1[Q][0] = (quant_val * zbin_boost[0]) >> 7;
 
@@ -1070,8 +989,8 @@
         cpi->Y2quant_fast[Q][0] = (1 << 16) / quant_val;
         invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + 0,
                      cpi->Y2quant_shift[Q] + 0, quant_val);
-        cpi->Y2zbin[Q][0] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
-        cpi->Y2round[Q][0] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+        cpi->Y2zbin[Q][0] = ((qzbin_factor * quant_val) + 64) >> 7;
+        cpi->Y2round[Q][0] = (qrounding_factor * quant_val) >> 7;
         cpi->common.Y2dequant[Q][0] = quant_val;
         cpi->zrun_zbin_boost_y2[Q][0] = (quant_val * zbin_boost[0]) >> 7;
 
@@ -1079,8 +998,8 @@
         cpi->UVquant_fast[Q][0] = (1 << 16) / quant_val;
         invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + 0,
                      cpi->UVquant_shift[Q] + 0, quant_val);
-        cpi->UVzbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;;
-        cpi->UVround[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->UVzbin[Q][0] = ((qzbin_factor * quant_val) + 64) >> 7;;
+        cpi->UVround[Q][0] = (qrounding_factor * quant_val) >> 7;
         cpi->common.UVdequant[Q][0] = quant_val;
         cpi->zrun_zbin_boost_uv[Q][0] = (quant_val * zbin_boost[0]) >> 7;
 
@@ -1093,8 +1012,8 @@
             cpi->Y1quant_fast[Q][rc] = (1 << 16) / quant_val;
             invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + rc,
                          cpi->Y1quant_shift[Q] + rc, quant_val);
-            cpi->Y1zbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
-            cpi->Y1round[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
+            cpi->Y1zbin[Q][rc] = ((qzbin_factor * quant_val) + 64) >> 7;
+            cpi->Y1round[Q][rc] = (qrounding_factor * quant_val) >> 7;
             cpi->common.Y1dequant[Q][rc] = quant_val;
             cpi->zrun_zbin_boost_y1[Q][i] = (quant_val * zbin_boost[i]) >> 7;
 
@@ -1102,8 +1021,8 @@
             cpi->Y2quant_fast[Q][rc] = (1 << 16) / quant_val;
             invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + rc,
                          cpi->Y2quant_shift[Q] + rc, quant_val);
-            cpi->Y2zbin[Q][rc] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
-            cpi->Y2round[Q][rc] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+            cpi->Y2zbin[Q][rc] = ((qzbin_factor * quant_val) + 64) >> 7;
+            cpi->Y2round[Q][rc] = (qrounding_factor * quant_val) >> 7;
             cpi->common.Y2dequant[Q][rc] = quant_val;
             cpi->zrun_zbin_boost_y2[Q][i] = (quant_val * zbin_boost[i]) >> 7;
 
@@ -1111,8 +1030,8 @@
             cpi->UVquant_fast[Q][rc] = (1 << 16) / quant_val;
             invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + rc,
                          cpi->UVquant_shift[Q] + rc, quant_val);
-            cpi->UVzbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
-            cpi->UVround[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
+            cpi->UVzbin[Q][rc] = ((qzbin_factor * quant_val) + 64) >> 7;
+            cpi->UVround[Q][rc] = (qrounding_factor * quant_val) >> 7;
             cpi->common.UVdequant[Q][rc] = quant_val;
             cpi->zrun_zbin_boost_uv[Q][i] = (quant_val * zbin_boost[i]) >> 7;
         }
@@ -1124,8 +1043,13 @@
     int i;
     int quant_val;
     int Q;
-
     int zbin_boost[16] = {0, 0, 8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 44, 44};
+    int qrounding_factor = 48;
+#if CONFIG_EXTEND_QRANGE
+    int qzbin_factor = vp8_dc_quant(Q,0) < 148 ) ? 84: 80;
+#else
+    int qzbin_factor = vp8_dc_quant(Q,0) < 37 ) ? 84: 80;
+#endif
 
     for (Q = 0; Q < QINDEX_RANGE; Q++)
     {
@@ -1132,22 +1056,22 @@
         // dc values
         quant_val = vp8_dc_quant(Q, cpi->common.y1dc_delta_q);
         cpi->Y1quant[Q][0] = (1 << 16) / quant_val;
-        cpi->Y1zbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
-        cpi->Y1round[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->Y1zbin[Q][0] = ((qzbin_factors * quant_val) + 64) >> 7;
+        cpi->Y1round[Q][0] = (qrounding_factor * quant_val) >> 7;
         cpi->common.Y1dequant[Q][0] = quant_val;
         cpi->zrun_zbin_boost_y1[Q][0] = (quant_val * zbin_boost[0]) >> 7;
 
         quant_val = vp8_dc2quant(Q, cpi->common.y2dc_delta_q);
         cpi->Y2quant[Q][0] = (1 << 16) / quant_val;
-        cpi->Y2zbin[Q][0] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
-        cpi->Y2round[Q][0] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+        cpi->Y2zbin[Q][0] = ((qzbin_factors * quant_val) + 64) >> 7;
+        cpi->Y2round[Q][0] = (qrounding_factor * quant_val) >> 7;
         cpi->common.Y2dequant[Q][0] = quant_val;
         cpi->zrun_zbin_boost_y2[Q][0] = (quant_val * zbin_boost[0]) >> 7;
 
         quant_val = vp8_dc_uv_quant(Q, cpi->common.uvdc_delta_q);
         cpi->UVquant[Q][0] = (1 << 16) / quant_val;
-        cpi->UVzbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;;
-        cpi->UVround[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->UVzbin[Q][0] = ((qzbin_factors * quant_val) + 64) >> 7;;
+        cpi->UVround[Q][0] = (qrounding_factor * quant_val) >> 7;
         cpi->common.UVdequant[Q][0] = quant_val;
         cpi->zrun_zbin_boost_uv[Q][0] = (quant_val * zbin_boost[0]) >> 7;
 
@@ -1158,22 +1082,22 @@
 
             quant_val = vp8_ac_yquant(Q);
             cpi->Y1quant[Q][rc] = (1 << 16) / quant_val;
-            cpi->Y1zbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
-            cpi->Y1round[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
+            cpi->Y1zbin[Q][rc] = ((qzbin_factors * quant_val) + 64) >> 7;
+            cpi->Y1round[Q][rc] = (qrounding_factor * quant_val) >> 7;
             cpi->common.Y1dequant[Q][rc] = quant_val;
             cpi->zrun_zbin_boost_y1[Q][i] = (quant_val * zbin_boost[i]) >> 7;
 
             quant_val = vp8_ac2quant(Q, cpi->common.y2ac_delta_q);
             cpi->Y2quant[Q][rc] = (1 << 16) / quant_val;
-            cpi->Y2zbin[Q][rc] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
-            cpi->Y2round[Q][rc] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+            cpi->Y2zbin[Q][rc] = ((qzbin_factors * quant_val) + 64) >> 7;
+            cpi->Y2round[Q][rc] = (qrounding_factors * quant_val) >> 7;
             cpi->common.Y2dequant[Q][rc] = quant_val;
             cpi->zrun_zbin_boost_y2[Q][i] = (quant_val * zbin_boost[i]) >> 7;
 
             quant_val = vp8_ac_uv_quant(Q, cpi->common.uvac_delta_q);
             cpi->UVquant[Q][rc] = (1 << 16) / quant_val;
-            cpi->UVzbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
-            cpi->UVround[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
+            cpi->UVzbin[Q][rc] = ((qzbin_factors * quant_val) + 64) >> 7;
+            cpi->UVround[Q][rc] = (qrounding_factors * quant_val) >> 7;
             cpi->common.UVdequant[Q][rc] = quant_val;
             cpi->zrun_zbin_boost_uv[Q][i] = (quant_val * zbin_boost[i]) >> 7;
         }
--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -236,28 +236,23 @@
                 (cpi->RDMULT * rd_iifactor[cpi->twopass.next_iiratio]) >> 4;
     }
 
-#if !CONFIG_EXTEND_QRANGE
-#else
     if (cpi->RDMULT < 7)
         cpi->RDMULT = 7;
-#endif
+
     cpi->mb.errorperbit = (cpi->RDMULT / 110);
     cpi->mb.errorperbit += (cpi->mb.errorperbit==0);
 
-#if CONFIG_EXTEND_QRANGE
-    if(cpi->mb.errorperbit<1)
-        cpi->mb.errorperbit=1;
-#endif
     vp8_set_speed_features(cpi);
 
-    q = (int)pow(vp8_dc_quant(QIndex,0), 1.25);
-
-    if (q < 8)
-        q = 8;
-
 #if CONFIG_EXTEND_QRANGE
+    q = (int)pow(vp8_dc_quant(QIndex,0)>>2, 1.25);
+    q = q << 2;
     cpi->RDMULT *= 16;
+#else
+    q = (int)pow(vp8_dc_quant(QIndex,0), 1.25);
 #endif
+    if (q < 8)
+        q = 8;
 
     if (cpi->RDMULT > 1000)
     {