| /* |
| * 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. |
| */ |
| |
| |
| #if CONFIG_DEBUG |
| #include <assert.h> |
| #endif |
| #include <stdio.h> |
| |
| #include "treecoder.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; |
| |
| #if CONFIG_DEBUG |
| assert(tree_len); |
| #endif |
| |
| 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; |
| #if CONFIG_DEBUG |
| assert(j < tree_len && 0 <= L); |
| #endif |
| |
| branch_ct [j] [b] += ct; |
| i = tree[ i + b]; |
| } |
| while (i > 0); |
| |
| #if CONFIG_DEBUG |
| assert(!L); |
| #endif |
| } |
| 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 Pfac, |
| int rd |
| ) |
| { |
| 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 CONFIG_DEBUG |
| assert(tot < (1 << 24)); /* no overflow below */ |
| #endif |
| |
| if (tot) |
| { |
| const unsigned int p = ((c[0] * Pfac) + (rd ? 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); |
| } |