xref: /aosp_15_r20/external/libvpx/vpx_dsp/bitwriter.h (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #ifndef VPX_VPX_DSP_BITWRITER_H_
12*fb1b10abSAndroid Build Coastguard Worker #define VPX_VPX_DSP_BITWRITER_H_
13*fb1b10abSAndroid Build Coastguard Worker 
14*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
15*fb1b10abSAndroid Build Coastguard Worker 
16*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/compiler_attributes.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
18*fb1b10abSAndroid Build Coastguard Worker 
19*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/prob.h"
20*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_BITSTREAM_DEBUG
21*fb1b10abSAndroid Build Coastguard Worker #include "vpx_util/vpx_debug_util.h"
22*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_BITSTREAM_DEBUG
23*fb1b10abSAndroid Build Coastguard Worker 
24*fb1b10abSAndroid Build Coastguard Worker #ifdef __cplusplus
25*fb1b10abSAndroid Build Coastguard Worker extern "C" {
26*fb1b10abSAndroid Build Coastguard Worker #endif
27*fb1b10abSAndroid Build Coastguard Worker 
28*fb1b10abSAndroid Build Coastguard Worker typedef struct vpx_writer {
29*fb1b10abSAndroid Build Coastguard Worker   unsigned int lowvalue;
30*fb1b10abSAndroid Build Coastguard Worker   unsigned int range;
31*fb1b10abSAndroid Build Coastguard Worker   int count;
32*fb1b10abSAndroid Build Coastguard Worker   // Whether there has been an error.
33*fb1b10abSAndroid Build Coastguard Worker   int error;
34*fb1b10abSAndroid Build Coastguard Worker   // We maintain the invariant that pos <= size, i.e., we never write beyond
35*fb1b10abSAndroid Build Coastguard Worker   // the end of the buffer. If pos would be incremented to be greater than
36*fb1b10abSAndroid Build Coastguard Worker   // size, leave pos unchanged and set error to 1.
37*fb1b10abSAndroid Build Coastguard Worker   unsigned int pos;
38*fb1b10abSAndroid Build Coastguard Worker   unsigned int size;
39*fb1b10abSAndroid Build Coastguard Worker   uint8_t *buffer;
40*fb1b10abSAndroid Build Coastguard Worker } vpx_writer;
41*fb1b10abSAndroid Build Coastguard Worker 
42*fb1b10abSAndroid Build Coastguard Worker void vpx_start_encode(vpx_writer *br, uint8_t *source, size_t size);
43*fb1b10abSAndroid Build Coastguard Worker // Returns 0 on success and returns -1 in case of error.
44*fb1b10abSAndroid Build Coastguard Worker int vpx_stop_encode(vpx_writer *br);
45*fb1b10abSAndroid Build Coastguard Worker 
vpx_write(vpx_writer * br,int bit,int probability)46*fb1b10abSAndroid Build Coastguard Worker static INLINE VPX_NO_UNSIGNED_SHIFT_CHECK void vpx_write(vpx_writer *br,
47*fb1b10abSAndroid Build Coastguard Worker                                                          int bit,
48*fb1b10abSAndroid Build Coastguard Worker                                                          int probability) {
49*fb1b10abSAndroid Build Coastguard Worker   unsigned int split;
50*fb1b10abSAndroid Build Coastguard Worker   int count = br->count;
51*fb1b10abSAndroid Build Coastguard Worker   unsigned int range = br->range;
52*fb1b10abSAndroid Build Coastguard Worker   unsigned int lowvalue = br->lowvalue;
53*fb1b10abSAndroid Build Coastguard Worker   int shift;
54*fb1b10abSAndroid Build Coastguard Worker 
55*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_BITSTREAM_DEBUG
56*fb1b10abSAndroid Build Coastguard Worker   /*
57*fb1b10abSAndroid Build Coastguard Worker   int queue_r = 0;
58*fb1b10abSAndroid Build Coastguard Worker   int frame_idx_r = 0;
59*fb1b10abSAndroid Build Coastguard Worker   int queue_w = bitstream_queue_get_write();
60*fb1b10abSAndroid Build Coastguard Worker   int frame_idx_w = bitstream_queue_get_frame_write();
61*fb1b10abSAndroid Build Coastguard Worker   if (frame_idx_w == frame_idx_r && queue_w == queue_r) {
62*fb1b10abSAndroid Build Coastguard Worker     fprintf(stderr, "\n *** bitstream queue at frame_idx_w %d queue_w %d\n",
63*fb1b10abSAndroid Build Coastguard Worker             frame_idx_w, queue_w);
64*fb1b10abSAndroid Build Coastguard Worker     assert(0);
65*fb1b10abSAndroid Build Coastguard Worker   }
66*fb1b10abSAndroid Build Coastguard Worker   */
67*fb1b10abSAndroid Build Coastguard Worker   bitstream_queue_push(bit, probability);
68*fb1b10abSAndroid Build Coastguard Worker #endif
69*fb1b10abSAndroid Build Coastguard Worker 
70*fb1b10abSAndroid Build Coastguard Worker   split = 1 + (((range - 1) * probability) >> 8);
71*fb1b10abSAndroid Build Coastguard Worker 
72*fb1b10abSAndroid Build Coastguard Worker   range = split;
73*fb1b10abSAndroid Build Coastguard Worker 
74*fb1b10abSAndroid Build Coastguard Worker   if (bit) {
75*fb1b10abSAndroid Build Coastguard Worker     lowvalue += split;
76*fb1b10abSAndroid Build Coastguard Worker     range = br->range - split;
77*fb1b10abSAndroid Build Coastguard Worker   }
78*fb1b10abSAndroid Build Coastguard Worker 
79*fb1b10abSAndroid Build Coastguard Worker   shift = vpx_norm[range];
80*fb1b10abSAndroid Build Coastguard Worker 
81*fb1b10abSAndroid Build Coastguard Worker   range <<= shift;
82*fb1b10abSAndroid Build Coastguard Worker   count += shift;
83*fb1b10abSAndroid Build Coastguard Worker 
84*fb1b10abSAndroid Build Coastguard Worker   if (count >= 0) {
85*fb1b10abSAndroid Build Coastguard Worker     int offset = shift - count;
86*fb1b10abSAndroid Build Coastguard Worker 
87*fb1b10abSAndroid Build Coastguard Worker     if (!br->error) {
88*fb1b10abSAndroid Build Coastguard Worker       if ((lowvalue << (offset - 1)) & 0x80000000) {
89*fb1b10abSAndroid Build Coastguard Worker         int x = (int)br->pos - 1;
90*fb1b10abSAndroid Build Coastguard Worker 
91*fb1b10abSAndroid Build Coastguard Worker         while (x >= 0 && br->buffer[x] == 0xff) {
92*fb1b10abSAndroid Build Coastguard Worker           br->buffer[x] = 0;
93*fb1b10abSAndroid Build Coastguard Worker           x--;
94*fb1b10abSAndroid Build Coastguard Worker         }
95*fb1b10abSAndroid Build Coastguard Worker 
96*fb1b10abSAndroid Build Coastguard Worker         // TODO(wtc): How to prove x >= 0?
97*fb1b10abSAndroid Build Coastguard Worker         br->buffer[x] += 1;
98*fb1b10abSAndroid Build Coastguard Worker       }
99*fb1b10abSAndroid Build Coastguard Worker 
100*fb1b10abSAndroid Build Coastguard Worker       if (br->pos < br->size) {
101*fb1b10abSAndroid Build Coastguard Worker         br->buffer[br->pos++] = (lowvalue >> (24 - offset)) & 0xff;
102*fb1b10abSAndroid Build Coastguard Worker       } else {
103*fb1b10abSAndroid Build Coastguard Worker         br->error = 1;
104*fb1b10abSAndroid Build Coastguard Worker       }
105*fb1b10abSAndroid Build Coastguard Worker     }
106*fb1b10abSAndroid Build Coastguard Worker     lowvalue <<= offset;
107*fb1b10abSAndroid Build Coastguard Worker     shift = count;
108*fb1b10abSAndroid Build Coastguard Worker     lowvalue &= 0xffffff;
109*fb1b10abSAndroid Build Coastguard Worker     count -= 8;
110*fb1b10abSAndroid Build Coastguard Worker   }
111*fb1b10abSAndroid Build Coastguard Worker 
112*fb1b10abSAndroid Build Coastguard Worker   lowvalue <<= shift;
113*fb1b10abSAndroid Build Coastguard Worker   br->count = count;
114*fb1b10abSAndroid Build Coastguard Worker   br->lowvalue = lowvalue;
115*fb1b10abSAndroid Build Coastguard Worker   br->range = range;
116*fb1b10abSAndroid Build Coastguard Worker }
117*fb1b10abSAndroid Build Coastguard Worker 
vpx_write_bit(vpx_writer * w,int bit)118*fb1b10abSAndroid Build Coastguard Worker static INLINE void vpx_write_bit(vpx_writer *w, int bit) {
119*fb1b10abSAndroid Build Coastguard Worker   vpx_write(w, bit, 128);  // vpx_prob_half
120*fb1b10abSAndroid Build Coastguard Worker }
121*fb1b10abSAndroid Build Coastguard Worker 
vpx_write_literal(vpx_writer * w,int data,int bits)122*fb1b10abSAndroid Build Coastguard Worker static INLINE void vpx_write_literal(vpx_writer *w, int data, int bits) {
123*fb1b10abSAndroid Build Coastguard Worker   int bit;
124*fb1b10abSAndroid Build Coastguard Worker 
125*fb1b10abSAndroid Build Coastguard Worker   for (bit = bits - 1; bit >= 0; bit--) vpx_write_bit(w, 1 & (data >> bit));
126*fb1b10abSAndroid Build Coastguard Worker }
127*fb1b10abSAndroid Build Coastguard Worker 
128*fb1b10abSAndroid Build Coastguard Worker #define vpx_write_prob(w, v) vpx_write_literal((w), (v), 8)
129*fb1b10abSAndroid Build Coastguard Worker 
130*fb1b10abSAndroid Build Coastguard Worker #ifdef __cplusplus
131*fb1b10abSAndroid Build Coastguard Worker }  // extern "C"
132*fb1b10abSAndroid Build Coastguard Worker #endif
133*fb1b10abSAndroid Build Coastguard Worker 
134*fb1b10abSAndroid Build Coastguard Worker #endif  // VPX_VPX_DSP_BITWRITER_H_
135