xref: /aosp_15_r20/external/libvpx/vp8/common/treecoder.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
13*fb1b10abSAndroid Build Coastguard Worker 
14*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/treecoder.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_integer.h"
16*fb1b10abSAndroid Build Coastguard Worker 
tree2tok(struct vp8_token_struct * const p,vp8_tree t,int i,int v,int L)17*fb1b10abSAndroid Build Coastguard Worker static void tree2tok(struct vp8_token_struct *const p, vp8_tree t, int i, int v,
18*fb1b10abSAndroid Build Coastguard Worker                      int L) {
19*fb1b10abSAndroid Build Coastguard Worker   v += v;
20*fb1b10abSAndroid Build Coastguard Worker   ++L;
21*fb1b10abSAndroid Build Coastguard Worker 
22*fb1b10abSAndroid Build Coastguard Worker   do {
23*fb1b10abSAndroid Build Coastguard Worker     const vp8_tree_index j = t[i++];
24*fb1b10abSAndroid Build Coastguard Worker 
25*fb1b10abSAndroid Build Coastguard Worker     if (j <= 0) {
26*fb1b10abSAndroid Build Coastguard Worker       p[-j].value = v;
27*fb1b10abSAndroid Build Coastguard Worker       p[-j].Len = L;
28*fb1b10abSAndroid Build Coastguard Worker     } else {
29*fb1b10abSAndroid Build Coastguard Worker       tree2tok(p, t, j, v, L);
30*fb1b10abSAndroid Build Coastguard Worker     }
31*fb1b10abSAndroid Build Coastguard Worker   } while (++v & 1);
32*fb1b10abSAndroid Build Coastguard Worker }
33*fb1b10abSAndroid Build Coastguard Worker 
vp8_tokens_from_tree(struct vp8_token_struct * p,vp8_tree t)34*fb1b10abSAndroid Build Coastguard Worker void vp8_tokens_from_tree(struct vp8_token_struct *p, vp8_tree t) {
35*fb1b10abSAndroid Build Coastguard Worker   tree2tok(p, t, 0, 0, 0);
36*fb1b10abSAndroid Build Coastguard Worker }
37*fb1b10abSAndroid Build Coastguard Worker 
vp8_tokens_from_tree_offset(struct vp8_token_struct * p,vp8_tree t,int offset)38*fb1b10abSAndroid Build Coastguard Worker void vp8_tokens_from_tree_offset(struct vp8_token_struct *p, vp8_tree t,
39*fb1b10abSAndroid Build Coastguard Worker                                  int offset) {
40*fb1b10abSAndroid Build Coastguard Worker   tree2tok(p - offset, t, 0, 0, 0);
41*fb1b10abSAndroid Build Coastguard Worker }
42*fb1b10abSAndroid Build Coastguard Worker 
branch_counts(int n,vp8_token tok[],vp8_tree tree,unsigned int branch_ct[][2],const unsigned int num_events[])43*fb1b10abSAndroid Build Coastguard Worker static void branch_counts(int n, /* n = size of alphabet */
44*fb1b10abSAndroid Build Coastguard Worker                           vp8_token tok[/* n */], vp8_tree tree,
45*fb1b10abSAndroid Build Coastguard Worker                           unsigned int branch_ct[/* n-1 */][2],
46*fb1b10abSAndroid Build Coastguard Worker                           const unsigned int num_events[/* n */]) {
47*fb1b10abSAndroid Build Coastguard Worker   const int tree_len = n - 1;
48*fb1b10abSAndroid Build Coastguard Worker   int t = 0;
49*fb1b10abSAndroid Build Coastguard Worker 
50*fb1b10abSAndroid Build Coastguard Worker   assert(tree_len);
51*fb1b10abSAndroid Build Coastguard Worker 
52*fb1b10abSAndroid Build Coastguard Worker   do {
53*fb1b10abSAndroid Build Coastguard Worker     branch_ct[t][0] = branch_ct[t][1] = 0;
54*fb1b10abSAndroid Build Coastguard Worker   } while (++t < tree_len);
55*fb1b10abSAndroid Build Coastguard Worker 
56*fb1b10abSAndroid Build Coastguard Worker   t = 0;
57*fb1b10abSAndroid Build Coastguard Worker 
58*fb1b10abSAndroid Build Coastguard Worker   do {
59*fb1b10abSAndroid Build Coastguard Worker     int L = tok[t].Len;
60*fb1b10abSAndroid Build Coastguard Worker     const int enc = tok[t].value;
61*fb1b10abSAndroid Build Coastguard Worker     const unsigned int ct = num_events[t];
62*fb1b10abSAndroid Build Coastguard Worker 
63*fb1b10abSAndroid Build Coastguard Worker     vp8_tree_index i = 0;
64*fb1b10abSAndroid Build Coastguard Worker 
65*fb1b10abSAndroid Build Coastguard Worker     do {
66*fb1b10abSAndroid Build Coastguard Worker       const int b = (enc >> --L) & 1;
67*fb1b10abSAndroid Build Coastguard Worker       const int j = i >> 1;
68*fb1b10abSAndroid Build Coastguard Worker       assert(j < tree_len && 0 <= L);
69*fb1b10abSAndroid Build Coastguard Worker 
70*fb1b10abSAndroid Build Coastguard Worker       branch_ct[j][b] += ct;
71*fb1b10abSAndroid Build Coastguard Worker       i = tree[i + b];
72*fb1b10abSAndroid Build Coastguard Worker     } while (i > 0);
73*fb1b10abSAndroid Build Coastguard Worker 
74*fb1b10abSAndroid Build Coastguard Worker     assert(!L);
75*fb1b10abSAndroid Build Coastguard Worker   } while (++t < n);
76*fb1b10abSAndroid Build Coastguard Worker }
77*fb1b10abSAndroid Build Coastguard Worker 
vp8_tree_probs_from_distribution(int n,vp8_token tok[],vp8_tree tree,vp8_prob probs[],unsigned int branch_ct[][2],const unsigned int num_events[],unsigned int Pfactor,int Round)78*fb1b10abSAndroid Build Coastguard Worker void vp8_tree_probs_from_distribution(int n, /* n = size of alphabet */
79*fb1b10abSAndroid Build Coastguard Worker                                       vp8_token tok[/* n */], vp8_tree tree,
80*fb1b10abSAndroid Build Coastguard Worker                                       vp8_prob probs[/* n-1 */],
81*fb1b10abSAndroid Build Coastguard Worker                                       unsigned int branch_ct[/* n-1 */][2],
82*fb1b10abSAndroid Build Coastguard Worker                                       const unsigned int num_events[/* n */],
83*fb1b10abSAndroid Build Coastguard Worker                                       unsigned int Pfactor, int Round) {
84*fb1b10abSAndroid Build Coastguard Worker   const int tree_len = n - 1;
85*fb1b10abSAndroid Build Coastguard Worker   int t = 0;
86*fb1b10abSAndroid Build Coastguard Worker 
87*fb1b10abSAndroid Build Coastguard Worker   branch_counts(n, tok, tree, branch_ct, num_events);
88*fb1b10abSAndroid Build Coastguard Worker 
89*fb1b10abSAndroid Build Coastguard Worker   do {
90*fb1b10abSAndroid Build Coastguard Worker     const unsigned int *const c = branch_ct[t];
91*fb1b10abSAndroid Build Coastguard Worker     const unsigned int tot = c[0] + c[1];
92*fb1b10abSAndroid Build Coastguard Worker 
93*fb1b10abSAndroid Build Coastguard Worker     if (tot) {
94*fb1b10abSAndroid Build Coastguard Worker       const unsigned int p =
95*fb1b10abSAndroid Build Coastguard Worker           (unsigned int)(((uint64_t)c[0] * Pfactor) + (Round ? tot >> 1 : 0)) /
96*fb1b10abSAndroid Build Coastguard Worker           tot;
97*fb1b10abSAndroid Build Coastguard Worker       probs[t] = p < 256 ? (p ? p : 1) : 255; /* agree w/old version for now */
98*fb1b10abSAndroid Build Coastguard Worker     } else {
99*fb1b10abSAndroid Build Coastguard Worker       probs[t] = vp8_prob_half;
100*fb1b10abSAndroid Build Coastguard Worker     }
101*fb1b10abSAndroid Build Coastguard Worker   } while (++t < tree_len);
102*fb1b10abSAndroid Build Coastguard Worker }
103