1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
|
/*! @file bitstream.c
*
* @brief Implementation of a bitstream for reading bits from a byte stream.
*
* @version 1.0.0
*
* (C) Copyright 2018 GoPro Inc (http://gopro.com/).
*
* Licensed under either:
* - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
* - MIT license, http://opensource.org/licenses/MIT
* at your option.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common.h"
/*!
@brief Return a mask with the specified number of bits set to one
*/
BITWORD BitMask(int n)
{
if (n < bit_word_count)
{
BITWORD mask = 0;
if (n > 0) {
mask = ((1 << n) - 1);
}
return mask;
}
return BIT_WORD_MAX;
}
/*!
@brief Initialize a bitstream data structure
This routine is the constructor for the bitstream data type.
The sample offset stack is used to mark the offset to a position
in the bitstream for computing the size field of sample chunks.
*/
CODEC_ERROR InitBitstream(BITSTREAM *bitstream)
{
if (bitstream != NULL)
{
bitstream->error = BITSTREAM_ERROR_OKAY;
bitstream->stream = NULL;
bitstream->buffer = 0;
bitstream->count = 0;
#if VC5_ENABLED_PART(VC5_PART_SECTIONS)
// Initialize the stack of sample offsets
memset(bitstream->sample_offset_stack, 0, sizeof(bitstream->sample_offset_stack));
bitstream->sample_offset_count = 0;
#endif
return CODEC_ERROR_OKAY;
}
return CODEC_ERROR_NULLPTR;
}
/*!
@brief Attach a bitstream to a byte stream.
It is permitted for the byte stream to be NULL, in which case the
bitstream will not be able to replenish its internal buffer, but
the consequences are undefined.
*/
CODEC_ERROR AttachBitstream(struct _bitstream *bitstream, struct _stream *stream)
{
assert(bitstream != NULL);
bitstream->stream = stream;
return CODEC_ERROR_OKAY;
}
/*!
@brief Detach a bitstream from a byte stream.
Any resources allocated by the bitstream are released without deallocating
the bitstream data structure itself. The byte stream associated with the
bitstream is not closed by this routine. The byte stream must be closed,
if and when appropriate, by the caller.
*/
CODEC_ERROR ReleaseBitstream(BITSTREAM *bitstream)
{
//TODO: What cleanup needs to be performed?
(void) bitstream;
return CODEC_ERROR_OKAY;
}
/*!
@brief Return the specified number of bits from the bitstream
*/
BITWORD GetBits(BITSTREAM *stream, BITCOUNT count)
{
// Return zero if the request cannot be satisfied
BITWORD bits = 0;
// Check that the number of requested bits is valid
//assert(0 <= count && count <= bit_word_count);
assert(count <= bit_word_count);
// Check that the unused portion of the bit buffer is empty
assert((stream->buffer & BitMask(bit_word_count - stream->count)) == 0);
if (count == 0) goto finish;
// Are there enough bits in the buffer to satisfy the request?
if (count <= stream->count)
{
// Right align the requested number of bits in the bit buffer
bits = (stream->buffer >> (bit_word_count - count));
// Reduce the number of bits in the bit buffer
stream->buffer <<= count;
stream->count = (stream->count - count);
}
else
{
BITCOUNT low_bit_count;
// Use the remaining bits in the bit buffer
assert(stream->count > 0 || stream->buffer == 0);
bits = (stream->buffer >> (bit_word_count - count));
// Compute the number of bits to be used from the next word
low_bit_count = count - stream->count;
stream->count = 0;
assert(low_bit_count > 0);
// Fill the bit buffer
assert(stream->count == 0);
GetBuffer(stream);
assert(stream->count >= low_bit_count);
// Use the new bits in the bit buffer
bits |= (stream->buffer >> (bit_word_count - low_bit_count));
// Reduce the number of bits in the bit buffer
if (low_bit_count < bit_word_count) {
stream->buffer <<= low_bit_count;
}
else {
stream->buffer = 0;
}
assert(low_bit_count <= stream->count);
stream->count = (stream->count - low_bit_count);
}
finish:
// The bit count should never be negative or larger than the size of the bit buffer
//assert(0 <= stream->count && stream->count <= bit_word_count);
assert(stream->count <= bit_word_count);
// The unused bits in the bit buffer should all be zero
assert((stream->buffer & BitMask(bit_word_count - stream->count)) == 0);
// The unused bits in the result should all be zero
assert((bits & ~BitMask(count)) == 0);
return bits;
}
/*!
@brief Read more bits and append to an existing word of bits
Read the specified number of bits from the bitstream and append
the new bits to the right end of the word supplied as an argument.
This is a convenience routine that is used to accumulate bits that
may match a codeword.
*/
BITWORD AddBits(BITSTREAM *bitstream, BITWORD bits, BITCOUNT count)
{
BITWORD new_bits = GetBits(bitstream, count);
assert((new_bits & ~BitMask(count)) == 0);
bits = (bits << count) | new_bits;
return bits;
}
/*!
@brief Write a longword (32 bits) to the stream
*/
CODEC_ERROR PutLong(BITSTREAM *stream, BITWORD longword)
{
return PutBits(stream, longword, bit_word_count);
}
/*!
@brief Write the specified number of bits to the bitstream
*/
CODEC_ERROR PutBits(BITSTREAM *stream, BITWORD bits, BITCOUNT count)
{
BITCOUNT unused_bit_count;
if (count == 0) {
return CODEC_ERROR_OKAY;
}
// Check that the unused portion of the input bits is empty
assert((bits & (BitMask(bit_word_count - count) << count)) == 0);
// Check that the number of input bits is valid
//assert(0 <= count && count <= bit_word_count);
assert(count <= bit_word_count);
// Check that the unused portion of the bit buffer is empty
unused_bit_count = bit_word_count - stream->count;
assert((stream->buffer & BitMask(unused_bit_count)) == 0);
// Is there room in the bit buffer for the new bits?
if (count <= unused_bit_count)
{
// Fill the remaining space in the bit buffer
stream->buffer |= (bits << (unused_bit_count - count));
// Reduce the number of unused bits in the bit buffer
stream->count += count;
}
else
{
// Any room in the bit buffer?
if (unused_bit_count > 0)
{
// Use the number of input bits that will fit in the bit buffer
stream->buffer |= (bits >> (count - unused_bit_count));
// Reduce the number of input bits by the amount used
count -= unused_bit_count;
//assert(count >= 0);
}
// Write the bit buffer to the byte stream
PutWord(stream->stream, stream->buffer );
// Insert the remaining input bits into the bit buffer
stream->buffer = (bits << (bit_word_count - count));
// Increment the number of bits in the bit buffer
stream->count = count;
}
return CODEC_ERROR_OKAY;
}
/*!
@brief Fill the internal bitstream buffer by reading a byte stream
@todo Need to modify this routine to return an error code if it cannot
read from the byte stream associated with the bitstream.
*/
CODEC_ERROR GetBuffer(BITSTREAM *bitstream)
{
// Need to signal an underflow error?
if (! (bitstream != NULL && bitstream->stream != NULL)) {
assert(0);
if( bitstream->error == BITSTREAM_ERROR_UNDERFLOW )
return CODEC_ERROR_OUTOFMEMORY;
}
// The bit buffer should be empty
assert(bitstream->count == 0);
// Fill the bit buffer with a word from the byte stream
bitstream->buffer = Swap32(GetWord(bitstream->stream));
bitstream->count = bit_word_count;
return CODEC_ERROR_OKAY;
}
/*!
@brief Write the internal bitstream buffer to a byte stream
@todo Need to modify this routine to return an error code if it cannot
write to the byte stream associated with the bitstream.
*/
CODEC_ERROR PutBuffer(BITSTREAM *bitstream)
{
//TODO: Need to signal an overflow error
assert(bitstream != NULL && bitstream->stream != NULL);
// The bit buffer should be full
assert(bitstream->count == bit_word_count);
// Write the bit buffer to the byte stream
PutWord(bitstream->stream, bitstream->buffer );
// Empty the bit buffer
bitstream->buffer = 0;
bitstream->count = 0;
return CODEC_ERROR_OKAY;
}
/*!
@brief Convert a bitstream error code to a codec error codec
The bitstream and byte stream modules use a separate enumeration
for error codes since these modules are used in other applications.
The bistream error code is embedded in a range of codec error codes
that are reserved for bitstream errors.
*/
CODEC_ERROR CodecErrorBitstream(BITSTREAM_ERROR error)
{
uint32_t codec_error = CODEC_ERROR_BITSTREAM;
codec_error |= (uint32_t)error;
return (CODEC_ERROR)codec_error;
}
/*!
@brief Convert a bitstream error code into a codec error code
The bitstream and byte stream modules might be used in other
applications and have their own errors codes. This routine
embeds a bitstream error code into a codec error code. The
bitstream error code is carried in the low bits of the codec
error code.
@todo Eliminate separate error codes for bitstreams?
*/
CODEC_ERROR BitstreamCodecError(BITSTREAM *bitstream)
{
assert(bitstream != NULL);
if (! (bitstream != NULL)) {
return CODEC_ERROR_NULLPTR;
}
return CodecErrorBitstream(bitstream->error);
}
/*!
@brief Read a block of bytes from the bitstream
*/
CODEC_ERROR GetByteArray(BITSTREAM *bitstream, uint8_t *array, size_t size)
{
size_t i;
for (i = 0; i < size; i++)
{
array[i] = GetBits(bitstream, 8);
}
return CODEC_ERROR_OKAY;
}
/*!
@brief Write a block of bytes into the bitstream
*/
CODEC_ERROR PutByteArray(BITSTREAM *bitstream, const uint8_t *array, size_t size)
{
size_t i;
for (i = 0; i < size; i++)
{
PutBits(bitstream, array[i], 8);
}
return CODEC_ERROR_OKAY;
}
/*!
@brief Write any bits in the buffer to the byte stream
*/
CODEC_ERROR FlushBitstream(BITSTREAM *bitstream)
{
// Any bits remaining in the bit buffer?
if (bitstream->count > 0)
{
// Write the bit buffer to the output stream
PutBuffer(bitstream);
}
// Indicate that the bitstream buffer is empty
bitstream->count = 0;
bitstream->buffer = 0;
// Flush the output stream
FlushStream(bitstream->stream);
return CODEC_ERROR_OKAY;
}
/*!
@brief Get the current position in the byte stream
The current position in the byte stream associated with the
bitstream is returned. The intent is to allow the bitstream
(and the associated byte stream) to be restored to the saved
position.
@todo Need to record the state of the bitstream buffer and
bit count so that the entire bitstream state can be restored.
*/
size_t GetBitstreamPosition(BITSTREAM *bitstream)
{
if (bitstream->count == bit_word_count) {
PutBuffer(bitstream);
}
// The bit buffer must be empty
assert(bitstream->count == 0);
// The bit buffer must be empty
return (bitstream->stream->byte_count);
}
/*!
@brief Rewind the bitstream
This routine rewinds the bitstream to the beginning of the byte stream
that has been attached to the bitstream. The byte stream is also reset.
If the byte stream could not be reset, then the internal bitstream state
is not reset.
*/
CODEC_ERROR RewindBitstream(BITSTREAM *bitstream)
{
assert(bitstream != NULL);
if (! (bitstream != NULL)) {
return CODEC_ERROR_NULLPTR;
}
if (bitstream->stream != NULL) {
CODEC_ERROR error = RewindStream(bitstream->stream);
if (error != CODEC_ERROR_OKAY) {
return error;
}
}
// Reset the bitstream internal state
bitstream->buffer = 0;
bitstream->count = 0;
bitstream->error = BITSTREAM_ERROR_OKAY;
return CODEC_ERROR_OKAY;
}
|