1 /*****************************************************************************
2 * bytes.c
3 *****************************************************************************
4 * Copyright (C) 2010-2017 L-SMASH project
5 *
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
20
21 /* This file is available under an ISC license. */
22
23 #include "internal.h" /* must be placed first */
24
25 #include <string.h>
26 #include <limits.h>
27
lsmash_bs_create(void)28 lsmash_bs_t *lsmash_bs_create( void )
29 {
30 lsmash_bs_t *bs = lsmash_malloc_zero( sizeof(lsmash_bs_t) );
31 if( !bs )
32 return NULL;
33 bs->unseekable = 1;
34 bs->buffer.internal = 1;
35 bs->buffer.max_size = BS_MAX_DEFAULT_READ_SIZE;
36 return bs;
37 }
38
bs_buffer_free(lsmash_bs_t * bs)39 static void bs_buffer_free( lsmash_bs_t *bs )
40 {
41 if( bs->buffer.internal )
42 lsmash_free( bs->buffer.data );
43 bs->buffer.data = NULL;
44 bs->buffer.alloc = 0;
45 bs->buffer.store = 0;
46 bs->buffer.pos = 0;
47 }
48
lsmash_bs_cleanup(lsmash_bs_t * bs)49 void lsmash_bs_cleanup( lsmash_bs_t *bs )
50 {
51 if( !bs )
52 return;
53 bs_buffer_free( bs );
54 lsmash_free( bs );
55 }
56
lsmash_bs_set_empty_stream(lsmash_bs_t * bs,uint8_t * data,size_t size)57 int lsmash_bs_set_empty_stream( lsmash_bs_t *bs, uint8_t *data, size_t size )
58 {
59 if( !bs )
60 return LSMASH_ERR_FUNCTION_PARAM;
61 bs->stream = NULL; /* empty stream */
62 bs->eof = 1; /* unreadable because of empty stream */
63 bs->eob = 0; /* readable on the buffer */
64 bs->error = 0;
65 bs->unseekable = 1; /* only seek on the buffer */
66 bs->written = size; /* behave as if the size of the empty stream is 'size' */
67 bs->offset = size; /* behave as if the poiter of the stream is at the end */
68 bs->buffer.unseekable = 0; /* only seek on the buffer */
69 bs->buffer.internal = 0; /* must not be allocated internally */
70 bs->buffer.data = data;
71 bs->buffer.store = size;
72 bs->buffer.alloc = size;
73 bs->buffer.pos = 0;
74 bs->buffer.max_size = 0; /* make no sense */
75 bs->buffer.count = 0;
76 bs->read = NULL;
77 bs->write = NULL;
78 bs->seek = NULL;
79 return 0;
80 }
81
lsmash_bs_empty(lsmash_bs_t * bs)82 void lsmash_bs_empty( lsmash_bs_t *bs )
83 {
84 if( !bs )
85 return;
86 if( bs->buffer.data )
87 memset( bs->buffer.data, 0, bs->buffer.alloc );
88 bs->buffer.store = 0;
89 bs->buffer.pos = 0;
90 }
91
bs_alloc(lsmash_bs_t * bs,size_t alloc)92 static void bs_alloc( lsmash_bs_t *bs, size_t alloc )
93 {
94 if( (bs->buffer.alloc >= alloc) || bs->error )
95 return;
96 if( !bs->buffer.internal )
97 {
98 /* We cannot re-allocate the memory block. */
99 bs->error = 1;
100 return;
101 }
102 alloc = LSMASH_MAX( alloc, bs->buffer.max_size );
103 uint8_t *data;
104 if( !bs->buffer.data )
105 data = lsmash_malloc( alloc );
106 else
107 data = lsmash_realloc( bs->buffer.data, alloc );
108 if( !data )
109 {
110 bs_buffer_free( bs );
111 bs->error = 1;
112 return;
113 }
114 bs->buffer.internal = 1;
115 bs->buffer.data = data;
116 bs->buffer.alloc = alloc;
117 }
118
bs_estimate_seek_offset(lsmash_bs_t * bs,int64_t offset,int whence)119 static uint64_t bs_estimate_seek_offset( lsmash_bs_t *bs, int64_t offset, int whence )
120 {
121 /* Calculate the offset after the seek. */
122 uint64_t dst_offset;
123 if( whence == SEEK_SET )
124 {
125 assert( offset >= 0 );
126 if( bs->written < offset )
127 dst_offset = bs->written;
128 else
129 dst_offset = offset;
130 }
131 else if( whence == SEEK_CUR )
132 {
133 if( offset < 0 && bs->offset < -offset )
134 dst_offset = 0;
135 else if( offset > 0 && bs->written < bs->offset + offset )
136 dst_offset = bs->written;
137 else
138 dst_offset = bs->offset + offset;
139 }
140 else /* if( whence == SEEK_END ) */
141 {
142 assert( offset <= 0 );
143 if( bs->written < -offset )
144 dst_offset = 0;
145 else
146 dst_offset = bs->written + offset;
147 }
148 return dst_offset;
149 }
150
151 /* TODO: Support offset > INT64_MAX */
lsmash_bs_write_seek(lsmash_bs_t * bs,int64_t offset,int whence)152 int64_t lsmash_bs_write_seek( lsmash_bs_t *bs, int64_t offset, int whence )
153 {
154 if( bs->unseekable )
155 return LSMASH_ERR_NAMELESS;
156 if( whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END )
157 return LSMASH_ERR_FUNCTION_PARAM;
158 /* Try to seek the stream. */
159 int64_t ret = bs->seek( bs->stream, offset, whence );
160 if( ret < 0 )
161 return ret;
162 bs->offset = bs_estimate_seek_offset( bs, offset, whence );
163 bs->eof = 0;
164 bs->eob = 0;
165 return ret;
166 }
167
168 /* TODO: Support offset > INT64_MAX */
lsmash_bs_read_seek(lsmash_bs_t * bs,int64_t offset,int whence)169 int64_t lsmash_bs_read_seek( lsmash_bs_t *bs, int64_t offset, int whence )
170 {
171 if( whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END )
172 return LSMASH_ERR_FUNCTION_PARAM;
173 if( whence == SEEK_CUR )
174 offset -= lsmash_bs_get_remaining_buffer_size( bs );
175 /* Check whether we can seek on the buffer. */
176 if( !bs->buffer.unseekable )
177 {
178 assert( bs->offset >= bs->buffer.store );
179 uint64_t dst_offset = bs_estimate_seek_offset( bs, offset, whence );
180 uint64_t offset_s = bs->offset - bs->buffer.store;
181 uint64_t offset_e = bs->offset;
182 if( bs->unseekable || (dst_offset >= offset_s && dst_offset < offset_e) )
183 {
184 /* OK, we can. So, seek on the buffer. */
185 bs->buffer.pos = dst_offset - offset_s;
186 bs->eob = 0;
187 return lsmash_bs_get_stream_pos( bs );
188 }
189 }
190 if( bs->unseekable )
191 return LSMASH_ERR_NAMELESS;
192 /* Try to seek the stream. */
193 int64_t ret = bs->seek( bs->stream, offset, whence );
194 if( ret < 0 )
195 return ret;
196 bs->offset = ret;
197 bs->written = LSMASH_MAX( bs->written, bs->offset );
198 bs->eof = 0;
199 bs->eob = 0;
200 /* The data on the buffer is invalid. */
201 lsmash_bs_empty( bs );
202 return ret;
203 }
204
bs_dispose_past_data(lsmash_bs_t * bs)205 static void bs_dispose_past_data( lsmash_bs_t *bs )
206 {
207 /* Move remainder bytes. */
208 assert( bs->buffer.store >= bs->buffer.pos );
209 size_t remainder = lsmash_bs_get_remaining_buffer_size( bs );
210 if( bs->buffer.pos && remainder )
211 memmove( lsmash_bs_get_buffer_data_start( bs ), lsmash_bs_get_buffer_data( bs ), remainder );
212 bs->buffer.store = remainder;
213 bs->buffer.pos = 0;
214 }
215
216 /*---- bitstream writer ----*/
lsmash_bs_put_byte(lsmash_bs_t * bs,uint8_t value)217 void lsmash_bs_put_byte( lsmash_bs_t *bs, uint8_t value )
218 {
219 if( bs->buffer.internal
220 || bs->buffer.data )
221 {
222 bs_alloc( bs, bs->buffer.store + 1 );
223 if( bs->error )
224 return;
225 bs->buffer.data[ bs->buffer.store ] = value;
226 }
227 ++ bs->buffer.store;
228 }
229
lsmash_bs_put_bytes(lsmash_bs_t * bs,uint32_t size,void * value)230 void lsmash_bs_put_bytes( lsmash_bs_t *bs, uint32_t size, void *value )
231 {
232 if( size == 0 || !value )
233 return;
234 if( bs->buffer.internal
235 || bs->buffer.data )
236 {
237 bs_alloc( bs, bs->buffer.store + size );
238 if( bs->error )
239 return;
240 memcpy( lsmash_bs_get_buffer_data_end( bs ), value, size );
241 }
242 bs->buffer.store += size;
243 }
244
lsmash_bs_put_be16(lsmash_bs_t * bs,uint16_t value)245 void lsmash_bs_put_be16( lsmash_bs_t *bs, uint16_t value )
246 {
247 lsmash_bs_put_byte( bs, value >> 8 );
248 lsmash_bs_put_byte( bs, value );
249 }
250
lsmash_bs_put_be24(lsmash_bs_t * bs,uint32_t value)251 void lsmash_bs_put_be24( lsmash_bs_t *bs, uint32_t value )
252 {
253 lsmash_bs_put_byte( bs, value >> 16 );
254 lsmash_bs_put_be16( bs, value );
255 }
256
lsmash_bs_put_be32(lsmash_bs_t * bs,uint32_t value)257 void lsmash_bs_put_be32( lsmash_bs_t *bs, uint32_t value )
258 {
259 lsmash_bs_put_be16( bs, value >> 16 );
260 lsmash_bs_put_be16( bs, value );
261 }
262
lsmash_bs_put_be64(lsmash_bs_t * bs,uint64_t value)263 void lsmash_bs_put_be64( lsmash_bs_t *bs, uint64_t value )
264 {
265 lsmash_bs_put_be32( bs, value >> 32 );
266 lsmash_bs_put_be32( bs, value );
267 }
268
lsmash_bs_put_byte_from_64(lsmash_bs_t * bs,uint64_t value)269 void lsmash_bs_put_byte_from_64( lsmash_bs_t *bs, uint64_t value )
270 {
271 lsmash_bs_put_byte( bs, value );
272 }
273
lsmash_bs_put_be16_from_64(lsmash_bs_t * bs,uint64_t value)274 void lsmash_bs_put_be16_from_64( lsmash_bs_t *bs, uint64_t value )
275 {
276 lsmash_bs_put_be16( bs, value );
277 }
278
lsmash_bs_put_be24_from_64(lsmash_bs_t * bs,uint64_t value)279 void lsmash_bs_put_be24_from_64( lsmash_bs_t *bs, uint64_t value )
280 {
281 lsmash_bs_put_be24( bs, value );
282 }
283
lsmash_bs_put_be32_from_64(lsmash_bs_t * bs,uint64_t value)284 void lsmash_bs_put_be32_from_64( lsmash_bs_t *bs, uint64_t value )
285 {
286 lsmash_bs_put_be32( bs, value );
287 }
288
lsmash_bs_put_le16(lsmash_bs_t * bs,uint16_t value)289 void lsmash_bs_put_le16( lsmash_bs_t *bs, uint16_t value )
290 {
291 lsmash_bs_put_byte( bs, value );
292 lsmash_bs_put_byte( bs, value >> 8 );
293 }
294
lsmash_bs_put_le32(lsmash_bs_t * bs,uint32_t value)295 void lsmash_bs_put_le32( lsmash_bs_t *bs, uint32_t value )
296 {
297 lsmash_bs_put_le16( bs, value );
298 lsmash_bs_put_le16( bs, value >> 16 );
299 }
300
lsmash_bs_flush_buffer(lsmash_bs_t * bs)301 int lsmash_bs_flush_buffer( lsmash_bs_t *bs )
302 {
303 if( !bs )
304 return LSMASH_ERR_FUNCTION_PARAM;
305 if( bs->buffer.store == 0
306 || (bs->stream && bs->write && !bs->buffer.data) )
307 return 0;
308 if( bs->error
309 || (bs->stream && bs->write && bs->write( bs->stream, lsmash_bs_get_buffer_data_start( bs ), bs->buffer.store ) != bs->buffer.store) )
310 {
311 bs_buffer_free( bs );
312 bs->error = 1;
313 return LSMASH_ERR_NAMELESS;
314 }
315 if( bs->write )
316 {
317 bs->written += bs->buffer.store;
318 bs->offset += bs->buffer.store;
319 }
320 bs->buffer.store = 0;
321 return 0;
322 }
323
lsmash_bs_write_data(lsmash_bs_t * bs,const uint8_t * buf,size_t size)324 int lsmash_bs_write_data( lsmash_bs_t *bs, const uint8_t *buf, size_t size )
325 {
326 if( !bs || size > INT_MAX )
327 return LSMASH_ERR_FUNCTION_PARAM;
328 if( !buf || size == 0 )
329 return 0;
330 if( bs->error || !bs->stream )
331 {
332 bs_buffer_free( bs );
333 bs->error = 1;
334 return LSMASH_ERR_NAMELESS;
335 }
336 int write_size = bs->write( bs->stream, (uint8_t *)buf, size );
337 bs->written += write_size;
338 bs->offset += write_size;
339 return write_size != size ? LSMASH_ERR_NAMELESS : 0;
340 }
341
lsmash_bs_export_data(lsmash_bs_t * bs,uint32_t * length)342 void *lsmash_bs_export_data( lsmash_bs_t *bs, uint32_t *length )
343 {
344 if( !bs || !bs->buffer.data || bs->buffer.store == 0 || bs->error )
345 return NULL;
346 void *buf = lsmash_memdup( lsmash_bs_get_buffer_data_start( bs ), bs->buffer.store );
347 if( !buf )
348 return NULL;
349 if( length )
350 *length = bs->buffer.store;
351 return buf;
352 }
353 /*---- ----*/
354
355 /*---- bitstream reader ----*/
bs_fill_buffer(lsmash_bs_t * bs)356 static void bs_fill_buffer( lsmash_bs_t *bs )
357 {
358 if( bs->eof || bs->error )
359 return;
360 if( !bs->read || !bs->stream || bs->buffer.max_size == 0 )
361 {
362 bs->eof = 1;
363 return;
364 }
365 if( !bs->buffer.data )
366 {
367 bs_alloc( bs, bs->buffer.max_size );
368 if( bs->error )
369 return;
370 }
371 /* Read bytes from the stream to fill the buffer. */
372 bs_dispose_past_data( bs );
373 while( bs->buffer.alloc > bs->buffer.store )
374 {
375 uint64_t invalid_buffer_size = bs->buffer.alloc - bs->buffer.store;
376 int max_read_size = LSMASH_MIN( invalid_buffer_size, bs->buffer.max_size );
377 int read_size = bs->read( bs->stream, lsmash_bs_get_buffer_data_end( bs ), max_read_size );
378 if( read_size == 0 )
379 {
380 bs->eof = 1;
381 return;
382 }
383 else if( read_size < 0 )
384 {
385 bs->error = 1;
386 return;
387 }
388 bs->buffer.unseekable = 0;
389 bs->buffer.store += read_size;
390 bs->offset += read_size;
391 bs->written = LSMASH_MAX( bs->written, bs->offset );
392 }
393 }
394
lsmash_bs_show_byte(lsmash_bs_t * bs,uint32_t offset)395 uint8_t lsmash_bs_show_byte( lsmash_bs_t *bs, uint32_t offset )
396 {
397 if( bs->error )
398 return 0;
399 if( offset >= lsmash_bs_get_remaining_buffer_size( bs ) )
400 {
401 bs_fill_buffer( bs );
402 if( bs->error )
403 return 0;
404 if( offset >= lsmash_bs_get_remaining_buffer_size( bs ) )
405 {
406 if( bs->eof )
407 /* No more read from both the stream and the buffer. */
408 return 0;
409 /* We need increase the buffer size. */
410 bs_alloc( bs, bs->buffer.pos + offset + 1 );
411 bs_fill_buffer( bs );
412 if( bs->error )
413 return 0;
414 }
415 }
416 return bs->buffer.data[ bs->buffer.pos + offset ];
417 }
418
lsmash_bs_show_be16(lsmash_bs_t * bs,uint32_t offset)419 uint16_t lsmash_bs_show_be16( lsmash_bs_t *bs, uint32_t offset )
420 {
421 return ((uint16_t)lsmash_bs_show_byte( bs, offset ) << 8)
422 | ((uint16_t)lsmash_bs_show_byte( bs, offset + 1 ));
423 }
424
lsmash_bs_show_be24(lsmash_bs_t * bs,uint32_t offset)425 uint32_t lsmash_bs_show_be24( lsmash_bs_t *bs, uint32_t offset )
426 {
427 return ((uint32_t)lsmash_bs_show_byte( bs, offset ) << 16)
428 | ((uint32_t)lsmash_bs_show_byte( bs, offset + 1 ) << 8)
429 | ((uint32_t)lsmash_bs_show_byte( bs, offset + 2 ));
430 }
431
lsmash_bs_show_be32(lsmash_bs_t * bs,uint32_t offset)432 uint32_t lsmash_bs_show_be32( lsmash_bs_t *bs, uint32_t offset )
433 {
434 return ((uint32_t)lsmash_bs_show_byte( bs, offset ) << 24)
435 | ((uint32_t)lsmash_bs_show_byte( bs, offset + 1 ) << 16)
436 | ((uint32_t)lsmash_bs_show_byte( bs, offset + 2 ) << 8)
437 | ((uint32_t)lsmash_bs_show_byte( bs, offset + 3 ));
438 }
439
lsmash_bs_show_be64(lsmash_bs_t * bs,uint32_t offset)440 uint64_t lsmash_bs_show_be64( lsmash_bs_t *bs, uint32_t offset )
441 {
442 return ((uint64_t)lsmash_bs_show_byte( bs, offset ) << 56)
443 | ((uint64_t)lsmash_bs_show_byte( bs, offset + 1 ) << 48)
444 | ((uint64_t)lsmash_bs_show_byte( bs, offset + 2 ) << 40)
445 | ((uint64_t)lsmash_bs_show_byte( bs, offset + 3 ) << 32)
446 | ((uint64_t)lsmash_bs_show_byte( bs, offset + 4 ) << 24)
447 | ((uint64_t)lsmash_bs_show_byte( bs, offset + 5 ) << 16)
448 | ((uint64_t)lsmash_bs_show_byte( bs, offset + 6 ) << 8)
449 | ((uint64_t)lsmash_bs_show_byte( bs, offset + 7 ));
450 }
451
lsmash_bs_get_byte(lsmash_bs_t * bs)452 uint8_t lsmash_bs_get_byte( lsmash_bs_t *bs )
453 {
454 if( bs->eob || bs->error )
455 return 0;
456 assert( bs->buffer.pos <= bs->buffer.store );
457 if( bs->buffer.pos == bs->buffer.store )
458 {
459 bs_fill_buffer( bs );
460 if( bs->error )
461 return 0;
462 if( bs->buffer.pos == bs->buffer.store && bs->eof )
463 {
464 /* No more read from both the stream and the buffer. */
465 bs->eob = 1;
466 return 0;
467 }
468 }
469 ++ bs->buffer.count; /* increment counter */
470 return bs->buffer.data[ bs->buffer.pos ++ ];
471 }
472
lsmash_bs_skip_bytes(lsmash_bs_t * bs,uint32_t size)473 void lsmash_bs_skip_bytes( lsmash_bs_t *bs, uint32_t size )
474 {
475 if( bs->eob || bs->error || size == 0 )
476 return;
477 uint64_t remainder;
478 uint64_t offset = 0;
479 while( size > lsmash_bs_get_remaining_buffer_size( bs ) )
480 {
481 remainder = lsmash_bs_get_remaining_buffer_size( bs );
482 offset += remainder;
483 size -= remainder;
484 bs->buffer.pos = bs->buffer.store;
485 if( bs->eof )
486 {
487 /* No more read from both the stream and the buffer. */
488 bs->eob = 1;
489 break;
490 }
491 else
492 {
493 bs_fill_buffer( bs );
494 if( bs->error )
495 break;
496 }
497 }
498 remainder = LSMASH_MIN( size, lsmash_bs_get_remaining_buffer_size( bs ) );
499 offset += remainder;
500 bs->buffer.pos += remainder;
501 bs->buffer.count += offset;
502 }
503
lsmash_bs_skip_bytes_64(lsmash_bs_t * bs,uint64_t size)504 void lsmash_bs_skip_bytes_64( lsmash_bs_t *bs, uint64_t size )
505 {
506 while( size )
507 {
508 uint64_t skip_bytes = LSMASH_MIN( size, UINT32_MAX );
509 lsmash_bs_skip_bytes( bs, (uint32_t)skip_bytes );
510 size -= skip_bytes;
511 if( bs->eob )
512 return;
513 }
514 }
515
bs_get_bytes(lsmash_bs_t * bs,uint32_t size,uint8_t * buf)516 static int64_t bs_get_bytes( lsmash_bs_t *bs, uint32_t size, uint8_t *buf )
517 {
518 size_t remainder;
519 size_t remain_size = size;
520 uintptr_t offset = 0;
521 while( remain_size > lsmash_bs_get_remaining_buffer_size( bs ) )
522 {
523 remainder = lsmash_bs_get_remaining_buffer_size( bs );
524 memcpy( buf + offset, lsmash_bs_get_buffer_data( bs ), remainder );
525 offset += remainder;
526 remain_size -= remainder;
527 bs->buffer.pos = bs->buffer.store;
528 if( bs->eof )
529 {
530 /* No more read from both the stream and the buffer. */
531 bs->eob = 1;
532 break;
533 }
534 else
535 {
536 bs_fill_buffer( bs );
537 if( bs->error )
538 {
539 bs->buffer.count += offset;
540 return LSMASH_ERR_NAMELESS;
541 }
542 }
543 }
544 remainder = LSMASH_MIN( remain_size, lsmash_bs_get_remaining_buffer_size( bs ) );
545 memcpy( buf + offset, lsmash_bs_get_buffer_data( bs ), remainder );
546 offset += remainder;
547 bs->buffer.pos += remainder;
548 bs->buffer.count += offset;
549 if( offset < size )
550 memset( buf + offset, 0, size - offset );
551 return (int64_t)offset;
552 }
553
lsmash_bs_get_bytes(lsmash_bs_t * bs,uint32_t size)554 uint8_t *lsmash_bs_get_bytes( lsmash_bs_t *bs, uint32_t size )
555 {
556 if( bs->eob || bs->error || size == 0 )
557 return NULL;
558 uint8_t *value = lsmash_malloc( size );
559 if( !value )
560 {
561 bs->error = 1;
562 return NULL;
563 }
564 if( bs_get_bytes( bs, size, value ) < 0 )
565 {
566 lsmash_free( value );
567 return NULL;
568 }
569 return value;
570 }
571
lsmash_bs_get_bytes_ex(lsmash_bs_t * bs,uint32_t size,uint8_t * value)572 int64_t lsmash_bs_get_bytes_ex( lsmash_bs_t *bs, uint32_t size, uint8_t *value )
573 {
574 if( size == 0 )
575 return 0;
576 if( bs->eob || bs->error )
577 return LSMASH_ERR_NAMELESS;
578 return bs_get_bytes( bs, size, value );
579 }
580
lsmash_bs_get_be16(lsmash_bs_t * bs)581 uint16_t lsmash_bs_get_be16( lsmash_bs_t *bs )
582 {
583 uint16_t value = lsmash_bs_get_byte( bs );
584 return (value<<8) | lsmash_bs_get_byte( bs );
585 }
586
lsmash_bs_get_be24(lsmash_bs_t * bs)587 uint32_t lsmash_bs_get_be24( lsmash_bs_t *bs )
588 {
589 uint32_t value = lsmash_bs_get_byte( bs );
590 return (value<<16) | lsmash_bs_get_be16( bs );
591 }
592
lsmash_bs_get_be32(lsmash_bs_t * bs)593 uint32_t lsmash_bs_get_be32( lsmash_bs_t *bs )
594 {
595 uint32_t value = lsmash_bs_get_be16( bs );
596 return (value<<16) | lsmash_bs_get_be16( bs );
597 }
598
lsmash_bs_get_be64(lsmash_bs_t * bs)599 uint64_t lsmash_bs_get_be64( lsmash_bs_t *bs )
600 {
601 uint64_t value = lsmash_bs_get_be32( bs );
602 return (value<<32) | lsmash_bs_get_be32( bs );
603 }
604
lsmash_bs_get_byte_to_64(lsmash_bs_t * bs)605 uint64_t lsmash_bs_get_byte_to_64( lsmash_bs_t *bs )
606 {
607 return lsmash_bs_get_byte( bs );
608 }
609
lsmash_bs_get_be16_to_64(lsmash_bs_t * bs)610 uint64_t lsmash_bs_get_be16_to_64( lsmash_bs_t *bs )
611 {
612 return lsmash_bs_get_be16( bs );
613 }
614
lsmash_bs_get_be24_to_64(lsmash_bs_t * bs)615 uint64_t lsmash_bs_get_be24_to_64( lsmash_bs_t *bs )
616 {
617 return lsmash_bs_get_be24( bs );
618 }
619
lsmash_bs_get_be32_to_64(lsmash_bs_t * bs)620 uint64_t lsmash_bs_get_be32_to_64( lsmash_bs_t *bs )
621 {
622 return lsmash_bs_get_be32( bs );
623 }
624
lsmash_bs_get_le16(lsmash_bs_t * bs)625 uint16_t lsmash_bs_get_le16( lsmash_bs_t *bs )
626 {
627 uint16_t value = lsmash_bs_get_byte( bs );
628 return value | (lsmash_bs_get_byte( bs ) << 8);
629 }
630
lsmash_bs_get_le32(lsmash_bs_t * bs)631 uint32_t lsmash_bs_get_le32( lsmash_bs_t *bs )
632 {
633 uint32_t value = lsmash_bs_get_le16( bs );
634 return value | (lsmash_bs_get_le16( bs ) << 16);
635 }
636
lsmash_bs_read(lsmash_bs_t * bs,uint32_t size)637 int lsmash_bs_read( lsmash_bs_t *bs, uint32_t size )
638 {
639 if( !bs || size > INT_MAX )
640 return LSMASH_ERR_FUNCTION_PARAM;
641 if( size == 0 )
642 return 0;
643 bs_alloc( bs, bs->buffer.store + size );
644 if( bs->error || !bs->stream )
645 {
646 bs->error = 1;
647 return LSMASH_ERR_NAMELESS;
648 }
649 int read_size = bs->read( bs->stream, lsmash_bs_get_buffer_data_end( bs ), size );
650 if( read_size == 0 )
651 {
652 bs->eof = 1;
653 return 0;
654 }
655 else if( read_size < 0 )
656 {
657 bs->error = 1;
658 return LSMASH_ERR_NAMELESS;
659 }
660 bs->buffer.store += read_size;
661 bs->offset += read_size;
662 bs->written = LSMASH_MAX( bs->written, bs->offset );
663 return read_size;
664 }
665
lsmash_bs_read_data(lsmash_bs_t * bs,uint8_t * buf,size_t * size)666 int lsmash_bs_read_data( lsmash_bs_t *bs, uint8_t *buf, size_t *size )
667 {
668 if( !bs || !size || *size > INT_MAX )
669 return LSMASH_ERR_FUNCTION_PARAM;
670 if( !buf || *size == 0 )
671 return 0;
672 if( bs->error || !bs->stream )
673 {
674 bs->error = 1;
675 return LSMASH_ERR_NAMELESS;
676 }
677 int read_size = bs->read( bs->stream, buf, *size );
678 if( read_size == 0 )
679 bs->eof = 1;
680 else if( read_size < 0 )
681 {
682 bs->error = 1;
683 return LSMASH_ERR_NAMELESS;
684 }
685 bs->buffer.unseekable = 1;
686 bs->offset += read_size;
687 *size = read_size;
688 bs->written = LSMASH_MAX( bs->written, bs->offset );
689 return 0;
690 }
691
lsmash_bs_import_data(lsmash_bs_t * bs,void * data,uint32_t length)692 int lsmash_bs_import_data( lsmash_bs_t *bs, void *data, uint32_t length )
693 {
694 if( !bs || !data || length == 0 )
695 return LSMASH_ERR_FUNCTION_PARAM;
696 if( bs->error )
697 return LSMASH_ERR_NAMELESS;
698 bs_alloc( bs, bs->buffer.store + length );
699 if( bs->error || !bs->buffer.data ) /* means, failed to alloc. */
700 {
701 bs_buffer_free( bs );
702 return LSMASH_ERR_NAMELESS;
703 }
704 memcpy( lsmash_bs_get_buffer_data_end( bs ), data, length );
705 bs->buffer.store += length;
706 return 0;
707 }
708