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 #include <math.h>
     12 #include <stdio.h>
     13 #include <string.h>
     14 #include <assert.h>
     15 #include "onyx_int.h"
     16 #include "tokenize.h"
     17 #include "vpx_mem/vpx_mem.h"
     18 
     19 /* Global event counters used for accumulating statistics across several
     20    compressions, then generating context.c = initial stats. */
     21 
     22 void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t);
     23 void vp8_fix_contexts(MACROBLOCKD *x);
     24 
     25 #include "dct_value_tokens.h"
     26 #include "dct_value_cost.h"
     27 
     28 const TOKENVALUE *const vp8_dct_value_tokens_ptr =
     29     dct_value_tokens + DCT_MAX_VALUE;
     30 const short *const vp8_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
     31 
     32 #if 0
     33 int skip_true_count = 0;
     34 int skip_false_count = 0;
     35 #endif
     36 
     37 /* function used to generate dct_value_tokens and dct_value_cost tables */
     38 /*
     39 static void fill_value_tokens()
     40 {
     41 
     42     TOKENVALUE *t = dct_value_tokens + DCT_MAX_VALUE;
     43     const vp8_extra_bit_struct *e = vp8_extra_bits;
     44 
     45     int i = -DCT_MAX_VALUE;
     46     int sign = 1;
     47 
     48     do
     49     {
     50         if (!i)
     51             sign = 0;
     52 
     53         {
     54             const int a = sign ? -i : i;
     55             int eb = sign;
     56 
     57             if (a > 4)
     58             {
     59                 int j = 4;
     60 
     61                 while (++j < 11  &&  e[j].base_val <= a) {}
     62 
     63                 t[i].Token = --j;
     64                 eb |= (a - e[j].base_val) << 1;
     65             }
     66             else
     67                 t[i].Token = a;
     68 
     69             t[i].Extra = eb;
     70         }
     71 
     72         // initialize the cost for extra bits for all possible coefficient
     73 value.
     74         {
     75             int cost = 0;
     76             const vp8_extra_bit_struct *p = vp8_extra_bits + t[i].Token;
     77 
     78             if (p->base_val)
     79             {
     80                 const int extra = t[i].Extra;
     81                 const int Length = p->Len;
     82 
     83                 if (Length)
     84                     cost += vp8_treed_cost(p->tree, p->prob, extra >> 1,
     85 Length);
     86 
     87                 cost += vp8_cost_bit(vp8_prob_half, extra & 1); // sign
     88                 dct_value_cost[i + DCT_MAX_VALUE] = cost;
     89             }
     90 
     91         }
     92 
     93     }
     94     while (++i < DCT_MAX_VALUE);
     95 
     96     vp8_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE;
     97     vp8_dct_value_cost_ptr   = dct_value_cost + DCT_MAX_VALUE;
     98 }
     99 */
    100 
    101 static void tokenize2nd_order_b(MACROBLOCK *x, TOKENEXTRA **tp, VP8_COMP *cpi) {
    102   MACROBLOCKD *xd = &x->e_mbd;
    103   int pt;              /* near block/prev token context index */
    104   int c;               /* start at DC */
    105   TOKENEXTRA *t = *tp; /* store tokens starting here */
    106   const BLOCKD *b;
    107   const short *qcoeff_ptr;
    108   ENTROPY_CONTEXT *a;
    109   ENTROPY_CONTEXT *l;
    110   int band, rc, v, token;
    111   int eob;
    112 
    113   b = xd->block + 24;
    114   qcoeff_ptr = b->qcoeff;
    115   a = (ENTROPY_CONTEXT *)xd->above_context + 8;
    116   l = (ENTROPY_CONTEXT *)xd->left_context + 8;
    117   eob = xd->eobs[24];
    118   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    119 
    120   if (!eob) {
    121     /* c = band for this case */
    122     t->Token = DCT_EOB_TOKEN;
    123     t->context_tree = cpi->common.fc.coef_probs[1][0][pt];
    124     t->skip_eob_node = 0;
    125 
    126     ++x->coef_counts[1][0][pt][DCT_EOB_TOKEN];
    127     t++;
    128     *tp = t;
    129     *a = *l = 0;
    130     return;
    131   }
    132 
    133   v = qcoeff_ptr[0];
    134   t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
    135   token = vp8_dct_value_tokens_ptr[v].Token;
    136   t->Token = token;
    137 
    138   t->context_tree = cpi->common.fc.coef_probs[1][0][pt];
    139   t->skip_eob_node = 0;
    140   ++x->coef_counts[1][0][pt][token];
    141   pt = vp8_prev_token_class[token];
    142   t++;
    143   c = 1;
    144 
    145   for (; c < eob; ++c) {
    146     rc = vp8_default_zig_zag1d[c];
    147     band = vp8_coef_bands[c];
    148     v = qcoeff_ptr[rc];
    149 
    150     t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
    151     token = vp8_dct_value_tokens_ptr[v].Token;
    152 
    153     t->Token = token;
    154     t->context_tree = cpi->common.fc.coef_probs[1][band][pt];
    155 
    156     t->skip_eob_node = ((pt == 0));
    157 
    158     ++x->coef_counts[1][band][pt][token];
    159 
    160     pt = vp8_prev_token_class[token];
    161     t++;
    162   }
    163   if (c < 16) {
    164     band = vp8_coef_bands[c];
    165     t->Token = DCT_EOB_TOKEN;
    166     t->context_tree = cpi->common.fc.coef_probs[1][band][pt];
    167 
    168     t->skip_eob_node = 0;
    169 
    170     ++x->coef_counts[1][band][pt][DCT_EOB_TOKEN];
    171 
    172     t++;
    173   }
    174 
    175   *tp = t;
    176   *a = *l = 1;
    177 }
    178 
    179 static void tokenize1st_order_b(
    180     MACROBLOCK *x, TOKENEXTRA **tp,
    181     int type, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
    182     VP8_COMP *cpi) {
    183   MACROBLOCKD *xd = &x->e_mbd;
    184   unsigned int block;
    185   const BLOCKD *b;
    186   int pt; /* near block/prev token context index */
    187   int c;
    188   int token;
    189   TOKENEXTRA *t = *tp; /* store tokens starting here */
    190   const short *qcoeff_ptr;
    191   ENTROPY_CONTEXT *a;
    192   ENTROPY_CONTEXT *l;
    193   int band, rc, v;
    194   int tmp1, tmp2;
    195 
    196   b = xd->block;
    197   /* Luma */
    198   for (block = 0; block < 16; block++, b++) {
    199     const int eob = *b->eob;
    200     tmp1 = vp8_block2above[block];
    201     tmp2 = vp8_block2left[block];
    202     qcoeff_ptr = b->qcoeff;
    203     a = (ENTROPY_CONTEXT *)xd->above_context + tmp1;
    204     l = (ENTROPY_CONTEXT *)xd->left_context + tmp2;
    205 
    206     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    207 
    208     c = type ? 0 : 1;
    209 
    210     if (c >= eob) {
    211       /* c = band for this case */
    212       t->Token = DCT_EOB_TOKEN;
    213       t->context_tree = cpi->common.fc.coef_probs[type][c][pt];
    214       t->skip_eob_node = 0;
    215 
    216       ++x->coef_counts[type][c][pt][DCT_EOB_TOKEN];
    217       t++;
    218       *tp = t;
    219       *a = *l = 0;
    220       continue;
    221     }
    222 
    223     v = qcoeff_ptr[c];
    224 
    225     t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
    226     token = vp8_dct_value_tokens_ptr[v].Token;
    227     t->Token = token;
    228 
    229     t->context_tree = cpi->common.fc.coef_probs[type][c][pt];
    230     t->skip_eob_node = 0;
    231     ++x->coef_counts[type][c][pt][token];
    232     pt = vp8_prev_token_class[token];
    233     t++;
    234     c++;
    235 
    236     assert(eob <= 16);
    237     for (; c < eob; ++c) {
    238       rc = vp8_default_zig_zag1d[c];
    239       band = vp8_coef_bands[c];
    240       v = qcoeff_ptr[rc];
    241 
    242       t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
    243       token = vp8_dct_value_tokens_ptr[v].Token;
    244 
    245       t->Token = token;
    246       t->context_tree = cpi->common.fc.coef_probs[type][band][pt];
    247 
    248       t->skip_eob_node = (pt == 0);
    249       ++x->coef_counts[type][band][pt][token];
    250 
    251       pt = vp8_prev_token_class[token];
    252       t++;
    253     }
    254     if (c < 16) {
    255       band = vp8_coef_bands[c];
    256       t->Token = DCT_EOB_TOKEN;
    257       t->context_tree = cpi->common.fc.coef_probs[type][band][pt];
    258 
    259       t->skip_eob_node = 0;
    260       ++x->coef_counts[type][band][pt][DCT_EOB_TOKEN];
    261 
    262       t++;
    263     }
    264     *tp = t;
    265     *a = *l = 1;
    266   }
    267 
    268   /* Chroma */
    269   for (block = 16; block < 24; block++, b++) {
    270     const int eob = *b->eob;
    271     tmp1 = vp8_block2above[block];
    272     tmp2 = vp8_block2left[block];
    273     qcoeff_ptr = b->qcoeff;
    274     a = (ENTROPY_CONTEXT *)xd->above_context + tmp1;
    275     l = (ENTROPY_CONTEXT *)xd->left_context + tmp2;
    276 
    277     VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    278 
    279     if (!eob) {
    280       /* c = band for this case */
    281       t->Token = DCT_EOB_TOKEN;
    282       t->context_tree = cpi->common.fc.coef_probs[2][0][pt];
    283       t->skip_eob_node = 0;
    284 
    285       ++x->coef_counts[2][0][pt][DCT_EOB_TOKEN];
    286       t++;
    287       *tp = t;
    288       *a = *l = 0;
    289       continue;
    290     }
    291 
    292     v = qcoeff_ptr[0];
    293 
    294     t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
    295     token = vp8_dct_value_tokens_ptr[v].Token;
    296     t->Token = token;
    297 
    298     t->context_tree = cpi->common.fc.coef_probs[2][0][pt];
    299     t->skip_eob_node = 0;
    300     ++x->coef_counts[2][0][pt][token];
    301     pt = vp8_prev_token_class[token];
    302     t++;
    303     c = 1;
    304 
    305     assert(eob <= 16);
    306     for (; c < eob; ++c) {
    307       rc = vp8_default_zig_zag1d[c];
    308       band = vp8_coef_bands[c];
    309       v = qcoeff_ptr[rc];
    310 
    311       t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
    312       token = vp8_dct_value_tokens_ptr[v].Token;
    313 
    314       t->Token = token;
    315       t->context_tree = cpi->common.fc.coef_probs[2][band][pt];
    316 
    317       t->skip_eob_node = (pt == 0);
    318 
    319       ++x->coef_counts[2][band][pt][token];
    320 
    321       pt = vp8_prev_token_class[token];
    322       t++;
    323     }
    324     if (c < 16) {
    325       band = vp8_coef_bands[c];
    326       t->Token = DCT_EOB_TOKEN;
    327       t->context_tree = cpi->common.fc.coef_probs[2][band][pt];
    328 
    329       t->skip_eob_node = 0;
    330 
    331       ++x->coef_counts[2][band][pt][DCT_EOB_TOKEN];
    332 
    333       t++;
    334     }
    335     *tp = t;
    336     *a = *l = 1;
    337   }
    338 }
    339 
    340 static int mb_is_skippable(MACROBLOCKD *x, int has_y2_block) {
    341   int skip = 1;
    342   int i = 0;
    343 
    344   if (has_y2_block) {
    345     for (i = 0; i < 16; ++i) skip &= (x->eobs[i] < 2);
    346   }
    347 
    348   for (; i < 24 + has_y2_block; ++i) skip &= (!x->eobs[i]);
    349 
    350   return skip;
    351 }
    352 
    353 void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t) {
    354   MACROBLOCKD *xd = &x->e_mbd;
    355   int plane_type;
    356   int has_y2_block;
    357 
    358   has_y2_block = (xd->mode_info_context->mbmi.mode != B_PRED &&
    359                   xd->mode_info_context->mbmi.mode != SPLITMV);
    360 
    361   xd->mode_info_context->mbmi.mb_skip_coeff = mb_is_skippable(xd, has_y2_block);
    362   if (xd->mode_info_context->mbmi.mb_skip_coeff) {
    363     if (!cpi->common.mb_no_coeff_skip) {
    364       vp8_stuff_mb(cpi, x, t);
    365     } else {
    366       vp8_fix_contexts(xd);
    367       x->skip_true_count++;
    368     }
    369 
    370     return;
    371   }
    372 
    373   plane_type = 3;
    374   if (has_y2_block) {
    375     tokenize2nd_order_b(x, t, cpi);
    376     plane_type = 0;
    377   }
    378 
    379   tokenize1st_order_b(x, t, plane_type, cpi);
    380 }
    381 
    382 static void stuff2nd_order_b(TOKENEXTRA **tp, ENTROPY_CONTEXT *a,
    383                              ENTROPY_CONTEXT *l, VP8_COMP *cpi, MACROBLOCK *x) {
    384   int pt;              /* near block/prev token context index */
    385   TOKENEXTRA *t = *tp; /* store tokens starting here */
    386   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    387 
    388   t->Token = DCT_EOB_TOKEN;
    389   t->context_tree = cpi->common.fc.coef_probs[1][0][pt];
    390   t->skip_eob_node = 0;
    391   ++x->coef_counts[1][0][pt][DCT_EOB_TOKEN];
    392   ++t;
    393 
    394   *tp = t;
    395   pt = 0;
    396   *a = *l = pt;
    397 }
    398 
    399 static void stuff1st_order_b(TOKENEXTRA **tp, ENTROPY_CONTEXT *a,
    400                              ENTROPY_CONTEXT *l, int type, VP8_COMP *cpi,
    401                              MACROBLOCK *x) {
    402   int pt; /* near block/prev token context index */
    403   int band;
    404   TOKENEXTRA *t = *tp; /* store tokens starting here */
    405   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    406   band = type ? 0 : 1;
    407   t->Token = DCT_EOB_TOKEN;
    408   t->context_tree = cpi->common.fc.coef_probs[type][band][pt];
    409   t->skip_eob_node = 0;
    410   ++x->coef_counts[type][band][pt][DCT_EOB_TOKEN];
    411   ++t;
    412   *tp = t;
    413   pt = 0; /* 0 <-> all coeff data is zero */
    414   *a = *l = pt;
    415 }
    416 
    417 static void stuff1st_order_buv(TOKENEXTRA **tp, ENTROPY_CONTEXT *a,
    418                                ENTROPY_CONTEXT *l, VP8_COMP *cpi,
    419                                MACROBLOCK *x) {
    420   int pt;              /* near block/prev token context index */
    421   TOKENEXTRA *t = *tp; /* store tokens starting here */
    422   VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
    423 
    424   t->Token = DCT_EOB_TOKEN;
    425   t->context_tree = cpi->common.fc.coef_probs[2][0][pt];
    426   t->skip_eob_node = 0;
    427   ++x->coef_counts[2][0][pt][DCT_EOB_TOKEN];
    428   ++t;
    429   *tp = t;
    430   pt = 0; /* 0 <-> all coeff data is zero */
    431   *a = *l = pt;
    432 }
    433 
    434 void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t) {
    435   MACROBLOCKD *xd = &x->e_mbd;
    436   ENTROPY_CONTEXT *A = (ENTROPY_CONTEXT *)xd->above_context;
    437   ENTROPY_CONTEXT *L = (ENTROPY_CONTEXT *)xd->left_context;
    438   int plane_type;
    439   int b;
    440   plane_type = 3;
    441   if ((xd->mode_info_context->mbmi.mode != B_PRED &&
    442        xd->mode_info_context->mbmi.mode != SPLITMV)) {
    443     stuff2nd_order_b(t, A + vp8_block2above[24], L + vp8_block2left[24], cpi,
    444                      x);
    445     plane_type = 0;
    446   }
    447 
    448   for (b = 0; b < 16; ++b) {
    449     stuff1st_order_b(t, A + vp8_block2above[b], L + vp8_block2left[b],
    450                      plane_type, cpi, x);
    451   }
    452 
    453   for (b = 16; b < 24; ++b) {
    454     stuff1st_order_buv(t, A + vp8_block2above[b], L + vp8_block2left[b], cpi,
    455                        x);
    456   }
    457 }
    458 void vp8_fix_contexts(MACROBLOCKD *x) {
    459   /* Clear entropy contexts for Y2 blocks */
    460   if (x->mode_info_context->mbmi.mode != B_PRED &&
    461       x->mode_info_context->mbmi.mode != SPLITMV) {
    462     memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
    463     memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
    464   } else {
    465     memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) - 1);
    466     memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) - 1);
    467   }
    468 }
    469