[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