bd84685f78
The previous implementation visited each node in the tree multiple times because it used each symbol's encoding to revisit the branches taken and increment its count. Instead, we can traverse the tree depth first and calculate the probabilities and branch counts as we walk back up. The complexity goes from somewhere between O(nlogn) and O(n^2) (depending on how balanced the tree is) to O(n). Only tested one clip (256kbps, CIF), saw 13% decoding perf improvement. Note that this optimization should port trivially to VP8 as well. In VP8, the decoder doesn't use this function, but it does routinely show up on the profile for realtime encoding. Change-Id: I4f2848e4f41dc9a7694f73f3e75034bce08d1b12
85 lines
2.3 KiB
C
85 lines
2.3 KiB
C
/*
|
|
* 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 "vpx_config.h"
|
|
|
|
#if defined(CONFIG_DEBUG) && CONFIG_DEBUG
|
|
#include <assert.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
|
|
#include "vp9/common/vp9_treecoder.h"
|
|
|
|
static void tree2tok(
|
|
struct vp9_token_struct *const p,
|
|
vp9_tree t,
|
|
int i,
|
|
int v,
|
|
int L
|
|
) {
|
|
v += v;
|
|
++L;
|
|
|
|
do {
|
|
const vp9_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 vp9_tokens_from_tree(struct vp9_token_struct *p, vp9_tree t) {
|
|
tree2tok(p, t, 0, 0, 0);
|
|
}
|
|
|
|
void vp9_tokens_from_tree_offset(struct vp9_token_struct *p, vp9_tree t,
|
|
int offset) {
|
|
tree2tok(p - offset, t, 0, 0, 0);
|
|
}
|
|
|
|
static unsigned int convert_distribution(unsigned int i,
|
|
vp9_tree tree,
|
|
vp9_prob probs[],
|
|
unsigned int branch_ct[][2],
|
|
const unsigned int num_events[],
|
|
unsigned int tok0_offset) {
|
|
unsigned int left, right;
|
|
|
|
if (tree[i] <= 0) {
|
|
left = num_events[-tree[i] - tok0_offset];
|
|
} else {
|
|
left = convert_distribution(tree[i], tree, probs, branch_ct,
|
|
num_events, tok0_offset);
|
|
}
|
|
if (tree[i + 1] <= 0) {
|
|
right = num_events[-tree[i + 1] - tok0_offset];
|
|
} else {
|
|
right = convert_distribution(tree[i + 1], tree, probs, branch_ct,
|
|
num_events, tok0_offset);
|
|
}
|
|
probs[i>>1] = get_binary_prob(left, right);
|
|
branch_ct[i>>1][0] = left;
|
|
branch_ct[i>>1][1] = right;
|
|
return left + right;
|
|
}
|
|
|
|
void vp9_tree_probs_from_distribution(
|
|
vp9_tree tree,
|
|
vp9_prob probs [ /* n-1 */ ],
|
|
unsigned int branch_ct [ /* n-1 */ ] [2],
|
|
const unsigned int num_events[ /* n */ ],
|
|
unsigned int tok0_offset) {
|
|
convert_distribution(0, tree, probs, branch_ct, num_events, tok0_offset);
|
|
}
|