• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #ifndef AOM_AOM_DSP_BITREADER_H_
13 #define AOM_AOM_DSP_BITREADER_H_
14 
15 #include <assert.h>
16 #include <limits.h>
17 
18 #include "config/aom_config.h"
19 
20 #include "aom/aomdx.h"
21 #include "aom/aom_integer.h"
22 #include "aom_dsp/entdec.h"
23 #include "aom_dsp/odintrin.h"
24 #include "aom_dsp/prob.h"
25 
26 #if CONFIG_BITSTREAM_DEBUG
27 #include "aom_util/debug_util.h"
28 #endif  // CONFIG_BITSTREAM_DEBUG
29 
30 #if CONFIG_ACCOUNTING
31 #include "av1/decoder/accounting.h"
32 #define ACCT_STR_NAME acct_str
33 #define ACCT_STR_PARAM , const char *ACCT_STR_NAME
34 #define ACCT_STR_ARG(s) , s
35 #else
36 #define ACCT_STR_PARAM
37 #define ACCT_STR_ARG(s)
38 #endif
39 
40 #define aom_read(r, prob, ACCT_STR_NAME) \
41   aom_read_(r, prob ACCT_STR_ARG(ACCT_STR_NAME))
42 #define aom_read_bit(r, ACCT_STR_NAME) \
43   aom_read_bit_(r ACCT_STR_ARG(ACCT_STR_NAME))
44 #define aom_read_tree(r, tree, probs, ACCT_STR_NAME) \
45   aom_read_tree_(r, tree, probs ACCT_STR_ARG(ACCT_STR_NAME))
46 #define aom_read_literal(r, bits, ACCT_STR_NAME) \
47   aom_read_literal_(r, bits ACCT_STR_ARG(ACCT_STR_NAME))
48 #define aom_read_cdf(r, cdf, nsymbs, ACCT_STR_NAME) \
49   aom_read_cdf_(r, cdf, nsymbs ACCT_STR_ARG(ACCT_STR_NAME))
50 #define aom_read_symbol(r, cdf, nsymbs, ACCT_STR_NAME) \
51   aom_read_symbol_(r, cdf, nsymbs ACCT_STR_ARG(ACCT_STR_NAME))
52 
53 #ifdef __cplusplus
54 extern "C" {
55 #endif
56 
57 struct aom_reader {
58   const uint8_t *buffer;
59   const uint8_t *buffer_end;
60   od_ec_dec ec;
61 #if CONFIG_ACCOUNTING
62   Accounting *accounting;
63 #endif
64   uint8_t allow_update_cdf;
65 };
66 
67 typedef struct aom_reader aom_reader;
68 
69 int aom_reader_init(aom_reader *r, const uint8_t *buffer, size_t size);
70 
71 const uint8_t *aom_reader_find_begin(aom_reader *r);
72 
73 const uint8_t *aom_reader_find_end(aom_reader *r);
74 
75 // Returns true if the bit reader has tried to decode more data from the buffer
76 // than was actually provided.
77 int aom_reader_has_overflowed(const aom_reader *r);
78 
79 // Returns the position in the bit reader in bits.
80 uint32_t aom_reader_tell(const aom_reader *r);
81 
82 // Returns the position in the bit reader in 1/8th bits.
83 uint32_t aom_reader_tell_frac(const aom_reader *r);
84 
85 #if CONFIG_ACCOUNTING
aom_process_accounting(const aom_reader * r ACCT_STR_PARAM)86 static INLINE void aom_process_accounting(const aom_reader *r ACCT_STR_PARAM) {
87   if (r->accounting != NULL) {
88     uint32_t tell_frac;
89     tell_frac = aom_reader_tell_frac(r);
90     aom_accounting_record(r->accounting, ACCT_STR_NAME,
91                           tell_frac - r->accounting->last_tell_frac);
92     r->accounting->last_tell_frac = tell_frac;
93   }
94 }
95 
aom_update_symb_counts(const aom_reader * r,int is_binary)96 static INLINE void aom_update_symb_counts(const aom_reader *r, int is_binary) {
97   if (r->accounting != NULL) {
98     r->accounting->syms.num_multi_syms += !is_binary;
99     r->accounting->syms.num_binary_syms += !!is_binary;
100   }
101 }
102 #endif
103 
aom_read_(aom_reader * r,int prob ACCT_STR_PARAM)104 static INLINE int aom_read_(aom_reader *r, int prob ACCT_STR_PARAM) {
105   int p = (0x7FFFFF - (prob << 15) + prob) >> 8;
106   int bit = od_ec_decode_bool_q15(&r->ec, p);
107 
108 #if CONFIG_BITSTREAM_DEBUG
109   {
110     int i;
111     int ref_bit, ref_nsymbs;
112     aom_cdf_prob ref_cdf[16];
113     const int queue_r = bitstream_queue_get_read();
114     const int frame_idx = aom_bitstream_queue_get_frame_read();
115     bitstream_queue_pop(&ref_bit, ref_cdf, &ref_nsymbs);
116     if (ref_nsymbs != 2) {
117       fprintf(stderr,
118               "\n *** [bit] nsymbs error, frame_idx_r %d nsymbs %d ref_nsymbs "
119               "%d queue_r %d\n",
120               frame_idx, 2, ref_nsymbs, queue_r);
121       assert(0);
122     }
123     if ((ref_nsymbs != 2) || (ref_cdf[0] != (aom_cdf_prob)p) ||
124         (ref_cdf[1] != 32767)) {
125       fprintf(stderr,
126               "\n *** [bit] cdf error, frame_idx_r %d cdf {%d, %d} ref_cdf {%d",
127               frame_idx, p, 32767, ref_cdf[0]);
128       for (i = 1; i < ref_nsymbs; ++i) fprintf(stderr, ", %d", ref_cdf[i]);
129       fprintf(stderr, "} queue_r %d\n", queue_r);
130       assert(0);
131     }
132     if (bit != ref_bit) {
133       fprintf(stderr,
134               "\n *** [bit] symb error, frame_idx_r %d symb %d ref_symb %d "
135               "queue_r %d\n",
136               frame_idx, bit, ref_bit, queue_r);
137       assert(0);
138     }
139   }
140 #endif
141 
142 #if CONFIG_ACCOUNTING
143   if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
144   aom_update_symb_counts(r, 1);
145 #endif
146   return bit;
147 }
148 
aom_read_bit_(aom_reader * r ACCT_STR_PARAM)149 static INLINE int aom_read_bit_(aom_reader *r ACCT_STR_PARAM) {
150   int ret;
151   ret = aom_read(r, 128, NULL);  // aom_prob_half
152 #if CONFIG_ACCOUNTING
153   if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
154 #endif
155   return ret;
156 }
157 
aom_read_literal_(aom_reader * r,int bits ACCT_STR_PARAM)158 static INLINE int aom_read_literal_(aom_reader *r, int bits ACCT_STR_PARAM) {
159   int literal = 0, bit;
160 
161   for (bit = bits - 1; bit >= 0; bit--) literal |= aom_read_bit(r, NULL) << bit;
162 #if CONFIG_ACCOUNTING
163   if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
164 #endif
165   return literal;
166 }
167 
aom_read_cdf_(aom_reader * r,const aom_cdf_prob * cdf,int nsymbs ACCT_STR_PARAM)168 static INLINE int aom_read_cdf_(aom_reader *r, const aom_cdf_prob *cdf,
169                                 int nsymbs ACCT_STR_PARAM) {
170   int symb;
171   assert(cdf != NULL);
172   symb = od_ec_decode_cdf_q15(&r->ec, cdf, nsymbs);
173 
174 #if CONFIG_BITSTREAM_DEBUG
175   {
176     int i;
177     int cdf_error = 0;
178     int ref_symb, ref_nsymbs;
179     aom_cdf_prob ref_cdf[16];
180     const int queue_r = bitstream_queue_get_read();
181     const int frame_idx = aom_bitstream_queue_get_frame_read();
182     bitstream_queue_pop(&ref_symb, ref_cdf, &ref_nsymbs);
183     if (nsymbs != ref_nsymbs) {
184       fprintf(stderr,
185               "\n *** nsymbs error, frame_idx_r %d nsymbs %d ref_nsymbs %d "
186               "queue_r %d\n",
187               frame_idx, nsymbs, ref_nsymbs, queue_r);
188       cdf_error = 0;
189       assert(0);
190     } else {
191       for (i = 0; i < nsymbs; ++i)
192         if (cdf[i] != ref_cdf[i]) cdf_error = 1;
193     }
194     if (cdf_error) {
195       fprintf(stderr, "\n *** cdf error, frame_idx_r %d cdf {%d", frame_idx,
196               cdf[0]);
197       for (i = 1; i < nsymbs; ++i) fprintf(stderr, ", %d", cdf[i]);
198       fprintf(stderr, "} ref_cdf {%d", ref_cdf[0]);
199       for (i = 1; i < ref_nsymbs; ++i) fprintf(stderr, ", %d", ref_cdf[i]);
200       fprintf(stderr, "} queue_r %d\n", queue_r);
201       assert(0);
202     }
203     if (symb != ref_symb) {
204       fprintf(
205           stderr,
206           "\n *** symb error, frame_idx_r %d symb %d ref_symb %d queue_r %d\n",
207           frame_idx, symb, ref_symb, queue_r);
208       assert(0);
209     }
210   }
211 #endif
212 
213 #if CONFIG_ACCOUNTING
214   if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
215   aom_update_symb_counts(r, (nsymbs == 2));
216 #endif
217   return symb;
218 }
219 
aom_read_symbol_(aom_reader * r,aom_cdf_prob * cdf,int nsymbs ACCT_STR_PARAM)220 static INLINE int aom_read_symbol_(aom_reader *r, aom_cdf_prob *cdf,
221                                    int nsymbs ACCT_STR_PARAM) {
222   int ret;
223   ret = aom_read_cdf(r, cdf, nsymbs, ACCT_STR_NAME);
224   if (r->allow_update_cdf) update_cdf(cdf, ret, nsymbs);
225   return ret;
226 }
227 
228 #ifdef __cplusplus
229 }  // extern "C"
230 #endif
231 
232 #endif  // AOM_AOM_DSP_BITREADER_H_
233