/src/avm/avm_dsp/bitwriter.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Alliance for Open Media. All rights reserved |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 3-Clause Clear License |
5 | | * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear |
6 | | * License was not distributed with this source code in the LICENSE file, you |
7 | | * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/. If the |
8 | | * Alliance for Open Media Patent License 1.0 was not distributed with this |
9 | | * source code in the PATENTS file, you can obtain it at |
10 | | * aomedia.org/license/patent-license/. |
11 | | */ |
12 | | |
13 | | #ifndef AVM_AVM_DSP_BITWRITER_H_ |
14 | | #define AVM_AVM_DSP_BITWRITER_H_ |
15 | | |
16 | | #include <assert.h> |
17 | | |
18 | | #include "config/avm_config.h" |
19 | | |
20 | | #include "avm_dsp/entenc.h" |
21 | | #include "avm_dsp/prob.h" |
22 | | #include "avm_dsp_common.h" |
23 | | #include "avm_dsp/recenter.h" |
24 | | |
25 | | #if CONFIG_RD_DEBUG |
26 | | #include "av2/common/blockd.h" |
27 | | #include "av2/common/cost.h" |
28 | | #endif |
29 | | |
30 | | #if CONFIG_BITSTREAM_DEBUG |
31 | | #include "avm_util/debug_util.h" |
32 | | #endif // CONFIG_BITSTREAM_DEBUG |
33 | | |
34 | | #ifdef __cplusplus |
35 | | extern "C" { |
36 | | #endif |
37 | | |
38 | | struct avm_writer { |
39 | | unsigned int pos; |
40 | | uint8_t *buffer; |
41 | | od_ec_enc ec; |
42 | | uint8_t allow_update_cdf; |
43 | | uint64_t frame_symbol_count; |
44 | | }; |
45 | | |
46 | | typedef struct avm_writer avm_writer; |
47 | | |
48 | | typedef struct TOKEN_STATS { |
49 | | int cost; |
50 | | #if CONFIG_RD_DEBUG |
51 | | int txb_coeff_cost_map[TXB_COEFF_COST_MAP_SIZE][TXB_COEFF_COST_MAP_SIZE]; |
52 | | #endif |
53 | | } TOKEN_STATS; |
54 | | |
55 | 0 | static INLINE void init_token_stats(TOKEN_STATS *token_stats) { |
56 | 0 | #if CONFIG_RD_DEBUG |
57 | 0 | int r, c; |
58 | 0 | for (r = 0; r < TXB_COEFF_COST_MAP_SIZE; ++r) { |
59 | 0 | for (c = 0; c < TXB_COEFF_COST_MAP_SIZE; ++c) { |
60 | 0 | token_stats->txb_coeff_cost_map[r][c] = 0; |
61 | 0 | } |
62 | 0 | } |
63 | 0 | #endif |
64 | 0 | token_stats->cost = 0; |
65 | 0 | } Unexecuted instantiation: decodetxb.c:init_token_stats Unexecuted instantiation: level.c:init_token_stats Unexecuted instantiation: hr_coding.c:init_token_stats |
66 | | |
67 | | void avm_start_encode(avm_writer *w, uint8_t *buffer); |
68 | | |
69 | | int avm_stop_encode(avm_writer *w); |
70 | | |
71 | | #if CONFIG_BITSTREAM_DEBUG |
72 | | // Push a literal (one or more equi-probably symbols) into |
73 | | // the bitstream debug queue, in the same order it is |
74 | | // encoded into the stream (msb to lsb). |
75 | | static INLINE void bitstream_queue_push_literal(int data, int bits) { |
76 | | avm_cdf_prob cdf[2] = { 128, 32767 }; |
77 | | for (int bit = bits - 1; bit >= 0; bit--) { |
78 | | bitstream_queue_push(1 & (data >> bit), cdf, 2); |
79 | | } |
80 | | } |
81 | | #endif // CONFIG_BITSTREAM_DEBUG |
82 | | |
83 | 0 | static INLINE void avm_write(avm_writer *w, int bit, int probability) { |
84 | 0 | int p = (0x7FFFFF - (probability << 15) + probability) >> 8; |
85 | 0 | #if CONFIG_BITSTREAM_DEBUG |
86 | 0 | avm_cdf_prob cdf[2] = { (avm_cdf_prob)p, 32767 }; |
87 | 0 | bitstream_queue_push(bit, cdf, 2); |
88 | 0 | #endif // CONFIG_BITSTREAM_DEBUG |
89 | 0 |
|
90 | 0 | avm_od_ec_encode_bool_q15(&w->ec, bit, p); |
91 | 0 | } Unexecuted instantiation: decodetxb.c:avm_write Unexecuted instantiation: level.c:avm_write Unexecuted instantiation: hr_coding.c:avm_write |
92 | | |
93 | 0 | static INLINE void avm_write_bit(avm_writer *w, int bit) { |
94 | 0 | #if CONFIG_BITSTREAM_DEBUG |
95 | 0 | bitstream_queue_push_literal(bit, 1); |
96 | 0 | #endif // CONFIG_BITSTREAM_DEBUG |
97 | 0 | od_ec_encode_literal_bypass(&w->ec, bit, 1); |
98 | 0 | } Unexecuted instantiation: decodetxb.c:avm_write_bit Unexecuted instantiation: level.c:avm_write_bit Unexecuted instantiation: hr_coding.c:avm_write_bit |
99 | | |
100 | 0 | static INLINE void avm_write_literal(avm_writer *w, int data, int bits) { |
101 | 0 | #if CONFIG_BITSTREAM_DEBUG |
102 | 0 | bitstream_queue_push_literal(data, bits); |
103 | 0 | #endif // CONFIG_BITSTREAM_DEBUG |
104 | 0 | int n; |
105 | 0 | w->frame_symbol_count += bits; |
106 | 0 | while (bits > 0) { |
107 | 0 | n = bits >= 8 ? 8 : bits; |
108 | 0 | od_ec_encode_literal_bypass(&w->ec, (data >> (bits - n)), n); |
109 | 0 | bits -= n; |
110 | 0 | data &= ((1 << bits) - 1); |
111 | 0 | } |
112 | 0 | } Unexecuted instantiation: decodetxb.c:avm_write_literal Unexecuted instantiation: level.c:avm_write_literal Unexecuted instantiation: hr_coding.c:avm_write_literal |
113 | | |
114 | | static INLINE void avm_write_cdf(avm_writer *w, int symb, |
115 | 0 | const avm_cdf_prob *cdf, int nsymbs) { |
116 | 0 | #if CONFIG_BITSTREAM_DEBUG |
117 | 0 | bitstream_queue_push(symb, cdf, nsymbs); |
118 | 0 | #endif // CONFIG_BITSTREAM_DEBUG |
119 | 0 |
|
120 | 0 | avm_od_ec_encode_cdf_q15(&w->ec, symb, cdf, nsymbs); |
121 | 0 | } Unexecuted instantiation: decodetxb.c:avm_write_cdf Unexecuted instantiation: level.c:avm_write_cdf Unexecuted instantiation: hr_coding.c:avm_write_cdf |
122 | | |
123 | | static INLINE void avm_write_symbol(avm_writer *w, int symb, avm_cdf_prob *cdf, |
124 | 0 | int nsymbs) { |
125 | 0 | w->frame_symbol_count++; |
126 | 0 | avm_write_cdf(w, symb, cdf, nsymbs); |
127 | 0 | if (w->allow_update_cdf) update_cdf(cdf, symb, nsymbs); |
128 | 0 | } Unexecuted instantiation: decodetxb.c:avm_write_symbol Unexecuted instantiation: level.c:avm_write_symbol Unexecuted instantiation: hr_coding.c:avm_write_symbol |
129 | | |
130 | | // Implements a code where a symbol with an alphabet size a power of 2 with |
131 | | // nsymb_bits bits (with nsymb_bits >= 3), is coded by decomposing the symbol |
132 | | // into 4 parts covering 1/8, 1/8, 1/4, 1/2 of the total number of symbols. |
133 | | // The part is arithmetically coded using the provided cdf of size 4. The |
134 | | // offset within each part is coded using fixed length binary codes with |
135 | | // (nsymb_bits - 3), (nsymb_bits - 3), (nsymb_bits - 2) or (nsymb_bits - 1) |
136 | | // bits, depending on the part. |
137 | | // |
138 | 0 | static INLINE int symb_to_part(int symb, int nsymb_bits) { |
139 | 0 | assert(nsymb_bits >= 3); |
140 | 0 | int part_offs[4] = { 0, 1 << (nsymb_bits - 3), 1 << (nsymb_bits - 2), |
141 | 0 | 1 << (nsymb_bits - 1) }; |
142 | 0 | if (symb < part_offs[1]) |
143 | 0 | return 0; |
144 | 0 | else if (symb < part_offs[2]) |
145 | 0 | return 1; |
146 | 0 | else if (symb < part_offs[3]) |
147 | 0 | return 2; |
148 | 0 | else |
149 | 0 | return 3; |
150 | 0 | } Unexecuted instantiation: decodetxb.c:symb_to_part Unexecuted instantiation: level.c:symb_to_part Unexecuted instantiation: hr_coding.c:symb_to_part |
151 | | |
152 | | static INLINE void avm_write_4part(avm_writer *w, int symb, avm_cdf_prob *cdf, |
153 | 0 | int nsymb_bits) { |
154 | 0 | assert(nsymb_bits >= 3); |
155 | 0 | int part; |
156 | 0 | int part_bits[4] = { (nsymb_bits - 3), (nsymb_bits - 3), (nsymb_bits - 2), |
157 | 0 | (nsymb_bits - 1) }; |
158 | 0 | int part_offs[4] = { 0, 1 << (nsymb_bits - 3), 1 << (nsymb_bits - 2), |
159 | 0 | 1 << (nsymb_bits - 1) }; |
160 | 0 | if (symb < part_offs[1]) |
161 | 0 | part = 0; |
162 | 0 | else if (symb < part_offs[2]) |
163 | 0 | part = 1; |
164 | 0 | else if (symb < part_offs[3]) |
165 | 0 | part = 2; |
166 | 0 | else |
167 | 0 | part = 3; |
168 | 0 | avm_write_symbol(w, part, cdf, 4); |
169 | 0 | avm_write_literal(w, symb - part_offs[part], part_bits[part]); |
170 | 0 | } Unexecuted instantiation: decodetxb.c:avm_write_4part Unexecuted instantiation: level.c:avm_write_4part Unexecuted instantiation: hr_coding.c:avm_write_4part |
171 | | |
172 | | // Implements a nsymb_bits bit 4-part code that codes a symbol symb given a |
173 | | // reference ref_symb after recentering symb around ref_symb. |
174 | | static INLINE void avm_write_4part_wref(avm_writer *w, int ref_symb, int symb, |
175 | 0 | avm_cdf_prob *cdf, int nsymb_bits) { |
176 | 0 | const int recentered_symb = |
177 | 0 | recenter_finite_nonneg(1 << nsymb_bits, ref_symb, symb); |
178 | 0 | avm_write_4part(w, recentered_symb, cdf, nsymb_bits); |
179 | 0 | } Unexecuted instantiation: decodetxb.c:avm_write_4part_wref Unexecuted instantiation: level.c:avm_write_4part_wref Unexecuted instantiation: hr_coding.c:avm_write_4part_wref |
180 | | |
181 | | static INLINE int64_t avm_count_4part(int symb, const int *part_cost, |
182 | 0 | int nsymb_bits, int scale_shift) { |
183 | 0 | assert(nsymb_bits >= 3); |
184 | 0 | int part_bits[4] = { (nsymb_bits - 3), (nsymb_bits - 3), (nsymb_bits - 2), |
185 | 0 | (nsymb_bits - 1) }; |
186 | 0 | int part_offs[4] = { 0, 1 << (nsymb_bits - 3), 1 << (nsymb_bits - 2), |
187 | 0 | 1 << (nsymb_bits - 1) }; |
188 | 0 | if (symb < part_offs[1]) |
189 | 0 | return part_cost[0] + (part_bits[0] << scale_shift); |
190 | 0 | else if (symb < part_offs[2]) |
191 | 0 | return part_cost[1] + (part_bits[1] << scale_shift); |
192 | 0 | else if (symb < part_offs[3]) |
193 | 0 | return part_cost[2] + (part_bits[2] << scale_shift); |
194 | 0 | else |
195 | 0 | return part_cost[3] + (part_bits[3] << scale_shift); |
196 | 0 | } Unexecuted instantiation: decodetxb.c:avm_count_4part Unexecuted instantiation: level.c:avm_count_4part Unexecuted instantiation: hr_coding.c:avm_count_4part |
197 | | |
198 | | static INLINE int64_t avm_count_4part_wref(int ref_symb, int symb, |
199 | | const int *part_cost, int nsymb_bits, |
200 | 0 | int scale_shift) { |
201 | 0 | const int recentered_symb = |
202 | 0 | recenter_finite_nonneg(1 << nsymb_bits, ref_symb, symb); |
203 | 0 | return avm_count_4part(recentered_symb, part_cost, nsymb_bits, scale_shift); |
204 | 0 | } Unexecuted instantiation: decodetxb.c:avm_count_4part_wref Unexecuted instantiation: level.c:avm_count_4part_wref Unexecuted instantiation: hr_coding.c:avm_count_4part_wref |
205 | | |
206 | | #ifdef __cplusplus |
207 | | } // extern "C" |
208 | | #endif |
209 | | |
210 | | #endif // AVM_AVM_DSP_BITWRITER_H_ |