media/libvpx/vp9/encoder/vp9_tokenize.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libvpx/vp9/encoder/vp9_tokenize.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,224 @@
     1.4 +/*
     1.5 + *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
     1.6 + *
     1.7 + *  Use of this source code is governed by a BSD-style license
     1.8 + *  that can be found in the LICENSE file in the root of the source
     1.9 + *  tree. An additional intellectual property rights grant can be found
    1.10 + *  in the file PATENTS.  All contributing project authors may
    1.11 + *  be found in the AUTHORS file in the root of the source tree.
    1.12 + */
    1.13 +
    1.14 +
    1.15 +#include <math.h>
    1.16 +#include <stdio.h>
    1.17 +#include <string.h>
    1.18 +#include <assert.h>
    1.19 +#include "vp9/encoder/vp9_onyx_int.h"
    1.20 +#include "vp9/encoder/vp9_tokenize.h"
    1.21 +#include "vpx_mem/vpx_mem.h"
    1.22 +
    1.23 +#include "vp9/common/vp9_pred_common.h"
    1.24 +#include "vp9/common/vp9_seg_common.h"
    1.25 +#include "vp9/common/vp9_entropy.h"
    1.26 +
    1.27 +static TOKENVALUE dct_value_tokens[DCT_MAX_VALUE * 2];
    1.28 +const TOKENVALUE *vp9_dct_value_tokens_ptr;
    1.29 +static int dct_value_cost[DCT_MAX_VALUE * 2];
    1.30 +const int *vp9_dct_value_cost_ptr;
    1.31 +
    1.32 +static void fill_value_tokens() {
    1.33 +  TOKENVALUE *const t = dct_value_tokens + DCT_MAX_VALUE;
    1.34 +  const vp9_extra_bit *const e = vp9_extra_bits;
    1.35 +
    1.36 +  int i = -DCT_MAX_VALUE;
    1.37 +  int sign = 1;
    1.38 +
    1.39 +  do {
    1.40 +    if (!i)
    1.41 +      sign = 0;
    1.42 +
    1.43 +    {
    1.44 +      const int a = sign ? -i : i;
    1.45 +      int eb = sign;
    1.46 +
    1.47 +      if (a > 4) {
    1.48 +        int j = 4;
    1.49 +
    1.50 +        while (++j < 11  &&  e[j].base_val <= a) {}
    1.51 +
    1.52 +        t[i].token = --j;
    1.53 +        eb |= (a - e[j].base_val) << 1;
    1.54 +      } else {
    1.55 +        t[i].token = a;
    1.56 +      }
    1.57 +      t[i].extra = eb;
    1.58 +    }
    1.59 +
    1.60 +    // initialize the cost for extra bits for all possible coefficient value.
    1.61 +    {
    1.62 +      int cost = 0;
    1.63 +      const vp9_extra_bit *p = &vp9_extra_bits[t[i].token];
    1.64 +
    1.65 +      if (p->base_val) {
    1.66 +        const int extra = t[i].extra;
    1.67 +        const int length = p->len;
    1.68 +
    1.69 +        if (length)
    1.70 +          cost += treed_cost(p->tree, p->prob, extra >> 1, length);
    1.71 +
    1.72 +        cost += vp9_cost_bit(vp9_prob_half, extra & 1); /* sign */
    1.73 +        dct_value_cost[i + DCT_MAX_VALUE] = cost;
    1.74 +      }
    1.75 +    }
    1.76 +  } while (++i < DCT_MAX_VALUE);
    1.77 +
    1.78 +  vp9_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE;
    1.79 +  vp9_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
    1.80 +}
    1.81 +
    1.82 +struct tokenize_b_args {
    1.83 +  VP9_COMP *cpi;
    1.84 +  MACROBLOCKD *xd;
    1.85 +  TOKENEXTRA **tp;
    1.86 +  TX_SIZE tx_size;
    1.87 +  uint8_t *token_cache;
    1.88 +};
    1.89 +
    1.90 +static void set_entropy_context_b(int plane, int block, BLOCK_SIZE plane_bsize,
    1.91 +                                  TX_SIZE tx_size, void *arg) {
    1.92 +  struct tokenize_b_args* const args = arg;
    1.93 +  MACROBLOCKD *const xd = args->xd;
    1.94 +  struct macroblockd_plane *pd = &xd->plane[plane];
    1.95 +  int aoff, loff;
    1.96 +  txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff);
    1.97 +  set_contexts(xd, pd, plane_bsize, tx_size, pd->eobs[block] > 0, aoff, loff);
    1.98 +}
    1.99 +
   1.100 +static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize,
   1.101 +                       TX_SIZE tx_size, void *arg) {
   1.102 +  struct tokenize_b_args* const args = arg;
   1.103 +  VP9_COMP *cpi = args->cpi;
   1.104 +  MACROBLOCKD *xd = args->xd;
   1.105 +  TOKENEXTRA **tp = args->tp;
   1.106 +  uint8_t *token_cache = args->token_cache;
   1.107 +  struct macroblockd_plane *pd = &xd->plane[plane];
   1.108 +  MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
   1.109 +  int pt; /* near block/prev token context index */
   1.110 +  int c = 0, rc = 0;
   1.111 +  TOKENEXTRA *t = *tp;        /* store tokens starting here */
   1.112 +  const int eob = pd->eobs[block];
   1.113 +  const PLANE_TYPE type = pd->plane_type;
   1.114 +  const int16_t *qcoeff_ptr = BLOCK_OFFSET(pd->qcoeff, block);
   1.115 +
   1.116 +  const int segment_id = mbmi->segment_id;
   1.117 +  const int16_t *scan, *nb;
   1.118 +  vp9_coeff_count *const counts = cpi->coef_counts[tx_size];
   1.119 +  vp9_coeff_probs_model *const coef_probs = cpi->common.fc.coef_probs[tx_size];
   1.120 +  const int ref = is_inter_block(mbmi);
   1.121 +  const uint8_t *const band_translate = get_band_translate(tx_size);
   1.122 +  const int seg_eob = get_tx_eob(&cpi->common.seg, segment_id, tx_size);
   1.123 +  int aoff, loff;
   1.124 +  txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff);
   1.125 +
   1.126 +  assert((!type && !plane) || (type && plane));
   1.127 +
   1.128 +  pt = get_entropy_context(tx_size, pd->above_context + aoff,
   1.129 +                                    pd->left_context + loff);
   1.130 +  get_scan(xd, tx_size, type, block, &scan, &nb);
   1.131 +  c = 0;
   1.132 +  do {
   1.133 +    const int band = band_translate[c];
   1.134 +    int token;
   1.135 +    int v = 0;
   1.136 +    rc = scan[c];
   1.137 +    if (c)
   1.138 +      pt = get_coef_context(nb, token_cache, c);
   1.139 +    if (c < eob) {
   1.140 +      v = qcoeff_ptr[rc];
   1.141 +      assert(-DCT_MAX_VALUE <= v  &&  v < DCT_MAX_VALUE);
   1.142 +
   1.143 +      t->extra = vp9_dct_value_tokens_ptr[v].extra;
   1.144 +      token    = vp9_dct_value_tokens_ptr[v].token;
   1.145 +    } else {
   1.146 +      token = DCT_EOB_TOKEN;
   1.147 +    }
   1.148 +
   1.149 +    t->token = token;
   1.150 +    t->context_tree = coef_probs[type][ref][band][pt];
   1.151 +    t->skip_eob_node = (c > 0) && (token_cache[scan[c - 1]] == 0);
   1.152 +
   1.153 +    assert(vp9_coef_encodings[t->token].len - t->skip_eob_node > 0);
   1.154 +
   1.155 +    ++counts[type][ref][band][pt][token];
   1.156 +    if (!t->skip_eob_node)
   1.157 +      ++cpi->common.counts.eob_branch[tx_size][type][ref][band][pt];
   1.158 +
   1.159 +    token_cache[rc] = vp9_pt_energy_class[token];
   1.160 +    ++t;
   1.161 +  } while (c < eob && ++c < seg_eob);
   1.162 +
   1.163 +  *tp = t;
   1.164 +
   1.165 +  set_contexts(xd, pd, plane_bsize, tx_size, c > 0, aoff, loff);
   1.166 +}
   1.167 +
   1.168 +struct is_skippable_args {
   1.169 +  MACROBLOCKD *xd;
   1.170 +  int *skippable;
   1.171 +};
   1.172 +
   1.173 +static void is_skippable(int plane, int block,
   1.174 +                         BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
   1.175 +                         void *argv) {
   1.176 +  struct is_skippable_args *args = argv;
   1.177 +  args->skippable[0] &= (!args->xd->plane[plane].eobs[block]);
   1.178 +}
   1.179 +
   1.180 +int vp9_sb_is_skippable(MACROBLOCKD *xd, BLOCK_SIZE bsize) {
   1.181 +  int result = 1;
   1.182 +  struct is_skippable_args args = {xd, &result};
   1.183 +  foreach_transformed_block(xd, bsize, is_skippable, &args);
   1.184 +  return result;
   1.185 +}
   1.186 +
   1.187 +int vp9_is_skippable_in_plane(MACROBLOCKD *xd, BLOCK_SIZE bsize,
   1.188 +                              int plane) {
   1.189 +  int result = 1;
   1.190 +  struct is_skippable_args args = {xd, &result};
   1.191 +  foreach_transformed_block_in_plane(xd, bsize, plane, is_skippable, &args);
   1.192 +  return result;
   1.193 +}
   1.194 +
   1.195 +void vp9_tokenize_sb(VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
   1.196 +                     BLOCK_SIZE bsize) {
   1.197 +  VP9_COMMON *const cm = &cpi->common;
   1.198 +  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
   1.199 +  MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
   1.200 +  TOKENEXTRA *t_backup = *t;
   1.201 +  const int mb_skip_context = vp9_get_pred_context_mbskip(xd);
   1.202 +  const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id,
   1.203 +                                              SEG_LVL_SKIP);
   1.204 +  struct tokenize_b_args arg = {cpi, xd, t, mbmi->tx_size, cpi->mb.token_cache};
   1.205 +
   1.206 +  mbmi->skip_coeff = vp9_sb_is_skippable(xd, bsize);
   1.207 +  if (mbmi->skip_coeff) {
   1.208 +    if (!dry_run)
   1.209 +      cm->counts.mbskip[mb_skip_context][1] += skip_inc;
   1.210 +    reset_skip_context(xd, bsize);
   1.211 +    if (dry_run)
   1.212 +      *t = t_backup;
   1.213 +    return;
   1.214 +  }
   1.215 +
   1.216 +  if (!dry_run) {
   1.217 +    cm->counts.mbskip[mb_skip_context][0] += skip_inc;
   1.218 +    foreach_transformed_block(xd, bsize, tokenize_b, &arg);
   1.219 +  } else {
   1.220 +    foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg);
   1.221 +    *t = t_backup;
   1.222 +  }
   1.223 +}
   1.224 +
   1.225 +void vp9_tokenize_initialize() {
   1.226 +  fill_value_tokens();
   1.227 +}

mercurial