shithub: libvpx

Download patch

ref: 5b42ae09aeecedfdff1dae9d59be9fbb2aba3392
parent: ae4db164e5ece4ffdf8d2f460940244763e5052d
author: Yaowu Xu <yaowu@google.com>
date: Wed Dec 1 10:50:14 EST 2010

experiment extending the quantizer range

Prior to this change, VP8 min quantizer is 4, which caps the
highest quality around 51DB. This experimental change extends
the min quantizer to 1, removes the cap and allows the highest
quality to be around ~73DB, consistent with the fdct/idct round trip
error. To test this change, at configure time use options:

--enable-experimental --enable-extend_qrange

The following is a brief log of changes in each of the patch sets

patch set 1:
In this commit, the quantization/dequantization constants are kept
unchanged, instead scaling factor 4 is rolled into fdct/idct.
Fixed Q0 encoding tests on mobile:
  Before:    9560.567kbps Overall PSNR:50.255DB VPXSSIM:98.288
  Now:   18035.774kbps Overall PSNR:73.022DB VPXSSIM:99.991

patch set 2:
regenerated dc/ac quantizer lookup tables based on the scaling
factor rolled in the fdct/idct. Also slightly extended the range
towards the high quantizer end.

patch set 3:
slightly tweaked the quantizer tables and generated bits_per_mb
table based on Paul's suggestions.

patch set 4:
fix a typo in idct, re-calculated tables relating active max Q
to active min Q

patch set 5:
added rdmult lookup table based on Q

patch set 6:
fix rdmult scale: dct coefficient has scaled up by 4

patch set 7:
make transform coefficients to be within 16bits

patch set 8:
normalize 2nd order quantizers

patch set 9:
fix mis-spellings

patch set 10:
change the configure script and macros to allow experimental code
to be enabled at configure time with --enable-extend_qrange

patch set 11:
rebase for merge

Change-Id: Ib50641ddd44aba2a52ed890222c309faa31cc59c

--- a/configure
+++ b/configure
@@ -214,6 +214,7 @@
     sys_mman_h
 "
 EXPERIMENT_LIST="
+    extend_qrange
 "
 CONFIG_LIST="
     external_build
--- a/vp8/common/generic/systemdependent.c
+++ b/vp8/common/generic/systemdependent.c
@@ -83,8 +83,18 @@
     vp8_arch_x86_common_init(ctx);
 #endif
 
+
 #if ARCH_ARM
     vp8_arch_arm_common_init(ctx);
 #endif
+#if CONFIG_EXTEND_QRANGE
+    rtcd->idct.idct1        = vp8_short_idct4x4llm_1_c;
+    rtcd->idct.idct16       = vp8_short_idct4x4llm_c;
+    rtcd->idct.idct1_scalar_add = vp8_dc_only_idct_add_c;
+    rtcd->idct.iwalsh1      = vp8_short_inv_walsh4x4_1_c;
+    rtcd->idct.iwalsh16     = vp8_short_inv_walsh4x4_c;
+
+#endif
+
 
 }
--- a/vp8/common/idctllm.c
+++ b/vp8/common/idctllm.c
@@ -22,6 +22,8 @@
  * so
  *         x * sqrt(2) * cos (pi/8) = x + x * (sqrt(2) *cos(pi/8)-1).
  **************************************************************************/
+#include "vpx_ports/config.h"
+
 static const int cospi8sqrt2minus1 = 20091;
 static const int sinpi8sqrt2      = 35468;
 static const int rounding = 0;
@@ -75,12 +77,20 @@
         d1 = temp1 + temp2;
 
 
+#if !CONFIG_EXTEND_QRANGE
         op[0] = (a1 + d1 + 4) >> 3;
         op[3] = (a1 - d1 + 4) >> 3;
 
         op[1] = (b1 + c1 + 4) >> 3;
         op[2] = (b1 - c1 + 4) >> 3;
+#else
+        op[0] = (a1 + d1 + 16) >> 5;
+        op[3] = (a1 - d1 + 16) >> 5;
 
+        op[1] = (b1 + c1 + 16) >> 5;
+        op[2] = (b1 - c1 + 16) >> 5;
+#endif
+
         ip += shortpitch;
         op += shortpitch;
     }
@@ -92,8 +102,11 @@
     int a1;
     short *op = output;
     int shortpitch = pitch >> 1;
+#if !CONFIG_EXTEND_QRANGE
     a1 = ((input[0] + 4) >> 3);
-
+#else
+    a1 = ((input[0] + 16) >> 5);
+#endif
     for (i = 0; i < 4; i++)
     {
         op[0] = a1;
@@ -106,7 +119,11 @@
 
 void vp8_dc_only_idct_add_c(short input_dc, unsigned char *pred_ptr, unsigned char *dst_ptr, int pitch, int stride)
 {
+#if !CONFIG_EXTEND_QRANGE
     int a1 = ((input_dc + 4) >> 3);
+#else
+    int a1 = ((input_dc + 16) >> 5);
+#endif
     int r, c;
 
     for (r = 0; r < 4; r++)
@@ -168,11 +185,17 @@
         c2 = a1 - b1;
         d2 = d1 - c1;
 
+#if !CONFIG_EXTEND_QRANGE
         op[0] = (a2 + 3) >> 3;
         op[1] = (b2 + 3) >> 3;
         op[2] = (c2 + 3) >> 3;
         op[3] = (d2 + 3) >> 3;
-
+#else
+        op[0] = (a2 + 1) >> 2;
+        op[1] = (b2 + 1) >> 2;
+        op[2] = (c2 + 1) >> 2;
+        op[3] = (d2 + 1) >> 2;
+#endif
         ip += 4;
         op += 4;
     }
@@ -184,7 +207,11 @@
     int a1;
     short *op = output;
 
-    a1 = ((input[0] + 3) >> 3);
+#if !CONFIG_EXTEND_QRANGE
+    a1 = (input[0] + 3 )>> 3;
+#else
+    a1 = (input[0] + 1 )>> 2;
+#endif
 
     for (i = 0; i < 4; i++)
     {
--- a/vp8/common/quant_common.c
+++ b/vp8/common/quant_common.c
@@ -11,6 +11,8 @@
 
 #include "quant_common.h"
 
+
+#if !CONFIG_EXTEND_QRANGE
 static const int dc_qlookup[QINDEX_RANGE] =
 {
     4,    5,    6,    7,    8,    9,   10,   10,   11,   12,   13,   14,   15,   16,   17,   17,
@@ -34,8 +36,33 @@
     155,  158,  161,  164,  167,  170,  173,  177,  181,  185,  189,  193,  197,  201,  205,  209,
     213,  217,  221,  225,  229,  234,  239,  245,  249,  254,  259,  264,  269,  274,  279,  284,
 };
+#else
 
+static const int dc_qlookup[QINDEX_RANGE] =
+{
+    4,    5,    6,    7,    8,    9,    10,   11,   12,   13,   14,   15,   16,   17,   18,   19,
+    20,   21,   22,   23,   24,   25,   26,   27,   28,   30,   32,   34,   36,   38,   40,   42,
+    44,   46,   49,   52,   55,   58,   61,   64,   67,   70,   73,   76,   79,   82,   85,   88,
+    92,    96,  100,  104,  108,  112,  116,  120,  124,  128,  132,  136,  140,  144,  148,  152,
+    156,  160,  164,  168,  172,  176,  180,  184,  188,  192,  196,  200,  205,  210,  215,  220,
+    225,  230,  235,  240,  245,  250,  255,  260,  265,  270,  275,  280,  285,  290,  295,  300,
+    310,  320,  330,  340,  350,  360,  370,  380,  390,  400,  410,  420,  430,  440,  450,  460,
+    472,  484,  496,  508,  520,  532,  544,  556,  572,  588,  608,  628,  648,  668,  692,  720,
+};
 
+static const 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,
+    54,   57,   60,   63,   66,   69,   72,   76,   80,   84,   88,   92,   96,   100,  105,  110,
+    115,  120,  125,  130,  135,  140,  146,  152,  158,  164,  170,  176,  182,  188,  194,  200,
+    206,  212,  218,  224,  232,  240,  248,  256,  264,  272,  280,  288,  296,  304,  312,  320,
+    330,  340,  350,  360,  370,  380,  392,  404,  416,  428,  440,  454,  468,  482,  496,  510,
+    524,  540,  556,  572,  588,  604,  622,  640,  658,  676,  696,  716,  736,  756,  776,  796,
+    820,  844,  868,  892,  916,  944,  972,  1000, 1032, 1064, 1096, 1128, 1168, 1208, 1252, 1300
+};
+#endif
+
 int vp8_dc_quant(int QIndex, int Delta)
 {
     int retval;
@@ -62,7 +89,11 @@
     else if (QIndex < 0)
         QIndex = 0;
 
+#if !CONFIG_EXTEND_QRANGE
     retval = dc_qlookup[ QIndex ] * 2;
+#else
+    retval = dc_qlookup[ QIndex ];
+#endif
     return retval;
 
 }
@@ -72,16 +103,13 @@
 
     QIndex = QIndex + Delta;
 
-    if (QIndex > 127)
-        QIndex = 127;
+    if (QIndex > 117)
+        QIndex = 117;
     else if (QIndex < 0)
         QIndex = 0;
 
     retval = dc_qlookup[ QIndex ];
 
-    if (retval > 132)
-        retval = 132;
-
     return retval;
 }
 
@@ -108,12 +136,13 @@
         QIndex = 127;
     else if (QIndex < 0)
         QIndex = 0;
-
+#if !CONFIG_EXTEND_QRANGE
     retval = (ac_qlookup[ QIndex ] * 155) / 100;
-
     if (retval < 8)
         retval = 8;
-
+#else
+    retval = ac_qlookup[ QIndex ];
+#endif
     return retval;
 }
 int vp8_ac_uv_quant(int QIndex, int Delta)
--- a/vp8/decoder/generic/dsystemdependent.c
+++ b/vp8/decoder/generic/dsystemdependent.c
@@ -39,7 +39,16 @@
     vp8_arch_x86_decode_init(pbi);
 #endif
 
+
 #if ARCH_ARM
     vp8_arch_arm_decode_init(pbi);
+#endif
+
+#if CONFIG_EXTEND_QRANGE
+    pbi->dequant.idct_add            = vp8_dequant_idct_add_c;
+    pbi->dequant.dc_idct_add         = vp8_dequant_dc_idct_add_c;
+    pbi->dequant.dc_idct_add_y_block = vp8_dequant_dc_idct_add_y_block_c;
+    pbi->dequant.idct_add_y_block    = vp8_dequant_idct_add_y_block_c;
+    pbi->dequant.idct_add_uv_block   = vp8_dequant_idct_add_uv_block_c;
 #endif
 }
--- a/vp8/encoder/dct.c
+++ b/vp8/encoder/dct.c
@@ -10,7 +10,7 @@
 
 
 #include <math.h>
-
+#include "vpx_ports/config.h"
 void vp8_short_fdct4x4_c(short *input, short *output, int pitch)
 {
     int i;
@@ -20,11 +20,17 @@
 
     for (i = 0; i < 4; i++)
     {
+#if CONFIG_EXTEND_QRANGE
+        a1 = ((ip[0] + ip[3])<<5);
+        b1 = ((ip[1] + ip[2])<<5);
+        c1 = ((ip[1] - ip[2])<<5);
+        d1 = ((ip[0] - ip[3])<<5);
+#else
         a1 = ((ip[0] + ip[3])<<3);
         b1 = ((ip[1] + ip[2])<<3);
         c1 = ((ip[1] - ip[2])<<3);
         d1 = ((ip[0] - ip[3])<<3);
-
+#endif
         op[0] = a1 + b1;
         op[2] = a1 - b1;
 
@@ -72,6 +78,7 @@
 
     for (i = 0; i < 4; i++)
     {
+#if !CONFIG_EXTEND_QRANGE
         a1 = ((ip[0] + ip[2])<<2);
         d1 = ((ip[1] + ip[3])<<2);
         c1 = ((ip[1] - ip[3])<<2);
@@ -78,6 +85,15 @@
         b1 = ((ip[0] - ip[2])<<2);
 
         op[0] = a1 + d1 + (a1!=0);
+#else
+        a1 = ((ip[0] + ip[2]));
+        d1 = ((ip[1] + ip[3]));
+        c1 = ((ip[1] - ip[3]));
+        b1 = ((ip[0] - ip[2]));
+
+
+        op[0] = a1 + d1;
+#endif
         op[1] = b1 + c1;
         op[2] = b1 - c1;
         op[3] = a1 - d1;
@@ -105,11 +121,17 @@
         c2 += c2<0;
         d2 += d2<0;
 
+#if !CONFIG_EXTEND_QRANGE
         op[0] = (a2+3) >> 3;
         op[4] = (b2+3) >> 3;
         op[8] = (c2+3) >> 3;
         op[12]= (d2+3) >> 3;
-
+#else
+        op[0] = (a2+1) >> 2;
+        op[4] = (b2+1) >> 2;
+        op[8] = (c2+1) >> 2;
+        op[12]= (d2+1) >> 2;
+#endif
         ip++;
         op++;
     }
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -709,7 +709,7 @@
             vp8_auto_select_speed(cpi);
     }
 
-    vp8_initialize_rd_consts(cpi, vp8_dc_quant(cm->base_qindex, cm->y1dc_delta_q));
+    vp8_initialize_rd_consts(cpi, cm->base_qindex + cm->y1dc_delta_q);
     vp8cx_initialize_me_consts(cpi, cm->base_qindex);
 
     // Copy data over into macro block data sturctures.
--- a/vp8/encoder/encodemb.c
+++ b/vp8/encoder/encodemb.c
@@ -245,7 +245,11 @@
 // TODO: experiments to find optimal multiple numbers
 #define Y1_RD_MULT 4
 #define UV_RD_MULT 2
+#if !CONFIG_EXTEND_QRANGE
 #define Y2_RD_MULT 16
+#else
+#define Y2_RD_MULT 4
+#endif
 
 static const int plane_rd_mult[4]=
 {
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -578,7 +578,7 @@
     //if ( 0 )
     {
         int flag[2] = {1, 1};
-        vp8_initialize_rd_consts(cpi, vp8_dc_quant(cm->base_qindex, cm->y1dc_delta_q));
+        vp8_initialize_rd_consts(cpi, cm->base_qindex+cm->y1dc_delta_q);
         vpx_memcpy(cm->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
         vp8_build_component_cost_table(cpi->mb.mvcost, cpi->mb.mvsadcost, (const MV_CONTEXT *) cm->fc.mvc, flag);
     }
--- a/vp8/encoder/generic/csystemdependent.c
+++ b/vp8/encoder/generic/csystemdependent.c
@@ -111,4 +111,12 @@
     vp8_arch_arm_encoder_init(cpi);
 #endif
 
+#if CONFIG_EXTEND_QRANGE
+    cpi->rtcd.fdct.short4x4                  = vp8_short_fdct4x4_c;
+    cpi->rtcd.fdct.short8x4                  = vp8_short_fdct8x4_c;
+    cpi->rtcd.fdct.fast4x4                   = vp8_short_fdct4x4_c;
+    cpi->rtcd.fdct.fast8x4                   = vp8_short_fdct8x4_c;
+    cpi->rtcd.fdct.walsh_short4x4            = vp8_short_walsh4x4_c;
+#endif
+
 }
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -151,7 +151,7 @@
 extern const int qzbin_factors[129];
 extern void vp8cx_init_quantizer(VP8_COMP *cpi);
 extern const int vp8cx_base_skip_false_prob[128];
-
+#if !CONFIG_EXTEND_QRANGE
 // Tables relating active max Q to active min Q
 static const int kf_low_motion_minq[QINDEX_RANGE] =
 {
@@ -219,7 +219,76 @@
     71,72,73,74,75,75,76,77,78,79,80,81,82,83,84,85,
     86,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
 };
+#else
+static const int kf_low_motion_minq[QINDEX_RANGE] =
+{
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+     1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+     4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8,
+    9, 9, 9, 10,10,11,11,12,12,13,13,14,14,15,15,16,
+    16,17,17,18,18,19,19,20,20,21,21,22,23,23,24,24,
+    25,25,26,27,28,29,30,30,31,32,33,34,35,35,36,36,
+    38,38,39,40,40,41,42,42,43,44,44,45,46,46,47,48,
+    49,49,50,50,51,52,52,53,54,55,56,57,58,59,60,61,
+};
+static const int kf_high_motion_minq[QINDEX_RANGE] =
+{
+     0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2,
+     2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6,
+     6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9,10,10,
+    11,11,12,13,14,15,16,17,18,19,20,21,22,23,24,24,
+    25,26,27,28,28,29,29,30,30,31,31,32,33,33,34,34,
+    35,36,37,38,39,39,40,41,41,42,43,44,45,45,46,46,
+    47,47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,
+    55,55,56,56,57,58,59,60,61,62,63,64,65,67,69,70,
+};
 
+static const int gf_low_motion_minq[QINDEX_RANGE] =
+{
+     0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4,
+     4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9,
+    10,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,
+    17,18,18,19,19,20,21,22,23,24,25,26,27,29,29,30,
+    31,32,33,34,35,36,37,38,39,40,41,41,42,42,43,43,
+    44,44,45,45,46,46,47,47,48,48,49,49,50,50,51,51,
+    52,52,53,53,54,54,55,55,56,56,57,57,58,59,60,61,
+    62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
+};
+static const int gf_mid_motion_minq[QINDEX_RANGE] =
+{
+     0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4,
+     4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9,10,
+    10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,
+    18,19,19,20,20,21,22,23,24,25,26,27,28,29,30,31,
+    32,33,34,35,35,36,36,37,37,38,38,39,39,40,40,41,
+    41,42,42,43,43,44,44,45,45,46,46,47,48,49,50,51,
+    52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,
+    68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,
+};
+static const int gf_high_motion_minq[QINDEX_RANGE] =
+{
+     0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4,
+     4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9,10,10,
+    11,11,12,12,13,14,15,16,17,18,18,19,19,20,20,21,
+    22,23,24,25,26,26,27,28,29,30,31,32,33,34,35,36,
+    37,38,39,39,40,40,40,41,41,41,42,42,43,43,44,44,
+    44,45,45,45,46,46,47,47,47,48,48,48,49,49,49,50,
+    50,50,51,51,52,53,54,54,55,56,57,57,58,59,60,61,
+    62,63,64,66,68,69,72,74,77,80,82,85,87,89,91,93,
+};
+
+static const int inter_minq[QINDEX_RANGE] =
+{
+     0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,
+     8, 9,10,11,12,13,14,15,16,17,18,18,19,19,20,21,
+    21,22,23,23,24,25,26,26,27,28,29,30,31,32,32,33,
+    34,35,36,36,37,38,39,40,40,41,41,42,43,44,44,45,
+    46,46,47,47,48,49,49,50,50,51,52,52,53,54,54,55,
+    55,56,57,57,58,59,60,60,61,62,63,63,64,65,66,67,
+    68,68,69,70,71,72,72,73,74,75,76,77,78,79,80,81,
+    81,82,83,84,85,86,87,88,89,90,90,91,92,93,94,95,
+};
+#endif
 void vp8_initialize()
 {
     static int init_done = 0;
@@ -3466,7 +3535,13 @@
     return code_key_frame;
 
 }
+#if !CONFIG_EXTEND_QRANGE
+#define FIRSTPASS_QINDEX 26
+#else
+#define FIRSTPASS_QINDEX 49
+#endif
 
+
 #if !(CONFIG_REALTIME_ONLY)
 static void Pass1Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
 {
@@ -4107,6 +4182,17 @@
 
         vp8_clear_system_state();  //__asm emms;
 
+#if 0
+        if (cpi->pass != 1)
+        {
+            FILE *f = fopen("q_used.stt", "a");
+            fprintf(f, "%4d, %4d, %8d\n", cpi->common.current_video_frame,
+                cpi->common.base_qindex, cpi->projected_frame_size);
+            fclose(f);
+        }
+#endif
+
+
         // Test to see if the stats generated for this frame indicate that we should have coded a key frame
         // (assuming that we didn't)!
         if (cpi->pass != 2 && cpi->oxcf.auto_key && cm->frame_type != KEY_FRAME)
@@ -4843,11 +4929,16 @@
         fclose(recon_file);
     }
 #endif
-
+#if 0
     // DEBUG
-    //vp8_write_yuv_frame("encoder_recon.yuv", cm->frame_to_show);
+    if(cm->current_video_frame>173 && cm->current_video_frame<178)
+    {
+        char filename[512];
+        sprintf(filename, "enc%04d.yuv", (int) cm->current_video_frame);
+        vp8_write_yuv_frame(filename, cm->frame_to_show);
+    }
+#endif
 
-
 }
 
 int vp8_is_gf_update_needed(VP8_PTR ptr)
@@ -5416,7 +5507,15 @@
                     cpi->totalp_v += v2;
                     cpi->totalp  += frame_psnr2;
                     cpi->total_sq_error2 += sq_error;
-
+#if 0
+                    {
+                        FILE *f = fopen("q_used.stt", "a");
+                        fprintf(f, "%5d : Y%f7.3:U%f7.3:V%f7.3:F%f7.3:S%7.3f\n",
+                            cpi->common.current_video_frame,y2, u2, v2,
+                            frame_psnr2, frame_ssim2);
+                        fclose(f);
+                    }
+#endif
                 }
             }
 
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -48,6 +48,7 @@
 // Work in progress recalibration of baseline rate tables based on
 // the assumption that bits per mb is inversely proportional to the
 // quantizer value.
+#if !CONFIG_EXTEND_QRANGE
 const int vp8_bits_per_mb[2][QINDEX_RANGE] =
 {
     // Intra case 450000/Qintra
@@ -89,10 +90,54 @@
         11445,  11220,  11003,  10795,  10594,  10401,  10215,  10035,
     }
 };
+#else
+const int vp8_bits_per_mb[2][QINDEX_RANGE] =
+{
+    // (Updated DEC 2010) Baseline estimate of Bits Per MB at each Q:
+    // 4500000/Qintra
+    {
+        4500000,3600000,3000000,2571428,2250000,2000000,1800000,1636363,
+        1500000,1384615,1285714,1200000,1125000,1058823,1000000, 947368,
+         900000, 818181, 750000, 692307, 642857, 600000, 562500, 529411,
+         500000, 473684, 450000, 428571, 409090, 391304, 375000, 352941,
+         333333, 315789, 300000, 285714, 272727, 260869, 250000, 236842,
+         225000, 214285, 204545, 195652, 187500, 180000, 171428, 163636,
+         156521, 150000, 144000, 138461, 133333, 128571, 123287, 118421,
+         113924, 109756, 105882, 102272,  98901,  95744,  92783,  90000,
+          87378,  84905,  82568,  80357,  77586,  75000,  72580,  70312,
+          68181,  66176,  64285,  62500,  60810,  59210,  57692,  56250,
+          54545,  52941,  51428,  50000,  48648,  47368,  45918,  44554,
+          43269,  42056,  40909,  39647,  38461,  37344,  36290,  35294,
+          34351,  33333,  32374,  31468,  30612,  29801,  28938,  28125,
+          27355,  26627,  25862,  25139,  24456,  23809,  23195,  22613,
+          21951,  21327,  20737,  20179,  19650,  19067,  18518,  18000,
+          17441,  16917,  16423,  15957,  15410,  14900,  14376,  13846,
+    },
+    //2850000/Qinter
+    {
+        2850000,2280000,1900000,1628571,1425000,1266666,1140000,1036363,
+         950000, 876923, 814285, 760000, 712500, 670588, 633333, 600000,
+         570000, 518181, 475000, 438461, 407142, 380000, 356250, 335294,
+         316666, 300000, 285000, 271428, 259090, 247826, 237500, 223529,
+         211111, 200000, 190000, 180952, 172727, 165217, 158333, 150000,
+         142500, 135714, 129545, 123913, 118750, 114000, 108571, 103636,
+          99130,  95000,  91200,  87692,  84444,  81428,  78082,  75000,
+          72151,  69512,  67058,  64772,  62637,  60638,  58762,  57000,
+          55339,  53773,  52293,  50892,  49137,  47500,  45967,  44531,
+          43181,  41911,  40714,  39583,  38513,  37500,  36538,  35625,
+          34545,  33529,  32571,  31666,  30810,  30000,  29081,  28217,
+          27403,  26635,  25909,  25110,  24358,  23651,  22983,  22352,
+          21755,  21111,  20503,  19930,  19387,  18874,  18327,  17812,
+          17325,  16863,  16379,  15921,  15489,  15079,  14690,  14321,
+          13902,  13507,  13133,  12780,  12445,  12076,  11728,  11400,
+          11046,  10714,  10401,  10106,   9760,   9437,   9105,   8769,
+      }
+  };
+  #endif
 
 const int vp8_kf_boost_qadjustment[QINDEX_RANGE] =
-{
-    128, 129, 130, 131, 132, 133, 134, 135,
+  {
+      128, 129, 130, 131, 132, 133, 134, 135,
     136, 137, 138, 139, 140, 141, 142, 143,
     144, 145, 146, 147, 148, 149, 150, 151,
     152, 153, 154, 155, 156, 157, 158, 159,
--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -158,6 +158,48 @@
                                       0,   0,   0,   0,   0,   0,   0,   0,
                                  };
 
+// 3* dc_qlookup[Q]*dc_qlookup[Q];
+#if !CONFIG_EXTEND_QRANGE
+static int rdmult_lut[QINDEX_RANGE]=
+{
+    48,75,108,147,192,243,300,300,
+    363,432,507,588,675,768,867,867,
+    972,1083,1200,1200,1323,1323,1452,1452,
+    1587,1587,1728,1875,1875,2028,2187,2352,
+    2523,2700,2883,3072,3267,3468,3675,3888,
+    4107,4107,4332,4563,4800,5043,5292,5547,
+    5808,6075,6348,6348,6627,6912,7203,7500,
+    7803,8112,8427,8748,9075,9408,9747,10092,
+    10443,10800,11163,11532,11907,12288,12675,13068,
+    13467,13872,14283,14700,15123,15552,15987,16428,
+    16875,17328,17328,17787,18252,18723,19200,19683,
+    20172,20667,21168,21675,22188,22707,23232,23763,
+    24843,25947,27075,27648,28812,30000,30603,31212,
+    32448,33708,34992,36300,37632,38988,40368,41772,
+    44652,46128,47628,49152,50700,52272,53868,55488,
+    57132,58800,61347,63075,65712,68403,71148,73947,
+};
+#else
+static int rdmult_lut[QINDEX_RANGE]=
+{
+    3,5,7,9,12,15,19,23,
+    27,32,37,42,48,54,61,68,
+    75,83,91,99,108,117,127,137,
+    147,169,192,217,243,271,300,331,
+    363,397,450,507,567,631,698,768,
+    842,919,999,1083,1170,1261,1355,1452,
+    1587,1728,1875,2028,2187,2352,2523,2700,
+    2883,3072,3267,3468,3675,3888,4107,4332,
+    4563,4800,5043,5292,5547,5808,6075,6348,
+    6627,6912,7203,7500,7880,8269,8667,9075,
+    9492,9919,10355,10800,11255,11719,12192,12675,
+    13167,13669,14180,14700,15230,15769,16317,16875,
+    18019,19200,20419,21675,22969,24300,25669,27075,
+    28519,30000,31519,33075,34669,36300,37969,39675,
+    41772,43923,46128,48387,50700,53067,55488,57963,
+    61347,64827,69312,73947,78732,83667,89787,97200,
+};
+#endif
 
 /* values are now correlated to quantizer */
 static int sad_per_bit16lut[QINDEX_RANGE] =
@@ -205,12 +247,16 @@
     cpi->mb.sadperbit4  =  sad_per_bit4lut[QIndex];
 }
 
-void vp8_initialize_rd_consts(VP8_COMP *cpi, int Qvalue)
+
+
+
+
+void vp8_initialize_rd_consts(VP8_COMP *cpi, int QIndex)
 {
     int q;
     int i;
-    double capped_q = (Qvalue < 160) ? (double)Qvalue : 160.0;
-    double rdconst = 3.00;
+    int *thresh;
+    int threshmult;
 
     vp8_clear_system_state();  //__asm emms;
 
@@ -218,7 +264,8 @@
     // for key frames, golden frames and arf frames.
     // if (cpi->common.refresh_golden_frame ||
     //     cpi->common.refresh_alt_ref_frame)
-    cpi->RDMULT = (int)(rdconst * (capped_q * capped_q));
+    QIndex=(QIndex<0)? 0 : ((QIndex>127)?127 : QIndex);
+    cpi->RDMULT = rdmult_lut[QIndex];
 
     // Extend rate multiplier along side quantizer zbin increases
     if (cpi->zbin_over_quant  > 0)
@@ -229,8 +276,7 @@
         // Experimental code using the same basic equation as used for Q above
         // The units of cpi->zbin_over_quant are 1/128 of Q bin size
         oq_factor = 1.0 + ((double)0.0015625 * cpi->zbin_over_quant);
-        modq = (int)((double)capped_q * oq_factor);
-        cpi->RDMULT = (int)(rdconst * (modq * modq));
+        cpi->RDMULT = (int)((double)cpi->RDMULT * oq_factor * oq_factor);
     }
 
     if (cpi->pass == 2 && (cpi->common.frame_type != KEY_FRAME))
@@ -241,20 +287,35 @@
             cpi->RDMULT += (cpi->RDMULT * rd_iifactor[cpi->next_iiratio]) >> 4;
     }
 
+#if !CONFIG_EXTEND_QRANGE
     if (cpi->RDMULT < 125)
         cpi->RDMULT = 125;
+#else
+    if (cpi->RDMULT < 7)
+        cpi->RDMULT = 7;
+#endif
 
     cpi->mb.errorperbit = (cpi->RDMULT / 100);
+#if CONFIG_EXTEND_QRANGE
+    if(cpi->mb.errorperbit<1)
+        cpi->mb.errorperbit=1;
+#endif
     vp8_set_speed_features(cpi);
 
     if (cpi->common.simpler_lpf)
         cpi->common.filter_type = SIMPLE_LOOPFILTER;
 
-    q = (int)pow(Qvalue, 1.25);
+    q = (int)pow(vp8_dc_quant(QIndex,0), 1.25);
 
     if (q < 8)
         q = 8;
 
+
+
+#if CONFIG_EXTEND_QRANGE
+    cpi->RDMULT *= 16;
+#endif
+
     if (cpi->RDMULT > 1000)
     {
         cpi->RDDIV = 1;
@@ -972,7 +1033,11 @@
 
     // Distortion
     d = ENCODEMB_INVOKE(rtcd, mberr)(mb, 1) << 2;
+#if CONFIG_EXTEND_QRANGE
+    d += ENCODEMB_INVOKE(rtcd, berr)(mb_y2->coeff, x_y2->dqcoeff)<<2;
+#else
     d += ENCODEMB_INVOKE(rtcd, berr)(mb_y2->coeff, x_y2->dqcoeff);
+#endif
 
     *Distortion = (d >> 4);