summaryrefslogtreecommitdiff
path: root/drivers/theora/enquant.c
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
commit0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch)
tree276c4d099e178eb67fbd14f61d77b05e3808e9e3 /drivers/theora/enquant.c
parent0e49da1687bc8192ed210947da52c9e5c5f301bb (diff)
GODOT IS OPEN SOURCE
Diffstat (limited to 'drivers/theora/enquant.c')
-rw-r--r--drivers/theora/enquant.c274
1 files changed, 274 insertions, 0 deletions
diff --git a/drivers/theora/enquant.c b/drivers/theora/enquant.c
new file mode 100644
index 0000000000..3372fed221
--- /dev/null
+++ b/drivers/theora/enquant.c
@@ -0,0 +1,274 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: enquant.c 16503 2009-08-22 18:14:02Z giles $
+
+ ********************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include "encint.h"
+
+
+
+void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo){
+ const th_quant_ranges *qranges;
+ const th_quant_base *base_mats[2*3*64];
+ int indices[2][3][64];
+ int nbase_mats;
+ int nbits;
+ int ci;
+ int qi;
+ int qri;
+ int qti;
+ int pli;
+ int qtj;
+ int plj;
+ int bmi;
+ int i;
+ i=_qinfo->loop_filter_limits[0];
+ for(qi=1;qi<64;qi++)i=OC_MAXI(i,_qinfo->loop_filter_limits[qi]);
+ nbits=OC_ILOG_32(i);
+ oggpackB_write(_opb,nbits,3);
+ for(qi=0;qi<64;qi++){
+ oggpackB_write(_opb,_qinfo->loop_filter_limits[qi],nbits);
+ }
+ /*580 bits for VP3.*/
+ i=1;
+ for(qi=0;qi<64;qi++)i=OC_MAXI(_qinfo->ac_scale[qi],i);
+ nbits=OC_ILOGNZ_32(i);
+ oggpackB_write(_opb,nbits-1,4);
+ for(qi=0;qi<64;qi++)oggpackB_write(_opb,_qinfo->ac_scale[qi],nbits);
+ /*516 bits for VP3.*/
+ i=1;
+ for(qi=0;qi<64;qi++)i=OC_MAXI(_qinfo->dc_scale[qi],i);
+ nbits=OC_ILOGNZ_32(i);
+ oggpackB_write(_opb,nbits-1,4);
+ for(qi=0;qi<64;qi++)oggpackB_write(_opb,_qinfo->dc_scale[qi],nbits);
+ /*Consolidate any duplicate base matrices.*/
+ nbase_mats=0;
+ for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){
+ qranges=_qinfo->qi_ranges[qti]+pli;
+ for(qri=0;qri<=qranges->nranges;qri++){
+ for(bmi=0;;bmi++){
+ if(bmi>=nbase_mats){
+ base_mats[bmi]=qranges->base_matrices+qri;
+ indices[qti][pli][qri]=nbase_mats++;
+ break;
+ }
+ else if(memcmp(base_mats[bmi][0],qranges->base_matrices[qri],
+ sizeof(base_mats[bmi][0]))==0){
+ indices[qti][pli][qri]=bmi;
+ break;
+ }
+ }
+ }
+ }
+ /*Write out the list of unique base matrices.
+ 1545 bits for VP3 matrices.*/
+ oggpackB_write(_opb,nbase_mats-1,9);
+ for(bmi=0;bmi<nbase_mats;bmi++){
+ for(ci=0;ci<64;ci++)oggpackB_write(_opb,base_mats[bmi][0][ci],8);
+ }
+ /*Now store quant ranges and their associated indices into the base matrix
+ list.
+ 46 bits for VP3 matrices.*/
+ nbits=OC_ILOG_32(nbase_mats-1);
+ for(i=0;i<6;i++){
+ qti=i/3;
+ pli=i%3;
+ qranges=_qinfo->qi_ranges[qti]+pli;
+ if(i>0){
+ if(qti>0){
+ if(qranges->nranges==_qinfo->qi_ranges[qti-1][pli].nranges&&
+ memcmp(qranges->sizes,_qinfo->qi_ranges[qti-1][pli].sizes,
+ qranges->nranges*sizeof(qranges->sizes[0]))==0&&
+ memcmp(indices[qti][pli],indices[qti-1][pli],
+ (qranges->nranges+1)*sizeof(indices[qti][pli][0]))==0){
+ oggpackB_write(_opb,1,2);
+ continue;
+ }
+ }
+ qtj=(i-1)/3;
+ plj=(i-1)%3;
+ if(qranges->nranges==_qinfo->qi_ranges[qtj][plj].nranges&&
+ memcmp(qranges->sizes,_qinfo->qi_ranges[qtj][plj].sizes,
+ qranges->nranges*sizeof(qranges->sizes[0]))==0&&
+ memcmp(indices[qti][pli],indices[qtj][plj],
+ (qranges->nranges+1)*sizeof(indices[qti][pli][0]))==0){
+ oggpackB_write(_opb,0,1+(qti>0));
+ continue;
+ }
+ oggpackB_write(_opb,1,1);
+ }
+ oggpackB_write(_opb,indices[qti][pli][0],nbits);
+ for(qi=qri=0;qi<63;qri++){
+ oggpackB_write(_opb,qranges->sizes[qri]-1,OC_ILOG_32(62-qi));
+ qi+=qranges->sizes[qri];
+ oggpackB_write(_opb,indices[qti][pli][qri+1],nbits);
+ }
+ }
+}
+
+static void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d){
+ ogg_uint32_t t;
+ int l;
+ _d<<=1;
+ l=OC_ILOGNZ_32(_d)-1;
+ t=1+((ogg_uint32_t)1<<16+l)/_d;
+ _this->m=(ogg_int16_t)(t-0x10000);
+ _this->l=l;
+}
+
+/*See comments at oc_dequant_tables_init() for how the quantization tables'
+ storage should be initialized.*/
+void oc_enquant_tables_init(ogg_uint16_t *_dequant[64][3][2],
+ oc_iquant *_enquant[64][3][2],const th_quant_info *_qinfo){
+ int qi;
+ int pli;
+ int qti;
+ /*Initialize the dequantization tables first.*/
+ oc_dequant_tables_init(_dequant,NULL,_qinfo);
+ /*Derive the quantization tables directly from the dequantization tables.*/
+ for(qi=0;qi<64;qi++)for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){
+ int zzi;
+ int plj;
+ int qtj;
+ int dupe;
+ dupe=0;
+ for(qtj=0;qtj<=qti;qtj++){
+ for(plj=0;plj<(qtj<qti?3:pli);plj++){
+ if(_dequant[qi][pli][qti]==_dequant[qi][plj][qtj]){
+ dupe=1;
+ break;
+ }
+ }
+ if(dupe)break;
+ }
+ if(dupe){
+ _enquant[qi][pli][qti]=_enquant[qi][plj][qtj];
+ continue;
+ }
+ /*In the original VP3.2 code, the rounding offset and the size of the
+ dead zone around 0 were controlled by a "sharpness" parameter.
+ We now R-D optimize the tokens for each block after quantization,
+ so the rounding offset should always be 1/2, and an explicit dead
+ zone is unnecessary.
+ Hence, all of that VP3.2 code is gone from here, and the remaining
+ floating point code has been implemented as equivalent integer
+ code with exact precision.*/
+ for(zzi=0;zzi<64;zzi++){
+ oc_iquant_init(_enquant[qi][pli][qti]+zzi,
+ _dequant[qi][pli][qti][zzi]);
+ }
+ }
+}
+
+
+
+/*This table gives the square root of the fraction of the squared magnitude of
+ each DCT coefficient relative to the total, scaled by 2**16, for both INTRA
+ and INTER modes.
+ These values were measured after motion-compensated prediction, before
+ quantization, over a large set of test video (from QCIF to 1080p) encoded at
+ all possible rates.
+ The DC coefficient takes into account the DPCM prediction (using the
+ quantized values from neighboring blocks, as the encoder does, but still
+ before quantization of the coefficient in the current block).
+ The results differ significantly from the expected variance (e.g., using an
+ AR(1) model of the signal with rho=0.95, as is frequently done to compute
+ the coding gain of the DCT).
+ We use them to estimate an "average" quantizer for a given quantizer matrix,
+ as this is used to parameterize a number of the rate control decisions.
+ These values are themselves probably quantizer-matrix dependent, since the
+ shape of the matrix affects the noise distribution in the reference frames,
+ but they should at least give us _some_ amount of adaptivity to different
+ matrices, as opposed to hard-coding a table of average Q values for the
+ current set.
+ The main features they capture are that a) only a few of the quantizers in
+ the upper-left corner contribute anything significant at all (though INTER
+ mode is significantly flatter) and b) the DPCM prediction of the DC
+ coefficient gives a very minor improvement in the INTRA case and a quite
+ significant one in the INTER case (over the expected variance).*/
+static const ogg_uint16_t OC_RPSD[2][64]={
+ {
+ 52725,17370,10399, 6867, 5115, 3798, 2942, 2076,
+ 17370, 9900, 6948, 4994, 3836, 2869, 2229, 1619,
+ 10399, 6948, 5516, 4202, 3376, 2573, 2015, 1461,
+ 6867, 4994, 4202, 3377, 2800, 2164, 1718, 1243,
+ 5115, 3836, 3376, 2800, 2391, 1884, 1530, 1091,
+ 3798, 2869, 2573, 2164, 1884, 1495, 1212, 873,
+ 2942, 2229, 2015, 1718, 1530, 1212, 1001, 704,
+ 2076, 1619, 1461, 1243, 1091, 873, 704, 474
+ },
+ {
+ 23411,15604,13529,11601,10683, 8958, 7840, 6142,
+ 15604,11901,10718, 9108, 8290, 6961, 6023, 4487,
+ 13529,10718, 9961, 8527, 7945, 6689, 5742, 4333,
+ 11601, 9108, 8527, 7414, 7084, 5923, 5175, 3743,
+ 10683, 8290, 7945, 7084, 6771, 5754, 4793, 3504,
+ 8958, 6961, 6689, 5923, 5754, 4679, 3936, 2989,
+ 7840, 6023, 5742, 5175, 4793, 3936, 3522, 2558,
+ 6142, 4487, 4333, 3743, 3504, 2989, 2558, 1829
+ }
+};
+
+/*The fraction of the squared magnitude of the residuals in each color channel
+ relative to the total, scaled by 2**16, for each pixel format.
+ These values were measured after motion-compensated prediction, before
+ quantization, over a large set of test video encoded at all possible rates.
+ TODO: These values are only from INTER frames; it should be re-measured for
+ INTRA frames.*/
+static const ogg_uint16_t OC_PCD[4][3]={
+ {59926, 3038, 2572},
+ {55201, 5597, 4738},
+ {55201, 5597, 4738},
+ {47682, 9669, 8185}
+};
+
+
+/*Compute an "average" quantizer for each qi level.
+ We do one for INTER and one for INTRA, since their behavior is very
+ different, but average across chroma channels.
+ The basic approach is to compute a harmonic average of the squared quantizer,
+ weighted by the expected squared magnitude of the DCT coefficients.
+ Under the (not quite true) assumption that DCT coefficients are
+ Laplacian-distributed, this preserves the product Q*lambda, where
+ lambda=sqrt(2/sigma**2) is the Laplacian distribution parameter (not to be
+ confused with the lambda used in R-D optimization throughout most of the
+ rest of the code).
+ The value Q*lambda completely determines the entropy of the coefficients.*/
+void oc_enquant_qavg_init(ogg_int64_t _log_qavg[2][64],
+ ogg_uint16_t *_dequant[64][3][2],int _pixel_fmt){
+ int qi;
+ int pli;
+ int qti;
+ int ci;
+ for(qti=0;qti<2;qti++)for(qi=0;qi<64;qi++){
+ ogg_int64_t q2;
+ q2=0;
+ for(pli=0;pli<3;pli++){
+ ogg_uint32_t qp;
+ qp=0;
+ for(ci=0;ci<64;ci++){
+ unsigned rq;
+ unsigned qd;
+ qd=_dequant[qi][pli][qti][OC_IZIG_ZAG[ci]];
+ rq=(OC_RPSD[qti][ci]+(qd>>1))/qd;
+ qp+=rq*(ogg_uint32_t)rq;
+ }
+ q2+=OC_PCD[_pixel_fmt][pli]*(ogg_int64_t)qp;
+ }
+ /*qavg=1.0/sqrt(q2).*/
+ _log_qavg[qti][qi]=OC_Q57(48)-oc_blog64(q2)>>1;
+ }
+}