| /* |
| * Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include <assert.h> |
| #include <stdio.h> |
| |
| #include "vp8/common/treecoder.h" |
| #include "vpx/vpx_integer.h" |
| |
| static void tree2tok(struct vp8_token_struct *const p, vp8_tree t, int i, int v, |
| int L) { |
| v += v; |
| ++L; |
| |
| do { |
| const vp8_tree_index j = t[i++]; |
| |
| if (j <= 0) { |
| p[-j].value = v; |
| p[-j].Len = L; |
| } else { |
| tree2tok(p, t, j, v, L); |
| } |
| } while (++v & 1); |
| } |
| |
| void vp8_tokens_from_tree(struct vp8_token_struct *p, vp8_tree t) { |
| tree2tok(p, t, 0, 0, 0); |
| } |
| |
| void vp8_tokens_from_tree_offset(struct vp8_token_struct *p, vp8_tree t, |
| int offset) { |
| tree2tok(p - offset, t, 0, 0, 0); |
| } |
| |
| static void branch_counts(int n, /* n = size of alphabet */ |
| vp8_token tok[/* n */], vp8_tree tree, |
| unsigned int branch_ct[/* n-1 */][2], |
| const unsigned int num_events[/* n */]) { |
| const int tree_len = n - 1; |
| int t = 0; |
| |
| assert(tree_len); |
| |
| do { |
| branch_ct[t][0] = branch_ct[t][1] = 0; |
| } while (++t < tree_len); |
| |
| t = 0; |
| |
| do { |
| int L = tok[t].Len; |
| const int enc = tok[t].value; |
| const unsigned int ct = num_events[t]; |
| |
| vp8_tree_index i = 0; |
| |
| do { |
| const int b = (enc >> --L) & 1; |
| const int j = i >> 1; |
| assert(j < tree_len && 0 <= L); |
| |
| branch_ct[j][b] += ct; |
| i = tree[i + b]; |
| } while (i > 0); |
| |
| assert(!L); |
| } while (++t < n); |
| } |
| |
| void vp8_tree_probs_from_distribution(int n, /* n = size of alphabet */ |
| vp8_token tok[/* n */], vp8_tree tree, |
| vp8_prob probs[/* n-1 */], |
| unsigned int branch_ct[/* n-1 */][2], |
| const unsigned int num_events[/* n */], |
| unsigned int Pfactor, int Round) { |
| const int tree_len = n - 1; |
| int t = 0; |
| |
| branch_counts(n, tok, tree, branch_ct, num_events); |
| |
| do { |
| const unsigned int *const c = branch_ct[t]; |
| const unsigned int tot = c[0] + c[1]; |
| |
| if (tot) { |
| const unsigned int p = |
| (unsigned int)(((uint64_t)c[0] * Pfactor) + (Round ? tot >> 1 : 0)) / |
| tot; |
| probs[t] = p < 256 ? (p ? p : 1) : 255; /* agree w/old version for now */ |
| } else { |
| probs[t] = vp8_prob_half; |
| } |
| } while (++t < tree_len); |
| } |