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

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Wed Jul 9 14:19:48 PDT 2008


Author: xiphmont
Date: 2008-07-09 14:19:47 -0700 (Wed, 09 Jul 2008)
New Revision: 15107

Modified:
   branches/theora-thusnelda/lib/enc/codec_internal.h
   branches/theora-thusnelda/lib/enc/dct_encode.c
   branches/theora-thusnelda/lib/enc/mode.c
Log:
Activate tokenize/rollback code.  Not yet used for intended purpose, but it is working.



Modified: branches/theora-thusnelda/lib/enc/codec_internal.h
===================================================================
--- branches/theora-thusnelda/lib/enc/codec_internal.h	2008-07-09 20:42:37 UTC (rev 15106)
+++ branches/theora-thusnelda/lib/enc/codec_internal.h	2008-07-09 21:19:47 UTC (rev 15107)
@@ -323,6 +323,8 @@
   int run;
 } token_checkpoint_t;
 
+extern void tokenlog_commit(CP_INSTANCE *cpi, token_checkpoint_t *stack, int n);
+extern void tokenlog_rollback(CP_INSTANCE *cpi, token_checkpoint_t *stack,int n);
 extern void dct_tokenize_init (CP_INSTANCE *cpi);
 extern void dct_tokenize_AC (CP_INSTANCE *cpi, int fi, ogg_int16_t *dct, int chroma, token_checkpoint_t **stack);
 extern void dct_tokenize_finish (CP_INSTANCE *cpi);

Modified: branches/theora-thusnelda/lib/enc/dct_encode.c
===================================================================
--- branches/theora-thusnelda/lib/enc/dct_encode.c	2008-07-09 20:42:37 UTC (rev 15106)
+++ branches/theora-thusnelda/lib/enc/dct_encode.c	2008-07-09 21:19:47 UTC (rev 15107)
@@ -21,98 +21,6 @@
 #include "dsp.h"
 #include "quant_lookup.h"
 
-static int acoffset[64]={
-  16,16,16,16,16,16, 32,32,
-  32,32,32,32,32,32,32, 48,
-  48,48,48,48,48,48,48,48,
-  48,48,48,48, 64,64,64,64,
-  64,64,64,64,64,64,64,64,
-  64,64,64,64,64,64,64,64,
-  64,64,64,64,64,64,64,64};
-
-void tokenlog_rollback(CP_INSTANCE *cpi, token_checkpoint_t *stack,int n){
-  int i;
-  for(i=n-1;i>=0;i--){
-    int coeff = stack[i].coeff;
-    if(stack[i].count>=0) cpi->dct_token_count[coeff] = stack[i].count; 
-    cpi->eob_run[coeff] = stack[i].run;
-    cpi->eob_pre[coeff] = stack[i].pre;
-  }
-}
-
-static void tokenlog_metrics(CP_INSTANCE *cpi, int coeff, int chroma, int token){
-  if(coeff == 0){
-    /* DC */
-    int i;
-    for ( i = 0; i < DC_HUFF_CHOICES; i++)
-      cpi->dc_bits[chroma][i] += cpi->HuffCodeLengthArray_VP3x[i][token];
-  }else if (coeff == 1){
-    /* AC == 1*/
-    int i,offset = acoffset[1];
-    for ( i = 0; i < AC_HUFF_CHOICES; i++)
-      cpi->ac1_bits[chroma][i] += cpi->HuffCodeLengthArray_VP3x[offset+i][token];
-  }else{
-    /* AC > 1*/
-    int i,offset = acoffset[coeff];
-    for ( i = 0; i < AC_HUFF_CHOICES; i++)
-      cpi->acN_bits[chroma][i] += cpi->HuffCodeLengthArray_VP3x[offset+i][token];
-  }
-}
-
-void tokenlog_commit(CP_INSTANCE *cpi, token_checkpoint_t *stack, int n){
-  int i;
-  for(i=0;i<n;i++){
-    int pos = stack[i].count;
-    if(pos>=0){
-      int coeff = stack[i].coeff;
-      int token = cpi->dct_token[coeff][pos];
-      int chroma = stack[i].chroma;
-      tokenlog_metrics(cpi,coeff,chroma,token);
-    }
-  }
-}
-
-static void tokenlog_mark(CP_INSTANCE *cpi, int coeff, token_checkpoint_t **stack){
-  (*stack)->coeff = coeff;
-  (*stack)->count = -1;
-  (*stack)->run = cpi->eob_run[coeff];
-  (*stack)->pre = cpi->eob_pre[coeff];
-  (*stack)++;
-}
-
-static void token_add(CP_INSTANCE *cpi, int chroma, int coeff, 
-			 unsigned char token, ogg_uint16_t eb,
-			 token_checkpoint_t **stack){
-  int pos = cpi->dct_token_count[coeff]++;
-  cpi->dct_token[coeff][pos] = token;
-  cpi->dct_token_eb[coeff][pos] = eb;
-  if(stack){
-    (*stack)->coeff = coeff;
-    (*stack)->count = pos;
-    (*stack)->chroma = chroma;
-    (*stack)->run = cpi->eob_run[coeff];
-    (*stack)->pre = cpi->eob_pre[coeff];
-    (*stack)++;
-  }else{
-    tokenlog_metrics(cpi,coeff,chroma,token);
-  }
-}
-
-/* does not offer logging option; only used in nonconditional EOBrun welding */
-static void token_prepend(CP_INSTANCE *cpi, int chroma, int coeff, 
-			  unsigned char token, ogg_uint16_t eb){
-  
-  cpi->dct_token[coeff]--;
-  cpi->dct_token_eb[coeff]--;
-#ifdef COLLECT_METRICS
-  cpi->dct_token_frag[coeff]--;
-#endif
-  cpi->dct_token[coeff][0] = token;
-  cpi->dct_token_eb[coeff][0] = eb;
-  cpi->dct_token_count[coeff]++;
-  tokenlog_metrics(cpi,coeff,chroma,token);
-}
-
 static void make_eobrun_token(int run, int *token, int *eb){
   if ( run <= 3 ) {
     if ( run == 1 ) {
@@ -142,40 +50,6 @@
   }
 }
 
-static void tokenize_eobrun(CP_INSTANCE *cpi, int pos, int run, token_checkpoint_t **stack){
-  int token=0,eb=0;
-  int chroma = !(run&0x8000);
-  make_eobrun_token(run&0x7fff, &token, &eb);
-  token_add(cpi, chroma, pos, token, eb, stack);
-}
-
-
-static void tokenize_prepend_eobrun(CP_INSTANCE *cpi, int chroma, int pos, int run){
-  int token=0,eb=0;
-  make_eobrun_token(run, &token, &eb);
-  token_prepend(cpi, chroma, pos, token, eb);
-}
-
-/* only used in nonconditional DC/stack1 fixups */
-static void token_add_raw(CP_INSTANCE *cpi, 
-			  int chroma,
-			  int fi,
-			  int coeff,
-			  int token,
-			  int eb){
-  
-  /* Emit pending EOB run if any */
-  if(cpi->eob_run[coeff]){
-    tokenize_eobrun(cpi,coeff,cpi->eob_run[coeff],NULL);
-    cpi->eob_run[coeff]=0;
-  }
-#ifdef COLLECT_METRICS
-  cpi->dct_token_frag[coeff][cpi->dct_token_count[coeff]] = fi;
-#endif
-  token_add(cpi,chroma,coeff,token,eb,NULL);
-  
-}
-
 static int make_dct_token(CP_INSTANCE *cpi, 
 			  int coeff,
 			  int coeff2,
@@ -249,59 +123,6 @@
   return token;
 }
 
-/* NULL stack to force commit */
-static int tokenize_dctval(CP_INSTANCE *cpi, 
-			   int chroma,
-			   int fi,
-			   int coeff,
-			   int coeff2,
-			   int val,
-			   token_checkpoint_t **stack){
-  int eb=0;
-  int token=make_dct_token(cpi,coeff,coeff2,val,&eb);
-  
-  /* Emit pending EOB run if any */
-  if(cpi->eob_run[coeff]){
-    tokenize_eobrun(cpi,coeff,cpi->eob_run[coeff],stack);
-    cpi->eob_run[coeff]=0;
-  }
-#ifdef COLLECT_METRICS
-  cpi->dct_token_frag[coeff][cpi->dct_token_count[coeff]] = fi;
-#endif
-  
-  token_add(cpi,chroma,coeff,token,eb,stack);
-  
-  if( ((token==DCT_SHORT_ZRL_TOKEN) || (token==DCT_ZRL_TOKEN)) && val)
-    return 0; /* we only flushed a preceeding zero run, not the value token. */
-  
-  return 1;
-}
-
-static void tokenize_mark_run(CP_INSTANCE *cpi, 
-			      int chroma,
-			      int fi,
-			      int pre,
-			      int coeff,
-			      token_checkpoint_t **stack){
-  
-  if(pre && cpi->dct_token_count[coeff] == 0){
-    if(stack)tokenlog_mark(cpi,coeff,stack); /* log an undo without logging a token */
-    cpi->eob_pre[coeff]++;
-  }else{
-    if((cpi->eob_run[coeff]&0x7fff) == 4095){
-      tokenize_eobrun(cpi,coeff,cpi->eob_run[coeff],stack);
-      cpi->eob_run[coeff] = 0;
-    }
-    
-    if(stack)tokenlog_mark(cpi,coeff,stack); /* log an undo without logging a token */
-    cpi->eob_run[coeff]++;
-    cpi->eob_run[coeff]|= !chroma<<15;
-  }	  
-#ifdef COLLECT_METRICS
-  cpi->dct_eob_fi_stack[coeff][cpi->dct_eob_fi_count[coeff]++]=fi;
-#endif
-}
-
 static int decode_eob_token(int token, int eb){
   switch(token){
   case DCT_EOB_TOKEN:
@@ -390,6 +211,189 @@
   }
 }
 
+/* token logging to allow a few fragments of efficient rollback.  SKIP
+   analysis is tied up in the tokenization process, so we need to be
+   able to undo a fragment's tokens on a whim */
+
+static int acoffset[64]={
+  16,16,16,16,16,16, 32,32,
+  32,32,32,32,32,32,32, 48,
+  48,48,48,48,48,48,48,48,
+  48,48,48,48, 64,64,64,64,
+  64,64,64,64,64,64,64,64,
+  64,64,64,64,64,64,64,64,
+  64,64,64,64,64,64,64,64};
+
+void tokenlog_rollback(CP_INSTANCE *cpi, token_checkpoint_t *stack,int n){
+  int i;
+  for(i=n-1;i>=0;i--){
+    int coeff = stack[i].coeff;
+    if(stack[i].count>=0) cpi->dct_token_count[coeff] = stack[i].count; 
+    cpi->eob_run[coeff] = stack[i].run;
+    cpi->eob_pre[coeff] = stack[i].pre;
+  }
+}
+
+static void tokenlog_metrics(CP_INSTANCE *cpi, int coeff, int chroma, int token){
+  if(coeff == 0){
+    /* DC */
+    int i;
+    for ( i = 0; i < DC_HUFF_CHOICES; i++)
+      cpi->dc_bits[chroma][i] += cpi->HuffCodeLengthArray_VP3x[i][token];
+  }else if (coeff == 1){
+    /* AC == 1*/
+    int i,offset = acoffset[1];
+    for ( i = 0; i < AC_HUFF_CHOICES; i++)
+      cpi->ac1_bits[chroma][i] += cpi->HuffCodeLengthArray_VP3x[offset+i][token];
+  }else{
+    /* AC > 1*/
+    int i,offset = acoffset[coeff];
+    for ( i = 0; i < AC_HUFF_CHOICES; i++)
+      cpi->acN_bits[chroma][i] += cpi->HuffCodeLengthArray_VP3x[offset+i][token];
+  }
+}
+
+void tokenlog_commit(CP_INSTANCE *cpi, token_checkpoint_t *stack, int n){
+  int i;
+  for(i=0;i<n;i++){
+    int pos = stack[i].count;
+    if(pos>=0){
+      int coeff = stack[i].coeff;
+      int token = cpi->dct_token[coeff][pos];
+      int chroma = stack[i].chroma;
+      tokenlog_metrics(cpi,coeff,chroma,token);
+    }
+  }
+}
+
+static void tokenlog_mark(CP_INSTANCE *cpi, int coeff, token_checkpoint_t **stack){
+  (*stack)->coeff = coeff;
+  (*stack)->count = -1;
+  (*stack)->run = cpi->eob_run[coeff];
+  (*stack)->pre = cpi->eob_pre[coeff];
+  (*stack)++;
+}
+
+static void token_add(CP_INSTANCE *cpi, int chroma, int coeff, 
+			 unsigned char token, ogg_uint16_t eb,
+			 token_checkpoint_t **stack){
+  int pos = cpi->dct_token_count[coeff]++;
+  cpi->dct_token[coeff][pos] = token;
+  cpi->dct_token_eb[coeff][pos] = eb;
+  if(stack){
+    (*stack)->coeff = coeff;
+    (*stack)->count = pos;
+    (*stack)->chroma = chroma;
+    (*stack)->run = cpi->eob_run[coeff];
+    (*stack)->pre = cpi->eob_pre[coeff];
+    (*stack)++;
+  }else{
+    tokenlog_metrics(cpi,coeff,chroma,token);
+  }
+}
+
+/* does not offer logging option; only used in nonconditional EOBrun welding */
+static void token_prepend(CP_INSTANCE *cpi, int chroma, int coeff, 
+			  unsigned char token, ogg_uint16_t eb){
+  
+  cpi->dct_token[coeff]--;
+  cpi->dct_token_eb[coeff]--;
+#ifdef COLLECT_METRICS
+  cpi->dct_token_frag[coeff]--;
+#endif
+  cpi->dct_token[coeff][0] = token;
+  cpi->dct_token_eb[coeff][0] = eb;
+  cpi->dct_token_count[coeff]++;
+  tokenlog_metrics(cpi,coeff,chroma,token);
+}
+
+static void tokenize_eobrun(CP_INSTANCE *cpi, int pos, int run, token_checkpoint_t **stack){
+  int token=0,eb=0;
+  int chroma = !(run&0x8000);
+  make_eobrun_token(run&0x7fff, &token, &eb);
+  token_add(cpi, chroma, pos, token, eb, stack);
+}
+
+
+static void tokenize_prepend_eobrun(CP_INSTANCE *cpi, int chroma, int pos, int run){
+  int token=0,eb=0;
+  make_eobrun_token(run, &token, &eb);
+  token_prepend(cpi, chroma, pos, token, eb);
+}
+
+/* only used in nonconditional DC/stack1 fixups */
+static void token_add_raw(CP_INSTANCE *cpi, 
+			  int chroma,
+			  int fi,
+			  int coeff,
+			  int token,
+			  int eb){
+  
+  /* Emit pending EOB run if any */
+  if(cpi->eob_run[coeff]){
+    tokenize_eobrun(cpi,coeff,cpi->eob_run[coeff],NULL);
+    cpi->eob_run[coeff]=0;
+  }
+#ifdef COLLECT_METRICS
+  cpi->dct_token_frag[coeff][cpi->dct_token_count[coeff]] = fi;
+#endif
+  token_add(cpi,chroma,coeff,token,eb,NULL);
+  
+}
+
+/* NULL stack to force commit */
+static int tokenize_dctval(CP_INSTANCE *cpi, 
+			   int chroma,
+			   int fi,
+			   int coeff,
+			   int coeff2,
+			   int val,
+			   token_checkpoint_t **stack){
+  int eb=0;
+  int token=make_dct_token(cpi,coeff,coeff2,val,&eb);
+  
+  /* Emit pending EOB run if any */
+  if(cpi->eob_run[coeff]){
+    tokenize_eobrun(cpi,coeff,cpi->eob_run[coeff],stack);
+    cpi->eob_run[coeff]=0;
+  }
+#ifdef COLLECT_METRICS
+  cpi->dct_token_frag[coeff][cpi->dct_token_count[coeff]] = fi;
+#endif
+  
+  token_add(cpi,chroma,coeff,token,eb,stack);
+  
+  if( ((token==DCT_SHORT_ZRL_TOKEN) || (token==DCT_ZRL_TOKEN)) && val)
+    return 0; /* we only flushed a preceeding zero run, not the value token. */
+  
+  return 1;
+}
+
+static void tokenize_mark_run(CP_INSTANCE *cpi, 
+			      int chroma,
+			      int fi,
+			      int pre,
+			      int coeff,
+			      token_checkpoint_t **stack){
+  
+  if(pre && cpi->dct_token_count[coeff] == 0){
+    if(stack)tokenlog_mark(cpi,coeff,stack); /* log an undo without logging a token */
+    cpi->eob_pre[coeff]++;
+  }else{
+    if((cpi->eob_run[coeff]&0x7fff) == 4095){
+      tokenize_eobrun(cpi,coeff,cpi->eob_run[coeff],stack);
+      cpi->eob_run[coeff] = 0;
+    }
+    
+    if(stack)tokenlog_mark(cpi,coeff,stack); /* log an undo without logging a token */
+    cpi->eob_run[coeff]++;
+    cpi->eob_run[coeff]|= !chroma<<15;
+  }	  
+#ifdef COLLECT_METRICS
+  cpi->dct_eob_fi_stack[coeff][cpi->dct_eob_fi_count[coeff]++]=fi;
+#endif
+}
+
 /* No final DC to encode yet (DC prediction hasn't been done) So
    simply assume there will be a nonzero DC value and code.  That's
    not a true assumption but it can be fixed-up as DC is tokenized

Modified: branches/theora-thusnelda/lib/enc/mode.c
===================================================================
--- branches/theora-thusnelda/lib/enc/mode.c	2008-07-09 20:42:37 UTC (rev 15106)
+++ branches/theora-thusnelda/lib/enc/mode.c	2008-07-09 21:19:47 UTC (rev 15107)
@@ -554,12 +554,13 @@
 
 static int TQB (CP_INSTANCE *cpi, plane_state_t *ps, int mode, int fi, mv_t mv, 
 		int uncoded_overhead, int coded_overhead, rd_metric_t *mo, long *rho_count,
-		ogg_int16_t *data){
+		token_checkpoint_t **stack){
   
   int keyframe = (cpi->FrameType == KEY_FRAME);
   int qi = ps->qi;
   ogg_int32_t *iq = ps->iq[mode != CODE_INTRA];
   ogg_int16_t buffer[64];
+  ogg_int16_t data[64];
   int bi = cpi->frag_buffer_index[fi];
   int stride = cpi->stride[ps->plane];
   unsigned char *frame_ptr = &cpi->frame[bi];
@@ -571,6 +572,7 @@
   ogg_int16_t *dequant = ps->re_q[mode != CODE_INTRA][ps->plane];
   int uncoded_ssd=0,coded_ssd=0,sad=0;
   int lambda = cpi->skip_lambda;
+  token_checkpoint_t *checkpoint=*stack;
 
   /* motion comp */
   switch(mode){
@@ -660,6 +662,9 @@
   }
   
   cpi->frag_dc[fi] = data[0];
+
+  /* tokenize */
+  dct_tokenize_AC(cpi, fi, data, fi>=cpi->frag_n[0], stack);
   
   /* reconstruct */
   while(!data[nonzero] && --nonzero);
@@ -701,6 +706,9 @@
     mo->uncoded_cost+=(uncoded_overhead<<OC_BIT_SCALE);
 
     if(uncoded_ssd+uncoded_overhead*lambda <= coded_ssd+coded_overhead*lambda+((cost*lambda)>>OC_BIT_SCALE)){ 
+      /* Hm, not worth it.  roll back */
+      tokenlog_rollback(cpi, checkpoint, (*stack)-checkpoint);
+      *stack = checkpoint;
       uncode_frag(cpi,fi,ps->plane);
 
       mo->ssd+=uncoded_ssd;
@@ -726,7 +734,8 @@
   int coded = 0;
   int i;
   fr_state_t fr_checkpoint;
-  ogg_int16_t dct[4][64];
+  token_checkpoint_t stack[64*5]; /* worst case token usage for 4 fragments*/
+  token_checkpoint_t *stackptr = stack;
 
   rd_metric_t mo;
   memset(&mo,0,sizeof(mo));
@@ -739,7 +748,7 @@
        raster order just to make it more difficult. */
     int bi = macroblock_phase_Y[mb_phase][i];
     int fi = mb->Ryuv[0][bi];
-    if(TQB(cpi,ps,mode,fi,mb->mv[bi],0,0,&mo,rc,dct[i])){
+    if(TQB(cpi,ps,mode,fi,mb->mv[bi],0,0,&mo,rc,&stackptr)){
       fr_codeblock(cpi,fr);
       coded++;
     }else{
@@ -756,7 +765,9 @@
 	 macroblock coding cost as a whole (mode and MV) */ 
       if(mo.uncoded_ssd+((cpi->skip_lambda*mo.uncoded_cost)>>OC_BIT_SCALE) <= 
 	 mo.ssd+((cpi->skip_lambda*(mo.cost+mode_overhead))>>(OC_BIT_SCALE))){     
+
 	/* taking macroblock overhead into account, it is not worth coding this MB */
+	tokenlog_rollback(cpi, stack, stackptr-stack);
 
 	memcpy(fr,&fr_checkpoint,sizeof(fr_checkpoint));
 	for(i=0;i<4;i++){
@@ -800,12 +811,8 @@
     }
   }
 
-  /* Tokenize now */
-  for ( i=0; i<4; i++ ){
-    int fi = mb->Hyuv[0][i];
-    if(cp[fi]) 
-      dct_tokenize_AC(cpi, fi, dct[i], 0, NULL);
-  }
+  /* Commit tokenization */
+  tokenlog_commit(cpi, stack, stackptr-stack);
 
   return coded;  
 }
@@ -819,7 +826,8 @@
   int coded = 0;
   unsigned char *cp=cpi->frag_coded;
   rd_metric_t mo;
-  ogg_int16_t dct[64];
+  token_checkpoint_t stack[64*2]; /* worst case token usage for 1 fragment*/
+  token_checkpoint_t *stackptr = stack;
   memset(&mo,0,sizeof(mo));
 
   for(i=0;i<16;i++){
@@ -858,9 +866,9 @@
       }else
 	mv = mb->mv[0];
 	
-      if(TQB(cpi,ps,mb->mode,fi,mv,0,0,&mo,rc,dct)){
+      if(TQB(cpi,ps,mb->mode,fi,mv,0,0,&mo,rc,&stackptr)){
 	fr_codeblock(cpi,fr);
-	dct_tokenize_AC(cpi, fi, dct, 1, NULL);
+	tokenlog_commit(cpi, stack, stackptr-stack);
 	coded++;
       }else{
 	fr_skipblock(cpi,fr);



More information about the commits mailing list