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