[xiph-commits] r17821 - in trunk/theora: lib tools

giles at svn.xiph.org giles at svn.xiph.org
Wed Feb 9 14:08:35 PST 2011


Author: giles
Date: 2011-02-09 14:08:34 -0800 (Wed, 09 Feb 2011)
New Revision: 17821

Modified:
   trunk/theora/lib/analyze.c
   trunk/theora/lib/collect.c
   trunk/theora/lib/collect.h
   trunk/theora/lib/encfrag.c
   trunk/theora/lib/encint.h
   trunk/theora/lib/encode.c
   trunk/theora/lib/mcenc.c
   trunk/theora/lib/modedec.h
   trunk/theora/tools/process_modedec_stats.c
Log:
Add a new speed level between the old levels 2 and 3.

This change inserts a new speed level OC_SP_LEVEL_NOSATD (3)
between OC_SP_LEVEL_FAST_ANALYSIS (still 2) and OC_SP_LEVEL_NOMC
(now 4). The new speed level further accelerates analysis by
using the cheaper SAD (sum of absolute differences) metric
for measuring distortion instead of the more expensive SATD
(sum of absolute transformed differences).

The new level is intermediate in both quality and encoding
speed between the adjacent speed levels, allowing smoother
adaptation to realtime encoding contraints. In particular
it's much closer to realtime 720p30 on current Core2 cpus.

The cheaper SAD metric is now also used for the fastest NOMC
speed level. This is a reduction in quality for this speed level
as well, but it also about 10% faster. Since the NOMC mode is
already very poor quality, used as a last resort when performance
is critical, we deemed this a better option than adding a further
NOMC_SATD mode or keeping the old NOMC behaviour.

To support the new speed level, parallel copies of the OC_MODE_RD
table are kept, one for each metric. The encoder context keeps
track of which on to use based ont eh current speed level. Analysis
code chooses which metric to calculate and use on the fly. The extra
conditionals did not measurably affect encoding time in benchmarks.

The metrics collection and fitting code used to generate modedec.h
is also updated to track both SAD and SATD measurements.

Thanks to Tim Terriberry and Greg Maxwell for their comments and
and contributions in reviewing this patch. The implementation
of oc_enc_frag_intra_sad is based on one from earlier development
work by Greg Maxwell.

Modified: trunk/theora/lib/analyze.c
===================================================================
--- trunk/theora/lib/analyze.c	2011-02-09 01:45:41 UTC (rev 17820)
+++ trunk/theora/lib/analyze.c	2011-02-09 22:08:34 UTC (rev 17821)
@@ -749,18 +749,25 @@
   }
 #if defined(OC_COLLECT_METRICS)
   {
+    unsigned sad;
     unsigned satd;
     switch(nmv_offs){
-      case 0:satd=oc_enc_frag_intra_satd(_enc,&dc,src,ystride);break;
+      case 0:{
+        sad=oc_enc_frag_intra_sad(_enc,src,ystride);
+        satd=oc_enc_frag_intra_satd(_enc,&dc,src,ystride);
+      }break;
       case 1:{
+        sad=oc_enc_frag_sad_thresh(_enc,src,ref+mv_offs[0],ystride,UINT_MAX);
         satd=oc_enc_frag_satd(_enc,&dc,src,ref+mv_offs[0],ystride);
         satd+=abs(dc);
       }break;
       default:{
+        sad=oc_enc_frag_sad_thresh(_enc,src,dst,ystride,UINT_MAX);
         satd=oc_enc_frag_satd(_enc,&dc,src,dst,ystride);
         satd+=abs(dc);
       }break;
     }
+    _enc->frag_sad[_fragi]=sad;
     _enc->frag_satd[_fragi]=satd;
   }
 #endif
@@ -1060,6 +1067,11 @@
  +((1<<OC_BIT_SCALE)>>1)>>OC_BIT_SCALE)
 
 static void oc_enc_mode_rd_init(oc_enc_ctx *_enc){
+#if !defined(OC_COLLECT_METRICS)
+  const
+#endif
+  oc_mode_rd (*oc_mode_rd_table)[3][2][OC_COMP_BINS]=
+   _enc->sp_level<OC_SP_LEVEL_NOSATD?OC_MODE_RD_SATD:OC_MODE_RD_SAD;
   int qii;
 #if defined(OC_COLLECT_METRICS)
   oc_enc_mode_metrics_load(_enc);
@@ -1091,10 +1103,10 @@
           int z0;
           int dy;
           int dz;
-          y0=OC_MODE_RD[modeline][pli][qti][bin].rate;
-          z0=OC_MODE_RD[modeline][pli][qti][bin].rmse;
-          dy=OC_MODE_RD[modeline+1][pli][qti][bin].rate-y0;
-          dz=OC_MODE_RD[modeline+1][pli][qti][bin].rmse-z0;
+          y0=oc_mode_rd_table[modeline][pli][qti][bin].rate;
+          z0=oc_mode_rd_table[modeline][pli][qti][bin].rmse;
+          dy=oc_mode_rd_table[modeline+1][pli][qti][bin].rate-y0;
+          dz=oc_mode_rd_table[modeline+1][pli][qti][bin].rmse-z0;
           _enc->mode_rd[qii][pli][qti][bin].rate=
            (ogg_int16_t)OC_CLAMPI(-32768,y0+(dy*dx+(dq>>1))/dq,32767);
           _enc->mode_rd[qii][pli][qti][bin].rmse=
@@ -1110,6 +1122,7 @@
 static unsigned oc_dct_cost2(oc_enc_ctx *_enc,unsigned *_ssd,
  int _qii,int _pli,int _qti,int _satd){
   unsigned rmse;
+  int      shift;
   int      bin;
   int      dx;
   int      y0;
@@ -1119,15 +1132,16 @@
   /*SATD metrics for chroma planes vary much less than luma, so we scale them
      by 4 to distribute them into the mode decision bins more evenly.*/
   _satd<<=_pli+1&2;
-  bin=OC_MINI(_satd>>OC_SATD_SHIFT,OC_COMP_BINS-2);
-  dx=_satd-(bin<<OC_SATD_SHIFT);
+  shift=_enc->sp_level<OC_SP_LEVEL_NOSATD?OC_SATD_SHIFT:OC_SAD_SHIFT;
+  bin=OC_MINI(_satd>>shift,OC_COMP_BINS-2);
+  dx=_satd-(bin<<shift);
   y0=_enc->mode_rd[_qii][_pli][_qti][bin].rate;
   z0=_enc->mode_rd[_qii][_pli][_qti][bin].rmse;
   dy=_enc->mode_rd[_qii][_pli][_qti][bin+1].rate-y0;
   dz=_enc->mode_rd[_qii][_pli][_qti][bin+1].rmse-z0;
-  rmse=OC_MAXI(z0+(dz*dx>>OC_SATD_SHIFT),0);
+  rmse=OC_MAXI(z0+(dz*dx>>shift),0);
   *_ssd=rmse*rmse>>2*OC_RMSE_SCALE-OC_BIT_SCALE;
-  return OC_MAXI(y0+(dy*dx>>OC_SATD_SHIFT),0);
+  return OC_MAXI(y0+(dy*dx>>shift),0);
 }
 
 /*activity_avg must be positive, or flat regions could get a zero weight, which
@@ -1419,7 +1433,12 @@
   ystride=_enc->state.ref_ystride[0];
   fragi=sb_maps[_mbi>>2][_mbi&3][0];
   frag_offs=frag_buf_offs[fragi];
-  satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+  if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+    satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+  }
+  else{
+    satd=oc_enc_frag_intra_sad(_enc,src+frag_offs,ystride);
+  }
   nqis=_enc->state.nqis;
   lambda=_enc->lambda;
   for(qii=0;qii<nqis;qii++){
@@ -1432,7 +1451,12 @@
   for(bi=1;bi<4;bi++){
     fragi=sb_maps[_mbi>>2][_mbi&3][bi];
     frag_offs=frag_buf_offs[fragi];
-    satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+    if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+      satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+    }
+    else{
+      satd=oc_enc_frag_intra_sad(_enc,src+frag_offs,ystride);
+    }
     for(qii=0;qii<nqis;qii++){
       oc_qii_state qt[3];
       unsigned     cur_ssd;
@@ -1507,7 +1531,12 @@
   src=_enc->state.ref_frame_data[OC_FRAME_IO];
   ystride=_enc->state.ref_ystride[_pli];
   frag_offs=_enc->state.frag_buf_offs[_fragi];
-  satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+  if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+    satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+  }
+  else{
+    satd=oc_enc_frag_intra_sad(_enc,src+frag_offs,ystride);
+  }
   /*Most chroma blocks have no AC coefficients to speak of anyway, so it's not
      worth spending the bits to change the AC quantizer.
     TODO: This may be worth revisiting when we separate out DC and AC
@@ -2062,18 +2091,30 @@
     for(bi=0;bi<4;bi++){
       fragi=sb_map[bi];
       frag_offs=frag_buf_offs[fragi];
-      frag_satd[bi]=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
-       ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
-      frag_satd[bi]+=abs(dc);
+      if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+        frag_satd[bi]=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+         ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
+        frag_satd[bi]+=abs(dc);
+      }
+      else{
+        frag_satd[bi]=oc_enc_frag_sad2_thresh(_enc,src+frag_offs,
+         ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+      }
     }
   }
   else{
     for(bi=0;bi<4;bi++){
       fragi=sb_map[bi];
       frag_offs=frag_buf_offs[fragi];
-      frag_satd[bi]=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
-       ref+frag_offs+mv_offs[0],ystride);
-      frag_satd[bi]+=abs(dc);
+      if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+        frag_satd[bi]=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+         ref+frag_offs+mv_offs[0],ystride);
+        frag_satd[bi]+=abs(dc);
+      }
+      else{
+        frag_satd[bi]=oc_enc_frag_sad(_enc,src+frag_offs,
+         ref+frag_offs+mv_offs[0],ystride);
+      }
     }
   }
   mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi];
@@ -2088,9 +2129,15 @@
       bi=mapi&3;
       fragi=mb_map[pli][bi];
       frag_offs=frag_buf_offs[fragi];
-      frag_satd[mapii]=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
-       ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
-      frag_satd[mapii]+=abs(dc);
+      if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+        frag_satd[mapii]=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+         ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
+        frag_satd[mapii]+=abs(dc);
+      }
+      else{
+        frag_satd[mapii]=oc_enc_frag_sad2_thresh(_enc,src+frag_offs,
+         ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+      }
     }
   }
   else{
@@ -2100,9 +2147,15 @@
       bi=mapi&3;
       fragi=mb_map[pli][bi];
       frag_offs=frag_buf_offs[fragi];
-      frag_satd[mapii]=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
-       ref+frag_offs+mv_offs[0],ystride);
-      frag_satd[mapii]+=abs(dc);
+      if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+        frag_satd[mapii]=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+         ref+frag_offs+mv_offs[0],ystride);
+        frag_satd[mapii]+=abs(dc);
+      }
+      else{
+        frag_satd[mapii]=oc_enc_frag_sad(_enc,src+frag_offs,
+         ref+frag_offs+mv_offs[0],ystride);
+      }
     }
   }
   oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,_rd_scale,1);

Modified: trunk/theora/lib/collect.c
===================================================================
--- trunk/theora/lib/collect.c	2011-02-09 01:45:41 UTC (rev 17820)
+++ trunk/theora/lib/collect.c	2011-02-09 22:08:34 UTC (rev 17821)
@@ -5,7 +5,7 @@
  * 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                *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2011                *
  * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
@@ -23,8 +23,10 @@
 #if defined(OC_COLLECT_METRICS)
 
 int              OC_HAS_MODE_METRICS;
-double           OC_MODE_RD_WEIGHT[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
-oc_mode_metrics  OC_MODE_METRICS[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+double           OC_MODE_RD_WEIGHT_SATD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+double           OC_MODE_RD_WEIGHT_SAD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+oc_mode_metrics  OC_MODE_METRICS_SATD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+oc_mode_metrics  OC_MODE_METRICS_SAD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
 const char      *OC_MODE_METRICS_FILENAME="modedec.stats";
 
 void oc_mode_metrics_add(oc_mode_metrics *_metrics,
@@ -411,7 +413,9 @@
 
 /*Compile collected SATD/logq/rate/RMSE metrics into a form that's immediately
    useful for mode decision.*/
-void oc_mode_metrics_update(int _niters_min,int _reweight){
+void oc_mode_metrics_update(oc_mode_metrics (*_metrics)[3][2][OC_COMP_BINS],
+ int _niters_min,int _reweight,oc_mode_rd (*_table)[3][2][OC_COMP_BINS],
+ int _shift,double (*_weight)[3][2][OC_COMP_BINS]){
   int niters;
   int prevdr;
   int prevdd;
@@ -424,7 +428,7 @@
   dd=dr=INT_MAX;
   niters=0;
   /*The encoder interpolates rate and RMSE terms bilinearly from an
-     OC_LOGQ_BINS by OC_COMP_BINS grid of sample points in OC_MODE_RD.
+     OC_LOGQ_BINS by OC_COMP_BINS grid of sample points in _table.
     To find the sample values at the grid points that minimize the total
      squared prediction error actually requires solving a relatively sparse
      linear system with a number of variables equal to the number of grid
@@ -463,58 +467,58 @@
             if(qi>0&&si>0){
               q0[n]=OC_MODE_LOGQ[qi-1][pli][qti];
               q1[n]=OC_MODE_LOGQ[qi][pli][qti];
-              s0[n]=si-1<<OC_SATD_SHIFT;
-              s1[n]=si<<OC_SATD_SHIFT;
-              ra[n]=ldexp(OC_MODE_RD[qi-1][pli][qti][si-1].rate,-OC_BIT_SCALE);
-              da[n]=ldexp(OC_MODE_RD[qi-1][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
-              rb[n]=ldexp(OC_MODE_RD[qi-1][pli][qti][si].rate,-OC_BIT_SCALE);
-              db[n]=ldexp(OC_MODE_RD[qi-1][pli][qti][si].rmse,-OC_RMSE_SCALE);
-              rc[n]=ldexp(OC_MODE_RD[qi][pli][qti][si-1].rate,-OC_BIT_SCALE);
-              dc[n]=ldexp(OC_MODE_RD[qi][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
-              *(m+n++)=*(OC_MODE_METRICS[qi-1][pli][qti]+si-1);
+              s0[n]=si-1<<_shift;
+              s1[n]=si<<_shift;
+              ra[n]=ldexp(_table[qi-1][pli][qti][si-1].rate,-OC_BIT_SCALE);
+              da[n]=ldexp(_table[qi-1][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+              rb[n]=ldexp(_table[qi-1][pli][qti][si].rate,-OC_BIT_SCALE);
+              db[n]=ldexp(_table[qi-1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+              rc[n]=ldexp(_table[qi][pli][qti][si-1].rate,-OC_BIT_SCALE);
+              dc[n]=ldexp(_table[qi][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+              *(m+n++)=*(_metrics[qi-1][pli][qti]+si-1);
             }
             if(qi>0){
               ds=si+1<OC_COMP_BINS?1:-1;
               q0[n]=OC_MODE_LOGQ[qi-1][pli][qti];
               q1[n]=OC_MODE_LOGQ[qi][pli][qti];
-              s0[n]=si+ds<<OC_SATD_SHIFT;
-              s1[n]=si<<OC_SATD_SHIFT;
-              ra[n]=ldexp(OC_MODE_RD[qi-1][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+              s0[n]=si+ds<<_shift;
+              s1[n]=si<<_shift;
+              ra[n]=ldexp(_table[qi-1][pli][qti][si+ds].rate,-OC_BIT_SCALE);
               da[n]=
-               ldexp(OC_MODE_RD[qi-1][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
-              rb[n]=ldexp(OC_MODE_RD[qi-1][pli][qti][si].rate,-OC_BIT_SCALE);
-              db[n]=ldexp(OC_MODE_RD[qi-1][pli][qti][si].rmse,-OC_RMSE_SCALE);
-              rc[n]=ldexp(OC_MODE_RD[qi][pli][qti][si+ds].rate,-OC_BIT_SCALE);
-              dc[n]=ldexp(OC_MODE_RD[qi][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
-              *(m+n++)=*(OC_MODE_METRICS[qi-1][pli][qti]+si);
+               ldexp(_table[qi-1][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+              rb[n]=ldexp(_table[qi-1][pli][qti][si].rate,-OC_BIT_SCALE);
+              db[n]=ldexp(_table[qi-1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+              rc[n]=ldexp(_table[qi][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+              dc[n]=ldexp(_table[qi][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+              *(m+n++)=*(_metrics[qi-1][pli][qti]+si);
             }
             if(qi+1<OC_LOGQ_BINS&&si>0){
               q0[n]=OC_MODE_LOGQ[qi+1][pli][qti];
               q1[n]=OC_MODE_LOGQ[qi][pli][qti];
-              s0[n]=si-1<<OC_SATD_SHIFT;
-              s1[n]=si<<OC_SATD_SHIFT;
-              ra[n]=ldexp(OC_MODE_RD[qi+1][pli][qti][si-1].rate,-OC_BIT_SCALE);
-              da[n]=ldexp(OC_MODE_RD[qi+1][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
-              rb[n]=ldexp(OC_MODE_RD[qi+1][pli][qti][si].rate,-OC_BIT_SCALE);
-              db[n]=ldexp(OC_MODE_RD[qi+1][pli][qti][si].rmse,-OC_RMSE_SCALE);
-              rc[n]=ldexp(OC_MODE_RD[qi][pli][qti][si-1].rate,-OC_BIT_SCALE);
-              dc[n]=ldexp(OC_MODE_RD[qi][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
-              *(m+n++)=*(OC_MODE_METRICS[qi][pli][qti]+si-1);
+              s0[n]=si-1<<_shift;
+              s1[n]=si<<_shift;
+              ra[n]=ldexp(_table[qi+1][pli][qti][si-1].rate,-OC_BIT_SCALE);
+              da[n]=ldexp(_table[qi+1][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+              rb[n]=ldexp(_table[qi+1][pli][qti][si].rate,-OC_BIT_SCALE);
+              db[n]=ldexp(_table[qi+1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+              rc[n]=ldexp(_table[qi][pli][qti][si-1].rate,-OC_BIT_SCALE);
+              dc[n]=ldexp(_table[qi][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+              *(m+n++)=*(_metrics[qi][pli][qti]+si-1);
             }
             if(qi+1<OC_LOGQ_BINS){
               ds=si+1<OC_COMP_BINS?1:-1;
               q0[n]=OC_MODE_LOGQ[qi+1][pli][qti];
               q1[n]=OC_MODE_LOGQ[qi][pli][qti];
-              s0[n]=si+ds<<OC_SATD_SHIFT;
-              s1[n]=si<<OC_SATD_SHIFT;
-              ra[n]=ldexp(OC_MODE_RD[qi+1][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+              s0[n]=si+ds<<_shift;
+              s1[n]=si<<_shift;
+              ra[n]=ldexp(_table[qi+1][pli][qti][si+ds].rate,-OC_BIT_SCALE);
               da[n]=
-               ldexp(OC_MODE_RD[qi+1][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
-              rb[n]=ldexp(OC_MODE_RD[qi+1][pli][qti][si].rate,-OC_BIT_SCALE);
-              db[n]=ldexp(OC_MODE_RD[qi+1][pli][qti][si].rmse,-OC_RMSE_SCALE);
-              rc[n]=ldexp(OC_MODE_RD[qi][pli][qti][si+ds].rate,-OC_BIT_SCALE);
-              dc[n]=ldexp(OC_MODE_RD[qi][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
-              *(m+n++)=*(OC_MODE_METRICS[qi][pli][qti]+si);
+               ldexp(_table[qi+1][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+              rb[n]=ldexp(_table[qi+1][pli][qti][si].rate,-OC_BIT_SCALE);
+              db[n]=ldexp(_table[qi+1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+              rc[n]=ldexp(_table[qi][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+              dc[n]=ldexp(_table[qi][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+              *(m+n++)=*(_metrics[qi][pli][qti]+si);
             }
             /*On the first pass, initialize with a simple weighted average of
                the neighboring bins.*/
@@ -528,19 +532,19 @@
               }
               r=w>1E-3?r/w:0;
               d=w>1E-3?d/w:0;
-              OC_MODE_RD_WEIGHT[qi][pli][qti][si]=w;
+              _weight[qi][pli][qti][si]=w;
             }
             else{
               /*Update the grid point and save the weight for later.*/
-              OC_MODE_RD_WEIGHT[qi][pli][qti][si]=
+              _weight[qi][pli][qti][si]=
                oc_mode_metrics_solve(&r,&d,m,s0,s1,q0,q1,ra,rb,rc,da,db,dc,n);
             }
             rate=OC_CLAMPI(-32768,(int)(ldexp(r,OC_BIT_SCALE)+0.5),32767);
             rmse=OC_CLAMPI(-32768,(int)(ldexp(d,OC_RMSE_SCALE)+0.5),32767);
-            dr+=abs(rate-OC_MODE_RD[qi][pli][qti][si].rate);
-            dd+=abs(rmse-OC_MODE_RD[qi][pli][qti][si].rmse);
-            OC_MODE_RD[qi][pli][qti][si].rate=(ogg_int16_t)rate;
-            OC_MODE_RD[qi][pli][qti][si].rmse=(ogg_int16_t)rmse;
+            dr+=abs(rate-_table[qi][pli][qti][si].rate);
+            dd+=abs(rmse-_table[qi][pli][qti][si].rmse);
+            _table[qi][pli][qti][si].rate=(ogg_int16_t)rate;
+            _table[qi][pli][qti][si].rmse=(ogg_int16_t)rmse;
           }
         }
       }
@@ -561,12 +565,12 @@
         for(qi=0;qi<OC_LOGQ_BINS;qi++){
           for(si=0;si<OC_COMP_BINS;si++){
             double wt;
-            wt=OC_MODE_RD_WEIGHT[qi][pli][qti][si];
+            wt=_weight[qi][pli][qti][si];
             wt/=OC_ZWEIGHT+wt;
-            OC_MODE_RD[qi][pli][qti][si].rate=(ogg_int16_t)
-             (OC_MODE_RD[qi][pli][qti][si].rate*wt+0.5);
-            OC_MODE_RD[qi][pli][qti][si].rmse=(ogg_int16_t)
-             (OC_MODE_RD[qi][pli][qti][si].rmse*wt+0.5);
+            _table[qi][pli][qti][si].rate=(ogg_int16_t)
+             (_table[qi][pli][qti][si].rate*wt+0.5);
+            _table[qi][pli][qti][si].rmse=(ogg_int16_t)
+             (_table[qi][pli][qti][si].rmse*wt+0.5);
           }
         }
       }
@@ -574,49 +578,32 @@
   }
 }
 
+/*Dump the in memory mode metrics to a file.
+  Note this data format isn't portable between different platforms.*/
 void oc_mode_metrics_dump(void){
   FILE *fmetrics;
   fmetrics=fopen(OC_MODE_METRICS_FILENAME,"wb");
   if(fmetrics!=NULL){
-    (void)fwrite(OC_MODE_METRICS,sizeof(OC_MODE_METRICS),1,fmetrics);
     (void)fwrite(OC_MODE_LOGQ,sizeof(OC_MODE_LOGQ),1,fmetrics);
+    (void)fwrite(OC_MODE_METRICS_SATD,sizeof(OC_MODE_METRICS_SATD),1,fmetrics);
+    (void)fwrite(OC_MODE_METRICS_SAD,sizeof(OC_MODE_METRICS_SAD),1,fmetrics);
     fclose(fmetrics);
   }
 }
 
-void oc_mode_metrics_print(FILE *_fout){
+void oc_mode_metrics_print_rd(FILE *_fout,const char *_table_name,
+#if !defined(OC_COLLECT_METRICS)
+ const oc_mode_rd (*_mode_rd_table)[3][2][OC_COMP_BINS]){
+#else
+ oc_mode_rd (*_mode_rd_table)[3][2][OC_COMP_BINS]){
+#endif
   int qii;
   fprintf(_fout,
-   "/*File generated by libtheora with OC_COLLECT_METRICS"
-   " defined at compile time.*/\n"
-   "#if !defined(_modedec_H)\n"
-   "# define _modedec_H (1)\n"
-   "# include \"encint.h\"\n"
-   "\n"
-   "\n"
-   "\n"
-   "/*The log of the average quantizer for each of the OC_MODE_RD table rows\n"
-   "   (e.g., for the represented qi's, and each pli and qti), in Q10 format.\n"
-   "  The actual statistics used by the encoder will be interpolated from\n"
-   "   that table based on log_plq for the actual quantization matrix used.*/\n"
    "# if !defined(OC_COLLECT_METRICS)\n"
    "static const\n"
    "# endif\n"
-   "ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2]={\n");
+   "oc_mode_rd %s[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={\n",_table_name);
   for(qii=0;qii<OC_LOGQ_BINS;qii++){
-    fprintf(_fout,"  { {0x%04X,0x%04X},{0x%04X,0x%04X},{0x%04X,0x%04X} }%s\n",
-     OC_MODE_LOGQ[qii][0][0],OC_MODE_LOGQ[qii][0][1],OC_MODE_LOGQ[qii][1][0],
-     OC_MODE_LOGQ[qii][1][1],OC_MODE_LOGQ[qii][2][0],OC_MODE_LOGQ[qii][2][1],
-     qii+1<OC_LOGQ_BINS?",":"");
-  }
-  fprintf(_fout,
-   "};\n"
-   "\n"
-   "# if !defined(OC_COLLECT_METRICS)\n"
-   "static const\n"
-   "# endif\n"
-   "oc_mode_rd OC_MODE_RD[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={\n");
-  for(qii=0;qii<OC_LOGQ_BINS;qii++){
     int pli;
     fprintf(_fout,"  {\n");
     for(pli=0;pli<3;pli++){
@@ -635,8 +622,8 @@
         for(bin=0;bin<OC_COMP_BINS;bin++){
           if(bin&&!(bin&0x3))fprintf(_fout,"\n        ");
           fprintf(_fout,"{%5i,%5i}",
-           OC_MODE_RD[qii][pli][qti][bin].rate,
-           OC_MODE_RD[qii][pli][qti][bin].rmse);
+           _mode_rd_table[qii][pli][qti][bin].rate,
+           _mode_rd_table[qii][pli][qti][bin].rmse);
           if(bin+1<OC_COMP_BINS)fprintf(_fout,",");
         }
         fprintf(_fout,"\n      }");
@@ -653,7 +640,40 @@
   }
   fprintf(_fout,
    "};\n"
+   "\n");
+}
+
+void oc_mode_metrics_print(FILE *_fout){
+  int qii;
+  fprintf(_fout,
+   "/*File generated by libtheora with OC_COLLECT_METRICS"
+   " defined at compile time.*/\n"
+   "#if !defined(_modedec_H)\n"
+   "# define _modedec_H (1)\n"
+   "# include \"encint.h\"\n"
    "\n"
+   "\n"
+   "\n"
+   "/*The log of the average quantizer for each of the OC_MODE_RD table rows\n"
+   "   (e.g., for the represented qi's, and each pli and qti), in Q10 format.\n"
+   "  The actual statistics used by the encoder will be interpolated from\n"
+   "   that table based on log_plq for the actual quantization matrix used.*/\n"
+   "# if !defined(OC_COLLECT_METRICS)\n"
+   "static const\n"
+   "# endif\n"
+   "ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2]={\n");
+  for(qii=0;qii<OC_LOGQ_BINS;qii++){
+    fprintf(_fout,"  { {0x%04X,0x%04X},{0x%04X,0x%04X},{0x%04X,0x%04X} }%s\n",
+     OC_MODE_LOGQ[qii][0][0],OC_MODE_LOGQ[qii][0][1],OC_MODE_LOGQ[qii][1][0],
+     OC_MODE_LOGQ[qii][1][1],OC_MODE_LOGQ[qii][2][0],OC_MODE_LOGQ[qii][2][1],
+     qii+1<OC_LOGQ_BINS?",":"");
+  }
+  fprintf(_fout,
+   "};\n"
+   "\n");
+  oc_mode_metrics_print_rd(_fout,"OC_MODE_RD_SATD",OC_MODE_RD_SATD);
+  oc_mode_metrics_print_rd(_fout,"OC_MODE_RD_SAD",OC_MODE_RD_SAD);
+  fprintf(_fout,
    "#endif\n");
 }
 
@@ -664,11 +684,15 @@
   /*Load any existing mode metrics if we haven't already.*/
   if(!OC_HAS_MODE_METRICS){
     FILE *fmetrics;
-    memset(OC_MODE_METRICS,0,sizeof(OC_MODE_METRICS));
+    memset(OC_MODE_METRICS_SATD,0,sizeof(OC_MODE_METRICS_SATD));
+    memset(OC_MODE_METRICS_SAD,0,sizeof(OC_MODE_METRICS_SAD));
     fmetrics=fopen(OC_MODE_METRICS_FILENAME,"rb");
     if(fmetrics!=NULL){
-      (void)fread(OC_MODE_METRICS,sizeof(OC_MODE_METRICS),1,fmetrics);
+      /*Read in the binary structures as written my oc_mode_metrics_dump().
+        Note this format isn't portable between different platforms.*/
       (void)fread(OC_MODE_LOGQ,sizeof(OC_MODE_LOGQ),1,fmetrics);
+      (void)fread(OC_MODE_METRICS_SATD,sizeof(OC_MODE_METRICS_SATD),1,fmetrics);
+      (void)fread(OC_MODE_METRICS_SAD,sizeof(OC_MODE_METRICS_SAD),1,fmetrics);
       fclose(fmetrics);
     }
     else{
@@ -683,7 +707,10 @@
         }
       }
     }
-    oc_mode_metrics_update(100,1);
+    oc_mode_metrics_update(OC_MODE_METRICS_SATD,100,1,
+     OC_MODE_RD_SATD,OC_SATD_SHIFT,OC_MODE_RD_WEIGHT_SATD);
+    oc_mode_metrics_update(OC_MODE_METRICS_SAD,100,1,
+     OC_MODE_RD_SAD,OC_SAD_SHIFT,OC_MODE_RD_WEIGHT_SAD);
     OC_HAS_MODE_METRICS=1;
   }
 }
@@ -810,6 +837,7 @@
     64,64,64,64,64,64,64,64
   };
   const oc_fragment *frags;
+  const unsigned    *frag_sad;
   const unsigned    *frag_satd;
   const unsigned    *frag_ssd;
   const ptrdiff_t   *coded_fragis;
@@ -840,6 +868,7 @@
   }
   qti=_enc->state.frame_type;
   frags=_enc->state.frags;
+  frag_sad=_enc->frag_sad;
   frag_satd=_enc->frag_satd;
   frag_ssd=_enc->frag_ssd;
   coded_fragis=_enc->state.coded_fragis;
@@ -876,7 +905,9 @@
       int       huffi;
       int       skip;
       int       mb_mode;
+      unsigned  sad;
       unsigned  satd;
+      double    sqrt_ssd;
       int       bin;
       int       qtj;
       fragi=coded_fragis[fragii];
@@ -914,20 +945,29 @@
       mb_mode=frags[fragi].mb_mode;
       qii=frags[fragi].qii;
       qi=_enc->state.qis[qii];
+      sad=frag_sad[fragi]<<(pli+1&2);
       satd=frag_satd[fragi]<<(pli+1&2);
-      bin=OC_MINI(satd>>OC_SATD_SHIFT,OC_COMP_BINS-1);
+      sqrt_ssd=sqrt(frag_ssd[fragi]);
       qtj=mb_mode!=OC_MODE_INTRA;
       /*Accumulate statistics.
         The rate (frag_bits) and RMSE (sqrt(frag_ssd)) are not scaled by
          OC_BIT_SCALE and OC_RMSE_SCALE; this lets us change the scale factor
          yet still use old data.*/
+      bin=OC_MINI(satd>>OC_SATD_SHIFT,OC_COMP_BINS-1);
       oc_mode_metrics_add(
-       OC_MODE_METRICS[modelines[qii][pli][qtj]][pli][qtj]+bin,
-       fragw,satd,_enc->log_plq[qi][pli][qtj],frag_bits,sqrt(frag_ssd[fragi]));
+       OC_MODE_METRICS_SATD[modelines[qii][pli][qtj]][pli][qtj]+bin,
+       fragw,satd,_enc->log_plq[qi][pli][qtj],frag_bits,sqrt_ssd);
+      bin=OC_MINI(sad>>OC_SAD_SHIFT,OC_COMP_BINS-1);
+      oc_mode_metrics_add(
+       OC_MODE_METRICS_SAD[modelines[qii][pli][qtj]][pli][qtj]+bin,
+       fragw,sad,_enc->log_plq[qi][pli][qtj],frag_bits,sqrt_ssd);
     }
   }
-  /*Update global SATD/logq/rate/RMSE estimation matrix.*/
-  oc_mode_metrics_update(4,1);
+  /*Update global SA(T)D/logq/rate/RMSE estimation matrix.*/
+  oc_mode_metrics_update(OC_MODE_METRICS_SATD,4,1,
+   OC_MODE_RD_SATD,OC_SATD_SHIFT,OC_MODE_RD_WEIGHT_SATD);
+  oc_mode_metrics_update(OC_MODE_METRICS_SAD,4,1,
+   OC_MODE_RD_SAD,OC_SAD_SHIFT,OC_MODE_RD_WEIGHT_SAD);
 }
 # endif
 

Modified: trunk/theora/lib/collect.h
===================================================================
--- trunk/theora/lib/collect.h	2011-02-09 01:45:41 UTC (rev 17820)
+++ trunk/theora/lib/collect.h	2011-02-09 22:08:34 UTC (rev 17821)
@@ -79,10 +79,12 @@
    out the contributions from AC and DC into separate tables.*/
 
 extern ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2];
-extern oc_mode_rd  OC_MODE_RD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+extern oc_mode_rd  OC_MODE_RD_SATD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+extern oc_mode_rd  OC_MODE_RD_SAD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
 
 extern int              OC_HAS_MODE_METRICS;
-extern oc_mode_metrics  OC_MODE_METRICS[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+extern oc_mode_metrics  OC_MODE_METRICS_SATD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+extern oc_mode_metrics  OC_MODE_METRICS_SAD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
 extern const char      *OC_MODE_METRICS_FILENAME;
 
 void oc_mode_metrics_dump();
@@ -97,8 +99,9 @@
  const int *_q0,const int *_q1,
  const double *_ra,const double *_rb,const double *_rc,
  const double *_da,const double *_db,const double *_dc,int _n);
-void oc_mode_metrics_update(int _niters_min,int _reweight);
-
+void oc_mode_metrics_update(oc_mode_metrics (*_metrics)[3][2][OC_COMP_BINS],
+ int _niters_min,int _reweight,oc_mode_rd (*_table)[3][2][OC_COMP_BINS],
+ int shift,double (*_weight)[3][2][OC_COMP_BINS]);
 void oc_enc_mode_metrics_load(oc_enc_ctx *_enc);
 void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc);
 

Modified: trunk/theora/lib/encfrag.c
===================================================================
--- trunk/theora/lib/encfrag.c	2011-02-09 01:45:41 UTC (rev 17820)
+++ trunk/theora/lib/encfrag.c	2011-02-09 22:08:34 UTC (rev 17821)
@@ -86,6 +86,27 @@
   return sad;
 }
 
+unsigned oc_enc_frag_intra_sad_c(const unsigned char *_src, int _ystride){
+  const unsigned char *src = _src;
+  unsigned dc;
+  unsigned sad;
+  int      i;
+  dc=0;
+  for(i=8;i-->0;){
+    int j;
+    for(j=0;j<8;j++)dc+=src[j];
+    src+=_ystride;
+  }
+  dc=dc+32>>6;
+  sad=0;
+  for(i=8;i-->0;){
+    int j;
+    for(j=0;j<8;j++)sad+=abs(_src[j]-dc);
+    _src+=_ystride;
+  }
+  return sad;
+}
+
 static void oc_diff_hadamard(ogg_int16_t _buf[64],const unsigned char *_src,
  const unsigned char *_ref,int _ystride){
   int i;

Modified: trunk/theora/lib/encint.h
===================================================================
--- trunk/theora/lib/encint.h	2011-02-09 01:45:41 UTC (rev 17820)
+++ trunk/theora/lib/encint.h	2011-02-09 22:08:34 UTC (rev 17821)
@@ -79,6 +79,10 @@
 #   define oc_enc_frag_sad2_thresh(_enc,_src,_ref1,_ref2,_ystride,_thresh) \
   ((*(_enc)->opt_vtable.frag_sad2_thresh)(_src,_ref1,_ref2,_ystride,_thresh))
 #  endif
+#  if !defined(oc_enc_frag_intra_sad)
+#   define oc_enc_frag_intra_sad(_enc,_src,_ystride) \
+  ((*(_enc)->opt_vtable.frag_intra_sad)(_src,_ystride))
+#  endif
 #  if !defined(oc_enc_frag_satd)
 #   define oc_enc_frag_satd(_enc,_dc,_src,_ref,_ystride) \
   ((*(_enc)->opt_vtable.frag_satd)(_dc,_src,_ref,_ystride))
@@ -148,6 +152,10 @@
 #   define oc_enc_frag_sad2_thresh(_enc,_src,_ref1,_ref2,_ystride,_thresh) \
   oc_enc_frag_sad2_thresh_c(_src,_ref1,_ref2,_ystride,_thresh)
 #  endif
+#  if !defined(oc_enc_frag_intra_sad)
+#   define oc_enc_frag_intra_sad(_enc,_src,_ystride) \
+  oc_enc_frag_intra_sad_c(_src,_ystride)
+#  endif
 #  if !defined(oc_enc_frag_satd)
 #   define oc_enc_frag_satd(_enc,_dc,_src,_ref,_ystride) \
   oc_enc_frag_satd_c(_dc,_src,_ref,_ystride)
@@ -212,10 +220,12 @@
 #define OC_SP_LEVEL_EARLY_SKIP    (1)
 /*Use analysis shortcuts, single quantizer, and faster tokenization.*/
 #define OC_SP_LEVEL_FAST_ANALYSIS (2)
+/*Use SAD instead of SATD*/
+#define OC_SP_LEVEL_NOSATD        (3)
 /*Disable motion compensation.*/
-#define OC_SP_LEVEL_NOMC          (3)
+#define OC_SP_LEVEL_NOMC          (4)
 /*Maximum valid speed level.*/
-#define OC_SP_LEVEL_MAX           (3)
+#define OC_SP_LEVEL_MAX           (4)
 
 
 /*The number of extra bits of precision at which to store rate metrics.*/
@@ -292,6 +302,7 @@
   unsigned (*frag_sad2_thresh)(const unsigned char *_src,
    const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
    unsigned _thresh);
+  unsigned (*frag_intra_sad)(const unsigned char *_src,int _ystride);
   unsigned (*frag_satd)(int *_dc,const unsigned char *_src,
    const unsigned char *_ref,int _ystride);
   unsigned (*frag_satd2)(int *_dc,const unsigned char *_src,
@@ -680,6 +691,8 @@
   /*The last DC coefficient for each plane and reference frame.*/
   int                      dc_pred_last[3][4];
 #if defined(OC_COLLECT_METRICS)
+  /*Fragment SAD statistics for MB mode estimation metrics.*/
+  unsigned                *frag_sad;
   /*Fragment SATD statistics for MB mode estimation metrics.*/
   unsigned                *frag_satd;
   /*Fragment SSD statistics for MB mode estimation metrics.*/
@@ -807,6 +820,7 @@
 unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src,
  const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
  unsigned _thresh);
+unsigned oc_enc_frag_intra_sad_c(const unsigned char *_src, int _ystride);
 unsigned oc_enc_frag_satd_c(int *_dc,const unsigned char *_src,
  const unsigned char *_ref,int _ystride);
 unsigned oc_enc_frag_satd2_c(int *_dc,const unsigned char *_src,

Modified: trunk/theora/lib/encode.c
===================================================================
--- trunk/theora/lib/encode.c	2011-02-09 01:45:41 UTC (rev 17820)
+++ trunk/theora/lib/encode.c	2011-02-09 22:08:34 UTC (rev 17821)
@@ -942,6 +942,7 @@
   _enc->opt_vtable.frag_sad=oc_enc_frag_sad_c;
   _enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_c;
   _enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_c;
+  _enc->opt_vtable.frag_intra_sad=oc_enc_frag_intra_sad_c;
   _enc->opt_vtable.frag_satd=oc_enc_frag_satd_c;
   _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_c;
   _enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_c;
@@ -1180,6 +1181,7 @@
      _enc->state.fplanes[pli].nfrags,sizeof(**_enc->extra_bits));
   }
 #if defined(OC_COLLECT_METRICS)
+  _enc->frag_sad=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_sad));
   _enc->frag_satd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_satd));
   _enc->frag_ssd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_ssd));
 #endif
@@ -1212,7 +1214,7 @@
    ||_enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL
    ||_enc->extra_bits[2]==NULL
 #if defined(OC_COLLECT_METRICS)
-   ||_enc->frag_satd==NULL||_enc->frag_ssd==NULL
+   ||_enc->frag_sad==NULL||_enc->frag_satd==NULL||_enc->frag_ssd==NULL
 #endif
    ||oc_enc_set_quant_params(_enc,NULL)<0){
     oc_enc_clear(_enc);
@@ -1237,6 +1239,7 @@
   oc_mode_metrics_dump();
   _ogg_free(_enc->frag_ssd);
   _ogg_free(_enc->frag_satd);
+  _ogg_free(_enc->frag_sad);
 #endif
   for(pli=3;pli-->0;){
     oc_free_2d(_enc->extra_bits[pli]);

Modified: trunk/theora/lib/mcenc.c
===================================================================
--- trunk/theora/lib/mcenc.c	2011-02-09 01:45:41 UTC (rev 17820)
+++ trunk/theora/lib/mcenc.c	2011-02-09 22:08:34 UTC (rev 17821)
@@ -164,7 +164,6 @@
   _mcenc->ncandidates=ncandidates;
 }
 
-#if 0
 static unsigned oc_sad16_halfpel(const oc_enc_ctx *_enc,
  const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4],
  int _mvoffset0,int _mvoffset1,const unsigned char *_src,
@@ -180,7 +179,6 @@
   }
   return err;
 }
-#endif
 
 static unsigned oc_satd16_halfpel(const oc_enc_ctx *_enc,
  const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4],
@@ -233,9 +231,15 @@
     ptrdiff_t frag_offs;
     int       dc;
     frag_offs=_frag_buf_offs[_fragis[bi]];
-    err+=oc_enc_frag_satd(_enc,&dc,
-     _src+frag_offs,_ref+frag_offs+mvoffset,_ystride);
-    err+=abs(dc);
+    if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+      err+=oc_enc_frag_satd(_enc,&dc,
+       _src+frag_offs,_ref+frag_offs+mvoffset,_ystride);
+      err+=abs(dc);
+    }
+    else{
+      err+=oc_enc_frag_sad(_enc,
+       _src+frag_offs,_ref+frag_offs+mvoffset,_ystride);
+    }
   }
   return err;
 }
@@ -642,8 +646,14 @@
     ymask=OC_SIGNMASK(((_vec[1]<<1)+dy)^dy);
     mvoffset0=mvoffset_base+(dx&xmask)+(offset_y[site]&ymask);
     mvoffset1=mvoffset_base+(dx&~xmask)+(offset_y[site]&~ymask);
-    err=oc_satd16_halfpel(_enc,frag_buf_offs,fragis,
-     mvoffset0,mvoffset1,src,ref,ystride,_best_err);
+    if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+      err=oc_satd16_halfpel(_enc,frag_buf_offs,fragis,
+       mvoffset0,mvoffset1,src,ref,ystride,_best_err);
+    }
+    else{
+      err=oc_sad16_halfpel(_enc,frag_buf_offs,fragis,
+           mvoffset0,mvoffset1,src,ref,ystride,_best_err);
+    }
     if(err<_best_err){
       _best_err=err;
       best_site=site;

Modified: trunk/theora/lib/modedec.h
===================================================================
--- trunk/theora/lib/modedec.h	2011-02-09 01:45:41 UTC (rev 17820)
+++ trunk/theora/lib/modedec.h	2011-02-09 22:08:34 UTC (rev 17821)
@@ -26,7 +26,7 @@
 # if !defined(OC_COLLECT_METRICS)
 static const
 # endif
-oc_mode_rd OC_MODE_RD[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={
+oc_mode_rd OC_MODE_RD_SATD[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={
   {
     {
       /*Y'  qi=0  INTRA*/
@@ -525,4 +525,506 @@
   }
 };
 
+# if !defined(OC_COLLECT_METRICS)
+static const
+# endif
+oc_mode_rd OC_MODE_RD_SAD[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={
+  {
+    {
+      /*Y'  qi=0  INTRA*/
+      {
+        {   33,  122},{   57, 1297},{   13, 2226},{  157, 3890},
+        {  227, 3682},{  169, 3084},{  197, 2700},{  227, 3238},
+        {  290, 4294},{  354, 5230},{  406, 5615},{  417, 5322},
+        {  452, 5462},{  455, 5683},{  493, 5938},{  553, 6374},
+        {  558, 6464},{  606, 6493},{  616, 6417},{  643, 6557},
+        {  641, 6664},{  716, 7285},{  748, 7518},{  747, 7502}
+      },
+      /*Y'  qi=0  INTER*/
+      {
+        {   16,  205},{    5, 1338},{   16, 2554},{    6, 3809},
+        {    9, 5188},{   58, 6446},{   76, 7561},{   95, 8648},
+        {  124, 9713},{  158,10787},{  193,11887},{  233,12991},
+        {  270,14116},{  307,15236},{  341,16346},{  372,17426},
+        {  398,18499},{  422,19594},{  448,20669},{  479,21732},
+        {  526,22720},{  583,23572},{  655,24516},{  758,24647}
+      }
+    },
+    {
+      /*Cb  qi=0  INTRA*/
+      {
+        {   26,   40},{   23,  589},{   27,  784},{   27, 1079},
+        {   24, 1186},{   25, 1641},{   25, 1915},{   29, 2207},
+        {   39, 2361},{   39, 2746},{   32, 3020},{   16, 3387},
+        {   31, 3604},{   36, 4076},{   69, 4426},{  102, 4724},
+        {  139, 4923},{  196, 5061},{  211, 5103},{  214, 5063},
+        {  161, 4466},{  208, 4793},{  218, 4537},{  219, 4539}
+      },
+      /*Cb  qi=0  INTER*/
+      {
+        {    3,  164},{    1,  535},{    1,  779},{    2, 1048},
+        {    3, 1267},{    1, 1625},{    2, 1921},{    5, 2224},
+        {    8, 2481},{    8, 2813},{    4, 3089},{   -2, 3386},
+        {   -9, 3642},{  -14, 3993},{  -11, 4300},{   -6, 4628},
+        {    4, 4929},{   25, 5299},{   44, 5623},{   83, 5915},
+        {   93, 6186},{   91, 6483},{   90, 6775},{   95, 6952}
+      }
+    },
+    {
+      /*Cr  qi=0  INTRA*/
+      {
+        {   22,   49},{   26,  579},{   23,  762},{   15, 1050},
+        {   20, 1191},{   24, 1608},{   26, 1875},{   35, 2173},
+        {   39, 2359},{   30, 2736},{   16, 2987},{    0, 3334},
+        {   14, 3625},{   11, 4095},{   57, 4512},{   95, 4793},
+        {  141, 4949},{  206, 5242},{  230, 5191},{  242, 5177},
+        {  178, 4775},{  237, 5010},{  223, 4656},{  224, 4657}
+      },
+      /*Cr  qi=0  INTER*/
+      {
+        {    3,  163},{    1,  536},{    1,  773},{    3, 1023},
+        {    2, 1225},{    1, 1607},{    1, 1900},{    5, 2204},
+        {    9, 2453},{    8, 2781},{    3, 3049},{   -5, 3338},
+        {  -13, 3570},{  -17, 3950},{  -13, 4255},{   -6, 4596},
+        {    7, 4893},{   33, 5300},{   53, 5632},{   97, 5942},
+        {  103, 6216},{   96, 6522},{   91, 6849},{   98, 6995}
+      }
+    }
+  },
+  {
+    {
+      /*Y'  qi=9  INTRA*/
+      {
+        {   47,  152},{   50, 1213},{  144, 2543},{  242, 2332},
+        {  210, 1894},{  250, 2386},{  328, 3094},{  407, 3419},
+        {  464, 3507},{  522, 3770},{  613, 4194},{  657, 4618},
+        {  753, 5137},{  796, 5248},{  842, 5110},{  927, 5330},
+        {  994, 5487},{ 1008, 5463},{ 1101, 5794},{ 1169, 5966},
+        { 1208, 6121},{ 1331, 6447},{ 1445, 6618},{ 1449, 6616}
+      },
+      /*Y'  qi=9  INTER*/
+      {
+        {    4,  218},{   16, 1314},{    4, 2563},{   37, 3882},
+        {   83, 5058},{  109, 6184},{  161, 7292},{  224, 8389},
+        {  287, 9485},{  349,10565},{  411,11608},{  464,12648},
+        {  518,13664},{  575,14650},{  649,15585},{  742,16451},
+        {  862,17214},{ 1003,17860},{ 1179,18325},{ 1372,18648},
+        { 1576,18878},{ 1795,18903},{ 2040,18880},{ 2116,18759}
+      }
+    },
+    {
+      /*Cb  qi=9  INTRA*/
+      {
+        {   27,   42},{   23,  587},{   34,  782},{   37, 1079},
+        {   34, 1204},{   42, 1630},{   37, 1887},{   25, 2210},
+        {   40, 2455},{   71, 2880},{  112, 3193},{  156, 3427},
+        {  168, 3403},{  217, 3488},{  203, 3335},{  224, 3200},
+        {  191, 2742},{  195, 2810},{  207, 2665},{  201, 2661},
+        {  169, 2078},{  211, 2720},{  226, 2813},{  228, 2824}
+      },
+      /*Cb  qi=9  INTER*/
+      {
+        {    4,  158},{    2,  537},{    3,  779},{    2, 1045},
+        {    3, 1284},{    7, 1629},{    7, 1917},{    1, 2218},
+        {   -4, 2497},{   -3, 2845},{    6, 3162},{   23, 3482},
+        {   42, 3788},{   62, 4116},{   76, 4416},{   84, 4700},
+        {   91, 4975},{   95, 5259},{   97, 5518},{   94, 5790},
+        {   99, 6052},{  111, 6311},{  126, 6601},{  136, 6719}
+      }
+    },
+    {
+      /*Cr  qi=9  INTRA*/
+      {
+        {   25,   50},{   32,  576},{   32,  762},{   21, 1049},
+        {   28, 1207},{   41, 1603},{   36, 1839},{   26, 2170},
+        {   34, 2462},{   59, 2872},{  109, 3176},{  157, 3364},
+        {  188, 3397},{  231, 3418},{  250, 3341},{  261, 3228},
+        {  222, 2814},{  258, 3091},{  234, 2915},{  228, 3042},
+        {  210, 2610},{  273, 3210},{  274, 3231},{  276, 3239}
+      },
+      /*Cr  qi=9  INTER*/
+      {
+        {    4,  156},{    2,  538},{    3,  772},{    2, 1028},
+        {    3, 1254},{    7, 1613},{    7, 1893},{    0, 2191},
+        {   -8, 2454},{   -4, 2811},{    7, 3121},{   27, 3442},
+        {   48, 3749},{   72, 4101},{   88, 4410},{   91, 4698},
+        {   99, 4988},{   99, 5279},{  101, 5542},{   95, 5813},
+        {   99, 6088},{  114, 6367},{  125, 6683},{  137, 6761}
+      }
+    }
+  },
+  {
+    {
+      /*Y'  qi=18  INTRA*/
+      {
+        {   51,   88},{   88, 1344},{  258, 1643},{  228, 1325},
+        {  372, 2208},{  443, 2371},{  520, 2382},{  584, 2477},
+        {  739, 2906},{  859, 3348},{ 1008, 3697},{ 1131, 3884},
+        { 1278, 4110},{ 1349, 4229},{ 1431, 4329},{ 1544, 4395},
+        { 1602, 4439},{ 1669, 4535},{ 1814, 4656},{ 1883, 4716},
+        { 1957, 4940},{ 2101, 5019},{ 2259, 5249},{ 2265, 5246}
+      },
+      /*Y'  qi=18  INTER*/
+      {
+        {   26,  195},{    1, 1317},{   45, 2595},{  103, 3750},
+        {  168, 4903},{  281, 6007},{  397, 7062},{  513, 8064},
+        {  630, 9010},{  758, 9902},{  906,10732},{ 1095,11463},
+        { 1338,12060},{ 1629,12490},{ 1969,12724},{ 2313,12842},
+        { 2666,12828},{ 2993,12747},{ 3294,12670},{ 3558,12553},
+        { 3813,12440},{ 3990,12379},{ 4177,12291},{ 4226,12265}
+      }
+    },
+    {
+      /*Cb  qi=18  INTRA*/
+      {
+        {   31,   43},{   33,  585},{   40,  781},{   58, 1077},
+        {   45, 1189},{   58, 1655},{   66, 1983},{  123, 2221},
+        {  168, 2193},{  227, 2321},{  241, 2246},{  250, 2208},
+        {  221, 1786},{  250, 2087},{  247, 2036},{  250, 2164},
+        {  241, 2054},{  287, 2453},{  302, 2551},{  335, 2758},
+        {  279, 2511},{  379, 2973},{  404, 3028},{  406, 3029}
+      },
+      /*Cb  qi=18  INTER*/
+      {
+        {    7,  153},{    4,  537},{    3,  777},{    9, 1034},
+        {    6, 1282},{    0, 1630},{    0, 1943},{   21, 2252},
+        {   48, 2567},{   67, 2881},{   83, 3178},{   89, 3463},
+        {   92, 3738},{   99, 4024},{  114, 4289},{  131, 4552},
+        {  153, 4814},{  179, 5081},{  207, 5333},{  241, 5581},
+        {  273, 5822},{  303, 6068},{  335, 6368},{  353, 6432}
+      }
+    },
+    {
+      /*Cr  qi=18  INTRA*/
+      {
+        {   31,   49},{   42,  575},{   42,  763},{   38, 1045},
+        {   41, 1184},{   56, 1631},{   87, 1968},{  163, 2177},
+        {  191, 2188},{  236, 2264},{  240, 2101},{  234, 2047},
+        {  206, 1651},{  222, 1966},{  238, 2013},{  240, 2176},
+        {  229, 2098},{  321, 2592},{  341, 2748},{  378, 3025},
+        {  367, 2849},{  442, 3283},{  453, 3315},{  455, 3313}
+      },
+      /*Cr  qi=18  INTER*/
+      {
+        {    6,  151},{    3,  539},{    3,  775},{    8, 1027},
+        {    6, 1260},{   -3, 1619},{    0, 1927},{   24, 2238},
+        {   58, 2558},{   76, 2871},{   92, 3173},{   96, 3461},
+        {   98, 3742},{  104, 4032},{  116, 4306},{  136, 4578},
+        {  158, 4839},{  185, 5123},{  217, 5383},{  250, 5642},
+        {  279, 5910},{  306, 6169},{  333, 6502},{  350, 6522}
+      }
+    }
+  },
+  {
+    {
+      /*Y'  qi=27  INTRA*/
+      {
+        {   10,   85},{  280, 1349},{  278,  815},{  497, 1699},
+        {  600, 1569},{  744, 1944},{  894, 2114},{ 1040, 2292},
+        { 1216, 2484},{ 1485, 2816},{ 1778, 3065},{ 1990, 3243},
+        { 2199, 3381},{ 2326, 3515},{ 2370, 3422},{ 2512, 3581},
+        { 2548, 3526},{ 2656, 3615},{ 2803, 3679},{ 2946, 3766},
+        { 3023, 3824},{ 3179, 3908},{ 3374, 4035},{ 3377, 4030}
+      },
+      /*Y'  qi=27  INTER*/
+      {
+        {   -2,  172},{   31, 1347},{  117, 2488},{  245, 3651},
+        {  448, 4719},{  668, 5679},{  918, 6524},{ 1204, 7255},
+        { 1557, 7848},{ 1998, 8281},{ 2511, 8531},{ 3055, 8642},
+        { 3582, 8648},{ 4062, 8611},{ 4482, 8582},{ 4845, 8560},
+        { 5140, 8560},{ 5423, 8581},{ 5645, 8596},{ 5855, 8586},
+        { 6061, 8608},{ 6211, 8558},{ 6402, 8583},{ 6472, 8575}
+      }
+    },
+    {
+      /*Cb  qi=27  INTRA*/
+      {
+        {   47,   49},{   35,  580},{   64,  778},{   69, 1071},
+        {   98, 1289},{  186, 1556},{  177, 1654},{  197, 1736},
+        {  211, 1373},{  284, 1742},{  321, 1840},{  344, 2024},
+        {  321, 1969},{  386, 2254},{  397, 2281},{  425, 2320},
+        {  396, 2088},{  448, 2284},{  462, 2213},{  482, 2274},
+        {  410, 1894},{  513, 2310},{  546, 2332},{  549, 2334}
+      },
+      /*Cb  qi=27  INTER*/
+      {
+        {   11,  145},{    5,  539},{   11,  771},{    0, 1033},
+        {    9, 1334},{   44, 1644},{   70, 1934},{   87, 2227},
+        {   96, 2508},{  113, 2812},{  139, 3085},{  174, 3352},
+        {  216, 3614},{  261, 3873},{  305, 4123},{  349, 4372},
+        {  396, 4611},{  442, 4853},{  493, 5088},{  543, 5313},
+        {  600, 5537},{  662, 5752},{  737, 6018},{  775, 6037}
+      }
+    },
+    {
+      /*Cr  qi=27  INTRA*/
+      {
+        {   49,   52},{   57,  570},{   61,  762},{   44, 1048},
+        {   80, 1291},{  196, 1513},{  224, 1522},{  242, 1532},
+        {  213, 1293},{  260, 1639},{  253, 1691},{  291, 1915},
+        {  294, 1897},{  367, 2178},{  395, 2258},{  432, 2310},
+        {  407, 2105},{  503, 2369},{  492, 2293},{  552, 2421},
+        {  496, 2099},{  598, 2549},{  624, 2531},{  627, 2532}
+      },
+      /*Cr  qi=27  INTER*/
+      {
+        {   10,  147},{    4,  538},{   11,  769},{    0, 1022},
+        {    9, 1318},{   51, 1635},{   80, 1925},{   97, 2214},
+        {  101, 2493},{  115, 2805},{  143, 3083},{  182, 3361},
+        {  226, 3625},{  270, 3898},{  319, 4157},{  366, 4405},
+        {  418, 4649},{  467, 4904},{  509, 5157},{  548, 5412},
+        {  589, 5659},{  636, 5909},{  683, 6208},{  710, 6190}
+      }
+    }
+  },
+  {
+    {
+      /*Y'  qi=36  INTRA*/
+      {
+        {   86,  252},{  345,  662},{  476, 1143},{  698, 1169},
+        {  894, 1457},{ 1218, 1728},{ 1465, 1849},{ 1731, 2019},
+        { 2183, 2298},{ 2666, 2511},{ 3116, 2731},{ 3371, 2813},
+        { 3621, 2923},{ 3675, 2949},{ 3710, 2921},{ 3740, 2896},
+        { 3746, 2895},{ 3886, 2978},{ 4069, 2991},{ 4229, 3016},
+        { 4338, 3102},{ 4530, 3124},{ 4751, 3248},{ 4753, 3244}
+      },
+      /*Y'  qi=36  INTER*/
+      {
+        {    0,  208},{   73, 1293},{  248, 2449},{  616, 3461},
+        { 1061, 4329},{ 1601, 4986},{ 2189, 5447},{ 2875, 5723},
+        { 3620, 5844},{ 4328, 5879},{ 4954, 5880},{ 5490, 5890},
+        { 5934, 5901},{ 6353, 5926},{ 6706, 5924},{ 7036, 5930},
+        { 7338, 5938},{ 7600, 5930},{ 7870, 5939},{ 8065, 5921},
+        { 8318, 5914},{ 8451, 5912},{ 8648, 5923},{ 8734, 5926}
+      }
+    },
+    {
+      /*Cb  qi=36  INTRA*/
+      {
+        {   52,   54},{   52,  575},{  103,  776},{  185, 1072},
+        {  172, 1069},{  211, 1302},{  217, 1413},{  285, 1586},
+        {  330, 1463},{  453, 1694},{  500, 1741},{  545, 1852},
+        {  501, 1650},{  584, 1874},{  587, 1856},{  638, 1919},
+        {  581, 1742},{  670, 1953},{  688, 1934},{  731, 2030},
+        {  637, 1794},{  806, 2123},{  840, 2091},{  843, 2091}
+      },
+      /*Cb  qi=36  INTER*/
+      {
+        {   19,  142},{   17,  534},{    6,  772},{   44, 1023},
+        {   82, 1296},{   94, 1614},{  117, 1903},{  158, 2187},
+        {  218, 2450},{  285, 2703},{  352, 2943},{  421, 3181},
+        {  489, 3415},{  564, 3644},{  647, 3861},{  748, 4060},
+        {  861, 4246},{  993, 4419},{ 1132, 4576},{ 1282, 4744},
+        { 1445, 4894},{ 1600, 5034},{ 1782, 5211},{ 1837, 5200}
+      }
+    },
+    {
+      /*Cr  qi=36  INTRA*/
+      {
+        {   62,   55},{   90,  561},{   56,  767},{  148, 1014},
+        {  207,  981},{  258, 1216},{  273, 1253},{  326, 1392},
+        {  338, 1383},{  417, 1613},{  443, 1629},{  497, 1734},
+        {  466, 1525},{  561, 1778},{  577, 1787},{  631, 1892},
+        {  591, 1706},{  715, 1980},{  730, 1958},{  822, 2113},
+        {  755, 1935},{  928, 2228},{  935, 2205},{  938, 2205}
+      },
+      /*Cr  qi=36  INTER*/
+      {
+        {   14,  145},{   16,  535},{    5,  772},{   44, 1017},
+        {   91, 1296},{  100, 1605},{  122, 1891},{  163, 2174},
+        {  225, 2443},{  294, 2707},{  362, 2962},{  436, 3210},
+        {  518, 3437},{  607, 3664},{  702, 3876},{  795, 4094},
+        {  886, 4310},{  980, 4538},{ 1089, 4749},{ 1216, 4927},
+        { 1357, 5116},{ 1506, 5247},{ 1758, 5338},{ 1787, 5306}
+      }
+    }
+  },
+  {
+    {
+      /*Y'  qi=45  INTRA*/
+      {
+        {  185,  246},{  513,  647},{  883,  891},{ 1313, 1142},
+        { 1760, 1351},{ 2368, 1595},{ 2828, 1718},{ 3097, 1780},
+        { 3762, 1951},{ 4454, 2121},{ 4986, 2227},{ 5281, 2281},
+        { 5477, 2299},{ 5431, 2288},{ 5425, 2283},{ 5439, 2290},
+        { 5324, 2249},{ 5509, 2279},{ 5703, 2321},{ 5896, 2348},
+        { 6049, 2370},{ 6253, 2425},{ 6415, 2432},{ 6419, 2430}
+      },
+      /*Y'  qi=45  INTER*/
+      {
+        {    6,  215},{  152, 1261},{  691, 2314},{ 1538, 3095},
+        { 2505, 3632},{ 3475, 3935},{ 4355, 4084},{ 5209, 4139},
+        { 5985, 4162},{ 6644, 4185},{ 7235, 4190},{ 7768, 4196},
+        { 8266, 4200},{ 8736, 4210},{ 9143, 4207},{ 9511, 4215},
+        { 9828, 4209},{10112, 4224},{10374, 4226},{10642, 4232},
+        {10842, 4219},{10971, 4208},{11200, 4211},{11299, 4216}
+      }
+    },
+    {
+      /*Cb  qi=45  INTRA*/
+      {
+        {   58,   71},{   66,  548},{  155,  762},{  213,  944},
+        {  192,  731},{  324, 1147},{  401, 1366},{  481, 1480},
+        {  508, 1238},{  657, 1522},{  727, 1563},{  794, 1611},
+        {  761, 1470},{  885, 1710},{  893, 1700},{  958, 1760},
+        {  893, 1543},{  985, 1719},{ 1014, 1732},{ 1082, 1784},
+        {  963, 1519},{ 1152, 1800},{ 1221, 1830},{ 1226, 1830}
+      },
+      /*Cb  qi=45  INTER*/
+      {
+        {   35,  135},{   12,  532},{   54,  769},{  106, 1007},
+        {  127, 1258},{  198, 1565},{  289, 1832},{  398, 2082},
+        {  520, 2302},{  653, 2511},{  800, 2705},{  956, 2897},
+        { 1143, 3064},{ 1358, 3220},{ 1623, 3335},{ 1913, 3444},
+        { 2198, 3534},{ 2502, 3626},{ 2787, 3711},{ 3114, 3783},
+        { 3454, 3831},{ 3711, 3871},{ 4163, 3901},{ 4221, 3890}
+      }
+    },
+    {
+      /*Cr  qi=45  INTRA*/
+      {
+        {   93,   68},{   72,  541},{  154,  769},{  239,  848},
+        {  214,  623},{  377, 1060},{  437, 1200},{  514, 1280},
+        {  512, 1160},{  625, 1453},{  657, 1470},{  718, 1516},
+        {  692, 1331},{  831, 1617},{  875, 1609},{  944, 1678},
+        {  886, 1469},{ 1061, 1699},{ 1082, 1714},{ 1226, 1823},
+        { 1113, 1581},{ 1324, 1872},{ 1370, 1925},{ 1374, 1924}
+      },
+      /*Cr  qi=45  INTER*/
+      {
+        {   31,  140},{   13,  533},{   52,  770},{  109, 1000},
+        {  134, 1253},{  201, 1555},{  298, 1821},{  411, 2076},
+        {  525, 2314},{  659, 2545},{  828, 2747},{ 1019, 2918},
+        { 1205, 3082},{ 1405, 3266},{ 1609, 3443},{ 1847, 3606},
+        { 2085, 3730},{ 2404, 3835},{ 2709, 3876},{ 3049, 3886},
+        { 3381, 3821},{ 3708, 3780},{ 4026, 3663},{ 4043, 3646}
+      }
+    }
+  },
+  {
+    {
+      /*Y'  qi=54  INTRA*/
+      {
+        {  316,  203},{  720,  585},{ 1596, 1077},{ 2316, 1289},
+        { 2687, 1439},{ 3133, 1593},{ 3495, 1706},{ 3836, 1775},
+        { 4249, 1892},{ 4804, 2031},{ 5320, 2139},{ 5617, 2203},
+        { 5726, 2199},{ 5726, 2176},{ 5682, 2146},{ 5677, 2127},
+        { 5717, 2124},{ 5707, 2129},{ 5853, 2148},{ 6110, 2180},
+        { 6454, 2247},{ 6714, 2287},{ 6845, 2304},{ 6854, 2303}
+      },
+      /*Y'  qi=54  INTER*/
+      {
+        {  -48,  217},{  314, 1261},{ 1450, 2126},{ 2761, 2728},
+        { 4275, 3012},{ 5408, 3167},{ 6305, 3245},{ 7165, 3290},
+        { 7966, 3325},{ 8698, 3359},{ 9352, 3377},{ 9907, 3391},
+        {10389, 3390},{10856, 3395},{11170, 3385},{11530, 3385},
+        {11780, 3362},{12018, 3362},{12266, 3361},{12443, 3339},
+        {12683, 3342},{12713, 3317},{12967, 3325},{13082, 3332}
+      }
+    },
+    {
+      /*Cb  qi=54  INTRA*/
+      {
+        {   94,   73},{   83,  557},{  152,  818},{  304,  919},
+        {  341,  819},{  506, 1128},{  593, 1281},{  700, 1389},
+        {  714, 1225},{  907, 1502},{  981, 1549},{ 1062, 1641},
+        { 1032, 1523},{ 1170, 1710},{ 1217, 1727},{ 1258, 1714},
+        { 1216, 1575},{ 1309, 1682},{ 1331, 1656},{ 1393, 1712},
+        { 1247, 1456},{ 1469, 1728},{ 1530, 1711},{ 1532, 1711}
+      },
+      /*Cb  qi=54  INTER*/
+      {
+        {   33,  133},{   12,  532},{   70,  770},{  171,  996},
+        {  279, 1233},{  427, 1503},{  600, 1736},{  824, 1939},
+        { 1101, 2097},{ 1411, 2237},{ 1735, 2374},{ 2097, 2493},
+        { 2486, 2606},{ 2916, 2691},{ 3297, 2771},{ 3715, 2826},
+        { 4088, 2855},{ 4460, 2886},{ 4849, 2911},{ 5198, 2932},
+        { 5489, 2940},{ 5875, 2981},{ 6208, 3017},{ 6270, 3012}
+      }
+    },
+    {
+      /*Cr  qi=54  INTRA*/
+      {
+        {  103,   63},{   83,  580},{  258,  796},{  301,  802},
+        {  361,  675},{  538, 1001},{  625, 1097},{  713, 1171},
+        {  699, 1103},{  868, 1380},{  915, 1400},{  970, 1491},
+        {  923, 1365},{ 1070, 1603},{ 1154, 1655},{ 1206, 1677},
+        { 1157, 1541},{ 1366, 1736},{ 1391, 1723},{ 1506, 1797},
+        { 1388, 1556},{ 1616, 1828},{ 1655, 1797},{ 1658, 1796}
+      },
+      /*Cr  qi=54  INTER*/
+      {
+        {   30,  138},{   14,  532},{   63,  771},{  176,  990},
+        {  299, 1226},{  438, 1496},{  606, 1735},{  814, 1950},
+        { 1089, 2127},{ 1417, 2281},{ 1761, 2421},{ 2104, 2571},
+        { 2467, 2701},{ 2881, 2827},{ 3303, 2900},{ 3735, 2917},
+        { 4183, 2913},{ 4529, 2882},{ 4915, 2844},{ 5168, 2796},
+        { 5410, 2763},{ 5562, 2753},{ 5815, 2764},{ 5832, 2755}
+      }
+    }
+  },
+  {
+    {
+      /*Y'  qi=63  INTRA*/
+      {
+        {  421,  194},{ 1272,  564},{ 3016,  943},{ 3831, 1079},
+        { 4282, 1174},{ 4799, 1290},{ 5166, 1348},{ 5259, 1350},
+        { 5720, 1426},{ 6501, 1539},{ 7048, 1606},{ 7328, 1642},
+        { 7374, 1622},{ 7349, 1612},{ 7192, 1578},{ 7207, 1571},
+        { 7161, 1555},{ 7259, 1573},{ 7432, 1592},{ 7710, 1613},
+        { 8167, 1672},{ 8425, 1697},{ 8597, 1710},{ 8602, 1710}
+      },
+      /*Y'  qi=63  INTER*/
+      {
+        { -584,  286},{ 1231, 1186},{ 3939, 1663},{ 6096, 1865},
+        { 7849, 1929},{ 8934, 1995},{ 9962, 2039},{11038, 2078},
+        {12016, 2092},{12889, 2100},{13617, 2096},{14221, 2089},
+        {14743, 2083},{15240, 2081},{15619, 2074},{15992, 2065},
+        {16314, 2065},{16529, 2059},{16822, 2056},{17041, 2049},
+        {17321, 2052},{17408, 2043},{17670, 2051},{17801, 2053}
+      }
+    },
+    {
+      /*Cb  qi=63  INTRA*/
+      {
+        {  154,   55},{  280,  582},{  507,  731},{  788,  853},
+        {  763,  738},{ 1141, 1008},{ 1323, 1090},{ 1540, 1220},
+        { 1487, 1089},{ 1861, 1322},{ 1983, 1347},{ 2145, 1425},
+        { 2047, 1317},{ 2334, 1475},{ 2352, 1413},{ 2458, 1467},
+        { 2243, 1270},{ 2464, 1413},{ 2423, 1335},{ 2506, 1385},
+        { 2182, 1180},{ 2565, 1376},{ 2555, 1321},{ 2557, 1321}
+      },
+      /*Cb  qi=63  INTER*/
+      {
+        {   34,  133},{    6,  531},{  139,  767},{  344,  975},
+        {  608, 1180},{ 1048, 1367},{ 1651, 1495},{ 2376, 1572},
+        { 3103, 1609},{ 3752, 1646},{ 4373, 1680},{ 4980, 1718},
+        { 5540, 1744},{ 6023, 1764},{ 6431, 1766},{ 6800, 1769},
+        { 7149, 1775},{ 7529, 1777},{ 7920, 1817},{ 8198, 1808},
+        { 8691, 1848},{ 8965, 1845},{ 9372, 1865},{ 9459, 1863}
+      }
+    },
+    {
+      /*Cr  qi=63  INTRA*/
+      {
+        {  121,   59},{  392,  570},{  609,  654},{  800,  760},
+        {  720,  598},{ 1192,  892},{ 1298,  897},{ 1470, 1027},
+        { 1411,  962},{ 1761, 1184},{ 1826, 1197},{ 1981, 1308},
+        { 1854, 1198},{ 2229, 1427},{ 2269, 1365},{ 2428, 1453},
+        { 2217, 1265},{ 2558, 1435},{ 2541, 1356},{ 2660, 1417},
+        { 2337, 1199},{ 2688, 1382},{ 2603, 1301},{ 2605, 1300}
+      },
+      /*Cr  qi=63  INTER*/
+      {
+        {   31,  137},{   10,  531},{  136,  768},{  360,  971},
+        {  638, 1166},{ 1029, 1373},{ 1604, 1519},{ 2351, 1595},
+        { 3129, 1640},{ 3861, 1691},{ 4491, 1751},{ 5101, 1783},
+        { 5635, 1784},{ 6136, 1779},{ 6550, 1763},{ 6905, 1746},
+        { 7172, 1726},{ 7495, 1732},{ 7738, 1735},{ 7949, 1735},
+        { 8211, 1744},{ 8424, 1740},{ 8779, 1764},{ 8812, 1760}
+      }
+    }
+  }
+};
+
 #endif

Modified: trunk/theora/tools/process_modedec_stats.c
===================================================================
--- trunk/theora/tools/process_modedec_stats.c	2011-02-09 01:45:41 UTC (rev 17820)
+++ trunk/theora/tools/process_modedec_stats.c	2011-02-09 22:08:34 UTC (rev 17821)
@@ -12,12 +12,29 @@
 
 
 ogg_int16_t     OC_MODE_LOGQ_TMP[OC_LOGQ_BINS][3][2];
-oc_mode_metrics OC_MODE_METRICS_TMP[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+oc_mode_metrics OC_MODE_METRICS_SATD_TMP[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+oc_mode_metrics OC_MODE_METRICS_SAD_TMP[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
 
 ogg_int16_t     OC_MODE_LOGQ_BASE[OC_LOGQ_BINS][3][2];
-oc_mode_metrics OC_MODE_METRICS_BASE[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+oc_mode_metrics OC_MODE_METRICS_SATD_BASE[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+oc_mode_metrics OC_MODE_METRICS_SAD_BASE[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
 
 
+static int logq_cmp(ogg_int16_t(*a)[3][2],ogg_int16_t(*b)[3][2]){
+  int pli;
+  int qti;
+  int qi;
+  for(pli=0;pli<3;pli++){
+    for(qti=0;qti<2;qti++){
+      for(qi=0;qi<OC_LOGQ_BINS-1;qi++){
+        if(a[qi][pli][qti]!=b[qi][pli][qti]){
+          return EXIT_FAILURE;
+        }
+      }
+    }
+  }
+  return EXIT_SUCCESS;
+}
 
 int main(int _argc,const char **_argv){
   FILE *fmetrics;
@@ -61,101 +78,130 @@
       return EXIT_FAILURE;
     }
     if(want_base){
-      if(fread(OC_MODE_METRICS_BASE,sizeof(OC_MODE_METRICS_BASE),1,fmetrics)<1){
-        fprintf(stderr,"Error reading from '%s'.\n",_argv[i]);
+      if(fread(OC_MODE_LOGQ_BASE,sizeof(OC_MODE_LOGQ_BASE),1,fmetrics)<1){
+        fprintf(stderr,"Error reading quantizer bins from '%s'.\n",_argv[i]);
         return EXIT_FAILURE;
       }
-      if(fread(OC_MODE_LOGQ_BASE,sizeof(OC_MODE_LOGQ_BASE),1,fmetrics)<1){
-        fprintf(stderr,"Error reading from '%s'.\n",_argv[i]);
+      if(fread(OC_MODE_METRICS_SATD_BASE,sizeof(OC_MODE_METRICS_SATD_BASE),1,fmetrics)<1){
+        fprintf(stderr,"Error reading SATD metrics from '%s'.\n",_argv[i]);
         return EXIT_FAILURE;
       }
+      if(fread(OC_MODE_METRICS_SAD_BASE,sizeof(OC_MODE_METRICS_SAD_BASE),1,fmetrics)<1){
+        fprintf(stderr,"Error reading SAD metrics from '%s'.\n",_argv[i]);
+        return EXIT_FAILURE;
+      }
       if(OC_HAS_MODE_METRICS){
-        for(pli=0;pli<3;pli++){
-          for(qti=0;qti<2;qti++){
-            for(qi=0;qi<OC_LOGQ_BINS-1;qi++){
-              if(OC_MODE_LOGQ[qi][pli][qti]!=OC_MODE_LOGQ_BASE[qi][pli][qti]){
-                fprintf(stderr,
-                 "Error: quantizer bins in '%s' do not match previous files.\n",
-                 _argv[i]);
-                return EXIT_FAILURE;
-              }
-            }
-          }
+        if(logq_cmp(OC_MODE_LOGQ,OC_MODE_LOGQ_BASE)){
+          fprintf(stderr,
+           "Error: quantizer bins in '%s' do not match previous files.\n",
+           _argv[i]);
+          return EXIT_FAILURE;
         }
       }
       want_base=0;
       have_base=1;
     }
     else if(!OC_HAS_MODE_METRICS){
-      if(fread(OC_MODE_METRICS,sizeof(OC_MODE_METRICS),1,fmetrics)<1){
-        fprintf(stderr,"Error reading from '%s'.\n",_argv[i]);
+      if(fread(OC_MODE_LOGQ,sizeof(OC_MODE_LOGQ),1,fmetrics)<1){
+        fprintf(stderr,"Error reading quantizer bins from '%s'.\n",_argv[i]);
         return EXIT_FAILURE;
       }
-      if(fread(OC_MODE_LOGQ,sizeof(OC_MODE_LOGQ),1,fmetrics)<1){
-        fprintf(stderr,"Error reading from '%s'.\n",_argv[i]);
+      if(fread(OC_MODE_METRICS_SATD,sizeof(OC_MODE_METRICS_SATD),1,fmetrics)<1){
+        fprintf(stderr,"Error reading SATD metrics from '%s'.\n",_argv[i]);
         return EXIT_FAILURE;
       }
+      if(fread(OC_MODE_METRICS_SAD,sizeof(OC_MODE_METRICS_SAD),1,fmetrics)<1){
+        fprintf(stderr,"Error reading SAD metrics from '%s'.\n",_argv[i]);
+        return EXIT_FAILURE;
+      }
       if(have_base){
-        for(pli=0;pli<3;pli++){
-          for(qti=0;qti<2;qti++){
-            for(qi=0;qi<OC_LOGQ_BINS-1;qi++){
-              if(OC_MODE_LOGQ[qi][pli][qti]!=OC_MODE_LOGQ_BASE[qi][pli][qti]){
-                fprintf(stderr,
-                 "Error: quantizer bins in '%s' do not match previous files.\n",
-                 _argv[i]);
-                return EXIT_FAILURE;
-              }
-            }
-          }
+        if(logq_cmp(OC_MODE_LOGQ,OC_MODE_LOGQ_BASE)){
+          fprintf(stderr,
+           "Error: quantizer bins in '%s' do not match previous files.\n",
+           _argv[i]);
+          return EXIT_FAILURE;
         }
       }
       OC_HAS_MODE_METRICS=1;
     }
     else{
-      if(fread(OC_MODE_METRICS_TMP,sizeof(OC_MODE_METRICS_TMP),1,fmetrics)<1){
-        fprintf(stderr,"Error reading from '%s'.\n",_argv[i]);
+      if(fread(OC_MODE_LOGQ_TMP,sizeof(OC_MODE_LOGQ_TMP),1,fmetrics)<1){
+        fprintf(stderr,"Error reading quantizer bins from '%s'.\n",_argv[i]);
         return EXIT_FAILURE;
       }
-      if(fread(OC_MODE_LOGQ_TMP,sizeof(OC_MODE_LOGQ_TMP),1,fmetrics)<1){
-        fprintf(stderr,"Error reading from '%s'.\n",_argv[i]);
+      if(fread(OC_MODE_METRICS_SATD_TMP,sizeof(OC_MODE_METRICS_SATD_TMP),1,fmetrics)<1){
+        fprintf(stderr,"Error reading SATD metrics from '%s'.\n",_argv[i]);
         return EXIT_FAILURE;
       }
+      if(fread(OC_MODE_METRICS_SAD_TMP,sizeof(OC_MODE_METRICS_SAD_TMP),1,fmetrics)<1){
+        fprintf(stderr,"Error reading SAD metrics from '%s'.\n",_argv[i]);
+        return EXIT_FAILURE;
+      }
+      if(logq_cmp(OC_MODE_LOGQ,OC_MODE_LOGQ_TMP)){
+        fprintf(stderr,
+         "Error: quantizer bins in '%s' do not match previous files.\n",
+         _argv[i]);
+        return EXIT_FAILURE;
+      }
       for(pli=0;pli<3;pli++){
         for(qti=0;qti<2;qti++){
           for(qi=0;qi<OC_LOGQ_BINS-1;qi++){
-            if(OC_MODE_LOGQ[qi][pli][qti]!=OC_MODE_LOGQ_TMP[qi][pli][qti]){
-              fprintf(stderr,
-               "Error: quantizer bins in '%s' do not match previous files.\n",
-               _argv[i]);
-              return EXIT_FAILURE;
+            for(si=0;si<OC_COMP_BINS;si++){
+              oc_mode_metrics m[3];
+              *(m+0)=*(OC_MODE_METRICS_SATD[qi][pli][qti]+si);
+              *(m+1)=*(OC_MODE_METRICS_SATD_TMP[qi][pli][qti]+si);
+              /*Subtract out the contribution from the base.*/
+              if(have_base){
+                m[2].w=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].w;
+                m[2].s=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].s;
+                m[2].q=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].q;
+                m[2].r=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].r;
+                m[2].d=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].d;
+                m[2].s2=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].s2;
+                m[2].sq=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].sq;
+                m[2].q2=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].q2;
+                m[2].sr=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].sr;
+                m[2].qr=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].qr;
+                m[2].r2=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].r2;
+                m[2].sd=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].sd;
+                m[2].qd=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].qd;
+                m[2].d2=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].d2;
+                m[2].s2q=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].s2q;
+                m[2].sq2=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].sq2;
+                m[2].sqr=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].sqr;
+                m[2].sqd=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].sqd;
+                m[2].s2q2=-OC_MODE_METRICS_SATD_BASE[qi][pli][qti][si].s2q2;
+              }
+              oc_mode_metrics_merge(OC_MODE_METRICS_SATD[qi][pli][qti]+si,
+               m,2+have_base);
             }
             for(si=0;si<OC_COMP_BINS;si++){
               oc_mode_metrics m[3];
-              *(m+0)=*(OC_MODE_METRICS[qi][pli][qti]+si);
-              *(m+1)=*(OC_MODE_METRICS_TMP[qi][pli][qti]+si);
+              *(m+0)=*(OC_MODE_METRICS_SAD[qi][pli][qti]+si);
+              *(m+1)=*(OC_MODE_METRICS_SAD_TMP[qi][pli][qti]+si);
               /*Subtract out the contribution from the base.*/
               if(have_base){
-                m[2].w=-OC_MODE_METRICS_BASE[qi][pli][qti][si].w;
-                m[2].s=-OC_MODE_METRICS_BASE[qi][pli][qti][si].s;
-                m[2].q=-OC_MODE_METRICS_BASE[qi][pli][qti][si].q;
-                m[2].r=-OC_MODE_METRICS_BASE[qi][pli][qti][si].r;
-                m[2].d=-OC_MODE_METRICS_BASE[qi][pli][qti][si].d;
-                m[2].s2=-OC_MODE_METRICS_BASE[qi][pli][qti][si].s2;
-                m[2].sq=-OC_MODE_METRICS_BASE[qi][pli][qti][si].sq;
-                m[2].q2=-OC_MODE_METRICS_BASE[qi][pli][qti][si].q2;
-                m[2].sr=-OC_MODE_METRICS_BASE[qi][pli][qti][si].sr;
-                m[2].qr=-OC_MODE_METRICS_BASE[qi][pli][qti][si].qr;
-                m[2].r2=-OC_MODE_METRICS_BASE[qi][pli][qti][si].r2;
-                m[2].sd=-OC_MODE_METRICS_BASE[qi][pli][qti][si].sd;
-                m[2].qd=-OC_MODE_METRICS_BASE[qi][pli][qti][si].qd;
-                m[2].d2=-OC_MODE_METRICS_BASE[qi][pli][qti][si].d2;
-                m[2].s2q=-OC_MODE_METRICS_BASE[qi][pli][qti][si].s2q;
-                m[2].sq2=-OC_MODE_METRICS_BASE[qi][pli][qti][si].sq2;
-                m[2].sqr=-OC_MODE_METRICS_BASE[qi][pli][qti][si].sqr;
-                m[2].sqd=-OC_MODE_METRICS_BASE[qi][pli][qti][si].sqd;
-                m[2].s2q2=-OC_MODE_METRICS_BASE[qi][pli][qti][si].s2q2;
+                m[2].w=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].w;
+                m[2].s=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].s;
+                m[2].q=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].q;
+                m[2].r=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].r;
+                m[2].d=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].d;
+                m[2].s2=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].s2;
+                m[2].sq=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].sq;
+                m[2].q2=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].q2;
+                m[2].sr=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].sr;
+                m[2].qr=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].qr;
+                m[2].r2=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].r2;
+                m[2].sd=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].sd;
+                m[2].qd=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].qd;
+                m[2].d2=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].d2;
+                m[2].s2q=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].s2q;
+                m[2].sq2=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].sq2;
+                m[2].sqr=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].sqr;
+                m[2].sqd=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].sqd;
+                m[2].s2q2=-OC_MODE_METRICS_SAD_BASE[qi][pli][qti][si].s2q2;
               }
-              oc_mode_metrics_merge(OC_MODE_METRICS[qi][pli][qti]+si,
+              oc_mode_metrics_merge(OC_MODE_METRICS_SAD[qi][pli][qti]+si,
                m,2+have_base);
             }
           }
@@ -184,7 +230,10 @@
   }
   /*Claim not to have metrics yet so update starts fresh.*/
   OC_HAS_MODE_METRICS=0;
-  oc_mode_metrics_update(100,0);
+  oc_mode_metrics_update(OC_MODE_METRICS_SATD,100,0,
+   OC_MODE_RD_SATD,OC_SATD_SHIFT,OC_MODE_RD_WEIGHT_SATD);
+  oc_mode_metrics_update(OC_MODE_METRICS_SAD,100,0,
+   OC_MODE_RD_SAD,OC_SAD_SHIFT,OC_MODE_RD_WEIGHT_SAD);
   oc_mode_metrics_print(stdout);
   if(have_output)oc_mode_metrics_dump();
   return EXIT_SUCCESS;



More information about the commits mailing list