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