Yushin Cho | 77bba8d | 2016-11-04 16:36:56 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved |
| 3 | * |
| 4 | * This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | * was not distributed with this source code in the LICENSE file, you can |
| 7 | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | * Media Patent License 1.0 was not distributed with this source code in the |
| 9 | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| 10 | */ |
| 11 | |
| 12 | /* clang-format off */ |
| 13 | |
| 14 | #ifdef HAVE_CONFIG_H |
| 15 | # include "config.h" |
| 16 | #endif |
| 17 | |
| 18 | #include "generic_code.h" |
| 19 | |
Nathan E. Egge | 8500142 | 2016-11-14 13:38:06 -0500 | [diff] [blame] | 20 | void aom_cdf_init(uint16_t *cdf, int ncdfs, int nsyms, int val, int first) { |
Yushin Cho | 77bba8d | 2016-11-04 16:36:56 -0700 | [diff] [blame] | 21 | int i; |
| 22 | int j; |
| 23 | for (i = 0; i < ncdfs; i++) { |
| 24 | for (j = 0; j < nsyms; j++) { |
| 25 | cdf[i*nsyms + j] = val*j + first; |
| 26 | } |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | /** Adapts a Q15 cdf after encoding/decoding a symbol. */ |
Nathan E. Egge | d6c2dc4 | 2016-11-15 10:07:58 -0500 | [diff] [blame] | 31 | void aom_cdf_adapt_q15(int val, uint16_t *cdf, int n, int *count, int rate) { |
Yushin Cho | 77bba8d | 2016-11-04 16:36:56 -0700 | [diff] [blame] | 32 | int i; |
| 33 | *count = OD_MINI(*count + 1, 1 << rate); |
| 34 | OD_ASSERT(cdf[n - 1] == 32768); |
| 35 | if (*count >= 1 << rate) { |
| 36 | /* Steady-state adaptation based on a simple IIR with dyadic rate. */ |
| 37 | for (i = 0; i < n; i++) { |
| 38 | int tmp; |
| 39 | /* When (i < val), we want the adjustment ((cdf[i] - tmp) >> rate) to be |
| 40 | positive so long as (cdf[i] > i + 1), and 0 when (cdf[i] == i + 1), |
| 41 | to ensure we don't drive any probabilities to 0. Replacing cdf[i] with |
| 42 | (i + 2) and solving ((i + 2 - tmp) >> rate == 1) for tmp produces |
| 43 | tmp == i + 2 - (1 << rate). Using this value of tmp with |
| 44 | cdf[i] == i + 1 instead gives an adjustment of 0 as desired. |
| 45 | |
| 46 | When (i >= val), we want ((cdf[i] - tmp) >> rate) to be negative so |
| 47 | long as cdf[i] < 32768 - (n - 1 - i), and 0 when |
| 48 | cdf[i] == 32768 - (n - 1 - i), again to ensure we don't drive any |
| 49 | probabilities to 0. Since right-shifting any negative value is still |
| 50 | negative, we can solve (32768 - (n - 1 - i) - tmp == 0) for tmp, |
| 51 | producing tmp = 32769 - n + i. Using this value of tmp with smaller |
| 52 | values of cdf[i] instead gives negative adjustments, as desired. |
| 53 | |
| 54 | Combining the two cases gives the expression below. These could be |
| 55 | stored in a lookup table indexed by n and rate to avoid the |
| 56 | arithmetic. */ |
| 57 | tmp = 2 - (1<<rate) + i + (32767 + (1<<rate) - n)*(i >= val); |
| 58 | cdf[i] -= (cdf[i] - tmp) >> rate; |
| 59 | } |
| 60 | } |
| 61 | else { |
| 62 | int alpha; |
| 63 | /* Initial adaptation for the first symbols. The adaptation rate is |
| 64 | computed to be equivalent to what od_{en,de}code_cdf_adapt() does |
| 65 | when the initial cdf is set to increment/4. */ |
| 66 | alpha = 4*32768/(n + 4**count); |
| 67 | for (i = 0; i < n; i++) { |
| 68 | int tmp; |
| 69 | tmp = (32768 - n)*(i >= val) + i + 1; |
| 70 | cdf[i] -= ((cdf[i] - tmp)*alpha) >> 15; |
| 71 | } |
| 72 | } |
| 73 | OD_ASSERT(cdf[n - 1] == 32768); |
| 74 | } |
| 75 | |
| 76 | /** Initializes the cdfs and freq counts for a model. |
| 77 | * |
| 78 | * @param [out] model model being initialized |
| 79 | */ |
| 80 | void generic_model_init(generic_encoder *model) { |
| 81 | int i; |
| 82 | int j; |
| 83 | model->increment = 64; |
| 84 | for (i = 0; i < GENERIC_TABLES; i++) { |
| 85 | for (j = 0; j < 16; j++) { |
| 86 | /* Do flat initialization equivalent to a single symbol in each bin. */ |
| 87 | model->cdf[i][j] = (j + 1) * model->increment; |
| 88 | } |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | /** Takes the base-2 log of E(x) in Q1. |
| 93 | * |
| 94 | * @param [in] ExQ16 expectation of x in Q16 |
| 95 | * |
| 96 | * @retval 2*log2(ExQ16/2^16) |
| 97 | */ |
| 98 | int log_ex(int ex_q16) { |
| 99 | int lg; |
| 100 | int lg_q1; |
| 101 | int odd; |
| 102 | lg = OD_ILOG(ex_q16); |
| 103 | if (lg < 15) { |
| 104 | odd = ex_q16*ex_q16 > 2 << 2*lg; |
| 105 | } |
| 106 | else { |
| 107 | int tmp; |
| 108 | tmp = ex_q16 >> (lg - 8); |
| 109 | odd = tmp*tmp > (1 << 15); |
| 110 | } |
| 111 | lg_q1 = OD_MAXI(0, 2*lg - 33 + odd); |
| 112 | return lg_q1; |
| 113 | } |
| 114 | |
| 115 | /** Updates the probability model based on the encoded/decoded value |
| 116 | * |
| 117 | * @param [in,out] model generic prob model |
| 118 | * @param [in,out] ExQ16 expectation of x |
| 119 | * @param [in] x variable encoded/decoded (used for ExQ16) |
| 120 | * @param [in] xs variable x after shift (used for the model) |
| 121 | * @param [in] id id of the icdf to adapt |
| 122 | * @param [in] integration integration period of ExQ16 (leaky average over |
| 123 | * 1<<integration samples) |
| 124 | */ |
| 125 | void generic_model_update(generic_encoder *model, int *ex_q16, int x, int xs, |
| 126 | int id, int integration) { |
| 127 | int i; |
| 128 | int xenc; |
| 129 | uint16_t *cdf; |
| 130 | cdf = model->cdf[id]; |
| 131 | /* Renormalize if we cannot add increment */ |
| 132 | if (cdf[15] + model->increment > 32767) { |
| 133 | for (i = 0; i < 16; i++) { |
| 134 | /* Second term ensures that the pdf is non-null */ |
| 135 | cdf[i] = (cdf[i] >> 1) + i + 1; |
| 136 | } |
| 137 | } |
| 138 | /* Update freq count */ |
| 139 | xenc = OD_MINI(15, xs); |
| 140 | /* This can be easily vectorized */ |
| 141 | for (i = xenc; i < 16; i++) cdf[i] += model->increment; |
| 142 | /* We could have saturated ExQ16 directly, but this is safe and simpler */ |
| 143 | x = OD_MINI(x, 32767); |
| 144 | OD_IIR_DIADIC(*ex_q16, x << 16, integration); |
| 145 | } |