Home | History | Annotate | Download | only in encoder
      1 /*
      2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 
     12 #include <math.h>
     13 #include <stdio.h>
     14 #include <string.h>
     15 #include <assert.h>
     16 #include "onyx_int.h"
     17 #include "tokenize.h"
     18 #include "vpx_mem/vpx_mem.h"
     19 
     20 /* Global event counters used for accumulating statistics across several
     21    compressions, then generating context.c = initial stats. */
     22 
     23 #ifdef ENTROPY_STATS
     24 _int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];
     25 #endif
     26 void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
     27 void vp8_fix_contexts(MACROBLOCKD *x);
     28 
     29 TOKENEXTRA vp8_dct_value_tokens[DCT_MAX_VALUE*2];
     30 const TOKENEXTRA *vp8_dct_value_tokens_ptr;
     31 int vp8_dct_value_cost[DCT_MAX_VALUE*2];
     32 const int *vp8_dct_value_cost_ptr;
     33 #if 0
     34 int skip_true_count = 0;
     35 int skip_false_count = 0;
     36 #endif
     37 static void fill_value_tokens()
     38 {
     39 
     40     TOKENEXTRA *const t = vp8_dct_value_tokens + DCT_MAX_VALUE;
     41     vp8_extra_bit_struct *const e = vp8_extra_bits;
     42 
     43     int i = -DCT_MAX_VALUE;
     44     int sign = 1;
     45 
     46     do
     47     {
     48         if (!i)
     49             sign = 0;
     50 
     51         {
     52             const int a = sign ? -i : i;
     53             int eb = sign;
     54 
     55             if (a > 4)
     56             {
     57                 int j = 4;
     58 
     59                 while (++j < 11  &&  e[j].base_val <= a) {}
     60 
     61                 t[i].Token = --j;
     62                 eb |= (a - e[j].base_val) << 1;
     63             }
     64             else
     65                 t[i].Token = a;
     66 
     67             t[i].Extra = eb;
     68         }
     69 
     70         // initialize the cost for extra bits for all possible coefficient value.
     71         {
     72             int cost = 0;
     73             vp8_extra_bit_struct *p = vp8_extra_bits + t[i].Token;
     74 
     75             if (p->base_val)
     76             {
     77                 const int extra = t[i].Extra;
     78                 const int Length = p->Len;
     79 
     80                 if (Length)
     81                     cost += vp8_treed_cost(p->tree, p->prob, extra >> 1, Length);
     82 
     83                 cost += vp8_cost_bit(vp8_prob_half, extra & 1); /* sign */
     84                 vp8_dct_value_cost[i + DCT_MAX_VALUE] = cost;
     85             }
     86 
     87         }
     88 
     89     }
     90     while (++i < DCT_MAX_VALUE);
     91 
     92     vp8_dct_value_tokens_ptr = vp8_dct_value_tokens + DCT_MAX_VALUE;
     93     vp8_dct_value_cost_ptr   = vp8_dct_value_cost + DCT_MAX_VALUE;
     94 }
     95 
     96 static void tokenize2nd_order_b
     97 (
     98     const BLOCKD *const b,
     99     TOKENEXTRA **tp,
    100     const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
    101     const FRAME_TYPE frametype,
    102     ENTROPY_CONTEXT *a,
    103     ENTROPY_CONTEXT *l,
    104     VP8_COMP *cpi
    105 )
    106 {
    107     int pt; /* near block/prev token context index */
    108     int c = 0;          /* start at DC */
    109     const int eob = b->eob;     /* one beyond last nonzero coeff */
    110     TOKENEXTRA *t = *tp;        /* store tokens starting here */
    111     int x;
    112     const short *qcoeff_ptr = b->qcoeff;
    113     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    114 
    115     do
    116     {
    117         const int band = vp8_coef_bands[c];
    118 
    119         if (c < eob)
    120         {
    121             int rc = vp8_default_zig_zag1d[c];
    122             const int v = qcoeff_ptr[rc];
    123 
    124             assert(-DCT_MAX_VALUE <= v  &&  v < (DCT_MAX_VALUE));
    125 
    126             t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
    127             x        = vp8_dct_value_tokens_ptr[v].Token;
    128         }
    129         else
    130             x = DCT_EOB_TOKEN;
    131 
    132         t->Token = x;
    133         t->context_tree = cpi->common.fc.coef_probs [type] [band] [pt];
    134 
    135         t->section = frametype * BLOCK_TYPES * 2 + 2 * type + (c == 0);
    136 
    137         t->skip_eob_node = pt == 0 && ((band > 0 && type > 0) || (band > 1 && type == 0));
    138 
    139         ++cpi->coef_counts       [type] [band] [pt] [x];
    140     }
    141     while (pt = vp8_prev_token_class[x], ++t, c < eob  &&  ++c < 16);
    142 
    143     *tp = t;
    144     pt = (c != !type); /* 0 <-> all coeff data is zero */
    145     *a = *l = pt;
    146 
    147 }
    148 
    149 static void tokenize1st_order_b
    150 (
    151     const BLOCKD *const b,
    152     TOKENEXTRA **tp,
    153     const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
    154     const FRAME_TYPE frametype,
    155     ENTROPY_CONTEXT *a,
    156     ENTROPY_CONTEXT *l,
    157     VP8_COMP *cpi
    158 )
    159 {
    160     int pt; /* near block/prev token context index */
    161     int c = type ? 0 : 1;       /* start at DC unless type 0 */
    162     const int eob = b->eob;     /* one beyond last nonzero coeff */
    163     TOKENEXTRA *t = *tp;        /* store tokens starting here */
    164     int x;
    165     const short *qcoeff_ptr = b->qcoeff;
    166     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    167 
    168     do
    169     {
    170         const int band = vp8_coef_bands[c];
    171 
    172         x = DCT_EOB_TOKEN;
    173 
    174         if (c < eob)
    175         {
    176             int rc = vp8_default_zig_zag1d[c];
    177             const int v = qcoeff_ptr[rc];
    178 
    179             assert(-DCT_MAX_VALUE <= v  &&  v < (DCT_MAX_VALUE));
    180 
    181             t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
    182             x        = vp8_dct_value_tokens_ptr[v].Token;
    183         }
    184 
    185         t->Token = x;
    186         t->context_tree = cpi->common.fc.coef_probs [type] [band] [pt];
    187 
    188         t->section = frametype * BLOCK_TYPES * 2 + 2 * type + (c == 0);
    189         t->skip_eob_node = pt == 0 && ((band > 0 && type > 0) || (band > 1 && type == 0));
    190 
    191         ++cpi->coef_counts       [type] [band] [pt] [x];
    192     }
    193     while (pt = vp8_prev_token_class[x], ++t, c < eob  &&  ++c < 16);
    194 
    195     *tp = t;
    196     pt = (c != !type); /* 0 <-> all coeff data is zero */
    197     *a = *l = pt;
    198 
    199 }
    200 
    201 void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
    202 {
    203     ENTROPY_CONTEXT * A = (ENTROPY_CONTEXT *)x->above_context;
    204     ENTROPY_CONTEXT * L = (ENTROPY_CONTEXT *)x->left_context;
    205     int plane_type;
    206     int b;
    207 
    208     TOKENEXTRA *start = *t;
    209     TOKENEXTRA *tp = *t;
    210 
    211     x->mode_info_context->mbmi.dc_diff = 1;
    212 
    213 #if 0
    214 
    215     if (x->mbmi.force_no_skip)
    216     {
    217         x->mbmi.mb_skip_coeff = 1;
    218         //reset for next_mb.
    219         x->mbmi.force_no_skip = 0;
    220     }
    221 
    222 #endif
    223 
    224 #if 1
    225 
    226     if (x->mode_info_context->mbmi.mb_skip_coeff)
    227     {
    228 
    229         cpi->skip_true_count++;
    230 
    231         if (!cpi->common.mb_no_coeff_skip)
    232             vp8_stuff_mb(cpi, x, t) ;
    233         else
    234         {
    235             vp8_fix_contexts(x);
    236         }
    237 
    238         if (x->mode_info_context->mbmi.mode != B_PRED && x->mode_info_context->mbmi.mode != SPLITMV)
    239             x->mode_info_context->mbmi.dc_diff = 0;
    240         else
    241             x->mode_info_context->mbmi.dc_diff = 1;
    242 
    243 
    244         return;
    245     }
    246 
    247     cpi->skip_false_count++;
    248 #endif
    249 #if 0
    250 
    251     if (x->mbmi.mode == B_PRED || x->mbmi.mode == SPLITMV)
    252     {
    253         int i, skip = 1;
    254 
    255         for (i = 0; i < 24; i++)
    256             skip &= (!x->block[i].eob);
    257 
    258         if (skip != x->mbmi.mb_skip_coeff)
    259             skip += 0;
    260 
    261         x->mbmi.mb_skip_coeff = skip;
    262     }
    263     else
    264     {
    265         int i, skip = 1;
    266 
    267         for (i = 0; i < 16; i++)
    268             skip &= (x->block[i].eob < 2);
    269 
    270         for (i = 16; i < 25; i++)
    271             skip &= (!x->block[i].eob);
    272 
    273         if (skip != x->mbmi.mb_skip_coeff)
    274             skip += 0;
    275 
    276         x->mbmi.mb_skip_coeff = skip;
    277     }
    278 
    279     vpx_memcpy(cpi->coef_counts_backup, cpi->coef_counts, sizeof(cpi->coef_counts));
    280 #endif
    281 
    282     if (x->mode_info_context->mbmi.mode == B_PRED || x->mode_info_context->mbmi.mode == SPLITMV)
    283     {
    284         plane_type = 3;
    285     }
    286     else
    287     {
    288         tokenize2nd_order_b(x->block + 24, t, 1, x->frame_type,
    289                    A + vp8_block2above[24], L + vp8_block2left[24], cpi);
    290         plane_type = 0;
    291 
    292     }
    293 
    294     for (b = 0; b < 16; b++)
    295         tokenize1st_order_b(x->block + b, t, plane_type, x->frame_type,
    296                             A + vp8_block2above[b],
    297                             L + vp8_block2left[b], cpi);
    298 
    299     for (b = 16; b < 24; b++)
    300         tokenize1st_order_b(x->block + b, t, 2, x->frame_type,
    301                             A + vp8_block2above[b],
    302                             L + vp8_block2left[b], cpi);
    303 
    304 #if 0
    305 
    306     if (cpi->common.mb_no_coeff_skip)
    307     {
    308         int skip = 1;
    309 
    310         while ((tp != *t) && skip)
    311         {
    312             skip = (skip && (tp->Token == DCT_EOB_TOKEN));
    313             tp ++;
    314         }
    315 
    316         if (skip != x->mbmi.mb_skip_coeff)
    317             skip += 0;
    318 
    319         x->mbmi.mb_skip_coeff = skip;
    320 
    321         if (x->mbmi.mb_skip_coeff == 1)
    322         {
    323             x->mbmi.dc_diff = 0;
    324             //redo the coutnts
    325             vpx_memcpy(cpi->coef_counts, cpi->coef_counts_backup, sizeof(cpi->coef_counts));
    326 
    327             *t = start;
    328             cpi->skip_true_count++;
    329             //skip_true_count++;
    330         }
    331         else
    332         {
    333 
    334             cpi->skip_false_count++;
    335             //skip_false_count++;
    336         }
    337     }
    338 
    339 #endif
    340 }
    341 
    342 
    343 #ifdef ENTROPY_STATS
    344 
    345 void init_context_counters(void)
    346 {
    347     vpx_memset(context_counters, 0, sizeof(context_counters));
    348 }
    349 
    350 void print_context_counters()
    351 {
    352 
    353     int type, band, pt, t;
    354 
    355     FILE *const f = fopen("context.c", "w");
    356 
    357     fprintf(f, "#include \"entropy.h\"\n");
    358 
    359     fprintf(f, "\n/* *** GENERATED FILE: DO NOT EDIT *** */\n\n");
    360 
    361     fprintf(f, "int Contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];\n\n");
    362 
    363     fprintf(f, "const int default_contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens] = {");
    364 
    365 # define Comma( X) (X? ",":"")
    366 
    367     type = 0;
    368 
    369     do
    370     {
    371         fprintf(f, "%s\n  { /* block Type %d */", Comma(type), type);
    372 
    373         band = 0;
    374 
    375         do
    376         {
    377             fprintf(f, "%s\n    { /* Coeff Band %d */", Comma(band), band);
    378 
    379             pt = 0;
    380 
    381             do
    382             {
    383                 fprintf(f, "%s\n      {", Comma(pt));
    384 
    385                 t = 0;
    386 
    387                 do
    388                 {
    389                     const _int64 x = context_counters [type] [band] [pt] [t];
    390                     const int y = (int) x;
    391 
    392                     assert(x == (_int64) y);  /* no overflow handling yet */
    393                     fprintf(f, "%s %d", Comma(t), y);
    394 
    395                 }
    396                 while (++t < vp8_coef_tokens);
    397 
    398                 fprintf(f, "}");
    399             }
    400             while (++pt < PREV_COEF_CONTEXTS);
    401 
    402             fprintf(f, "\n    }");
    403 
    404         }
    405         while (++band < COEF_BANDS);
    406 
    407         fprintf(f, "\n  }");
    408     }
    409     while (++type < BLOCK_TYPES);
    410 
    411     fprintf(f, "\n};\n");
    412     fclose(f);
    413 }
    414 #endif
    415 
    416 
    417 void vp8_tokenize_initialize()
    418 {
    419     fill_value_tokens();
    420 }
    421 
    422 
    423 static __inline void stuff2nd_order_b
    424 (
    425     const BLOCKD *const b,
    426     TOKENEXTRA **tp,
    427     const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
    428     const FRAME_TYPE frametype,
    429     ENTROPY_CONTEXT *a,
    430     ENTROPY_CONTEXT *l,
    431     VP8_COMP *cpi
    432 )
    433 {
    434     int pt; /* near block/prev token context index */
    435     TOKENEXTRA *t = *tp;        /* store tokens starting here */
    436     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    437     (void) frametype;
    438     (void) type;
    439     (void) b;
    440 
    441     t->Token = DCT_EOB_TOKEN;
    442     t->context_tree = cpi->common.fc.coef_probs [1] [0] [pt];
    443     t->section = 11;
    444     t->skip_eob_node = 0;
    445     ++cpi->coef_counts       [1] [0] [pt] [DCT_EOB_TOKEN];
    446     ++t;
    447 
    448     *tp = t;
    449     pt = 0;
    450     *a = *l = pt;
    451 
    452 }
    453 
    454 static __inline void stuff1st_order_b
    455 (
    456     const BLOCKD *const b,
    457     TOKENEXTRA **tp,
    458     const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
    459     const FRAME_TYPE frametype,
    460     ENTROPY_CONTEXT *a,
    461     ENTROPY_CONTEXT *l,
    462     VP8_COMP *cpi
    463 )
    464 {
    465     int pt; /* near block/prev token context index */
    466     TOKENEXTRA *t = *tp;        /* store tokens starting here */
    467     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    468     (void) frametype;
    469     (void) type;
    470     (void) b;
    471 
    472     t->Token = DCT_EOB_TOKEN;
    473     t->context_tree = cpi->common.fc.coef_probs [0] [1] [pt];
    474     t->section = 8;
    475     t->skip_eob_node = 0;
    476     ++cpi->coef_counts       [0] [1] [pt] [DCT_EOB_TOKEN];
    477     ++t;
    478     *tp = t;
    479     pt = 0; /* 0 <-> all coeff data is zero */
    480     *a = *l = pt;
    481 
    482 }
    483 static __inline
    484 void stuff1st_order_buv
    485 (
    486     const BLOCKD *const b,
    487     TOKENEXTRA **tp,
    488     const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
    489     const FRAME_TYPE frametype,
    490     ENTROPY_CONTEXT *a,
    491     ENTROPY_CONTEXT *l,
    492     VP8_COMP *cpi
    493 )
    494 {
    495     int pt; /* near block/prev token context index */
    496     TOKENEXTRA *t = *tp;        /* store tokens starting here */
    497     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    498     (void) frametype;
    499     (void) type;
    500     (void) b;
    501 
    502     t->Token = DCT_EOB_TOKEN;
    503     t->context_tree = cpi->common.fc.coef_probs [2] [0] [pt];
    504     t->section = 13;
    505     t->skip_eob_node = 0;
    506     ++cpi->coef_counts[2] [0] [pt] [DCT_EOB_TOKEN];
    507     ++t;
    508     *tp = t;
    509     pt = 0; /* 0 <-> all coeff data is zero */
    510     *a = *l = pt;
    511 
    512 }
    513 
    514 void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
    515 {
    516     ENTROPY_CONTEXT * A = (ENTROPY_CONTEXT *)x->above_context;
    517     ENTROPY_CONTEXT * L = (ENTROPY_CONTEXT *)x->left_context;
    518     int plane_type;
    519     int b;
    520 
    521     stuff2nd_order_b(x->block + 24, t, 1, x->frame_type,
    522                      A + vp8_block2above[24], L + vp8_block2left[24], cpi);
    523     plane_type = 0;
    524 
    525 
    526     if (x->mode_info_context->mbmi.mode != B_PRED && x->mode_info_context->mbmi.mode != SPLITMV)
    527         x->mode_info_context->mbmi.dc_diff = 0;
    528     else
    529         x->mode_info_context->mbmi.dc_diff = 1;
    530 
    531 
    532     for (b = 0; b < 16; b++)
    533         stuff1st_order_b(x->block + b, t, plane_type, x->frame_type,
    534                          A + vp8_block2above[b],
    535                          L + vp8_block2left[b], cpi);
    536 
    537     for (b = 16; b < 24; b++)
    538         stuff1st_order_buv(x->block + b, t, 2, x->frame_type,
    539                            A + vp8_block2above[b],
    540                            L + vp8_block2left[b], cpi);
    541 
    542 }
    543 void vp8_fix_contexts(MACROBLOCKD *x)
    544 {
    545     /* Clear entropy contexts for Y2 blocks */
    546     if (x->mode_info_context->mbmi.mode != B_PRED && x->mode_info_context->mbmi.mode != SPLITMV)
    547     {
    548         vpx_memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
    549         vpx_memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
    550     }
    551     else
    552     {
    553         vpx_memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES)-1);
    554         vpx_memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES)-1);
    555     }
    556 
    557 }
    558