Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Conrad <lessen42@gmail.com>2010-07-24 01:46:17 +0400
committerDavid Conrad <lessen42@gmail.com>2010-07-24 01:46:17 +0400
commitfe1b5d974acf7736151e2e13f2498f4fbd6af765 (patch)
treea5135bb741533094e8824b8b9ff63659aa43a811 /libavcodec/vp8.c
parent5474ec2ac8a4964c4d6a0b51cd00a0ec2e7bb9a6 (diff)
Decode DCT tokens by branching to a different code path for each branch
on the huffman tree, instead of traversing the tree in a while loop. Based on the similar optimization in libvpx's detokenize.c 10% faster at normal bitrates, and 30% faster for high-bitrate intra-only Originally committed as revision 24468 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/vp8.c')
-rw-r--r--libavcodec/vp8.c69
1 files changed, 47 insertions, 22 deletions
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index 81447c4fd8..acdaf56b03 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -800,36 +800,61 @@ static int decode_block_coeffs(VP56RangeCoder *c, DCTELEM block[16],
uint8_t probs[8][3][NUM_DCT_TOKENS-1],
int i, int zero_nhood, int16_t qmul[2])
{
- int token, nonzero = 0;
- int offset = 0;
+ uint8_t *token_prob;
+ int nonzero = 0;
+ int coeff;
- for (; i < 16; i++) {
- token = vp8_rac_get_tree_with_offset(c, vp8_coeff_tree, probs[vp8_coeff_band[i]][zero_nhood], offset);
+ do {
+ token_prob = probs[vp8_coeff_band[i]][zero_nhood];
- if (token == DCT_EOB)
- break;
- else if (token >= DCT_CAT1) {
- int cat = token-DCT_CAT1;
- token = vp8_rac_get_coeff(c, vp8_dct_cat_prob[cat]);
- token += 3 + (2<<cat);
- }
+ if (!vp56_rac_get_prob_branchy(c, token_prob[0])) // DCT_EOB
+ return nonzero;
- // after the first token, the non-zero prediction context becomes
- // based on the last decoded coeff
- if (!token) {
+skip_eob:
+ if (!vp56_rac_get_prob_branchy(c, token_prob[1])) { // DCT_0
zero_nhood = 0;
- offset = 1;
- continue;
- } else if (token == 1)
+ token_prob = probs[vp8_coeff_band[++i]][0];
+ if (i < 16)
+ goto skip_eob;
+ return nonzero; // invalid input; blocks should end with EOB
+ }
+
+ if (!vp56_rac_get_prob_branchy(c, token_prob[2])) { // DCT_1
+ coeff = 1;
zero_nhood = 1;
- else
+ } else {
zero_nhood = 2;
+ if (!vp56_rac_get_prob_branchy(c, token_prob[3])) { // DCT 2,3,4
+ coeff = vp56_rac_get_prob(c, token_prob[4]);
+ if (coeff)
+ coeff += vp56_rac_get_prob(c, token_prob[5]);
+ coeff += 2;
+ } else {
+ // DCT_CAT*
+ if (!vp56_rac_get_prob_branchy(c, token_prob[6])) {
+ if (!vp56_rac_get_prob_branchy(c, token_prob[7])) { // DCT_CAT1
+ coeff = 5 + vp56_rac_get_prob(c, vp8_dct_cat1_prob[0]);
+ } else { // DCT_CAT2
+ coeff = 7;
+ coeff += vp56_rac_get_prob(c, vp8_dct_cat2_prob[0]) << 1;
+ coeff += vp56_rac_get_prob(c, vp8_dct_cat2_prob[1]);
+ }
+ } else { // DCT_CAT3 and up
+ int a = vp56_rac_get_prob(c, token_prob[8]);
+ int b = vp56_rac_get_prob(c, token_prob[9+a]);
+ int cat = (a<<1) + b;
+ coeff = 3 + (8<<cat);
+ coeff += vp8_rac_get_coeff(c, vp8_dct_cat_prob[cat]);
+ }
+ }
+ }
+
// todo: full [16] qmat? load into register?
- block[zigzag_scan[i]] = (vp8_rac_get(c) ? -token : token) * qmul[!!i];
- nonzero = i+1;
- offset = 0;
- }
+ block[zigzag_scan[i]] = (vp8_rac_get(c) ? -coeff : coeff) * qmul[!!i];
+ nonzero = ++i;
+ } while (i < 16);
+
return nonzero;
}