Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1 | /* |
Yaowu Xu | 9c01aa1 | 2016-09-01 14:32:49 -0700 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 3 | * |
Yaowu Xu | 9c01aa1 | 2016-09-01 14:32:49 -0700 | [diff] [blame] | 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. |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 10 | */ |
| 11 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 12 | #ifndef AOM_DSP_PROB_H_ |
| 13 | #define AOM_DSP_PROB_H_ |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 14 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 15 | #include "./aom_config.h" |
| 16 | #include "./aom_dsp_common.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 17 | |
Thomas | 9ac5508 | 2016-09-23 18:04:17 +0100 | [diff] [blame] | 18 | #include "aom_ports/bitops.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 19 | #include "aom_ports/mem.h" |
| 20 | |
| 21 | #ifdef __cplusplus |
| 22 | extern "C" { |
| 23 | #endif |
| 24 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 25 | typedef uint8_t aom_prob; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 26 | |
Alex Converse | a1ac972 | 2016-10-12 15:59:58 -0700 | [diff] [blame] | 27 | // TODO(negge): Rename this aom_prob once we remove vpxbool. |
| 28 | typedef uint16_t aom_cdf_prob; |
| 29 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 30 | #define MAX_PROB 255 |
| 31 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 32 | #define aom_prob_half ((aom_prob)128) |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 33 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 34 | typedef int8_t aom_tree_index; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 35 | |
Yaowu Xu | 8af861b | 2016-11-01 12:12:11 -0700 | [diff] [blame] | 36 | #define TREE_SIZE(leaf_count) (-2 + 2 * (leaf_count)) |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 37 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 38 | #define aom_complement(x) (255 - x) |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 39 | |
| 40 | #define MODE_MV_COUNT_SAT 20 |
| 41 | |
| 42 | /* We build coding trees compactly in arrays. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 43 | Each node of the tree is a pair of aom_tree_indices. |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 44 | Array index often references a corresponding probability table. |
| 45 | Index <= 0 means done encoding/decoding and value = -Index, |
| 46 | Index > 0 means need another bit, specification at index. |
| 47 | Nonnegative indices are always even; processing begins at node 0. */ |
| 48 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 49 | typedef const aom_tree_index aom_tree[]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 50 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 51 | static INLINE aom_prob clip_prob(int p) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 52 | return (p > 255) ? 255 : (p < 1) ? 1 : p; |
| 53 | } |
| 54 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 55 | static INLINE aom_prob get_prob(int num, int den) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 56 | return (den == 0) ? 128u : clip_prob(((int64_t)num * 256 + (den >> 1)) / den); |
| 57 | } |
| 58 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 59 | static INLINE aom_prob get_binary_prob(int n0, int n1) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 60 | return get_prob(n0, n0 + n1); |
| 61 | } |
| 62 | |
| 63 | /* This function assumes prob1 and prob2 are already within [1,255] range. */ |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 64 | static INLINE aom_prob weighted_prob(int prob1, int prob2, int factor) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 65 | return ROUND_POWER_OF_TWO(prob1 * (256 - factor) + prob2 * factor, 8); |
| 66 | } |
| 67 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 68 | static INLINE aom_prob merge_probs(aom_prob pre_prob, const unsigned int ct[2], |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 69 | unsigned int count_sat, |
| 70 | unsigned int max_update_factor) { |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 71 | const aom_prob prob = get_binary_prob(ct[0], ct[1]); |
| 72 | const unsigned int count = AOMMIN(ct[0] + ct[1], count_sat); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 73 | const unsigned int factor = max_update_factor * count / count_sat; |
| 74 | return weighted_prob(pre_prob, prob, factor); |
| 75 | } |
| 76 | |
| 77 | // MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT; |
| 78 | static const int count_to_update_factor[MODE_MV_COUNT_SAT + 1] = { |
| 79 | 0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64, |
| 80 | 70, 76, 83, 89, 96, 102, 108, 115, 121, 128 |
| 81 | }; |
| 82 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 83 | static INLINE aom_prob mode_mv_merge_probs(aom_prob pre_prob, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 84 | const unsigned int ct[2]) { |
| 85 | const unsigned int den = ct[0] + ct[1]; |
| 86 | if (den == 0) { |
| 87 | return pre_prob; |
| 88 | } else { |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 89 | const unsigned int count = AOMMIN(den, MODE_MV_COUNT_SAT); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 90 | const unsigned int factor = count_to_update_factor[count]; |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 91 | const aom_prob prob = |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 92 | clip_prob(((int64_t)(ct[0]) * 256 + (den >> 1)) / den); |
| 93 | return weighted_prob(pre_prob, prob, factor); |
| 94 | } |
| 95 | } |
| 96 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 97 | void aom_tree_merge_probs(const aom_tree_index *tree, const aom_prob *pre_probs, |
| 98 | const unsigned int *counts, aom_prob *probs); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 99 | |
Alex Converse | aca9feb | 2016-10-10 11:08:10 -0700 | [diff] [blame] | 100 | #if CONFIG_EC_MULTISYMBOL |
Nathan E. Egge | 43acafd | 2016-03-06 13:41:53 -0500 | [diff] [blame] | 101 | int tree_to_cdf(const aom_tree_index *tree, const aom_prob *probs, |
Nathan E. Egge | 9ac1f7d | 2016-08-19 17:16:31 -0400 | [diff] [blame] | 102 | aom_tree_index root, aom_cdf_prob *cdf, aom_tree_index *ind, |
Nathan E. Egge | 43acafd | 2016-03-06 13:41:53 -0500 | [diff] [blame] | 103 | int *pth, int *len); |
Nathan E. Egge | e2ed411 | 2016-05-19 12:11:56 -0400 | [diff] [blame] | 104 | |
| 105 | static INLINE void av1_tree_to_cdf(const aom_tree_index *tree, |
Nathan E. Egge | 9ac1f7d | 2016-08-19 17:16:31 -0400 | [diff] [blame] | 106 | const aom_prob *probs, aom_cdf_prob *cdf) { |
Nathan E. Egge | e2ed411 | 2016-05-19 12:11:56 -0400 | [diff] [blame] | 107 | aom_tree_index index[16]; |
| 108 | int path[16]; |
| 109 | int dist[16]; |
| 110 | tree_to_cdf(tree, probs, 0, cdf, index, path, dist); |
| 111 | } |
| 112 | |
| 113 | #define av1_tree_to_cdf_1D(tree, probs, cdf, u) \ |
| 114 | do { \ |
| 115 | int i; \ |
| 116 | for (i = 0; i < u; i++) { \ |
| 117 | av1_tree_to_cdf(tree, probs[i], cdf[i]); \ |
| 118 | } \ |
| 119 | } while (0) |
| 120 | |
Nathan E. Egge | 439c502 | 2016-07-17 23:07:27 -0400 | [diff] [blame] | 121 | #define av1_tree_to_cdf_2D(tree, probs, cdf, v, u) \ |
Nathan E. Egge | e2ed411 | 2016-05-19 12:11:56 -0400 | [diff] [blame] | 122 | do { \ |
| 123 | int j; \ |
| 124 | int i; \ |
| 125 | for (j = 0; j < v; j++) { \ |
| 126 | for (i = 0; i < u; i++) { \ |
| 127 | av1_tree_to_cdf(tree, probs[j][i], cdf[j][i]); \ |
| 128 | } \ |
| 129 | } \ |
| 130 | } while (0) |
Nathan E. Egge | 8abf867 | 2016-07-20 13:12:31 -0400 | [diff] [blame] | 131 | |
| 132 | void av1_indices_from_tree(int *ind, int *inv, int len, |
| 133 | const aom_tree_index *tree); |
Nathan E. Egge | 43acafd | 2016-03-06 13:41:53 -0500 | [diff] [blame] | 134 | #endif |
| 135 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 136 | DECLARE_ALIGNED(16, extern const uint8_t, aom_norm[256]); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 137 | |
Thomas | 9ac5508 | 2016-09-23 18:04:17 +0100 | [diff] [blame] | 138 | #if CONFIG_EC_ADAPT |
| 139 | static INLINE void update_cdf(aom_cdf_prob *cdf, int val, int nsymbs) { |
Thomas Davies | f6c04ac | 2016-10-12 17:54:29 +0100 | [diff] [blame] | 140 | const int rate = 4 + get_msb(nsymbs); |
Thomas Davies | ef97ec0 | 2016-12-09 14:42:02 +0000 | [diff] [blame] | 141 | const int rate2 = 12 - rate; |
| 142 | int i, tmp; |
| 143 | int diff; |
| 144 | #if 1 |
| 145 | const int tmp0 = 1 << rate2; |
| 146 | tmp = tmp0; |
| 147 | diff = ((32768 - (nsymbs << rate2)) >> rate) << rate; |
| 148 | // Single loop (faster) |
| 149 | for (i = 0; i < nsymbs - 1; ++i, tmp += tmp0) { |
| 150 | tmp += (i == val ? diff : 0); |
| 151 | cdf[i] -= ((cdf[i] - tmp) >> rate); |
| 152 | } |
| 153 | #else |
Thomas Davies | f6c04ac | 2016-10-12 17:54:29 +0100 | [diff] [blame] | 154 | for (i = 0; i < nsymbs; ++i) { |
Thomas Davies | ef97ec0 | 2016-12-09 14:42:02 +0000 | [diff] [blame] | 155 | tmp = (i + 1) << rate2; |
Thomas Davies | f6c04ac | 2016-10-12 17:54:29 +0100 | [diff] [blame] | 156 | cdf[i] -= ((cdf[i] - tmp) >> rate); |
Thomas | 9ac5508 | 2016-09-23 18:04:17 +0100 | [diff] [blame] | 157 | } |
Thomas Davies | f6c04ac | 2016-10-12 17:54:29 +0100 | [diff] [blame] | 158 | diff = 32768 - cdf[nsymbs - 1]; |
Thomas | 9ac5508 | 2016-09-23 18:04:17 +0100 | [diff] [blame] | 159 | |
Thomas Davies | f6c04ac | 2016-10-12 17:54:29 +0100 | [diff] [blame] | 160 | for (i = val; i < nsymbs; ++i) { |
| 161 | cdf[i] += diff; |
| 162 | } |
Thomas Davies | ef97ec0 | 2016-12-09 14:42:02 +0000 | [diff] [blame] | 163 | #endif |
Thomas | 9ac5508 | 2016-09-23 18:04:17 +0100 | [diff] [blame] | 164 | } |
| 165 | #endif |
| 166 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 167 | #ifdef __cplusplus |
| 168 | } // extern "C" |
| 169 | #endif |
| 170 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 171 | #endif // AOM_DSP_PROB_H_ |