Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 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 "vpx_mem/vpx_mem.h" |
| 12 | #include "vpx_ports/mem.h" |
| 13 | |
Jingning Han | 54d66ef | 2015-08-06 21:14:07 -0700 | [diff] [blame] | 14 | #include "vp10/common/blockd.h" |
| 15 | #include "vp10/common/common.h" |
| 16 | #include "vp10/common/entropy.h" |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 17 | #if CONFIG_COEFFICIENT_RANGE_CHECKING |
Jingning Han | 54d66ef | 2015-08-06 21:14:07 -0700 | [diff] [blame] | 18 | #include "vp10/common/idct.h" |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 19 | #endif |
| 20 | |
Jingning Han | 54d66ef | 2015-08-06 21:14:07 -0700 | [diff] [blame] | 21 | #include "vp10/decoder/detokenize.h" |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 22 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 23 | #define EOB_CONTEXT_NODE 0 |
| 24 | #define ZERO_CONTEXT_NODE 1 |
| 25 | #define ONE_CONTEXT_NODE 2 |
| 26 | #define LOW_VAL_CONTEXT_NODE 0 |
| 27 | #define TWO_CONTEXT_NODE 1 |
| 28 | #define THREE_CONTEXT_NODE 2 |
| 29 | #define HIGH_LOW_CONTEXT_NODE 3 |
| 30 | #define CAT_ONE_CONTEXT_NODE 4 |
| 31 | #define CAT_THREEFOUR_CONTEXT_NODE 5 |
| 32 | #define CAT_THREE_CONTEXT_NODE 6 |
| 33 | #define CAT_FIVE_CONTEXT_NODE 7 |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 34 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 35 | #define INCREMENT_COUNT(token) \ |
| 36 | do { \ |
| 37 | if (counts) ++coef_counts[band][ctx][token]; \ |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 38 | } while (0) |
| 39 | |
| 40 | static INLINE int read_coeff(const vpx_prob *probs, int n, vpx_reader *r) { |
| 41 | int i, val = 0; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 42 | for (i = 0; i < n; ++i) val = (val << 1) | vpx_read(r, probs[i]); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 43 | return val; |
| 44 | } |
| 45 | |
Thomas | 1c122c2 | 2016-02-19 09:06:12 +0000 | [diff] [blame^] | 46 | #if CONFIG_AOM_QM |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 47 | static int decode_coefs(const MACROBLOCKD *xd, PLANE_TYPE type, |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 48 | tran_low_t *dqcoeff, TX_SIZE tx_size, const int16_t *dq, |
| 49 | int ctx, const int16_t *scan, const int16_t *nb, |
Thomas | 1c122c2 | 2016-02-19 09:06:12 +0000 | [diff] [blame^] | 50 | vpx_reader *r, const qm_val_t *iqm[2][TX_SIZES]) |
| 51 | #else |
| 52 | static int decode_coefs(const MACROBLOCKD *xd, PLANE_TYPE type, |
| 53 | tran_low_t *dqcoeff, TX_SIZE tx_size, const int16_t *dq, |
| 54 | int ctx, const int16_t *scan, const int16_t *nb, |
| 55 | vpx_reader *r) |
| 56 | #endif |
| 57 | { |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 58 | FRAME_COUNTS *counts = xd->counts; |
| 59 | const int max_eob = 16 << (tx_size << 1); |
| 60 | const FRAME_CONTEXT *const fc = xd->fc; |
| 61 | const int ref = is_inter_block(&xd->mi[0]->mbmi); |
Thomas | 1c122c2 | 2016-02-19 09:06:12 +0000 | [diff] [blame^] | 62 | #if CONFIG_AOM_QM |
| 63 | const qm_val_t *iqmatrix = iqm[!ref][tx_size]; |
| 64 | #endif |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 65 | int band, c = 0; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 66 | const vpx_prob(*coef_probs)[COEFF_CONTEXTS][UNCONSTRAINED_NODES] = |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 67 | fc->coef_probs[tx_size][type][ref]; |
| 68 | const vpx_prob *prob; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 69 | unsigned int(*coef_counts)[COEFF_CONTEXTS][UNCONSTRAINED_NODES + 1]; |
| 70 | unsigned int(*eob_branch_count)[COEFF_CONTEXTS]; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 71 | uint8_t token_cache[32 * 32]; |
| 72 | const uint8_t *band_translate = get_band_translate(tx_size); |
| 73 | const int dq_shift = (tx_size == TX_32X32); |
| 74 | int v, token; |
| 75 | int16_t dqv = dq[0]; |
| 76 | const uint8_t *cat1_prob; |
| 77 | const uint8_t *cat2_prob; |
| 78 | const uint8_t *cat3_prob; |
| 79 | const uint8_t *cat4_prob; |
| 80 | const uint8_t *cat5_prob; |
| 81 | const uint8_t *cat6_prob; |
| 82 | |
| 83 | if (counts) { |
| 84 | coef_counts = counts->coef[tx_size][type][ref]; |
| 85 | eob_branch_count = counts->eob_branch[tx_size][type][ref]; |
| 86 | } |
| 87 | |
Yaowu Xu | 3246fc0 | 2016-01-20 16:13:04 -0800 | [diff] [blame] | 88 | #if CONFIG_VPX_HIGHBITDEPTH |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 89 | if (xd->bd > VPX_BITS_8) { |
| 90 | if (xd->bd == VPX_BITS_10) { |
| 91 | cat1_prob = vp10_cat1_prob_high10; |
| 92 | cat2_prob = vp10_cat2_prob_high10; |
| 93 | cat3_prob = vp10_cat3_prob_high10; |
| 94 | cat4_prob = vp10_cat4_prob_high10; |
| 95 | cat5_prob = vp10_cat5_prob_high10; |
| 96 | cat6_prob = vp10_cat6_prob_high10; |
| 97 | } else { |
| 98 | cat1_prob = vp10_cat1_prob_high12; |
| 99 | cat2_prob = vp10_cat2_prob_high12; |
| 100 | cat3_prob = vp10_cat3_prob_high12; |
| 101 | cat4_prob = vp10_cat4_prob_high12; |
| 102 | cat5_prob = vp10_cat5_prob_high12; |
| 103 | cat6_prob = vp10_cat6_prob_high12; |
| 104 | } |
| 105 | } else { |
| 106 | cat1_prob = vp10_cat1_prob; |
| 107 | cat2_prob = vp10_cat2_prob; |
| 108 | cat3_prob = vp10_cat3_prob; |
| 109 | cat4_prob = vp10_cat4_prob; |
| 110 | cat5_prob = vp10_cat5_prob; |
| 111 | cat6_prob = vp10_cat6_prob; |
| 112 | } |
| 113 | #else |
| 114 | cat1_prob = vp10_cat1_prob; |
| 115 | cat2_prob = vp10_cat2_prob; |
| 116 | cat3_prob = vp10_cat3_prob; |
| 117 | cat4_prob = vp10_cat4_prob; |
| 118 | cat5_prob = vp10_cat5_prob; |
| 119 | cat6_prob = vp10_cat6_prob; |
| 120 | #endif |
| 121 | |
| 122 | while (c < max_eob) { |
| 123 | int val = -1; |
| 124 | band = *band_translate++; |
| 125 | prob = coef_probs[band][ctx]; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 126 | if (counts) ++eob_branch_count[band][ctx]; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 127 | if (!vpx_read(r, prob[EOB_CONTEXT_NODE])) { |
| 128 | INCREMENT_COUNT(EOB_MODEL_TOKEN); |
| 129 | break; |
| 130 | } |
| 131 | |
| 132 | while (!vpx_read(r, prob[ZERO_CONTEXT_NODE])) { |
| 133 | INCREMENT_COUNT(ZERO_TOKEN); |
| 134 | dqv = dq[1]; |
| 135 | token_cache[scan[c]] = 0; |
| 136 | ++c; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 137 | if (c >= max_eob) return c; // zero tokens at the end (no eob token) |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 138 | ctx = get_coef_context(nb, token_cache, c); |
| 139 | band = *band_translate++; |
| 140 | prob = coef_probs[band][ctx]; |
| 141 | } |
| 142 | |
| 143 | if (!vpx_read(r, prob[ONE_CONTEXT_NODE])) { |
| 144 | INCREMENT_COUNT(ONE_TOKEN); |
| 145 | token = ONE_TOKEN; |
| 146 | val = 1; |
| 147 | } else { |
| 148 | INCREMENT_COUNT(TWO_TOKEN); |
| 149 | token = vpx_read_tree(r, vp10_coef_con_tree, |
| 150 | vp10_pareto8_full[prob[PIVOT_NODE] - 1]); |
| 151 | switch (token) { |
| 152 | case TWO_TOKEN: |
| 153 | case THREE_TOKEN: |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 154 | case FOUR_TOKEN: val = token; break; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 155 | case CATEGORY1_TOKEN: |
| 156 | val = CAT1_MIN_VAL + read_coeff(cat1_prob, 1, r); |
| 157 | break; |
| 158 | case CATEGORY2_TOKEN: |
| 159 | val = CAT2_MIN_VAL + read_coeff(cat2_prob, 2, r); |
| 160 | break; |
| 161 | case CATEGORY3_TOKEN: |
| 162 | val = CAT3_MIN_VAL + read_coeff(cat3_prob, 3, r); |
| 163 | break; |
| 164 | case CATEGORY4_TOKEN: |
| 165 | val = CAT4_MIN_VAL + read_coeff(cat4_prob, 4, r); |
| 166 | break; |
| 167 | case CATEGORY5_TOKEN: |
| 168 | val = CAT5_MIN_VAL + read_coeff(cat5_prob, 5, r); |
| 169 | break; |
Ronald S. Bultje | 3461e8c | 2015-09-30 21:37:20 -0400 | [diff] [blame] | 170 | case CATEGORY6_TOKEN: { |
| 171 | #if CONFIG_MISC_FIXES |
| 172 | const int skip_bits = TX_SIZES - 1 - tx_size; |
| 173 | #else |
| 174 | const int skip_bits = 0; |
| 175 | #endif |
| 176 | const uint8_t *cat6p = cat6_prob + skip_bits; |
Yaowu Xu | 3246fc0 | 2016-01-20 16:13:04 -0800 | [diff] [blame] | 177 | #if CONFIG_VPX_HIGHBITDEPTH |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 178 | switch (xd->bd) { |
| 179 | case VPX_BITS_8: |
Ronald S. Bultje | 3461e8c | 2015-09-30 21:37:20 -0400 | [diff] [blame] | 180 | val = CAT6_MIN_VAL + read_coeff(cat6p, 14 - skip_bits, r); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 181 | break; |
| 182 | case VPX_BITS_10: |
Ronald S. Bultje | 3461e8c | 2015-09-30 21:37:20 -0400 | [diff] [blame] | 183 | val = CAT6_MIN_VAL + read_coeff(cat6p, 16 - skip_bits, r); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 184 | break; |
| 185 | case VPX_BITS_12: |
Ronald S. Bultje | 3461e8c | 2015-09-30 21:37:20 -0400 | [diff] [blame] | 186 | val = CAT6_MIN_VAL + read_coeff(cat6p, 18 - skip_bits, r); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 187 | break; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 188 | default: assert(0); return -1; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 189 | } |
| 190 | #else |
Ronald S. Bultje | 3461e8c | 2015-09-30 21:37:20 -0400 | [diff] [blame] | 191 | val = CAT6_MIN_VAL + read_coeff(cat6p, 14 - skip_bits, r); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 192 | #endif |
| 193 | break; |
Ronald S. Bultje | 3461e8c | 2015-09-30 21:37:20 -0400 | [diff] [blame] | 194 | } |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 195 | } |
| 196 | } |
Thomas | 1c122c2 | 2016-02-19 09:06:12 +0000 | [diff] [blame^] | 197 | #if CONFIG_AOM_QM |
| 198 | dqv = ((iqmatrix[scan[c]] * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >> |
| 199 | AOM_QM_BITS; |
| 200 | #endif |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 201 | v = (val * dqv) >> dq_shift; |
| 202 | #if CONFIG_COEFFICIENT_RANGE_CHECKING |
Yaowu Xu | 3246fc0 | 2016-01-20 16:13:04 -0800 | [diff] [blame] | 203 | #if CONFIG_VPX_HIGHBITDEPTH |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 204 | dqcoeff[scan[c]] = highbd_check_range((vpx_read_bit(r) ? -v : v), xd->bd); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 205 | #else |
| 206 | dqcoeff[scan[c]] = check_range(vpx_read_bit(r) ? -v : v); |
Yaowu Xu | 3246fc0 | 2016-01-20 16:13:04 -0800 | [diff] [blame] | 207 | #endif // CONFIG_VPX_HIGHBITDEPTH |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 208 | #else |
| 209 | dqcoeff[scan[c]] = vpx_read_bit(r) ? -v : v; |
| 210 | #endif // CONFIG_COEFFICIENT_RANGE_CHECKING |
| 211 | token_cache[scan[c]] = vp10_pt_energy_class[token]; |
| 212 | ++c; |
| 213 | ctx = get_coef_context(nb, token_cache, c); |
| 214 | dqv = dq[1]; |
| 215 | } |
| 216 | |
| 217 | return c; |
| 218 | } |
| 219 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 220 | // TODO(slavarnway): Decode version of vp10_set_context. Modify |
| 221 | // vp10_set_context |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 222 | // after testing is complete, then delete this version. |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 223 | static void dec_set_contexts(const MACROBLOCKD *xd, |
| 224 | struct macroblockd_plane *pd, TX_SIZE tx_size, |
| 225 | int has_eob, int aoff, int loff) { |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 226 | ENTROPY_CONTEXT *const a = pd->above_context + aoff; |
| 227 | ENTROPY_CONTEXT *const l = pd->left_context + loff; |
| 228 | const int tx_size_in_blocks = 1 << tx_size; |
| 229 | |
| 230 | // above |
| 231 | if (has_eob && xd->mb_to_right_edge < 0) { |
| 232 | int i; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 233 | const int blocks_wide = |
| 234 | pd->n4_w + (xd->mb_to_right_edge >> (5 + pd->subsampling_x)); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 235 | int above_contexts = tx_size_in_blocks; |
| 236 | if (above_contexts + aoff > blocks_wide) |
| 237 | above_contexts = blocks_wide - aoff; |
| 238 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 239 | for (i = 0; i < above_contexts; ++i) a[i] = has_eob; |
| 240 | for (i = above_contexts; i < tx_size_in_blocks; ++i) a[i] = 0; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 241 | } else { |
| 242 | memset(a, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks); |
| 243 | } |
| 244 | |
| 245 | // left |
| 246 | if (has_eob && xd->mb_to_bottom_edge < 0) { |
| 247 | int i; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 248 | const int blocks_high = |
| 249 | pd->n4_h + (xd->mb_to_bottom_edge >> (5 + pd->subsampling_y)); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 250 | int left_contexts = tx_size_in_blocks; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 251 | if (left_contexts + loff > blocks_high) left_contexts = blocks_high - loff; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 252 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 253 | for (i = 0; i < left_contexts; ++i) l[i] = has_eob; |
| 254 | for (i = left_contexts; i < tx_size_in_blocks; ++i) l[i] = 0; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 255 | } else { |
| 256 | memset(l, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks); |
| 257 | } |
| 258 | } |
| 259 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 260 | int vp10_decode_block_tokens(MACROBLOCKD *xd, int plane, const scan_order *sc, |
| 261 | int x, int y, TX_SIZE tx_size, vpx_reader *r, |
| 262 | int seg_id) { |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 263 | struct macroblockd_plane *const pd = &xd->plane[plane]; |
| 264 | const int16_t *const dequant = pd->seg_dequant[seg_id]; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 265 | const int ctx = |
| 266 | get_entropy_context(tx_size, pd->above_context + x, pd->left_context + y); |
Thomas | 1c122c2 | 2016-02-19 09:06:12 +0000 | [diff] [blame^] | 267 | #if CONFIG_AOM_QM |
| 268 | const int eob = |
| 269 | decode_coefs(xd, pd->plane_type, pd->dqcoeff, tx_size, dequant, ctx, |
| 270 | sc->scan, sc->neighbors, r, pd->seg_iqmatrix[seg_id]); |
| 271 | #else |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 272 | const int eob = decode_coefs(xd, pd->plane_type, pd->dqcoeff, tx_size, |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 273 | dequant, ctx, sc->scan, sc->neighbors, r); |
Thomas | 1c122c2 | 2016-02-19 09:06:12 +0000 | [diff] [blame^] | 274 | #endif |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 275 | dec_set_contexts(xd, pd, tx_size, eob > 0, x, y); |
| 276 | return eob; |
| 277 | } |
Thomas | 1c122c2 | 2016-02-19 09:06:12 +0000 | [diff] [blame^] | 278 | |
| 279 | |