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