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