/* * Copyright (c) 2016, Alliance for Open Media. All rights reserved * * This source code is subject to the terms of the BSD 2 Clause License and * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License * was not distributed with this source code in the LICENSE file, you can * obtain it at www.aomedia.org/license/software. If the Alliance for Open * Media Patent License 1.0 was not distributed with this source code in the * PATENTS file, you can obtain it at www.aomedia.org/license/patent. */ #include "./aom_config.h" #if CONFIG_EC_MULTISYMBOL #include #endif #include "aom_dsp/prob.h" #if CONFIG_DAALA_EC #include "aom_dsp/entcode.h" #endif const uint8_t aom_norm[256] = { 0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned int tree_merge_probs_impl(unsigned int i, const aom_tree_index *tree, const aom_prob *pre_probs, const unsigned int *counts, aom_prob *probs) { const int l = tree[i]; const unsigned int left_count = (l <= 0) ? counts[-l] : tree_merge_probs_impl(l, tree, pre_probs, counts, probs); const int r = tree[i + 1]; const unsigned int right_count = (r <= 0) ? counts[-r] : tree_merge_probs_impl(r, tree, pre_probs, counts, probs); const unsigned int ct[2] = { left_count, right_count }; probs[i >> 1] = mode_mv_merge_probs(pre_probs[i >> 1], ct); return left_count + right_count; } void aom_tree_merge_probs(const aom_tree_index *tree, const aom_prob *pre_probs, const unsigned int *counts, aom_prob *probs) { tree_merge_probs_impl(0, tree, pre_probs, counts, probs); } #if CONFIG_EC_MULTISYMBOL typedef struct tree_node tree_node; struct tree_node { aom_tree_index index; uint8_t probs[16]; uint8_t prob; int path; int len; int l; int r; aom_cdf_prob pdf; }; /* Compute the probability of this node in Q23 */ static uint32_t tree_node_prob(tree_node n, int i) { uint32_t prob; /* 1.0 in Q23 */ prob = 16777216; for (; i < n.len; i++) { prob = prob * n.probs[i] >> 8; } return prob; } static int tree_node_cmp(tree_node a, tree_node b) { int i; uint32_t pa; uint32_t pb; for (i = 0; i < AOMMIN(a.len, b.len) && a.probs[i] == b.probs[i]; i++) { } pa = tree_node_prob(a, i); pb = tree_node_prob(b, i); return pa > pb ? 1 : pa < pb ? -1 : 0; } /* Given a Q15 probability for symbol subtree rooted at tree[n], this function computes the probability of each symbol (defined as a node that has no children). */ static aom_cdf_prob tree_node_compute_probs(tree_node *tree, int n, aom_cdf_prob pdf) { if (tree[n].l == 0) { /* This prevents probability computations in Q15 that underflow from producing a symbol that has zero probability. */ if (pdf == 0) pdf = 1; tree[n].pdf = pdf; return pdf; } else { /* We process the smaller probability first, */ if (tree[n].prob < 128) { aom_cdf_prob lp; aom_cdf_prob rp; lp = (((uint32_t)pdf) * tree[n].prob + 128) >> 8; lp = tree_node_compute_probs(tree, tree[n].l, lp); rp = tree_node_compute_probs(tree, tree[n].r, lp > pdf ? 0 : pdf - lp); return lp + rp; } else { aom_cdf_prob rp; aom_cdf_prob lp; rp = (((uint32_t)pdf) * (256 - tree[n].prob) + 128) >> 8; rp = tree_node_compute_probs(tree, tree[n].r, rp); lp = tree_node_compute_probs(tree, tree[n].l, rp > pdf ? 0 : pdf - rp); return lp + rp; } } } static int tree_node_extract(tree_node *tree, int n, int symb, aom_cdf_prob *pdf, aom_tree_index *index, int *path, int *len) { if (tree[n].l == 0) { pdf[symb] = tree[n].pdf; if (index != NULL) index[symb] = tree[n].index; if (path != NULL) path[symb] = tree[n].path; if (len != NULL) len[symb] = tree[n].len; return symb + 1; } else { symb = tree_node_extract(tree, tree[n].l, symb, pdf, index, path, len); return tree_node_extract(tree, tree[n].r, symb, pdf, index, path, len); } } int tree_to_cdf(const aom_tree_index *tree, const aom_prob *probs, aom_tree_index root, aom_cdf_prob *cdf, aom_tree_index *index, int *path, int *len) { tree_node symb[2 * 16 - 1]; int nodes; int next[16]; int size; int nsymbs; int i; /* Create the root node with probability 1 in Q15. */ symb[0].index = root; symb[0].path = 0; symb[0].len = 0; symb[0].l = symb[0].r = 0; nodes = 1; next[0] = 0; size = 1; nsymbs = 1; while (size > 0 && nsymbs < 16) { int m; tree_node n; aom_tree_index j; uint8_t prob; m = 0; /* Find the internal node with the largest probability. */ for (i = 1; i < size; i++) { if (tree_node_cmp(symb[next[i]], symb[next[m]]) > 0) m = i; } i = next[m]; memmove(&next[m], &next[m + 1], sizeof(*next) * (size - (m + 1))); size--; /* Split this symbol into two symbols */ n = symb[i]; j = n.index; prob = probs[j >> 1]; /* Left */ n.index = tree[j]; n.path <<= 1; n.len++; n.probs[n.len - 1] = prob; symb[nodes] = n; if (n.index > 0) { next[size++] = nodes; } /* Right */ n.index = tree[j + 1]; n.path += 1; n.probs[n.len - 1] = 256 - prob; symb[nodes + 1] = n; if (n.index > 0) { next[size++] = nodes + 1; } symb[i].prob = prob; symb[i].l = nodes; symb[i].r = nodes + 1; nodes += 2; nsymbs++; } /* Compute the probabilities of each symbol in Q15 */ tree_node_compute_probs(symb, 0, 32768); /* Extract the cdf, index, path and length */ tree_node_extract(symb, 0, 0, cdf, index, path, len); /* Convert to CDF */ for (i = 1; i < nsymbs; i++) { cdf[i] = cdf[i - 1] + cdf[i]; } return nsymbs; } /* This code assumes that tree contains as unique leaf nodes the integer values 0 to len - 1 and produces the forward and inverse mapping tables in ind[] and inv[] respectively. */ void av1_indices_from_tree(int *ind, int *inv, int len, const aom_tree_index *tree) { int i; int index; for (i = index = 0; i < TREE_SIZE(len); i++) { const aom_tree_index j = tree[i]; if (j <= 0) { inv[index] = -j; ind[-j] = index++; } } } #endif