xref: /aosp_15_r20/external/mesa3d/src/util/vl_bitstream.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2023 Red Hat
3  * SPDX-License-Identifier: MIT
4  *
5  * This is a C rewrite of pieces of the d3d12 frontend which is:
6  * Copyright © Microsoft Corporation
7  */
8 #ifndef VL_BITSTREAM_H
9 #define VL_BITSTREAM_H
10 
11 struct vl_bitstream_encoder {
12    uint8_t *bits;
13    uint32_t bits_buffer_size;
14    uint32_t offset;
15 
16    uint32_t enc_buffer;
17 
18    int32_t bits_to_go;
19    bool prevent_start_code;
20 
21    bool internal_buffer;
22    bool overflow;
23 };
24 
25 #define VL_BITSTREAM_MAX_BUFFER 256
26 
27 static inline void
vl_bitstream_encoder_clear(struct vl_bitstream_encoder * enc,void * buffer_base,size_t buffer_offset,size_t buffer_limit)28 vl_bitstream_encoder_clear(struct vl_bitstream_encoder *enc,
29                            void *buffer_base,
30                            size_t buffer_offset,
31                            size_t buffer_limit)
32 {
33    memset(enc, 0, sizeof(*enc));
34    enc->bits_to_go = 32;
35 
36    if (!buffer_base) {
37       enc->bits = malloc(VL_BITSTREAM_MAX_BUFFER);
38       enc->bits_buffer_size = VL_BITSTREAM_MAX_BUFFER;
39       enc->internal_buffer = true;
40    } else {
41       enc->bits = (uint8_t *)buffer_base + buffer_offset;
42       enc->bits_buffer_size = buffer_limit;
43    }
44 }
45 
46 static inline void
vl_bitstream_encoder_free(struct vl_bitstream_encoder * enc)47 vl_bitstream_encoder_free(struct vl_bitstream_encoder *enc)
48 {
49    if (enc->internal_buffer)
50       free(enc->bits);
51 }
52 
53 static inline int
vl_bitstream_get_num_bits_for_byte_align(struct vl_bitstream_encoder * enc)54 vl_bitstream_get_num_bits_for_byte_align(struct vl_bitstream_encoder *enc)
55 {
56    return enc->bits_to_go & 7;
57 }
58 
59 static inline int
vl_bitstream_get_byte_count(struct vl_bitstream_encoder * enc)60 vl_bitstream_get_byte_count(struct vl_bitstream_encoder *enc)
61 {
62    return enc->offset + ((32 - enc->bits_to_go) >> 3);
63 }
64 
65 static inline bool
vl_bitstream_is_byte_aligned(struct vl_bitstream_encoder * enc)66 vl_bitstream_is_byte_aligned(struct vl_bitstream_encoder *enc)
67 {
68    if (enc->overflow)
69       enc->bits_to_go = 32;
70    return !(enc->bits_to_go & 7);
71 }
72 
73 static inline void
vl_bitstream_write_byte_start_code(struct vl_bitstream_encoder * enc,uint8_t val)74 vl_bitstream_write_byte_start_code(struct vl_bitstream_encoder *enc, uint8_t val)
75 {
76    int offset = enc->offset;
77    uint8_t *buffer = enc->bits + enc->offset;
78    if (enc->prevent_start_code && enc->offset > 1) {
79       if (((val & 0xfc) | buffer[-2] | buffer[-1]) == 0) {
80          *buffer++ = 3;
81          offset++;
82       }
83    }
84 
85    *buffer = val;
86    offset++;
87    enc->offset = offset;
88 }
89 
90 static inline bool
vl_bitstream_verify_buffer(struct vl_bitstream_encoder * enc,uint32_t bytes_to_write)91 vl_bitstream_verify_buffer(struct vl_bitstream_encoder *enc, uint32_t bytes_to_write)
92 {
93    if (enc->overflow)
94       return false;
95 
96    if (enc->offset + bytes_to_write > enc->bits_buffer_size) {
97       enc->overflow = true;
98       return false;
99    }
100    return true;
101 }
102 
103 static inline void
vl_bitstream_flush(struct vl_bitstream_encoder * enc)104 vl_bitstream_flush(struct vl_bitstream_encoder *enc)
105 {
106    ASSERTED bool is_aligned = vl_bitstream_is_byte_aligned(enc);
107    assert (is_aligned);
108 
109    uint32_t temp = (uint32_t)(32 - enc->bits_to_go);
110 
111    if (!vl_bitstream_verify_buffer(enc, temp >> 3)) {
112       return;
113    }
114 
115    while (temp > 0) {
116       vl_bitstream_write_byte_start_code(enc, (uint8_t)(enc->enc_buffer >> 24));
117       enc->enc_buffer <<= 8;
118       temp -= 8;
119    }
120 
121    enc->bits_to_go = 32;
122    enc->enc_buffer = 0;
123 }
124 
125 static inline void
vl_bitstream_put_bits(struct vl_bitstream_encoder * enc,int bits_count,uint32_t bits_val)126 vl_bitstream_put_bits(struct vl_bitstream_encoder *enc, int bits_count, uint32_t bits_val)
127 {
128    if (bits_count < enc->bits_to_go) {
129       enc->enc_buffer |= (bits_val << (enc->bits_to_go - bits_count));
130       enc->bits_to_go -= bits_count;
131    } else if (vl_bitstream_verify_buffer(enc, 4)) {
132       int left_over_bits = bits_count - enc->bits_to_go;
133       enc->enc_buffer |= (bits_val >> left_over_bits);
134 
135       {
136          uint8_t *temp = (uint8_t *)&enc->enc_buffer;
137          vl_bitstream_write_byte_start_code(enc, *(temp + 3));
138          vl_bitstream_write_byte_start_code(enc, *(temp + 2));
139          vl_bitstream_write_byte_start_code(enc, *(temp + 1));
140          vl_bitstream_write_byte_start_code(enc, *temp);
141       }
142 
143       enc->enc_buffer = 0;
144       enc->bits_to_go = 32 - left_over_bits;
145 
146       if (left_over_bits > 0)
147          enc->enc_buffer = (bits_val << (32 - left_over_bits));
148    }
149 }
150 
151 static inline int
vl_bitstream_get_exp_golomb0_code_len(uint32_t val)152 vl_bitstream_get_exp_golomb0_code_len(uint32_t val)
153 {
154    int len = 0;
155    val++;
156 
157    if (val >= 0x10000) {
158       val >>= 16;
159       len += 16;
160    }
161    if (val >= 0x100) {
162       val >>= 8;
163       len += 8;
164    }
165    assert(val < 256);
166 
167    return len + util_logbase2(val);
168 }
169 
170 static inline void
vl_bitstream_exp_golomb_ue(struct vl_bitstream_encoder * enc,uint32_t val)171 vl_bitstream_exp_golomb_ue(struct vl_bitstream_encoder *enc, uint32_t val)
172 {
173    if (val != UINT32_MAX) {
174       int len = vl_bitstream_get_exp_golomb0_code_len(val);
175       vl_bitstream_put_bits(enc, (len << 1) + 1, val + 1);
176    } else {
177       vl_bitstream_put_bits(enc, 32, 0);
178       vl_bitstream_put_bits(enc, 1, 1);
179       vl_bitstream_put_bits(enc, 32, 1);
180    }
181 }
182 
183 static inline void
vl_bitstream_exp_golomb_se(struct vl_bitstream_encoder * enc,int32_t val)184 vl_bitstream_exp_golomb_se(struct vl_bitstream_encoder *enc, int32_t val)
185 {
186    if (val > 0)
187       vl_bitstream_exp_golomb_ue(enc, (val << 1) - 1);
188    else
189       vl_bitstream_exp_golomb_ue(enc, ((-val) << 1) - (val == INT_MIN));
190 }
191 
192 static inline void
vl_bitstream_rbsp_trailing(struct vl_bitstream_encoder * enc)193 vl_bitstream_rbsp_trailing(struct vl_bitstream_encoder *enc)
194 {
195    vl_bitstream_put_bits(enc, 1, 1);
196    int left = vl_bitstream_get_num_bits_for_byte_align(enc);
197 
198    if (left)
199       vl_bitstream_put_bits(enc, left, 0);
200 
201    ASSERTED bool is_aligned = vl_bitstream_is_byte_aligned(enc);
202    assert(is_aligned);
203 }
204 #endif
205