xref: /rockchip-linux_mpp/mpp/codec/dec/vp9/vpx_rac.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2 *
3 * Copyright 2015 Rockchip Electronics Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 
18 
19 #include "vpx_rac.h"
20 
21 #define DEF( name, bytes, read, write) \
22     static unsigned int bytestream_get_ ## name(const uint8_t **b) \
23     { \
24         (*b) += bytes; \
25         return read(*b - bytes); \
26     }
27 
28 DEF(be24, 3, MPP_RB24, MPP_WB24)
29 DEF(be16, 2, MPP_RB16, MPP_WB16)
30 
31 const uint8_t vpx_norm_shift[256] = {
32     8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
33     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
34     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
35     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
36     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
37     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
38     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
39     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
40     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44 };
45 
vpx_init_range_decoder(VpxRangeCoder * c,const uint8_t * buf,int buf_size)46 void vpx_init_range_decoder(VpxRangeCoder *c, const uint8_t *buf, int buf_size)
47 {
48     c->high = 255;
49     c->bits = -16;
50     c->buffer = buf;
51     c->end = buf + buf_size;
52     c->code_word = bytestream_get_be24(&c->buffer);
53 }
54 
vpx_rac_renorm(VpxRangeCoder * c)55 unsigned int vpx_rac_renorm(VpxRangeCoder *c)
56 {
57     int shift = vpx_norm_shift[c->high];
58     int bits = c->bits;
59     unsigned int code_word = c->code_word;
60 
61     c->high   <<= shift;
62     code_word <<= shift;
63     bits       += shift;
64     if (bits >= 0 && c->buffer < c->end) {
65         code_word |= bytestream_get_be16(&c->buffer) << bits;
66         bits -= 16;
67     }
68     c->bits = bits;
69     return code_word;
70 }
71 
vpx_rac_get_prob(VpxRangeCoder * c,uint8_t prob)72 int vpx_rac_get_prob(VpxRangeCoder *c, uint8_t prob)
73 {
74     unsigned int code_word = vpx_rac_renorm(c);
75     unsigned int low = 1 + (((c->high - 1) * prob) >> 8);
76     unsigned int low_shift = low << 16;
77     int bit = code_word >= low_shift;
78 
79     c->high = bit ? c->high - low : low;
80     c->code_word = bit ? code_word - low_shift : code_word;
81 
82     return bit;
83 }
84 
85 // branchy variant, to be used where there's a branch based on the bit decoded
vpx_rac_get_prob_branchy(VpxRangeCoder * c,int prob)86 int vpx_rac_get_prob_branchy(VpxRangeCoder *c, int prob)
87 {
88     unsigned long code_word = vpx_rac_renorm(c);
89     unsigned low = 1 + (((c->high - 1) * prob) >> 8);
90     unsigned low_shift = low << 16;
91 
92     if (code_word >= low_shift) {
93         c->high     -= low;
94         c->code_word = code_word - low_shift;
95         return 1;
96     }
97 
98     c->high = low;
99     c->code_word = code_word;
100     return 0;
101 }
102 
103 // rounding is different than vpx_rac_get, is vpx_rac_get wrong?
vpx_rac_get(VpxRangeCoder * c)104 int vpx_rac_get(VpxRangeCoder *c)
105 {
106     return vpx_rac_get_prob(c, 128);
107 }
108 
vpx_rac_get_uint(VpxRangeCoder * c,int bits)109 int vpx_rac_get_uint(VpxRangeCoder *c, int bits)
110 {
111     int value = 0;
112 
113     while (bits--) {
114         value = (value << 1) | vpx_rac_get(c);
115     }
116 
117     return value;
118 }
119 
120