[xiph-commits] r14410 - branches/theora-thusnelda/lib/enc

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Thu Jan 17 10:04:23 PST 2008


Author: xiphmont
Date: 2008-01-17 10:04:21 -0800 (Thu, 17 Jan 2008)
New Revision: 14410

Modified:
   branches/theora-thusnelda/lib/enc/codec_internal.h
   branches/theora-thusnelda/lib/enc/dct_encode.c
   branches/theora-thusnelda/lib/enc/frinit.c
   branches/theora-thusnelda/lib/enc/mode.c
   branches/theora-thusnelda/lib/enc/mode_select.h
Log:
Move some work [that does not yet build/run] into SVN to move to remote machine


Modified: branches/theora-thusnelda/lib/enc/codec_internal.h
===================================================================
--- branches/theora-thusnelda/lib/enc/codec_internal.h	2008-01-17 07:51:18 UTC (rev 14409)
+++ branches/theora-thusnelda/lib/enc/codec_internal.h	2008-01-17 18:04:21 UTC (rev 14410)
@@ -204,6 +204,7 @@
   unsigned char   *frag_nonzero;
   ogg_int16_t     *frag_dc;
   dct_t           *frag_dct;
+  ogg_uint32_t    *frag_mbi;
 
   macroblock_t    *macro;
   superblock_t    *super[3];
@@ -255,7 +256,19 @@
   ogg_uint32_t     MVBits_0; /* count of bits used by MV coding mode 0 */
   ogg_uint32_t     MVBits_1; /* count of bits used by MV coding mode 1 */
 
+  /********************************************************************/
+  /* Fragment SAD->bitrate estimation tracking metrics */
+  int             *frag_sad;
+  int             *dct_token_frag_storage;
+  int             *dct_token_frag[64];
+  int             *dct_eob_fi_storage;
+  int             *dct_eob_fi_stack[64];
+  int              dct_eob_fi_count[64];
 
+  ogg_uint32_t     frag_bitrates[64][3][8][OC_SAD_BINS];
+  ogg_uint32_t     frag_distort[64][3][8][OC_SAD_BINS];
+  ogg_uint32_t     frag_distort_count[64][3][8][OC_SAD_BINS];
+
   /********************************************************************/
   /* Setup */
   int              keyframe_granule_shift;

Modified: branches/theora-thusnelda/lib/enc/dct_encode.c
===================================================================
--- branches/theora-thusnelda/lib/enc/dct_encode.c	2008-01-17 07:51:18 UTC (rev 14409)
+++ branches/theora-thusnelda/lib/enc/dct_encode.c	2008-01-17 18:04:21 UTC (rev 14410)
@@ -32,10 +32,11 @@
 
 /* plane == 0 for Y, 1 for UV */
 static void add_token(CP_INSTANCE *cpi, int plane, int coeff, 
-		      unsigned char token, ogg_uint16_t eb){
+		      unsigned char token, ogg_uint16_t eb, int fi){
 
   cpi->dct_token[coeff][cpi->dct_token_count[coeff]] = token;
   cpi->dct_token_eb[coeff][cpi->dct_token_count[coeff]] = eb;
+  cpi->dct_token_frag[coeff][cpi->dct_token_count[coeff]] = fi;
   cpi->dct_token_count[coeff]++;
 
   if(coeff == 0){
@@ -54,12 +55,14 @@
 }
 
 static void prepend_token(CP_INSTANCE *cpi, int plane, int coeff, 
-			  unsigned char token, ogg_uint16_t eb){
+			  unsigned char token, ogg_uint16_t eb, int fi){
 
   cpi->dct_token[coeff]--;
   cpi->dct_token_eb[coeff]--;
+  cpi->dct_token_frag[coeff]--;
   cpi->dct_token[coeff][0] = token;
   cpi->dct_token_eb[coeff][0] = eb;
+  cpi->dct_token_frag[coeff][0] = fi;
   cpi->dct_token_count[coeff]++;
 
   if(coeff == 0){
@@ -80,23 +83,23 @@
 static void emit_eob_run(CP_INSTANCE *cpi, int plane, int pos, int run){
   if ( run <= 3 ) {
     if ( run == 1 ) {
-      add_token(cpi, plane, pos, DCT_EOB_TOKEN, 0);
+      add_token(cpi, plane, pos, DCT_EOB_TOKEN, 0, 0);
     } else if ( run == 2 ) {
-      add_token(cpi, plane, pos, DCT_EOB_PAIR_TOKEN, 0);
+      add_token(cpi, plane, pos, DCT_EOB_PAIR_TOKEN, 0, 0);
     } else {
-      add_token(cpi, plane, pos, DCT_EOB_TRIPLE_TOKEN, 0);
+      add_token(cpi, plane, pos, DCT_EOB_TRIPLE_TOKEN, 0, 0);
     }
     
   } else {
     
     if ( run < 8 ) {
-      add_token(cpi, plane, pos, DCT_REPEAT_RUN_TOKEN, run-4);
+      add_token(cpi, plane, pos, DCT_REPEAT_RUN_TOKEN, run-4, 0);
     } else if ( run < 16 ) {
-      add_token(cpi, plane, pos, DCT_REPEAT_RUN2_TOKEN, run-8);
+      add_token(cpi, plane, pos, DCT_REPEAT_RUN2_TOKEN, run-8, 0);
     } else if ( run < 32 ) {
-      add_token(cpi, plane, pos, DCT_REPEAT_RUN3_TOKEN, run-16);
+      add_token(cpi, plane, pos, DCT_REPEAT_RUN3_TOKEN, run-16, 0);
     } else if ( run < 4096) {
-      add_token(cpi, plane, pos, DCT_REPEAT_RUN4_TOKEN, run);
+      add_token(cpi, plane, pos, DCT_REPEAT_RUN4_TOKEN, run, 0);
     }
   }
 }
@@ -104,23 +107,23 @@
 static void prepend_eob_run(CP_INSTANCE *cpi, int plane, int pos, int run){
   if ( run <= 3 ) {
     if ( run == 1 ) {
-      prepend_token(cpi, plane, pos, DCT_EOB_TOKEN, 0);
+      prepend_token(cpi, plane, pos, DCT_EOB_TOKEN, 0, 0);
     } else if ( run == 2 ) {
-      prepend_token(cpi, plane, pos, DCT_EOB_PAIR_TOKEN, 0);
+      prepend_token(cpi, plane, pos, DCT_EOB_PAIR_TOKEN, 0, 0);
     } else {
-      prepend_token(cpi, plane, pos, DCT_EOB_TRIPLE_TOKEN, 0);
+      prepend_token(cpi, plane, pos, DCT_EOB_TRIPLE_TOKEN, 0, 0);
     }
     
   } else {
     
     if ( run < 8 ) {
-      prepend_token(cpi, plane, pos, DCT_REPEAT_RUN_TOKEN, run-4);
+      prepend_token(cpi, plane, pos, DCT_REPEAT_RUN_TOKEN, run-4, 0);
     } else if ( run < 16 ) {
-      prepend_token(cpi, plane, pos, DCT_REPEAT_RUN2_TOKEN, run-8);
+      prepend_token(cpi, plane, pos, DCT_REPEAT_RUN2_TOKEN, run-8, 0);
     } else if ( run < 32 ) {
-      prepend_token(cpi, plane, pos, DCT_REPEAT_RUN3_TOKEN, run-16);
+      prepend_token(cpi, plane, pos, DCT_REPEAT_RUN3_TOKEN, run-16, 0);
     } else if ( run < 4096) {
-      prepend_token(cpi, plane, pos, DCT_REPEAT_RUN4_TOKEN, run);
+      prepend_token(cpi, plane, pos, DCT_REPEAT_RUN4_TOKEN, run, 0);
     }
   }
 }
@@ -128,46 +131,47 @@
 static void TokenizeDctValue (CP_INSTANCE *cpi, 
 			      int plane, 
 			      int coeff,
-			      ogg_int16_t DataValue){
+			      ogg_int16_t DataValue,
+			      int fi){
 
   int AbsDataVal = abs(DataValue);
   int neg = (DataValue<0);
 
   if ( AbsDataVal == 1 ){
 
-    add_token(cpi, plane, coeff, (neg ? MINUS_ONE_TOKEN : ONE_TOKEN), 0);
+    add_token(cpi, plane, coeff, (neg ? MINUS_ONE_TOKEN : ONE_TOKEN), 0, fi);
 
   } else if ( AbsDataVal == 2 ) {
 
-    add_token(cpi, plane, coeff, (neg ? MINUS_TWO_TOKEN : TWO_TOKEN), 0);
+    add_token(cpi, plane, coeff, (neg ? MINUS_TWO_TOKEN : TWO_TOKEN), 0, fi);
 
   } else if ( AbsDataVal <= MAX_SINGLE_TOKEN_VALUE ) {
 
-    add_token(cpi, plane, coeff, LOW_VAL_TOKENS + (AbsDataVal - DCT_VAL_CAT2_MIN), neg);
+    add_token(cpi, plane, coeff, LOW_VAL_TOKENS + (AbsDataVal - DCT_VAL_CAT2_MIN), neg, fi);
 
   } else if ( AbsDataVal <= 8 ) {
 
-    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY3, (AbsDataVal - DCT_VAL_CAT3_MIN) + (neg << 1));
+    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY3, (AbsDataVal - DCT_VAL_CAT3_MIN) + (neg << 1), fi);
 
   } else if ( AbsDataVal <= 12 ) {
 
-    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY4, (AbsDataVal - DCT_VAL_CAT4_MIN) + (neg << 2));
+    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY4, (AbsDataVal - DCT_VAL_CAT4_MIN) + (neg << 2), fi);
 
   } else if ( AbsDataVal <= 20 ) {
 
-    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY5, (AbsDataVal - DCT_VAL_CAT5_MIN) + (neg << 3));
+    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY5, (AbsDataVal - DCT_VAL_CAT5_MIN) + (neg << 3), fi);
 
   } else if ( AbsDataVal <= 36 ) {
 
-    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY6, (AbsDataVal - DCT_VAL_CAT6_MIN) + (neg << 4));
+    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY6, (AbsDataVal - DCT_VAL_CAT6_MIN) + (neg << 4), fi);
 
   } else if ( AbsDataVal <= 68 ) {
 
-    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY7, (AbsDataVal - DCT_VAL_CAT7_MIN) + (neg << 5));
+    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY7, (AbsDataVal - DCT_VAL_CAT7_MIN) + (neg << 5), fi);
 
   } else {
 
-    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY8, (AbsDataVal - DCT_VAL_CAT8_MIN) + (neg << 9));
+    add_token(cpi, plane, coeff, DCT_VAL_CATEGORY8, (AbsDataVal - DCT_VAL_CAT8_MIN) + (neg << 9), fi);
 
   } 
 }
@@ -187,19 +191,19 @@
   if ( AbsDataVal == 1 ) {
 
     if ( RunLength <= 5 ) 
-      add_token(cpi,plane,coeff, DCT_RUN_CATEGORY1 + RunLength - 1, neg);
+      add_token(cpi,plane,coeff, DCT_RUN_CATEGORY1 + RunLength - 1, neg, fi);
     else if ( RunLength <= 9 ) 
-      add_token(cpi,plane,coeff, DCT_RUN_CATEGORY1B, RunLength - 6 + (neg<<2));
+      add_token(cpi,plane,coeff, DCT_RUN_CATEGORY1B, RunLength - 6 + (neg<<2), fi);
     else 
-      add_token(cpi,plane,coeff, DCT_RUN_CATEGORY1C, RunLength - 10 + (neg<<3));
+      add_token(cpi,plane,coeff, DCT_RUN_CATEGORY1C, RunLength - 10 + (neg<<3), fi);
 
   } else if ( AbsDataVal <= 3 ) {
 
     if ( RunLength == 1 ) 
-      add_token(cpi,plane,coeff, DCT_RUN_CATEGORY2, AbsDataVal - 2 + (neg<<1));
+      add_token(cpi,plane,coeff, DCT_RUN_CATEGORY2, AbsDataVal - 2 + (neg<<1), fi);
     else
       add_token(cpi,plane,coeff, DCT_RUN_CATEGORY2B, 
-		(neg<<2) + ((AbsDataVal-2)<<1) + RunLength - 2);
+		(neg<<2) + ((AbsDataVal-2)<<1) + RunLength - 2, fi);
 
   }
 }
@@ -240,6 +244,7 @@
 		eob_ypre[coeff]++;
 	      else
 		eob_uvpre[coeff]++;
+	      cpi->dct_eob_fi_stack[coeff][cpi->dct_eob_fi_count[coeff]++]=fi;
 	    }else{
 	      if(eob_run[coeff] == 4095){
 		emit_eob_run(cpi,eob_plane[coeff],coeff,4095);
@@ -250,6 +255,7 @@
 		eob_plane[coeff]=plane;
 	      
 	      eob_run[coeff]++;
+	      cpi->dct_eob_fi_stack[coeff][cpi->dct_eob_fi_count[coeff]++]=fi;
 	    }
 	    coeff = BLOCK_SIZE;
 	  }else{
@@ -264,17 +270,17 @@
 	      ogg_uint32_t absval = abs(val);
 	      if ( ((absval == 1) && (zero_run <= 17)) ||
 		   ((absval <= 3) && (zero_run <= 3)) ) {
-		TokenizeDctRunValue( cpi, plane, coeff, zero_run, val);
+		TokenizeDctRunValue( cpi, plane, coeff, zero_run, val, fi);
 		coeff = i+1;
 	      }else{
 		if ( zero_run <= 8 )
-		  add_token(cpi, plane, coeff, DCT_SHORT_ZRL_TOKEN, zero_run - 1);
+		  add_token(cpi, plane, coeff, DCT_SHORT_ZRL_TOKEN, zero_run - 1, fi);
 		else
-		  add_token(cpi, plane, coeff, DCT_ZRL_TOKEN, zero_run - 1);
+		  add_token(cpi, plane, coeff, DCT_ZRL_TOKEN, zero_run - 1, fi);
 		coeff = i;
 	      }
 	    }else{
-	      TokenizeDctValue( cpi, plane, coeff, val );
+	      TokenizeDctValue(cpi, plane, coeff, val, fi);
 	      coeff = i+1;
 	    }
 	  }
@@ -300,10 +306,13 @@
   memset(cpi->ac_bits, 0, sizeof(cpi->ac_bits));
   memset(cpi->dct_token_count, 0, sizeof(cpi->dct_token_count));
   memset(cpi->dct_token_ycount, 0, sizeof(cpi->dct_token_ycount));
+  memset(cpi->dct_eob_fi_count, 0, sizeof(cpi->dct_eob_fi_count));
 
   for(i=0;i<BLOCK_SIZE;i++){
     cpi->dct_token[i] = cpi->dct_token_storage+cpi->frag_total*i;
     cpi->dct_token_eb[i] = cpi->dct_token_eb_storage+cpi->frag_total*i;
+    cpi->dct_token_frag[i] = cpi->dct_token_frag_storage+cpi->frag_total*i;
+    cpi->dct_eob_fi_stack[i] = cpi->dct_eob_fi_storage+cpi->frag_total*i;
   }
 
   /* Tokenize the dct data. */
@@ -512,6 +521,25 @@
   }
 }
 
+static int blockSAD(ogg_int16_t *b, int interp){
+  int j;
+  int sad = 0;
+
+  if(inter_p){
+    for(j=0;j<64;j++)
+      sad += abs(b[j]);
+  }else{
+    ogg_uint32_t acc = 0;
+    for(j=0;j<64;j++)
+      acc += b[j]; 
+    for(j=0;j<64;j++)
+      sad += abs ((b[j]<<6)-acc); 
+    sad>>=6;
+  }
+  
+  return sad;
+}
+
 void TransformQuantizeBlock (CP_INSTANCE *cpi, 
 			     coding_mode_t mode,
 			     int fi,
@@ -540,7 +568,8 @@
      forward DCT */
   BlockUpdateDifference(cpi, FiltPtr, DCTInput, 
 			MvDivisor, fi, cpi->stride[plane], mode, mv);
-  
+  cpi->frag_sad[fi] = blockSAD(DCTInput, inter);
+
   /* Proceed to encode the data into the encode buffer if the encoder
      is enabled. */
   /* Perform a 2D DCT transform on the data. */

Modified: branches/theora-thusnelda/lib/enc/frinit.c
===================================================================
--- branches/theora-thusnelda/lib/enc/frinit.c	2008-01-17 07:51:18 UTC (rev 14409)
+++ branches/theora-thusnelda/lib/enc/frinit.c	2008-01-17 18:04:21 UTC (rev 14410)
@@ -58,6 +58,12 @@
   if(cpi->frag_dc) _ogg_free(cpi->frag_dc);
   cpi->frag_dc = 0;
 
+  if(cpi->frag_mbi) _ogg_free(cpi->frag_mbi);
+  cpi->frag_mbi = 0;
+
+  if(cpi->frag_sad) _ogg_free(cpi->frag_sad);
+  cpi->frag_sad = 0;
+
   if(cpi->macro) _ogg_free(cpi->macro);
   cpi->macro = 0;
 
@@ -137,6 +143,8 @@
   cpi->frag_nonzero = calloc(cpi->frag_total, sizeof(*cpi->frag_nonzero));
   cpi->frag_dct = calloc(cpi->frag_total, sizeof(*cpi->frag_dct));
   cpi->frag_dc = calloc(cpi->frag_total, sizeof(*cpi->frag_dc));
+  cpi->frag_mbi = calloc(cpi->frag_total+1, sizeof(*cpi->frag_mbi));
+  cpi->frag_sad = calloc(cpi->frag_total, sizeof(*cpi->frag_sad));
 
   /* +1; the last entry is the 'invalid' mb, which contains only 'invalid' frags */
   cpi->macro = calloc(cpi->macro_total+1, sizeof(*cpi->macro));
@@ -241,27 +249,33 @@
       for(col=0;col<cpi->macro_h;col++){
 	int basecol = col*2;
 	int macroindex = row*cpi->macro_h + col;
+	int fragindex;
 	for(frag=0;frag<4;frag++){
 	  /* translate to fragment index */
 	  int frow = baserow + scany[frag];
 	  int fcol = basecol + scanx[frag];
 	  if(frow<cpi->frag_v[0] && fcol<cpi->frag_h[0]){
-	    int fragindex = frow*cpi->frag_h[0] + fcol;
-	    cpi->macro[macroindex].yuv[0][frag] = fragindex;
+	    fragindex = frow*cpi->frag_h[0] + fcol;	    
+	    cpi->frag_mbi[fragindex] = macroindex;
 	  }else
-	    cpi->macro[macroindex].yuv[0][frag] = cpi->frag_total;
+	    fragindex = cpi->frag_total;
+	  cpi->macro[macroindex].yuv[0][frag] = fragindex;
 	}
 	
-	if(row<cpi->frag_v[1] && col<cpi->frag_h[1])
-	  cpi->macro[macroindex].yuv[1][0] = cpi->frag_n[0] + macroindex;
-	else
-	  cpi->macro[macroindex].yuv[1][0] = cpi->frag_total;
-
-	if(row<cpi->frag_v[2] && col<cpi->frag_h[2])
-	  cpi->macro[macroindex].yuv[2][0] = cpi->frag_n[0] + cpi->frag_n[1] + macroindex; 
-	else
-	  cpi->macro[macroindex].yuv[2][0] = cpi->frag_total;
-
+	if(row<cpi->frag_v[1] && col<cpi->frag_h[1]){
+	  fragindex = cpi->frag_n[0] + macroindex;
+	  cpi->frag_mbi[fragindex] = macroindex;
+	}else
+	  fragindex = cpi->frag_total;
+	cpi->macro[macroindex].yuv[1][0] = fragindex;
+	
+	if(row<cpi->frag_v[2] && col<cpi->frag_h[2]){
+	  fragindex = cpi->frag_n[0] + cpi->frag_n[1] + macroindex; 
+	  cpi->frag_mbi[fragindex] = macroindex;
+	}else
+	  fragindex = cpi->frag_total;
+	cpi->macro[macroindex].yuv[2][0] = fragindex;
+	
       }
     }
   }
@@ -309,6 +323,7 @@
 	cpi->macro[cpi->macro_total].yuv[p][f] = cpi->frag_total;
     cpi->macro[cpi->macro_total].ncneighbors=0;
     cpi->macro[cpi->macro_total].npneighbors=0;
+    cpi->frag_mbi[cpi->frag_total] = cpi->macro_total;
   }
 
   /* allocate frames */
@@ -318,8 +333,22 @@
   cpi->recon = _ogg_malloc(cpi->frame_size*sizeof(*cpi->recon));
 
   cpi->dct_token_storage = _ogg_malloc(cpi->frag_total*BLOCK_SIZE*sizeof(*cpi->dct_token_storage));
+  cpi->dct_token_frag_storage = _ogg_malloc(cpi->frag_total*BLOCK_SIZE*sizeof(*cpi->dct_token_frag_storage));
   cpi->dct_token_eb_storage = _ogg_malloc(cpi->frag_total*BLOCK_SIZE*sizeof(*cpi->dct_token_eb_storage));
+  cpi->dct_eob_fi_storage = _ogg_malloc(cpi->frag_total*BLOCK_SIZE*sizeof(*cpi->dct_eob_fi_storage));
   
+  memset(cpi->frag_bitrates,0,sizeof(cpi->frag_distort));
+  memset(cpi->frag_distort_count,0,sizeof(cpi->frag_distort));
+  {
+    int qi,plane,mode,bin;
+    
+    for(qi=0;i<64;qi++)
+      for(plane=0;plane<3;plane++)
+	for(mode=0;mode<8;mode++)
+	  for(bin=0;bin<OC_SAD_BINS;bin++)
+	    cpi->frag_distort_count[qi][plane][mode][bin]=100;
+  }
+
   /* Re-initialise the pixel index table. */
   {
     ogg_uint32_t plane,row,col;

Modified: branches/theora-thusnelda/lib/enc/mode.c
===================================================================
--- branches/theora-thusnelda/lib/enc/mode.c	2008-01-17 07:51:18 UTC (rev 14409)
+++ branches/theora-thusnelda/lib/enc/mode.c	2008-01-17 18:04:21 UTC (rev 14410)
@@ -250,7 +250,7 @@
       b += stride;
   }
 
-  return sad;
+  return sad>>6;
 }
 
 /* equivalent to adding up the abs values of the AC components of a block */
@@ -262,24 +262,24 @@
   /* all frags in a macroblock are valid so long as the macroblock itself is valid */
   if(mbi < cpi->macro_total){ 
     if(all || cp[mb->yuv[0][0]])
-      cost += OC_RES_BITRATES[qi][0][OC_MODE_INTRA]
-	[OC_MINI(BIntraSAD(cpi,mb->yuv[0][0],0)>>12,15)];
+      cost += cpi->frag_bitrates[qi][0][OC_MODE_INTRA]
+	[OC_MINI(BIntraSAD(cpi,mb->yuv[0][0],0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
     if(all || cp[mb->yuv[0][1]])
-      cost += OC_RES_BITRATES[qi][0][OC_MODE_INTRA]
-	[OC_MINI(BIntraSAD(cpi,mb->yuv[0][1],0)>>12,15)];
+      cost += cpi->frag_bitrates[qi][0][OC_MODE_INTRA]
+	[OC_MINI(BIntraSAD(cpi,mb->yuv[0][1],0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
     if(all || cp[mb->yuv[0][2]])
-      cost += OC_RES_BITRATES[qi][0][OC_MODE_INTRA]
-	[OC_MINI(BIntraSAD(cpi,mb->yuv[0][2],0)>>12,15)];
+      cost += cpi->frag_bitrates[qi][0][OC_MODE_INTRA]
+	[OC_MINI(BIntraSAD(cpi,mb->yuv[0][2],0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
     if(all || cp[mb->yuv[0][3]])
-      cost += OC_RES_BITRATES[qi][0][OC_MODE_INTRA]
-	[OC_MINI(BIntraSAD(cpi,mb->yuv[0][3],0)>>12,15)];
+      cost += cpi->frag_bitrates[qi][0][OC_MODE_INTRA]
+	[OC_MINI(BIntraSAD(cpi,mb->yuv[0][3],0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
     
     if(all || cp[mb->yuv[1][0]])
-      cost += OC_RES_BITRATES[qi][1][OC_MODE_INTRA]
-	[OC_MINI(BIntraSAD(cpi,mb->yuv[1][0],1)>>12,15)];
+      cost += cpi->frag_bitrates[qi][1][OC_MODE_INTRA]
+	[OC_MINI(BIntraSAD(cpi,mb->yuv[1][0],1)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
     if(all || cp[mb->yuv[2][0]])
-      cost += OC_RES_BITRATES[qi][2][OC_MODE_INTRA]
-	[OC_MINI(BIntraSAD(cpi,mb->yuv[2][0],2)>>12,15)];
+      cost += cpi->frag_bitrates[qi][2][OC_MODE_INTRA]
+	[OC_MINI(BIntraSAD(cpi,mb->yuv[2][0],2)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
   }
   
   /* Bit costs are stored in the table with extra precision. Round them down to whole bits.*/
@@ -357,24 +357,24 @@
   int cost = 0;
 
   if(cp[mb->yuv[0][0]])
-    cost += OC_RES_BITRATES[qi][0][modei]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[0][0],0,goldenp,mv,0)>>6,15)];
+    cost += cpi->frag_bitrates[qi][0][modei]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[0][0],0,goldenp,mv,0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
   if(cp[mb->yuv[0][1]])
-    cost += OC_RES_BITRATES[qi][0][modei]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[0][1],0,goldenp,mv,0)>>6,15)];
+    cost += cpi->frag_bitrates[qi][0][modei]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[0][1],0,goldenp,mv,0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
   if(cp[mb->yuv[0][2]])
-    cost += OC_RES_BITRATES[qi][0][modei]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[0][2],0,goldenp,mv,0)>>6,15)];
+    cost += cpi->frag_bitrates[qi][0][modei]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[0][2],0,goldenp,mv,0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
   if(cp[mb->yuv[0][3]])
-    cost += OC_RES_BITRATES[qi][0][modei]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[0][3],0,goldenp,mv,0)>>6,15)];
+    cost += cpi->frag_bitrates[qi][0][modei]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[0][3],0,goldenp,mv,0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
 
   if(cp[mb->yuv[1][0]])
-    cost += OC_RES_BITRATES[qi][1][modei]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[1][0],1,goldenp,mv,1)>>6,15)];
+    cost += cpi->frag_bitrates[qi][1][modei]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[1][0],1,goldenp,mv,1)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
   if(cp[mb->yuv[2][0]])
-    cost += OC_RES_BITRATES[qi][2][modei]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[2][0],2,goldenp,mv,1)>>6,15)];
+    cost += cpi->frag_bitrates[qi][2][modei]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[2][0],2,goldenp,mv,1)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
 
   /* Bit costs are stored in the table with extra precision. Round them down to whole bits.*/
   return cost + (1<<OC_BIT_SCALE-1) >> OC_BIT_SCALE;
@@ -387,17 +387,17 @@
   mv_t ch;
 
   if(cp[mb->yuv[0][0]])
-    cost += OC_RES_BITRATES[qi][0][CODE_INTER_FOURMV]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[0][0],0,goldenp,mv[0],0)>>6,15)];
+    cost += cpi->frag_bitrates[qi][0][CODE_INTER_FOURMV]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[0][0],0,goldenp,mv[0],0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
   if(cp[mb->yuv[0][1]])
-    cost += OC_RES_BITRATES[qi][0][CODE_INTER_FOURMV]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[0][1],0,goldenp,mv[1],0)>>6,15)];
+    cost += cpi->frag_bitrates[qi][0][CODE_INTER_FOURMV]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[0][1],0,goldenp,mv[1],0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
   if(cp[mb->yuv[0][2]])
-    cost += OC_RES_BITRATES[qi][0][CODE_INTER_FOURMV]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[0][2],0,goldenp,mv[2],0)>>6,15)];
+    cost += cpi->frag_bitrates[qi][0][CODE_INTER_FOURMV]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[0][2],0,goldenp,mv[2],0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
   if(cp[mb->yuv[0][3]])
-    cost += OC_RES_BITRATES[qi][0][CODE_INTER_FOURMV]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[0][3],0,goldenp,mv[3],0)>>6,15)];
+    cost += cpi->frag_bitrates[qi][0][CODE_INTER_FOURMV]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[0][3],0,goldenp,mv[3],0)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
 
   /* Calculate motion vector as the average of the Y plane ones. */
   /* Uncoded members are 0,0 and not special-cased */
@@ -408,11 +408,11 @@
   ch.y = ( ch.y >= 0 ? (ch.y + 2) / 4 : (ch.y - 2) / 4);
   
   if(cp[mb->yuv[1][0]])
-    cost += OC_RES_BITRATES[qi][1][CODE_INTER_FOURMV]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[1][0],1,goldenp,ch,1)>>6,15)];
+    cost += cpi->frag_bitrates[qi][1][CODE_INTER_FOURMV]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[1][0],1,goldenp,ch,1)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
   if(cp[mb->yuv[2][0]])
-    cost += OC_RES_BITRATES[qi][2][CODE_INTER_FOURMV]
-      [OC_MINI(BInterSAD(cpi,mb->yuv[2][0],2,goldenp,ch,1)>>6,15)];
+    cost += cpi->frag_bitrates[qi][2][CODE_INTER_FOURMV]
+      [OC_MINI(BInterSAD(cpi,mb->yuv[2][0],2,goldenp,ch,1)>>OC_SAD_SHIFT,OC_SAD_CLAMP)];
 
   /* Bit costs are stored in the table with extra precision. Round them down to whole bits.*/
   return cost + (1<<OC_BIT_SCALE-1) >> OC_BIT_SCALE;
@@ -569,7 +569,7 @@
 
   if(cpi->FrameType != KEY_FRAME){
 
-    //if(interbits>intrabits) return 1; /* short circuit */
+    if(interbits>intrabits) return 1; /* short circuit */
     
     /* finish adding flagging overhead costs to inter bit counts */
     
@@ -580,7 +580,7 @@
     
     interbits+=cpi->chooser.scheme_bits[cpi->chooser.scheme_list[0]];
     
-    //if(interbits>intrabits) return 1; /* short circuit */
+    if(interbits>intrabits) return 1; /* short circuit */
 
     /* The easiest way to count the bits needed for coded/not coded fragments is
        to code them. */
@@ -590,11 +590,168 @@
       interbits += oggpackB_bits(cpi->oggbuffer) - bits;
     }
     
-    //if(interbits>intrabits) return 1; 
+    if(interbits>intrabits) return 1; 
     
   }
 
   return 0;
 }
 
+static void UpdateModeEstimation(CP_INSTANCE *cpi){
+  /* compile collected SAD/rate metrics into an immediately useful
+     mode estimation form */
 
+  int qi,plane,mode,bin;
+  
+  //for(qi=0;i<64;qi++)
+  qi = cpi->BaseQ;
+  for(plane=0;plane<3;plane++)
+    for(mode=0;mode<8;mode++)
+      for(bin=0;bin<OC_SAD_BINS;bin++){
+	int bits = cpi->frag_distort[qi][plane][mode][bin];
+	int frags = cpi->frag_distort_count[qi][plane][mode][bin];
+
+	if(frags){
+
+	  while(bits > (1<<24)-(frags>>1)){
+	    bits >>= 1;
+	    frags >>= 1;
+	  }
+	  cpi->frag_distort[qi][plane][mode][bin] = bits;
+	  cpi->frag_distort_count[qi][plane][mode][bin] = frags;
+	  cpi->frag_bitrates[qi][plane][mode][bin] = (bits + (frags>>1)) / frags;
+	  
+	}else{
+	  cpi->frag_bitrates[qi][plane][mode][bin] = 0;
+	}
+      }
+}
+
+static int ModeMetricsGroup(CP_INSTANCE *cpi, int group, int huffY, int huffC, int prerun){
+  int ti,plane;
+  int *stack = cpi->dct_eob_fi_stack[group];
+  int ty = cpi->dct_token_ycount[group];
+
+  for(ti=0;ti<cpi->dct_token_count[group];ti++){
+    int huff = (ti<ty?huffY:huffC);
+    int token = cpi->dct_token[group][ti];
+    int bits = cpi->HuffCodeLengthArray_VP3x[huff][token[i]] + cpi->ExtraBitLengths_VP3x[token[i]];
+    
+    if(token>DCT_REPEAT_RUN4_TOKEN){
+      /* not an EOB run; this token belongs to a single fragment */
+      
+
+
+    }else{
+      /* EOB run; its bits should be split up between all the fragments in the run */
+      int run = parse_eob_run(token, cpi->dct_token_eb[group][ti]);
+      int fracbits = ((bits<<OC_BIT_SCALE) + (run>>1))/run;
+      int eobptr = eobcounts[group];
+
+      if(ti+1<n){
+	/* EOB entirely ensconced within this group */
+	while(run--){
+	  int fi = stack[eobptr++];
+	  int bin = OC_MINI(sp[fi] >> OC_SAD_SHIFT, OC_SAD_CLAMP);
+	  int plane = (fi < y ? 0 : (fi < u ? 1 : 2));
+
+
+
+      }else{
+	/* this EOB is the last token in this group, so it may span into the next group */
+	int n = cpi->dct_eob_fi_count[group];
+
+
+
+	
+	while(run--){
+	  int fi = stack[eobptr++];
+	  int bin = OC_MINI(sp[fi] >> OC_SAD_SHIFT, OC_SAD_CLAMP);
+      int plane = (fi < y ? 0 : (fi < u ? 1 : 2));
+
+	  int eobfi;
+	if(eobptr >= cpi->dct_eob_fi_count[group]){
+	  eobptr = eobcounts[group+1]++;
+	  eobfi = cpi->dct_eob_fi_stack[group+1][eobptr];
+	}else{
+	  eobcounts[group]++;
+	  eobfi = cpi->dct_eob_fi_stack[group][eobptr];
+	}
+
+	int 
+
+
+      }
+
+    }
+  }
+
+  int i;
+  oggpack_buffer *opb=cpi->oggbuffer;
+  int y = cpi->dct_token_ycount[group];
+  unsigned char *token = cpi->dct_token[group];
+  ogg_uint16_t *eb = cpi->dct_token_eb[group];
+ 
+  for(i=0; i<y; i++){
+    oggpackB_write( opb, cpi->HuffCodeArray_VP3x[huffY][token[i]],
+		    cpi->HuffCodeLengthArray_VP3x[huffY][token[i]] );
+    if (cpi->ExtraBitLengths_VP3x[token[i]] > 0) 
+      oggpackB_write( opb, eb[i], cpi->ExtraBitLengths_VP3x[token[i]] );
+  }
+
+  for(; i<cpi->dct_token_count[group]; i++){
+    oggpackB_write( opb, cpi->HuffCodeArray_VP3x[huffC][token[i]],
+		    cpi->HuffCodeLengthArray_VP3x[huffC][token[i]] );
+    if (cpi->ExtraBitLengths_VP3x[token[i]] > 0) 
+      oggpackB_write( opb, eb[i], cpi->ExtraBitLengths_VP3x[token[i]] );
+  }
+}
+
+
+
+
+
+
+
+}
+
+void ModeMetrics(CP_INSTANCE *cpi, int huff[4]){
+  int fi,ti,gi,n;
+  int y = cpi->frag_n[0];
+  int u = y + cpi->frag_n[1];
+  int v = y + cpi->frag_total;
+  unsigned char *cp = cpi->frag_coded;
+  unsigned char *sp = cpi->frag_sad;
+  unsigned char *mp = cpi->frag_mbi;
+  int eobcounts[64];
+  int qi = cpi->BaseQ; /* temporary */
+
+  memset(eobcounts,0,sizeof(eobcounts));
+
+  /* count coded frags by mode and SAD bin */
+  for(fi=0;fi<v;fi++)
+    if(cp[fi]){
+      macroblock_t *mb = cpi->macro[mp[fi]];
+      int mode = mb->mode;
+      int bin = OC_MINI(sp[fi] >> OC_SAD_SHIFT, OC_SAD_CLAMP);
+      int plane = (fi < y ? 0 : (fi < u ? 1 : 2));
+      cpi->frag_distort_count[qi][plane][mode][bin]++;
+    }
+
+  /* count bits for tokens */
+  ModeMetricsGroup(cpi, 0, huff[0], huff[1]);
+
+  for(gi=1;gi<=AC_TABLE_2_THRESH;gi++)
+    ModeMetricsGroup(cpi, gi,  huff[2], huff[3]);
+  for(;gi<=AC_TABLE_3_THRESH;gi++)
+    ModeMetricsGroup(cpi, gi, huff[2]+AC_HUFF_CHOICES, huff[3]+AC_HUFF_CHOICES);
+  for(;gi<=AC_TABLE_4_THRESH;gi++)
+    ModeMetricsGroup(cpi, gi, huff[2]+AC_HUFF_CHOICES*2, huff[3]+AC_HUFF_CHOICES*2);
+  for(;gi<=BLOCK_SIZE;gi++)
+    ModeMetricsGroup(cpi, gi, huff[2]+AC_HUFF_CHOICES*3, huff[3]+AC_HUFF_CHOICES*3);
+
+  /* update global SAD/rate estimation matrix */
+  UpdateModeEstimation(cpi);
+
+
+}

Modified: branches/theora-thusnelda/lib/enc/mode_select.h
===================================================================
--- branches/theora-thusnelda/lib/enc/mode_select.h	2008-01-17 07:51:18 UTC (rev 14409)
+++ branches/theora-thusnelda/lib/enc/mode_select.h	2008-01-17 18:04:21 UTC (rev 14410)
@@ -17,6 +17,10 @@
 
 #include "codec_internal.h"
 
+#define OC_SAD_BINS (16)
+#define OC_SAD_CLAMP (OC_SAD_BINS-1)
+#define OC_SAD_SHIFT (6)
+
 #define OC_BIT_SCALE (7)
 
 /* [qi][plane][mode][sad_bin] */



More information about the commits mailing list