[xiph-commits] r14057 - trunk/theora/lib/dec
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Sun Oct 28 10:10:19 PDT 2007
Author: xiphmont
Date: 2007-10-28 10:10:19 -0700 (Sun, 28 Oct 2007)
New Revision: 14057
Modified:
trunk/theora/lib/dec/quant.c
Log:
Correct a decode quant matrix initilization bug where duplicate detection/shortcircuiting was
failing to account for different clamp values in inter/intra matricies.
Simultaneously make dupe detection more aggressive
Modified: trunk/theora/lib/dec/quant.c
===================================================================
--- trunk/theora/lib/dec/quant.c 2007-10-27 17:45:51 UTC (rev 14056)
+++ trunk/theora/lib/dec/quant.c 2007-10-28 17:10:19 UTC (rev 14057)
@@ -20,13 +20,9 @@
#include <ogg/ogg.h>
#include "quant.h"
-
-
unsigned OC_DC_QUANT_MIN[2]={4<<2,8<<2};
unsigned OC_AC_QUANT_MIN[2]={2<<2,4<<2};
-
-
/*Initializes the dequantization tables from a set of quantizer info.
Currently the dequantizer (and elsewhere enquantizer) tables are expected to
be initialized as pointing to the storage reserved for them in the
@@ -41,67 +37,96 @@
matrices being used for the current frame, and to recalculate these as the
qi values change between frames (this is what VP3 did).*/
void oc_dequant_tables_init(oc_quant_table *_dequant[2][3],
- int _pp_dc_scale[64],const th_quant_info *_qinfo){
- int qti;
- int pli;
- for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){
- int qi;
- int qri;
- /*These simple checks help us improve cache coherency later.*/
- if(pli>0&&memcmp(_qinfo->qi_ranges[qti]+pli-1,
- _qinfo->qi_ranges[qti]+pli,sizeof(_qinfo->qi_ranges[qti][pli]))==0){
- _dequant[qti][pli]=_dequant[qti][pli-1];
- continue;
- }
- if(qti>0&&memcmp(_qinfo->qi_ranges[qti-1]+pli,
- _qinfo->qi_ranges[qti]+pli,sizeof(_qinfo->qi_ranges[qti][pli]))==0){
- _dequant[qti][pli]=_dequant[qti-1][pli];
- continue;
- }
- for(qi=qri=0;qri<=_qinfo->qi_ranges[qti][pli].nranges;qri++){
- th_quant_base base;
- ogg_uint32_t q;
- int qi_start;
- int qi_end;
- int ci;
- memcpy(base,_qinfo->qi_ranges[qti][pli].base_matrices[qri],
- sizeof(base));
- qi_start=qi;
- if(qri==_qinfo->qi_ranges[qti][pli].nranges)qi_end=qi+1;
- else qi_end=qi+_qinfo->qi_ranges[qti][pli].sizes[qri];
- for(;;){
- ogg_uint32_t qfac;
- /*In the original VP3.2 code, the rounding offset and the size of the
- dead zone around 0 were controlled by a "sharpness" parameter.
- The size of our dead zone is now controlled by the per-coefficient
- quality thresholds returned by our HVS module.
- We round down from a more accurate value when the quality of the
- reconstruction does not fall below our threshold and it saves bits.
- 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.*/
- /*Scale DC the coefficient from the proper table.*/
- qfac=(ogg_uint32_t)_qinfo->dc_scale[qi]*base[0];
- if(_pp_dc_scale!=NULL)_pp_dc_scale[qi]=(int)(qfac/160);
- q=(qfac/100)<<2;
- q=OC_CLAMPI(OC_DC_QUANT_MIN[qti],q,OC_QUANT_MAX);
- _dequant[qti][pli][qi][0]=(ogg_uint16_t)q;
- /*Now scale AC coefficients from the proper table.*/
- for(ci=1;ci<64;ci++){
- q=((ogg_uint32_t)_qinfo->ac_scale[qi]*base[ci]/100)<<2;
- q=OC_CLAMPI(OC_AC_QUANT_MIN[qti],q,OC_QUANT_MAX);
- _dequant[qti][pli][qi][ci]=(ogg_uint16_t)q;
- }
- if(++qi>=qi_end)break;
- /*Interpolate the next base matrix.*/
- for(ci=0;ci<64;ci++){
- base[ci]=(unsigned char)(
- (2*((qi_end-qi)*_qinfo->qi_ranges[qti][pli].base_matrices[qri][ci]+
- (qi-qi_start)*_qinfo->qi_ranges[qti][pli].base_matrices[qri+1][ci])
- +_qinfo->qi_ranges[qti][pli].sizes[qri])/
- (2*_qinfo->qi_ranges[qti][pli].sizes[qri]));
- }
+ int _pp_dc_scale[64],
+ const th_quant_info *_qinfo){
+ int qti; /* coding mode: intra or inter */
+ int pli; /* Y U V */
+ for(qti=0;qti<2;qti++){
+ for(pli=0;pli<3;pli++){
+ oc_quant_tables stage;
+
+ int qi; /* quality index */
+ int qri; /* range iterator */
+
+ for(qi=0,qri=0; qri<=_qinfo->qi_ranges[qti][pli].nranges; qri++){
+ th_quant_base base;
+
+ ogg_uint32_t q;
+ int qi_start;
+ int qi_end;
+ int ci;
+ memcpy(base,_qinfo->qi_ranges[qti][pli].base_matrices[qri],
+ sizeof(base));
+
+ qi_start=qi;
+ if(qri==_qinfo->qi_ranges[qti][pli].nranges)
+ qi_end=qi+1;
+ else
+ qi_end=qi+_qinfo->qi_ranges[qti][pli].sizes[qri];
+
+ /* Iterate over quality indicies in this range */
+ for(;;){
+
+ /*In the original VP3.2 code, the rounding offset and the size of the
+ dead zone around 0 were controlled by a "sharpness" parameter.
+ The size of our dead zone is now controlled by the per-coefficient
+ quality thresholds returned by our HVS module.
+ We round down from a more accurate value when the quality of the
+ reconstruction does not fall below our threshold and it saves bits.
+ 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 postprocess, not dequant */
+ if(_pp_dc_scale!=NULL)
+ _pp_dc_scale[qi]=(int)((ogg_uint32_t)_qinfo->dc_scale[qi]*base[0]/160);
+
+ /*Scale DC the coefficient from the proper table.*/
+ q=((ogg_uint32_t)_qinfo->dc_scale[qi]*base[0]/100)<<2;
+ q=OC_CLAMPI(OC_DC_QUANT_MIN[qti],q,OC_QUANT_MAX);
+ stage[qi][0]=(ogg_uint16_t)q;
+
+ /*Now scale AC coefficients from the proper table.*/
+ for(ci=1;ci<64;ci++){
+ q=((ogg_uint32_t)_qinfo->ac_scale[qi]*base[ci]/100)<<2;
+ q=OC_CLAMPI(OC_AC_QUANT_MIN[qti],q,OC_QUANT_MAX);
+ stage[qi][ci]=(ogg_uint16_t)q;
+ }
+
+ if(++qi>=qi_end)break;
+
+ /*Interpolate the next base matrix.*/
+ for(ci=0;ci<64;ci++){
+ base[ci]=(unsigned char)
+ ((2*((qi_end-qi)*_qinfo->qi_ranges[qti][pli].base_matrices[qri][ci]+
+ (qi-qi_start)*_qinfo->qi_ranges[qti][pli].base_matrices[qri+1][ci])
+ +_qinfo->qi_ranges[qti][pli].sizes[qri])/
+ (2*_qinfo->qi_ranges[qti][pli].sizes[qri]));
+ }
+ }
}
+
+ /* Staging matricies complete; commit to memory only if this
+ isn't a duplicate of a preceeding plane. This simple check
+ helps us improve cache coherency later.*/
+ {
+ int dupe = 0;
+ int i,j;
+ for(i=0;i<=qti;i++){
+ for(j=0;j<(i<qti?3:pli);j++){
+ if(!memcmp(stage,_dequant[i][j],sizeof(stage))){
+ dupe = 1;
+ break;
+ }
+ }
+ if(dupe)break;
+ }
+ if(dupe){
+ _dequant[qti][pli]=_dequant[i][j];
+ }else{
+ memcpy(_dequant[qti][pli],stage,sizeof(stage));
+ }
+ }
}
}
}
More information about the commits
mailing list