Add a new speed level between the old levels 2 and 3.
authorRalph Giles <giles@xiph.org>
Wed, 9 Feb 2011 22:08:34 +0000 (22:08 +0000)
committerRalph Giles <giles@xiph.org>
Wed, 9 Feb 2011 22:08:34 +0000 (22:08 +0000)
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.

svn path=/trunk/theora/; revision=17821

lib/analyze.c
lib/collect.c
lib/collect.h
lib/encfrag.c
lib/encint.h
lib/encode.c
lib/mcenc.c
lib/modedec.h
tools/process_modedec_stats.c

index b34b3ed..d0d42f4 100644 (file)
@@ -749,18 +749,25 @@ static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc,
   }
 #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 @@ static void oc_enc_sb_transform_quantize_inter_chroma(oc_enc_ctx *_enc,
  +((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 @@ static void oc_enc_mode_rd_init(oc_enc_ctx *_enc){
           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 void oc_enc_mode_rd_init(oc_enc_ctx *_enc){
 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 @@ static unsigned oc_dct_cost2(oc_enc_ctx *_enc,unsigned *_ssd,
   /*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 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
   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 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
   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 @@ static unsigned oc_analyze_intra_chroma_block(oc_enc_ctx *_enc,
   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 @@ static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
     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 @@ static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
       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 @@ static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
       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);
index 23a42ed..c0d8a27 100644 (file)
@@ -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/                  *
  *                                                                  *
  ********************************************************************
 #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 @@ double oc_mode_metrics_solve(double *_r,double *_d,
 
 /*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 @@ void oc_mode_metrics_update(int _niters_min,int _reweight){
   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 @@ void oc_mode_metrics_update(int _niters_min,int _reweight){
             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 @@ void oc_mode_metrics_update(int _niters_min,int _reweight){
               }
               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 @@ void oc_mode_metrics_update(int _niters_min,int _reweight){
         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,48 +578,31 @@ void oc_mode_metrics_update(int _niters_min,int _reweight){
   }
 }
 
+/*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");
-  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");
+   "oc_mode_rd %s[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={\n",_table_name);
   for(qii=0;qii<OC_LOGQ_BINS;qii++){
     int pli;
     fprintf(_fout,"  {\n");
@@ -635,8 +622,8 @@ void oc_mode_metrics_print(FILE *_fout){
         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 @@ void oc_mode_metrics_print(FILE *_fout){
   }
   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 @@ void oc_enc_mode_metrics_load(oc_enc_ctx *_enc){
   /*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 @@ void oc_enc_mode_metrics_load(oc_enc_ctx *_enc){
         }
       }
     }
-    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 @@ void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc){
     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 @@ void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc){
   }
   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 @@ void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc){
       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 @@ void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc){
       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_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[modelines[qii][pli][qtj]][pli][qtj]+bin,
-       fragw,satd,_enc->log_plq[qi][pli][qtj],frag_bits,sqrt(frag_ssd[fragi]));
+       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
 
index 0601cfc..9458b84 100644 (file)
@@ -79,10 +79,12 @@ struct oc_mode_metrics{
    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 @@ double oc_mode_metrics_solve(double *_r,double *_d,
  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);
 
index 687e0c8..0e18111 100644 (file)
@@ -86,6 +86,27 @@ unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src,
   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;
index 2c80734..b5ce6f5 100644 (file)
@@ -79,6 +79,10 @@ typedef struct oc_token_checkpoint    oc_token_checkpoint;
 #   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 @@ typedef struct oc_token_checkpoint    oc_token_checkpoint;
 #   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 @@ typedef struct oc_token_checkpoint    oc_token_checkpoint;
 #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 @@ struct oc_enc_opt_vtable{
   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 @@ struct th_enc_ctx{
   /*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_sad_thresh_c(const unsigned char *_src,
 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,
index d55dac1..90dc46c 100644 (file)
@@ -942,6 +942,7 @@ void oc_enc_accel_init_c(oc_enc_ctx *_enc){
   _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 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
      _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 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
    ||_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 @@ static void oc_enc_clear(oc_enc_ctx *_enc){
   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]);
index f6c84be..82eb824 100644 (file)
@@ -164,7 +164,6 @@ static void oc_mcenc_find_candidates_b(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
   _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 @@ static unsigned oc_sad16_halfpel(const oc_enc_ctx *_enc,
   }
   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 @@ static int oc_mcenc_ysatd_check_mbcandidate_fullpel(const oc_enc_ctx *_enc,
     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 @@ static unsigned oc_mcenc_ysatd_halfpel_mbrefine(const oc_enc_ctx *_enc,
     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;
index 270853b..efe640e 100644 (file)
@@ -26,7 +26,7 @@ ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2]={
 # 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 @@ oc_mode_rd OC_MODE_RD[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={
   }
 };
 
+# 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
index 7ce88ee..2d80d4e 100644 (file)
 
 
 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 @@ int main(int _argc,const char **_argv){
       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 @@ int main(int _argc,const char **_argv){
   }
   /*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;