xref: /aosp_15_r20/external/libopenapv/src/oapv_bs.c (revision abb65b4b03b69e1d508d4d9a44dcf199df16e7c3)
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  * All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * - Redistributions of source code must retain the above copyright notice,
9  *   this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright notice,
12  *   this list of conditions and the following disclaimer in the documentation
13  *   and/or other materials provided with the distribution.
14  *
15  * - Neither the name of the copyright owner, nor the names of its contributors
16  *   may be used to endorse or promote products derived from this software
17  *   without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "oapv_def.h"
33 
34 ///////////////////////////////////////////////////////////////////////////////
35 // start of encoder code
36 #if ENABLE_ENCODER
37 ///////////////////////////////////////////////////////////////////////////////
38 /* number of bytes to be sunk */
39 #define BSW_GET_SINK_BYTE(bs) ((32 - (bs)->leftbits + 7) >> 3)
40 
bsw_flush(oapv_bs_t * bs,int bytes)41 static int bsw_flush(oapv_bs_t *bs, int bytes)
42 {
43     if(bytes == 0)
44         bytes = BSW_GET_SINK_BYTE(bs);
45 
46     while(bytes--) {
47         *bs->cur++ = (bs->code >> 24) & 0xFF;
48         bs->code <<= 8;
49     }
50 
51     bs->leftbits = 32;
52 
53     return 0;
54 }
55 
oapv_bsw_init(oapv_bs_t * bs,u8 * buf,int size,oapv_bs_fn_flush_t fn_flush)56 void oapv_bsw_init(oapv_bs_t *bs, u8 *buf, int size, oapv_bs_fn_flush_t fn_flush)
57 {
58     bs->size = size;
59     bs->beg = buf;
60     bs->cur = buf;
61     bs->end = buf + size - 1;
62     bs->code = 0;
63     bs->leftbits = 32;
64     bs->fn_flush = (fn_flush == NULL ? bsw_flush : fn_flush);
65     bs->is_bin_count = 0;
66     bs->bin_count = 0;
67 }
68 
oapv_bsw_deinit(oapv_bs_t * bs)69 void oapv_bsw_deinit(oapv_bs_t *bs)
70 {
71     bs->fn_flush(bs, 0);
72 }
73 
oapv_bsw_sink(oapv_bs_t * bs)74 void *oapv_bsw_sink(oapv_bs_t *bs)
75 {
76     oapv_assert_rv(bs->cur + BSW_GET_SINK_BYTE(bs) <= bs->end, NULL);
77     bs->fn_flush(bs, 0);
78     bs->code = 0;
79     bs->leftbits = 32;
80     return (void *)bs->cur;
81 }
82 
oapv_bsw_write_direct(void * bits,u32 val,int len)83 int oapv_bsw_write_direct(void *bits, u32 val, int len)
84 {
85     int            i;
86     unsigned char *p = (unsigned char *)bits;
87 
88     oapv_assert_rv((len & 0x7) == 0, -1); // len should be byte-aligned
89 
90     val <<= (32 - len);
91     for(i = 0; i < (len >> 3); i++) {
92         p[i] = (val >> 24) & 0xFF;
93         val <<= 8;
94     }
95     return 0;
96 }
97 
oapv_bsw_write1(oapv_bs_t * bs,int val)98 int oapv_bsw_write1(oapv_bs_t *bs, int val)
99 {
100     oapv_assert(bs);
101 
102     if(bs->is_bin_count) {
103         bs->bin_count++;
104         return 0;
105     }
106 
107     bs->leftbits--;
108     bs->code |= ((val & 0x1) << bs->leftbits);
109 
110     if(bs->leftbits == 0) {
111         oapv_assert_rv(bs->cur <= bs->end, -1);
112         bs->fn_flush(bs, 0);
113 
114         bs->code = 0;
115         bs->leftbits = 32;
116     }
117 
118     return 0;
119 }
120 
oapv_bsw_write(oapv_bs_t * bs,u32 val,int len)121 int oapv_bsw_write(oapv_bs_t *bs, u32 val, int len) /* len(1 ~ 32) */
122 {
123     int leftbits;
124 
125     oapv_assert(bs);
126 
127     if(bs->is_bin_count) {
128         bs->bin_count += len;
129         return 0;
130     }
131 
132     leftbits = bs->leftbits;
133     val <<= (32 - len);
134     bs->code |= (val >> (32 - leftbits));
135 
136     if(len < leftbits) {
137         bs->leftbits -= len;
138     }
139     else {
140         oapv_assert_rv(bs->cur + 4 <= bs->end, -1);
141 
142         bs->leftbits = 0;
143         bs->fn_flush(bs, 0);
144         bs->code = (leftbits < 32 ? val << leftbits : 0);
145         bs->leftbits = 32 - (len - leftbits);
146     }
147 
148     return 0;
149 }
150 
151 ///////////////////////////////////////////////////////////////////////////////
152 // end of encoder code
153 #endif // ENABLE_ENCODER
154 ///////////////////////////////////////////////////////////////////////////////
155 
156 ///////////////////////////////////////////////////////////////////////////////
157 // start of decoder code
158 #if ENABLE_DECODER
159 ///////////////////////////////////////////////////////////////////////////////
160 
161 /* Table of count of leading zero for 4 bit value */
162 static const u8 tbl_zero_count4[16] = {
163     4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
164 };
165 
166 // skip code if lefbits are larger than skip bit count;
bsr_skip_code(oapv_bs_t * bs,int size)167 static void inline bsr_skip_code(oapv_bs_t *bs, int size)
168 {
169     oapv_assert(size <= 32);
170     oapv_assert(bs->leftbits >= size);
171     if(size == 32) {
172         bs->code = 0;
173         bs->leftbits = 0;
174     }
175     else {
176         bs->code <<= size;
177         bs->leftbits -= size;
178     }
179 }
180 
bsr_flush(oapv_bs_t * bs,int byte)181 static int bsr_flush(oapv_bs_t *bs, int byte)
182 {
183     int shift = 24, remained;
184     u32 code = 0;
185 
186     oapv_assert(byte);
187 
188     remained = (int)(bs->end - bs->cur) + 1;
189     if(byte > remained)
190         byte = remained;
191 
192     if(byte <= 0) {
193         bs->code = 0;
194         bs->leftbits = 0;
195         return -1;
196     }
197 
198     bs->leftbits = byte << 3;
199 
200     bs->cur += byte;
201     while(byte) {
202         code |= *(bs->cur - byte) << shift;
203         byte--;
204         shift -= 8;
205     }
206     bs->code = code;
207     return 0;
208 }
209 
oapv_bsr_init(oapv_bs_t * bs,u8 * buf,int size,oapv_bs_fn_flush_t fn_flush)210 void oapv_bsr_init(oapv_bs_t *bs, u8 *buf, int size, oapv_bs_fn_flush_t fn_flush)
211 {
212     bs->size = size;
213     bs->cur = buf;
214     bs->beg = buf;
215     bs->end = buf + size - 1;
216     bs->code = 0;
217     bs->leftbits = 0;
218     bs->fn_flush = (fn_flush == NULL) ? bsr_flush : fn_flush;
219 }
220 
oapv_bsr_clz_in_code(u32 code)221 int oapv_bsr_clz_in_code(u32 code)
222 {
223     int clz, bits4, shift;
224 
225     if(code == 0)
226         return 32; /* to protect infinite loop */
227 
228     bits4 = 0;
229     clz = 0;
230     shift = 28;
231 
232     while(bits4 == 0 && shift >= 0) {
233         bits4 = (code >> shift) & 0xf;
234         clz += tbl_zero_count4[bits4];
235         shift -= 4;
236     }
237     return clz;
238 }
239 
oapv_bsr_align8(oapv_bs_t * bs)240 void oapv_bsr_align8(oapv_bs_t *bs)
241 {
242     /*
243     while (!bsr_is_align8(bs)) {
244         oapv_bsr_read1(bs);
245     }
246     */
247     int size;
248 
249     size = bs->leftbits & 0x7;
250 
251     bs->code <<= size;
252     bs->leftbits -= size;
253 }
254 
oapv_bsr_skip(oapv_bs_t * bs,int size)255 void oapv_bsr_skip(oapv_bs_t *bs, int size)
256 {
257     oapv_assert(size > 0 && size <= 32);
258 
259     if(bs->leftbits < size) {
260         size -= bs->leftbits;
261         if(bs->fn_flush(bs, 4)) {
262             // oapv_trace("already reached the end of bitstream\n");  /* should be updated */
263             return;
264         }
265     }
266     bsr_skip_code(bs, size);
267 }
268 
oapv_bsr_peek(oapv_bs_t * bs,u32 * val,int size)269 void oapv_bsr_peek(oapv_bs_t *bs, u32 *val, int size)
270 {
271     int byte, leftbits;
272     u32 code = 0;
273 
274     if(bs->leftbits < size) {
275         byte = (32 - bs->leftbits) >> 3;
276 
277         /* We should not check the return value
278         because this function could be failed at the EOB. */
279         if(byte) {
280             code = bs->code;
281             leftbits = bs->leftbits;
282 
283             bs->fn_flush(bs, byte);
284 
285             bs->code >>= leftbits;
286             bs->code |= code;
287             bs->leftbits += leftbits;
288         }
289     }
290 
291     oapv_assert(bs->leftbits <= 32);
292 
293     code = bs->code >> (32 - size);
294     size -= bs->leftbits;
295 
296     if(size > 0) {
297         /* even though we update several bytes, the requested size would be
298         larger than current bs->leftbits.
299         In this case, we should read one more byte, but we could not store
300         the read byte. */
301         if(bs->cur <= bs->end) {
302             code |= *(bs->cur) >> (8 - size);
303         }
304     }
305     *val = code;
306 }
307 
oapv_bsr_sink(oapv_bs_t * bs)308 void *oapv_bsr_sink(oapv_bs_t *bs)
309 {
310     oapv_assert_rv(bs->cur + BSW_GET_SINK_BYTE(bs) <= bs->end, NULL);
311     oapv_assert_rv((bs->leftbits & 7) == 0, NULL);
312     bs->cur = bs->cur - (bs->leftbits >> 3);
313     bs->code = 0;
314     bs->leftbits = 0;
315     return (void *)bs->cur;
316 }
317 
oapv_bsr_move(oapv_bs_t * bs,u8 * pos)318 void oapv_bsr_move(oapv_bs_t *bs, u8 *pos)
319 {
320     bs->code = 0;
321     bs->leftbits = 0;
322     bs->cur = pos;
323 }
324 
oapv_bsr_read(oapv_bs_t * bs,int size)325 u32 oapv_bsr_read(oapv_bs_t *bs, int size)
326 {
327     u32 code = 0;
328 
329     oapv_assert(size > 0);
330 
331     if(bs->leftbits < size) {
332         code = bs->code >> (32 - size);
333         size -= bs->leftbits;
334         if(bs->fn_flush(bs, 4)) {
335             oapv_trace("already reached the end of bitstream\n"); /* should be updated */
336             return (u32)(-1);
337         }
338     }
339     code |= bs->code >> (32 - size);
340 
341     bsr_skip_code(bs, size);
342 
343     return code;
344 }
345 
oapv_bsr_read1(oapv_bs_t * bs)346 int oapv_bsr_read1(oapv_bs_t *bs)
347 {
348     int code;
349     if(bs->leftbits == 0) {
350         if(bs->fn_flush(bs, 4)) {
351             oapv_trace("already reached the end of bitstream\n"); /* should be updated */
352             return -1;
353         }
354     }
355     code = (int)(bs->code >> 31);
356 
357     bs->code <<= 1;
358     bs->leftbits -= 1;
359 
360     return code;
361 }
362 
363 ///////////////////////////////////////////////////////////////////////////////
364 // end of decoder code
365 #endif // ENABLE_DECODER
366 ///////////////////////////////////////////////////////////////////////////////
367