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 "vp9/encoder/vp9_onyx_int.h" 17#include "vp9/encoder/vp9_tokenize.h" 18#include "vpx_mem/vpx_mem.h" 19 20#include "vp9/common/vp9_pred_common.h" 21#include "vp9/common/vp9_seg_common.h" 22#include "vp9/common/vp9_entropy.h" 23 24static TOKENVALUE dct_value_tokens[DCT_MAX_VALUE * 2]; 25const TOKENVALUE *vp9_dct_value_tokens_ptr; 26static int dct_value_cost[DCT_MAX_VALUE * 2]; 27const int *vp9_dct_value_cost_ptr; 28 29static void fill_value_tokens() { 30 TOKENVALUE *const t = dct_value_tokens + DCT_MAX_VALUE; 31 const vp9_extra_bit *const e = vp9_extra_bits; 32 33 int i = -DCT_MAX_VALUE; 34 int sign = 1; 35 36 do { 37 if (!i) 38 sign = 0; 39 40 { 41 const int a = sign ? -i : i; 42 int eb = sign; 43 44 if (a > 4) { 45 int j = 4; 46 47 while (++j < 11 && e[j].base_val <= a) {} 48 49 t[i].token = --j; 50 eb |= (a - e[j].base_val) << 1; 51 } else { 52 t[i].token = a; 53 } 54 t[i].extra = eb; 55 } 56 57 // initialize the cost for extra bits for all possible coefficient value. 58 { 59 int cost = 0; 60 const vp9_extra_bit *p = &vp9_extra_bits[t[i].token]; 61 62 if (p->base_val) { 63 const int extra = t[i].extra; 64 const int length = p->len; 65 66 if (length) 67 cost += treed_cost(p->tree, p->prob, extra >> 1, length); 68 69 cost += vp9_cost_bit(vp9_prob_half, extra & 1); /* sign */ 70 dct_value_cost[i + DCT_MAX_VALUE] = cost; 71 } 72 } 73 } while (++i < DCT_MAX_VALUE); 74 75 vp9_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE; 76 vp9_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE; 77} 78 79struct tokenize_b_args { 80 VP9_COMP *cpi; 81 MACROBLOCKD *xd; 82 TOKENEXTRA **tp; 83 TX_SIZE tx_size; 84 uint8_t *token_cache; 85}; 86 87static void set_entropy_context_b(int plane, int block, BLOCK_SIZE plane_bsize, 88 TX_SIZE tx_size, void *arg) { 89 struct tokenize_b_args* const args = arg; 90 MACROBLOCKD *const xd = args->xd; 91 struct macroblockd_plane *pd = &xd->plane[plane]; 92 int aoff, loff; 93 txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff); 94 set_contexts(xd, pd, plane_bsize, tx_size, pd->eobs[block] > 0, aoff, loff); 95} 96 97static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize, 98 TX_SIZE tx_size, void *arg) { 99 struct tokenize_b_args* const args = arg; 100 VP9_COMP *cpi = args->cpi; 101 MACROBLOCKD *xd = args->xd; 102 TOKENEXTRA **tp = args->tp; 103 uint8_t *token_cache = args->token_cache; 104 struct macroblockd_plane *pd = &xd->plane[plane]; 105 MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi; 106 int pt; /* near block/prev token context index */ 107 int c = 0, rc = 0; 108 TOKENEXTRA *t = *tp; /* store tokens starting here */ 109 const int eob = pd->eobs[block]; 110 const PLANE_TYPE type = pd->plane_type; 111 const int16_t *qcoeff_ptr = BLOCK_OFFSET(pd->qcoeff, block); 112 113 const int segment_id = mbmi->segment_id; 114 const int16_t *scan, *nb; 115 vp9_coeff_count *const counts = cpi->coef_counts[tx_size]; 116 vp9_coeff_probs_model *const coef_probs = cpi->common.fc.coef_probs[tx_size]; 117 const int ref = is_inter_block(mbmi); 118 const uint8_t *const band_translate = get_band_translate(tx_size); 119 const int seg_eob = get_tx_eob(&cpi->common.seg, segment_id, tx_size); 120 int aoff, loff; 121 txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff); 122 123 assert((!type && !plane) || (type && plane)); 124 125 pt = get_entropy_context(tx_size, pd->above_context + aoff, 126 pd->left_context + loff); 127 get_scan(xd, tx_size, type, block, &scan, &nb); 128 c = 0; 129 do { 130 const int band = band_translate[c]; 131 int token; 132 int v = 0; 133 rc = scan[c]; 134 if (c) 135 pt = get_coef_context(nb, token_cache, c); 136 if (c < eob) { 137 v = qcoeff_ptr[rc]; 138 assert(-DCT_MAX_VALUE <= v && v < DCT_MAX_VALUE); 139 140 t->extra = vp9_dct_value_tokens_ptr[v].extra; 141 token = vp9_dct_value_tokens_ptr[v].token; 142 } else { 143 token = DCT_EOB_TOKEN; 144 } 145 146 t->token = token; 147 t->context_tree = coef_probs[type][ref][band][pt]; 148 t->skip_eob_node = (c > 0) && (token_cache[scan[c - 1]] == 0); 149 150 assert(vp9_coef_encodings[t->token].len - t->skip_eob_node > 0); 151 152 ++counts[type][ref][band][pt][token]; 153 if (!t->skip_eob_node) 154 ++cpi->common.counts.eob_branch[tx_size][type][ref][band][pt]; 155 156 token_cache[rc] = vp9_pt_energy_class[token]; 157 ++t; 158 } while (c < eob && ++c < seg_eob); 159 160 *tp = t; 161 162 set_contexts(xd, pd, plane_bsize, tx_size, c > 0, aoff, loff); 163} 164 165struct is_skippable_args { 166 MACROBLOCKD *xd; 167 int *skippable; 168}; 169 170static void is_skippable(int plane, int block, 171 BLOCK_SIZE plane_bsize, TX_SIZE tx_size, 172 void *argv) { 173 struct is_skippable_args *args = argv; 174 args->skippable[0] &= (!args->xd->plane[plane].eobs[block]); 175} 176 177int vp9_sb_is_skippable(MACROBLOCKD *xd, BLOCK_SIZE bsize) { 178 int result = 1; 179 struct is_skippable_args args = {xd, &result}; 180 foreach_transformed_block(xd, bsize, is_skippable, &args); 181 return result; 182} 183 184int vp9_is_skippable_in_plane(MACROBLOCKD *xd, BLOCK_SIZE bsize, 185 int plane) { 186 int result = 1; 187 struct is_skippable_args args = {xd, &result}; 188 foreach_transformed_block_in_plane(xd, bsize, plane, is_skippable, &args); 189 return result; 190} 191 192void vp9_tokenize_sb(VP9_COMP *cpi, TOKENEXTRA **t, int dry_run, 193 BLOCK_SIZE bsize) { 194 VP9_COMMON *const cm = &cpi->common; 195 MACROBLOCKD *const xd = &cpi->mb.e_mbd; 196 MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi; 197 TOKENEXTRA *t_backup = *t; 198 const int mb_skip_context = vp9_get_pred_context_mbskip(xd); 199 const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id, 200 SEG_LVL_SKIP); 201 struct tokenize_b_args arg = {cpi, xd, t, mbmi->tx_size, cpi->mb.token_cache}; 202 203 mbmi->skip_coeff = vp9_sb_is_skippable(xd, bsize); 204 if (mbmi->skip_coeff) { 205 if (!dry_run) 206 cm->counts.mbskip[mb_skip_context][1] += skip_inc; 207 reset_skip_context(xd, bsize); 208 if (dry_run) 209 *t = t_backup; 210 return; 211 } 212 213 if (!dry_run) { 214 cm->counts.mbskip[mb_skip_context][0] += skip_inc; 215 foreach_transformed_block(xd, bsize, tokenize_b, &arg); 216 } else { 217 foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg); 218 *t = t_backup; 219 } 220} 221 222void vp9_tokenize_initialize() { 223 fill_value_tokens(); 224} 225