1 /*
2  * Copyright (c) 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 #include "./aom_config.h"
13 
14 #include <string.h>
15 
16 #include "aom_dsp/prob.h"
17 
tree_merge_probs_impl(unsigned int i,const aom_tree_index * tree,const aom_prob * pre_probs,const unsigned int * counts,aom_prob * probs)18 static unsigned int tree_merge_probs_impl(unsigned int i,
19                                           const aom_tree_index *tree,
20                                           const aom_prob *pre_probs,
21                                           const unsigned int *counts,
22                                           aom_prob *probs) {
23   const int l = tree[i];
24   const unsigned int left_count =
25       (l <= 0) ? counts[-l]
26                : tree_merge_probs_impl(l, tree, pre_probs, counts, probs);
27   const int r = tree[i + 1];
28   const unsigned int right_count =
29       (r <= 0) ? counts[-r]
30                : tree_merge_probs_impl(r, tree, pre_probs, counts, probs);
31   const unsigned int ct[2] = { left_count, right_count };
32   probs[i >> 1] = mode_mv_merge_probs(pre_probs[i >> 1], ct);
33   return left_count + right_count;
34 }
35 
aom_tree_merge_probs(const aom_tree_index * tree,const aom_prob * pre_probs,const unsigned int * counts,aom_prob * probs)36 void aom_tree_merge_probs(const aom_tree_index *tree, const aom_prob *pre_probs,
37                           const unsigned int *counts, aom_prob *probs) {
38   tree_merge_probs_impl(0, tree, pre_probs, counts, probs);
39 }
40 
41 typedef struct tree_node tree_node;
42 
43 struct tree_node {
44   aom_tree_index index;
45   uint8_t probs[16];
46   uint8_t prob;
47   int path;
48   int len;
49   int l;
50   int r;
51   aom_cdf_prob pdf;
52 };
53 
54 /* Compute the probability of this node in Q23 */
tree_node_prob(tree_node n,int i)55 static uint32_t tree_node_prob(tree_node n, int i) {
56   uint32_t prob;
57   /* 1.0 in Q23 */
58   prob = 16777216;
59   for (; i < n.len; i++) {
60     prob = prob * n.probs[i] >> 8;
61   }
62   return prob;
63 }
64 
tree_node_cmp(tree_node a,tree_node b)65 static int tree_node_cmp(tree_node a, tree_node b) {
66   int i;
67   uint32_t pa;
68   uint32_t pb;
69   for (i = 0; i < AOMMIN(a.len, b.len) && a.probs[i] == b.probs[i]; i++) {
70   }
71   pa = tree_node_prob(a, i);
72   pb = tree_node_prob(b, i);
73   return pa > pb ? 1 : pa < pb ? -1 : 0;
74 }
75 
76 /* Given a Q15 probability for symbol subtree rooted at tree[n], this function
77     computes the probability of each symbol (defined as a node that has no
78     children). */
tree_node_compute_probs(tree_node * tree,int n,aom_cdf_prob pdf)79 static aom_cdf_prob tree_node_compute_probs(tree_node *tree, int n,
80                                             aom_cdf_prob pdf) {
81   if (tree[n].l == 0) {
82     /* This prevents probability computations in Q15 that underflow from
83         producing a symbol that has zero probability. */
84     if (pdf == 0) pdf = 1;
85     tree[n].pdf = pdf;
86     return pdf;
87   } else {
88     /* We process the smaller probability first,  */
89     if (tree[n].prob < 128) {
90       aom_cdf_prob lp;
91       aom_cdf_prob rp;
92       lp = (((uint32_t)pdf) * tree[n].prob + 128) >> 8;
93       lp = tree_node_compute_probs(tree, tree[n].l, lp);
94       rp = tree_node_compute_probs(tree, tree[n].r, lp > pdf ? 0 : pdf - lp);
95       return lp + rp;
96     } else {
97       aom_cdf_prob rp;
98       aom_cdf_prob lp;
99       rp = (((uint32_t)pdf) * (256 - tree[n].prob) + 128) >> 8;
100       rp = tree_node_compute_probs(tree, tree[n].r, rp);
101       lp = tree_node_compute_probs(tree, tree[n].l, rp > pdf ? 0 : pdf - rp);
102       return lp + rp;
103     }
104   }
105 }
106 
tree_node_extract(tree_node * tree,int n,int symb,aom_cdf_prob * pdf,aom_tree_index * index,int * path,int * len)107 static int tree_node_extract(tree_node *tree, int n, int symb,
108                              aom_cdf_prob *pdf, aom_tree_index *index,
109                              int *path, int *len) {
110   if (tree[n].l == 0) {
111     pdf[symb] = tree[n].pdf;
112     if (index != NULL) index[symb] = tree[n].index;
113     if (path != NULL) path[symb] = tree[n].path;
114     if (len != NULL) len[symb] = tree[n].len;
115     return symb + 1;
116   } else {
117     symb = tree_node_extract(tree, tree[n].l, symb, pdf, index, path, len);
118     return tree_node_extract(tree, tree[n].r, symb, pdf, index, path, len);
119   }
120 }
121 
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)122 int tree_to_cdf(const aom_tree_index *tree, const aom_prob *probs,
123                 aom_tree_index root, aom_cdf_prob *cdf, aom_tree_index *index,
124                 int *path, int *len) {
125   tree_node symb[2 * 16 - 1];
126   int nodes;
127   int next[16];
128   int size;
129   int nsymbs;
130   int i;
131   /* Create the root node with probability 1 in Q15. */
132   symb[0].index = root;
133   symb[0].path = 0;
134   symb[0].len = 0;
135   symb[0].l = symb[0].r = 0;
136   nodes = 1;
137   next[0] = 0;
138   size = 1;
139   nsymbs = 1;
140   while (size > 0 && nsymbs < 16) {
141     int m;
142     tree_node n;
143     aom_tree_index j;
144     uint8_t prob;
145     m = 0;
146     /* Find the internal node with the largest probability. */
147     for (i = 1; i < size; i++) {
148       if (tree_node_cmp(symb[next[i]], symb[next[m]]) > 0) m = i;
149     }
150     i = next[m];
151     memmove(&next[m], &next[m + 1], sizeof(*next) * (size - (m + 1)));
152     size--;
153     /* Split this symbol into two symbols */
154     n = symb[i];
155     j = n.index;
156     prob = probs[j >> 1];
157     /* Left */
158     n.index = tree[j];
159     n.path <<= 1;
160     n.len++;
161     n.probs[n.len - 1] = prob;
162     symb[nodes] = n;
163     if (n.index > 0) {
164       next[size++] = nodes;
165     }
166     /* Right */
167     n.index = tree[j + 1];
168     n.path += 1;
169     n.probs[n.len - 1] = 256 - prob;
170     symb[nodes + 1] = n;
171     if (n.index > 0) {
172       next[size++] = nodes + 1;
173     }
174     symb[i].prob = prob;
175     symb[i].l = nodes;
176     symb[i].r = nodes + 1;
177     nodes += 2;
178     nsymbs++;
179   }
180   /* Compute the probabilities of each symbol in Q15 */
181   tree_node_compute_probs(symb, 0, CDF_PROB_TOP);
182   /* Extract the cdf, index, path and length */
183   tree_node_extract(symb, 0, 0, cdf, index, path, len);
184   /* Convert to CDF */
185   cdf[0] = AOM_ICDF(cdf[0]);
186   for (i = 1; i < nsymbs; i++) {
187     cdf[i] = AOM_ICDF(AOM_ICDF(cdf[i - 1]) + cdf[i]);
188   }
189   // Store symbol count at the end of the CDF
190   cdf[nsymbs] = 0;
191   return nsymbs;
192 }
193 
194 /* This code assumes that tree contains as unique leaf nodes the integer values
195     0 to len - 1 and produces the forward and inverse mapping tables in ind[]
196     and inv[] respectively. */
tree_to_index(int * stack_index,int * ind,int * inv,const aom_tree_index * tree,int value,int index)197 static void tree_to_index(int *stack_index, int *ind, int *inv,
198                           const aom_tree_index *tree, int value, int index) {
199   value *= 2;
200 
201   do {
202     const aom_tree_index content = tree[index];
203     ++index;
204     if (content <= 0) {
205       inv[*stack_index] = -content;
206       ind[-content] = *stack_index;
207       ++(*stack_index);
208     } else {
209       tree_to_index(stack_index, ind, inv, tree, value, content);
210     }
211   } while (++value & 1);
212 }
213 
av1_indices_from_tree(int * ind,int * inv,const aom_tree_index * tree)214 void av1_indices_from_tree(int *ind, int *inv, const aom_tree_index *tree) {
215   int stack_index = 0;
216   tree_to_index(&stack_index, ind, inv, tree, 0, 0);
217 }
218