1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2000-2012
6 * All rights reserved
7 *
8 * This file is part of GPAC / common tools sub-project
9 *
10 * GPAC is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * GPAC is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; see the file COPYING. If not, write to
22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26 #include <gpac/bitstream.h>
27
28 /*the default size for new streams allocation...*/
29 #define BS_MEM_BLOCK_ALLOC_SIZE 4096
30
31 /*private types*/
32 enum
33 {
34 GF_BITSTREAM_FILE_READ = GF_BITSTREAM_WRITE + 1,
35 GF_BITSTREAM_FILE_WRITE,
36 /*private mode if we own the buffer*/
37 GF_BITSTREAM_WRITE_DYN
38 };
39
40 struct __tag_bitstream
41 {
42 /*original stream data*/
43 FILE *stream;
44
45 /*original data*/
46 char *original;
47 /*the size of our buffer in bytes*/
48 u64 size;
49 /*current position in BYTES*/
50 u64 position;
51 /*the byte readen/written*/
52 u32 current;
53 /*the number of bits in the current byte*/
54 u32 nbBits;
55 /*the bitstream mode*/
56 u32 bsmode;
57
58 void(*EndOfStream)(void *par);
59 void *par;
60
61
62 char *buffer_io;
63 u32 buffer_io_size, buffer_written;
64 };
65
66
67 GF_EXPORT
gf_bs_new(const char * buffer,u64 BufferSize,u32 mode)68 GF_BitStream *gf_bs_new(const char *buffer, u64 BufferSize, u32 mode)
69 {
70 GF_BitStream *tmp;
71 if ((buffer && !BufferSize)) return NULL;
72
73 tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
74 if (!tmp) return NULL;
75 memset(tmp, 0, sizeof(GF_BitStream));
76
77 tmp->original = (char*)buffer;
78 tmp->size = BufferSize;
79
80 tmp->position = 0;
81 tmp->current = 0;
82 tmp->bsmode = mode;
83 tmp->stream = NULL;
84
85 switch (tmp->bsmode) {
86 case GF_BITSTREAM_READ:
87 tmp->nbBits = 8;
88 tmp->current = 0;
89 break;
90 case GF_BITSTREAM_WRITE:
91 tmp->nbBits = 0;
92 if (!buffer) {
93 /*if BufferSize is specified, use it. This is typically used when AvgSize of
94 some buffers is known, but some exceed it.*/
95 if (BufferSize) {
96 tmp->size = BufferSize;
97 }
98 else {
99 tmp->size = BS_MEM_BLOCK_ALLOC_SIZE;
100 }
101 tmp->original = (char *)gf_malloc(sizeof(char) * ((u32)tmp->size));
102 if (!tmp->original) {
103 gf_free(tmp);
104 return NULL;
105 }
106 tmp->bsmode = GF_BITSTREAM_WRITE_DYN;
107 }
108 else {
109 tmp->original = (char*)buffer;
110 tmp->size = BufferSize;
111 }
112 break;
113 default:
114 /*the stream constructor is not the same...*/
115 gf_free(tmp);
116 return NULL;
117 }
118 return tmp;
119 }
120
121 GF_EXPORT
gf_bs_from_file(FILE * f,u32 mode)122 GF_BitStream *gf_bs_from_file(FILE *f, u32 mode)
123 {
124 GF_BitStream *tmp;
125 if (!f) return NULL;
126
127 tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
128 if (!tmp) return NULL;
129 memset(tmp, 0, sizeof(GF_BitStream));
130 /*switch to internal mode*/
131 mode = (mode == GF_BITSTREAM_READ) ? GF_BITSTREAM_FILE_READ : GF_BITSTREAM_FILE_WRITE;
132 tmp->bsmode = mode;
133 tmp->current = 0;
134 tmp->nbBits = (mode == GF_BITSTREAM_FILE_READ) ? 8 : 0;
135 tmp->original = NULL;
136 tmp->position = 0;
137 tmp->stream = f;
138
139 /*get the size of this file (for read streams)*/
140 tmp->position = gf_ftell(f);
141 gf_fseek(f, 0, SEEK_END);
142 tmp->size = gf_ftell(f);
143 gf_fseek(f, tmp->position, SEEK_SET);
144 return tmp;
145 }
146
bs_flush_cache(GF_BitStream * bs)147 static void bs_flush_cache(GF_BitStream *bs)
148 {
149 if (bs->buffer_written) {
150 u32 nb_write = (u32)fwrite(bs->buffer_io, 1, bs->buffer_written, bs->stream);
151 bs->size += nb_write;
152 bs->position += nb_write;
153 bs->buffer_written = 0;
154 }
155 }
156
157
158 GF_EXPORT
gf_bs_set_output_buffering(GF_BitStream * bs,u32 size)159 GF_Err gf_bs_set_output_buffering(GF_BitStream *bs, u32 size)
160 {
161 if (!bs->stream) return GF_OK;
162 if (bs->bsmode != GF_BITSTREAM_FILE_WRITE) {
163 return GF_OK;
164 }
165 bs_flush_cache(bs);
166 bs->buffer_io = (char*)gf_realloc(bs->buffer_io, size);
167 if (!bs->buffer_io) return GF_IO_ERR;
168 bs->buffer_io_size = size;
169 bs->buffer_written = 0;
170 return GF_OK;
171 }
172
173
174 GF_EXPORT
gf_bs_get_output_buffering(GF_BitStream * bs)175 u32 gf_bs_get_output_buffering(GF_BitStream *bs)
176 {
177 return bs ? bs->buffer_io_size : 0;
178 }
179
180 GF_EXPORT
gf_bs_del(GF_BitStream * bs)181 void gf_bs_del(GF_BitStream *bs)
182 {
183 if (!bs) return;
184 /*if we are in dynamic mode (alloc done by the bitstream), free the buffer if still present*/
185 if ((bs->bsmode == GF_BITSTREAM_WRITE_DYN) && bs->original) gf_free(bs->original);
186 if (bs->buffer_io)
187 bs_flush_cache(bs);
188 gf_free(bs);
189 }
190
191
192 /*returns 1 if aligned wrt current mode, 0 otherwise*/
BS_IsAlign(GF_BitStream * bs)193 static Bool BS_IsAlign(GF_BitStream *bs)
194 {
195 switch (bs->bsmode) {
196 case GF_BITSTREAM_READ:
197 case GF_BITSTREAM_FILE_READ:
198 return ((8 == bs->nbBits) ? GF_TRUE : GF_FALSE);
199 default:
200 return !bs->nbBits;
201 }
202 }
203
204
205 /*fetch a new byte in the bitstream switch between packets*/
BS_ReadByte(GF_BitStream * bs)206 static u8 BS_ReadByte(GF_BitStream *bs)
207 {
208 if (bs->bsmode == GF_BITSTREAM_READ) {
209 if (bs->position >= bs->size) {
210 if (bs->EndOfStream) bs->EndOfStream(bs->par);
211 return 0;
212 }
213 return (u32)bs->original[bs->position++];
214 }
215 if (bs->buffer_io)
216 bs_flush_cache(bs);
217
218 /*we are in FILE mode, test for end of file*/
219 if (!feof(bs->stream)) {
220 bs->position++;
221 return (u32)fgetc(bs->stream);
222 }
223 if (bs->EndOfStream) bs->EndOfStream(bs->par);
224 return 0;
225 }
226
227 #define NO_OPTS
228
229 #ifndef NO_OPTS
230 static u32 bit_mask[] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
231 static u32 bits_mask[] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F };
232 #endif
233
234 GF_EXPORT
gf_bs_read_bit(GF_BitStream * bs)235 u8 gf_bs_read_bit(GF_BitStream *bs)
236 {
237 if (bs->nbBits == 8) {
238 bs->current = BS_ReadByte(bs);
239 bs->nbBits = 0;
240 }
241 #ifdef NO_OPTS
242 {
243 s32 ret;
244 bs->current <<= 1;
245 bs->nbBits++;
246 ret = (bs->current & 0x100) >> 8;
247 return (u8)ret;
248 }
249 #else
250 return (u8)(bs->current & bit_mask[bs->nbBits++]) ? 1 : 0;
251 #endif
252
253 }
254
255 GF_EXPORT
gf_bs_read_int(GF_BitStream * bs,u32 nBits)256 u32 gf_bs_read_int(GF_BitStream *bs, u32 nBits)
257 {
258 u32 ret;
259
260 #ifndef NO_OPTS
261 if (nBits + bs->nbBits <= 8) {
262 bs->nbBits += nBits;
263 ret = (bs->current >> (8 - bs->nbBits)) & bits_mask[nBits];
264 return ret;
265 }
266 #endif
267 ret = 0;
268 while (nBits-- > 0) {
269 ret <<= 1;
270 ret |= gf_bs_read_bit(bs);
271 }
272 return ret;
273 }
274
275 GF_EXPORT
gf_bs_read_u8(GF_BitStream * bs)276 u32 gf_bs_read_u8(GF_BitStream *bs)
277 {
278 assert(bs->nbBits == 8);
279 return (u32)BS_ReadByte(bs);
280 }
281
282 GF_EXPORT
gf_bs_read_u8_until_delimiter(GF_BitStream * bs,u8 delimiter,u8 * out,u32 max_length)283 u32 gf_bs_read_u8_until_delimiter(GF_BitStream *bs, u8 delimiter, u8* out, u32 max_length) {
284 u32 i = 0;
285 char token = 0;
286 u64 cur_pos = gf_bs_get_position(bs);
287
288 if (!max_length) out = NULL;
289
290 while (gf_bs_available(bs) && (!max_length || i < max_length)) {
291 gf_bs_read_data(bs, &token, 1);
292 if (token == delimiter) goto found;
293 if (out) out[i] = token;
294 i++;
295 }
296
297 /* Delimiter not found */
298 gf_bs_seek(bs, cur_pos);
299 return 0;
300
301 found:
302 return i;
303 }
304
305 GF_EXPORT
gf_bs_read_u16(GF_BitStream * bs)306 u32 gf_bs_read_u16(GF_BitStream *bs)
307 {
308 u32 ret;
309 assert(bs->nbBits == 8);
310 ret = BS_ReadByte(bs);
311 ret <<= 8;
312 ret |= BS_ReadByte(bs);
313 return ret;
314 }
315
316
317 GF_EXPORT
gf_bs_read_u24(GF_BitStream * bs)318 u32 gf_bs_read_u24(GF_BitStream *bs)
319 {
320 u32 ret;
321 assert(bs->nbBits == 8);
322 ret = BS_ReadByte(bs);
323 ret <<= 8;
324 ret |= BS_ReadByte(bs);
325 ret <<= 8;
326 ret |= BS_ReadByte(bs);
327 return ret;
328 }
329
330 GF_EXPORT
gf_bs_read_u32(GF_BitStream * bs)331 u32 gf_bs_read_u32(GF_BitStream *bs)
332 {
333 u32 ret;
334 assert(bs->nbBits == 8);
335 ret = BS_ReadByte(bs);
336 ret <<= 8;
337 ret |= BS_ReadByte(bs);
338 ret <<= 8;
339 ret |= BS_ReadByte(bs);
340 ret <<= 8;
341 ret |= BS_ReadByte(bs);
342 return ret;
343 }
344
345 GF_EXPORT
gf_bs_read_u64(GF_BitStream * bs)346 u64 gf_bs_read_u64(GF_BitStream *bs)
347 {
348 u64 ret;
349 ret = gf_bs_read_u32(bs);
350 ret <<= 32;
351 ret |= gf_bs_read_u32(bs);
352 return ret;
353 }
354
355 GF_EXPORT
gf_bs_read_long_int(GF_BitStream * bs,u32 nBits)356 u64 gf_bs_read_long_int(GF_BitStream *bs, u32 nBits)
357 {
358 u64 ret = 0;
359 if (nBits>64) {
360 gf_bs_read_long_int(bs, nBits - 64);
361 ret = gf_bs_read_long_int(bs, 64);
362 }
363 else {
364 while (nBits-- > 0) {
365 ret <<= 1;
366 ret |= gf_bs_read_bit(bs);
367 }
368 }
369 return ret;
370 }
371
372
373 GF_EXPORT
gf_bs_read_float(GF_BitStream * bs)374 Float gf_bs_read_float(GF_BitStream *bs)
375 {
376 char buf[4] = "\0\0\0";
377 #ifdef NO_OPTS
378 s32 i;
379 for (i = 0; i < 32; i++)
380 buf[3 - i / 8] |= gf_bs_read_bit(bs) << (7 - i % 8);
381 #else
382 buf[3] = gf_bs_read_int(bs, 8);
383 buf[2] = gf_bs_read_int(bs, 8);
384 buf[1] = gf_bs_read_int(bs, 8);
385 buf[0] = gf_bs_read_int(bs, 8);
386 #endif
387 return (*(Float *)buf);
388 }
389
390 GF_EXPORT
gf_bs_read_double(GF_BitStream * bs)391 Double gf_bs_read_double(GF_BitStream *bs)
392 {
393 char buf[8] = "\0\0\0\0\0\0\0";
394 s32 i;
395 for (i = 0; i < 64; i++)
396 buf[7 - i / 8] |= gf_bs_read_bit(bs) << (7 - i % 8);
397 return (*(Double *)buf);
398 }
399
400 GF_EXPORT
gf_bs_read_data(GF_BitStream * bs,char * data,u32 nbBytes)401 u32 gf_bs_read_data(GF_BitStream *bs, char *data, u32 nbBytes)
402 {
403 u64 orig = bs->position;
404
405 if (bs->position + nbBytes > bs->size) return 0;
406
407 if (BS_IsAlign(bs)) {
408 s32 bytes_read;
409 switch (bs->bsmode) {
410 case GF_BITSTREAM_READ:
411 case GF_BITSTREAM_WRITE:
412 case GF_BITSTREAM_WRITE_DYN:
413 memcpy(data, bs->original + bs->position, nbBytes);
414 bs->position += nbBytes;
415 return nbBytes;
416 case GF_BITSTREAM_FILE_READ:
417 case GF_BITSTREAM_FILE_WRITE:
418 if (bs->buffer_io)
419 bs_flush_cache(bs);
420 bytes_read = (s32)fread(data, 1, nbBytes, bs->stream);
421 if (bytes_read<0) return 0;
422 bs->position += bytes_read;
423 return bytes_read;
424 default:
425 return 0;
426 }
427 }
428
429 while (nbBytes-- > 0) {
430 *data++ = gf_bs_read_int(bs, 8);
431 }
432 return (u32)(bs->position - orig);
433
434 }
435
436
437
BS_WriteByte(GF_BitStream * bs,u8 val)438 static void BS_WriteByte(GF_BitStream *bs, u8 val)
439 {
440 /*we don't allow write on READ buffers*/
441 if ((bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) return;
442 if (!bs->original && !bs->stream) return;
443
444 /*we are in MEM mode*/
445 if ((bs->bsmode == GF_BITSTREAM_WRITE) || (bs->bsmode == GF_BITSTREAM_WRITE_DYN)) {
446 if (bs->position == bs->size) {
447 /*no more space...*/
448 if (bs->bsmode != GF_BITSTREAM_WRITE_DYN) return;
449 /*gf_realloc if enough space...*/
450 if (bs->size > 0xFFFFFFFF) return;
451 bs->original = (char*)gf_realloc(bs->original, (u32)(bs->size * 2));
452 if (!bs->original) return;
453 bs->size *= 2;
454 }
455 if (bs->original)
456 bs->original[bs->position] = val;
457 bs->position++;
458 return;
459 }
460 if (bs->buffer_io) {
461 if (bs->buffer_written == bs->buffer_io_size) {
462 bs_flush_cache(bs);
463 }
464 bs->buffer_io[bs->buffer_written] = val;
465 bs->buffer_written++;
466 if (bs->buffer_written == bs->buffer_io_size) {
467 bs_flush_cache(bs);
468 }
469 return;
470 }
471 /*we are in FILE mode, no pb for any gf_realloc...*/
472 fputc(val, bs->stream);
473 /*check we didn't rewind the stream*/
474 if (bs->size == bs->position) bs->size++;
475 bs->position += 1;
476 }
477
BS_WriteBit(GF_BitStream * bs,u32 bit)478 static void BS_WriteBit(GF_BitStream *bs, u32 bit)
479 {
480 bs->current <<= 1;
481 bs->current |= bit;
482 if (++bs->nbBits == 8) {
483 bs->nbBits = 0;
484 BS_WriteByte(bs, (u8)bs->current);
485 bs->current = 0;
486 }
487 }
488
489 GF_EXPORT
gf_bs_write_int(GF_BitStream * bs,s32 value,s32 nBits)490 void gf_bs_write_int(GF_BitStream *bs, s32 value, s32 nBits)
491 {
492 value <<= sizeof(s32) * 8 - nBits;
493 while (--nBits >= 0) {
494 BS_WriteBit(bs, value < 0);
495 value <<= 1;
496 }
497 }
498
499 GF_EXPORT
gf_bs_write_long_int(GF_BitStream * bs,s64 value,s32 nBits)500 void gf_bs_write_long_int(GF_BitStream *bs, s64 value, s32 nBits)
501 {
502 if (nBits>64) {
503 gf_bs_write_int(bs, 0, nBits - 64);
504 gf_bs_write_long_int(bs, value, 64);
505 }
506 else {
507 value <<= sizeof(s64) * 8 - nBits;
508 while (--nBits >= 0) {
509 BS_WriteBit(bs, value < 0);
510 value <<= 1;
511 }
512 }
513 }
514
515 GF_EXPORT
gf_bs_write_u8(GF_BitStream * bs,u32 value)516 void gf_bs_write_u8(GF_BitStream *bs, u32 value)
517 {
518 assert(!bs->nbBits);
519 BS_WriteByte(bs, (u8)value);
520 }
521
522 GF_EXPORT
gf_bs_write_u16(GF_BitStream * bs,u32 value)523 void gf_bs_write_u16(GF_BitStream *bs, u32 value)
524 {
525 assert(!bs->nbBits);
526 BS_WriteByte(bs, (u8)((value >> 8) & 0xff));
527 BS_WriteByte(bs, (u8)((value) & 0xff));
528 }
529
530 GF_EXPORT
gf_bs_write_u24(GF_BitStream * bs,u32 value)531 void gf_bs_write_u24(GF_BitStream *bs, u32 value)
532 {
533 assert(!bs->nbBits);
534 BS_WriteByte(bs, (u8)((value >> 16) & 0xff));
535 BS_WriteByte(bs, (u8)((value >> 8) & 0xff));
536 BS_WriteByte(bs, (u8)((value) & 0xff));
537 }
538
539 GF_EXPORT
gf_bs_write_u32(GF_BitStream * bs,u32 value)540 void gf_bs_write_u32(GF_BitStream *bs, u32 value)
541 {
542 assert(!bs->nbBits);
543 BS_WriteByte(bs, (u8)((value >> 24) & 0xff));
544 BS_WriteByte(bs, (u8)((value >> 16) & 0xff));
545 BS_WriteByte(bs, (u8)((value >> 8) & 0xff));
546 BS_WriteByte(bs, (u8)((value) & 0xff));
547 }
548
549 GF_EXPORT
gf_bs_write_u64(GF_BitStream * bs,u64 value)550 void gf_bs_write_u64(GF_BitStream *bs, u64 value)
551 {
552 assert(!bs->nbBits);
553 gf_bs_write_u32(bs, (u32)((value >> 32) & 0xffffffff));
554 gf_bs_write_u32(bs, (u32)(value & 0xffffffff));
555 }
556
557 GF_EXPORT
gf_bs_write_byte(GF_BitStream * bs,u8 byte,u32 repeat_count)558 u32 gf_bs_write_byte(GF_BitStream *bs, u8 byte, u32 repeat_count)
559 {
560 if (!BS_IsAlign(bs) || bs->buffer_io) {
561 u32 count = 0;
562 while (count<repeat_count) {
563 gf_bs_write_int(bs, byte, 8);
564 count++;
565 }
566 return count;
567 }
568
569 switch (bs->bsmode) {
570 case GF_BITSTREAM_WRITE:
571 if (bs->position + repeat_count > bs->size)
572 return 0;
573 memset(bs->original + bs->position, byte, repeat_count);
574 bs->position += repeat_count;
575 return repeat_count;
576 case GF_BITSTREAM_WRITE_DYN:
577 /*need to gf_realloc ...*/
578 if (bs->position + repeat_count> bs->size) {
579 u32 new_size = (u32)(bs->size * 2);
580 if (!new_size) new_size = BS_MEM_BLOCK_ALLOC_SIZE;
581
582 if (bs->size + repeat_count > 0xFFFFFFFF)
583 return 0;
584 while (new_size < (u32)(bs->size + repeat_count))
585 new_size *= 2;
586 bs->original = (char*)gf_realloc(bs->original, sizeof(u32)*new_size);
587 if (!bs->original)
588 return 0;
589 bs->size = new_size;
590 }
591 memset(bs->original + bs->position, byte, repeat_count);
592 bs->position += repeat_count;
593 return repeat_count;
594 case GF_BITSTREAM_FILE_READ:
595 case GF_BITSTREAM_FILE_WRITE:
596
597 if (gf_fwrite(&byte, 1, repeat_count, bs->stream) != repeat_count) return 0;
598 if (bs->size == bs->position) bs->size += repeat_count;
599 bs->position += repeat_count;
600 return repeat_count;
601 default:
602 return 0;
603 }
604 }
605
606
607
608 GF_EXPORT
gf_bs_write_float(GF_BitStream * bs,Float value)609 void gf_bs_write_float(GF_BitStream *bs, Float value)
610 {
611 u32 i;
612 union
613 {
614 float f;
615 char sz[4];
616 } float_value;
617 float_value.f = value;
618
619 for (i = 0; i < 32; i++)
620 BS_WriteBit(bs, (float_value.sz[3 - i / 8] & 1 << (7 - i % 8)) != 0);
621
622 }
623
624 GF_EXPORT
gf_bs_write_double(GF_BitStream * bs,Double value)625 void gf_bs_write_double(GF_BitStream *bs, Double value)
626 {
627 u32 i;
628 union
629 {
630 Double d;
631 char sz[8];
632 } double_value;
633 double_value.d = value;
634 for (i = 0; i < 64; i++) {
635 BS_WriteBit(bs, (double_value.sz[7 - i / 8] & 1 << (7 - i % 8)) != 0);
636 }
637 }
638
639
640 GF_EXPORT
gf_bs_write_data(GF_BitStream * bs,const char * data,u32 nbBytes)641 u32 gf_bs_write_data(GF_BitStream *bs, const char *data, u32 nbBytes)
642 {
643 /*we need some feedback for this guy...*/
644 u64 begin = bs->position;
645 if (!nbBytes) return 0;
646
647 if (BS_IsAlign(bs)) {
648 switch (bs->bsmode) {
649 case GF_BITSTREAM_WRITE:
650 if (bs->position + nbBytes > bs->size)
651 return 0;
652 memcpy(bs->original + bs->position, data, nbBytes);
653 bs->position += nbBytes;
654 return nbBytes;
655 case GF_BITSTREAM_WRITE_DYN:
656 /*need to gf_realloc ...*/
657 if (bs->position + nbBytes > bs->size) {
658 u32 new_size = (u32)(bs->size * 2);
659 if (!new_size) new_size = BS_MEM_BLOCK_ALLOC_SIZE;
660
661 if (bs->size + nbBytes > 0xFFFFFFFF)
662 return 0;
663
664 while (new_size < (u32)(bs->size + nbBytes))
665 new_size *= 2;
666 bs->original = (char*)gf_realloc(bs->original, sizeof(u32)*new_size);
667 if (!bs->original)
668 return 0;
669 bs->size = new_size;
670 }
671 memcpy(bs->original + bs->position, data, nbBytes);
672 bs->position += nbBytes;
673 return nbBytes;
674 case GF_BITSTREAM_FILE_READ:
675 case GF_BITSTREAM_FILE_WRITE:
676 if (bs->buffer_io) {
677 if (bs->buffer_written + nbBytes > bs->buffer_io_size) {
678 bs_flush_cache(bs);
679 if (nbBytes>bs->buffer_io_size) {
680 bs->buffer_io = (char*)gf_realloc(bs->buffer_io, 2 * nbBytes);
681 bs->buffer_io_size = 2 * nbBytes;
682 }
683 }
684 memcpy(bs->buffer_io + bs->buffer_written, data, nbBytes);
685 bs->buffer_written += nbBytes;
686 return nbBytes;
687 }
688 if (gf_fwrite(data, nbBytes, 1, bs->stream) != 1) return 0;
689 if (bs->size == bs->position) bs->size += nbBytes;
690 bs->position += nbBytes;
691 return nbBytes;
692 default:
693 return 0;
694 }
695 }
696
697 while (nbBytes) {
698 gf_bs_write_int(bs, (s32)*data, 8);
699 data++;
700 nbBytes--;
701 }
702 return (u32)(bs->position - begin);
703 }
704
705 /*align return the num of bits read in READ mode, 0 in WRITE*/
706 GF_EXPORT
gf_bs_align(GF_BitStream * bs)707 u8 gf_bs_align(GF_BitStream *bs)
708 {
709 u8 res = 8 - bs->nbBits;
710 if ((bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) {
711 if (res > 0) {
712 gf_bs_read_int(bs, res);
713 }
714 return res;
715 }
716 if (bs->nbBits > 0) {
717 gf_bs_write_int(bs, 0, res);
718 return res;
719 }
720 return 0;
721 }
722
723
724 /*size available in the bitstream*/
725 GF_EXPORT
gf_bs_available(GF_BitStream * bs)726 u64 gf_bs_available(GF_BitStream *bs)
727 {
728 s64 cur, end;
729
730 /*in WRITE mode only, this should not be called, but return something big in case ...*/
731 if ((bs->bsmode == GF_BITSTREAM_WRITE)
732 || (bs->bsmode == GF_BITSTREAM_WRITE_DYN)
733 )
734 return (u64)-1;
735
736 /*we are in MEM mode*/
737 if (bs->bsmode == GF_BITSTREAM_READ) {
738 if ((s64)bs->size - (s64)bs->position < 0)
739 return 0;
740 else
741 return (bs->size - bs->position);
742 }
743 /*FILE READ: assume size hasn't changed, otherwise the user shall call gf_bs_get_refreshed_size*/
744 if (bs->bsmode == GF_BITSTREAM_FILE_READ) return (bs->size - bs->position);
745
746 if (bs->buffer_io)
747 bs_flush_cache(bs);
748
749 cur = gf_ftell(bs->stream);
750 gf_fseek(bs->stream, 0, SEEK_END);
751 end = gf_ftell(bs->stream);
752 gf_fseek(bs->stream, cur, SEEK_SET);
753 return (u64)(end - cur);
754 }
755
756 /*call this funct to set the buffer size to the nb of bytes written
757 Used only in WRITE mode, as we don't know the real size during allocation...
758 return -1 for bad param or gf_malloc failed
759 return nbBytes cut*/
BS_CutBuffer(GF_BitStream * bs)760 static s32 BS_CutBuffer(GF_BitStream *bs)
761 {
762 s32 nbBytes;
763 if ((bs->bsmode != GF_BITSTREAM_WRITE_DYN) && (bs->bsmode != GF_BITSTREAM_WRITE)) return (u32)-1;
764 /*Align our buffer or we're dead!*/
765 gf_bs_align(bs);
766
767 nbBytes = (u32)(bs->size - bs->position);
768 if (!nbBytes || (nbBytes == 0xFFFFFFFF) || (bs->position >= 0xFFFFFFFF)) return 0;
769 /*
770 bs->original = (char*)gf_realloc(bs->original, (u32) bs->position);
771 if (! bs->original) return (u32) -1;
772 */
773 /*just in case, re-adjust..*/
774 bs->size = bs->position;
775 return nbBytes;
776 }
777
778 /*For DYN mode, this gets the content out*/
779 GF_EXPORT
gf_bs_get_content(GF_BitStream * bs,char ** output,u32 * outSize)780 void gf_bs_get_content(GF_BitStream *bs, char **output, u32 *outSize)
781 {
782 /*only in WRITE MEM mode*/
783 if (bs->bsmode != GF_BITSTREAM_WRITE_DYN) return;
784 if (!bs->position && !bs->nbBits) {
785 *output = NULL;
786 *outSize = 0;
787 gf_free(bs->original);
788 }
789 else {
790 s32 copy = BS_CutBuffer(bs);
791 if (copy < 0) {
792 *output = NULL;
793 }
794 else
795 *output = bs->original;
796 *outSize = (u32)bs->size;
797 }
798 bs->original = NULL;
799 bs->size = 0;
800 bs->position = 0;
801 }
802
803 /* Skip nbytes.
804 Align
805 If READ (MEM or FILE) mode, just read n times 8 bit
806 If WRITE (MEM or FILE) mode, write n times 0 on 8 bit
807 */
808 GF_EXPORT
gf_bs_skip_bytes(GF_BitStream * bs,u64 nbBytes)809 void gf_bs_skip_bytes(GF_BitStream *bs, u64 nbBytes)
810 {
811 if (!bs || !nbBytes) return;
812
813 gf_bs_align(bs);
814
815 /*special case for file skipping...*/
816 if ((bs->bsmode == GF_BITSTREAM_FILE_WRITE) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) {
817 if (bs->buffer_io)
818 bs_flush_cache(bs);
819 gf_fseek(bs->stream, nbBytes, SEEK_CUR);
820 bs->position += nbBytes;
821 return;
822 }
823
824 /*special case for reading*/
825 if (bs->bsmode == GF_BITSTREAM_READ) {
826 bs->position += nbBytes;
827 return;
828 }
829 /*for writing we must do it this way, otherwise pb in dynamic buffers*/
830 while (nbBytes) {
831 gf_bs_write_int(bs, 0, 8);
832 nbBytes--;
833 }
834 }
835
836 /*Only valid for READ MEMORY*/
837 GF_EXPORT
gf_bs_rewind_bits(GF_BitStream * bs,u64 nbBits)838 void gf_bs_rewind_bits(GF_BitStream *bs, u64 nbBits)
839 {
840 u64 nbBytes;
841 if (bs->bsmode != GF_BITSTREAM_READ) return;
842
843 nbBits -= (bs->nbBits);
844 nbBytes = (nbBits + 8) >> 3;
845 nbBits = nbBytes * 8 - nbBits;
846 gf_bs_align(bs);
847 assert(bs->position >= nbBytes);
848 bs->position -= nbBytes + 1;
849 gf_bs_read_int(bs, (u32)nbBits);
850 return;
851 }
852
853 /*seek from beginning of stream: use internally even when non aligned!*/
BS_SeekIntern(GF_BitStream * bs,u64 offset)854 static GF_Err BS_SeekIntern(GF_BitStream *bs, u64 offset)
855 {
856 u32 i;
857 /*if mem, do it */
858 if ((bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_WRITE) || (bs->bsmode == GF_BITSTREAM_WRITE_DYN)) {
859 if (offset > 0xFFFFFFFF) return GF_IO_ERR;
860 if (!bs->original) return GF_BAD_PARAM;
861 /*0 for write, read will be done automatically*/
862 if (offset >= bs->size) {
863 if ((bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_WRITE)) return GF_BAD_PARAM;
864 /*in DYN, gf_realloc ...*/
865 bs->original = (char*)gf_realloc(bs->original, (u32)(offset + 1));
866 if (!bs->original)
867 return GF_OUT_OF_MEM;
868 for (i = 0; i < (u32)(offset + 1 - bs->size); i++) {
869 bs->original[bs->size + i] = 0;
870 }
871 bs->size = offset + 1;
872 }
873 bs->current = bs->original[offset];
874 bs->position = offset;
875 bs->nbBits = (bs->bsmode == GF_BITSTREAM_READ) ? 8 : 0;
876 return GF_OK;
877 }
878
879 if (bs->buffer_io)
880 bs_flush_cache(bs);
881
882 gf_fseek(bs->stream, offset, SEEK_SET);
883
884 bs->position = offset;
885 bs->current = 0;
886 /*setup NbBits so that next acccess to the buffer will trigger read/write*/
887 bs->nbBits = (bs->bsmode == GF_BITSTREAM_FILE_READ) ? 8 : 0;
888 return GF_OK;
889 }
890
891 /*seek from beginning of stream: align before anything else*/
892 GF_EXPORT
gf_bs_seek(GF_BitStream * bs,u64 offset)893 GF_Err gf_bs_seek(GF_BitStream *bs, u64 offset)
894 {
895 /*warning: we allow offset = bs->size for WRITE buffers*/
896 if (offset > bs->size) return GF_BAD_PARAM;
897
898 gf_bs_align(bs);
899 return BS_SeekIntern(bs, offset);
900 }
901
902 /*peek bits (as int!!) from orig position (ON BYTE BOUNDARIES, from 0) - only for read ...*/
903 GF_EXPORT
gf_bs_peek_bits(GF_BitStream * bs,u32 numBits,u64 byte_offset)904 u32 gf_bs_peek_bits(GF_BitStream *bs, u32 numBits, u64 byte_offset)
905 {
906 u64 curPos;
907 u32 curBits, ret, current;
908
909 if ((bs->bsmode != GF_BITSTREAM_READ) && (bs->bsmode != GF_BITSTREAM_FILE_READ)) return 0;
910 if (!numBits || (bs->size < bs->position + byte_offset)) return 0;
911
912 /*store our state*/
913 curPos = bs->position;
914 curBits = bs->nbBits;
915 current = bs->current;
916
917 if (byte_offset) gf_bs_seek(bs, bs->position + byte_offset);
918 ret = gf_bs_read_int(bs, numBits);
919
920 /*restore our cache - position*/
921 gf_bs_seek(bs, curPos);
922 /*to avoid re-reading our bits ...*/
923 bs->nbBits = curBits;
924 bs->current = current;
925 return ret;
926 }
927
928 GF_EXPORT
gf_bs_get_refreshed_size(GF_BitStream * bs)929 u64 gf_bs_get_refreshed_size(GF_BitStream *bs)
930 {
931 s64 offset;
932
933 switch (bs->bsmode) {
934 case GF_BITSTREAM_READ:
935 case GF_BITSTREAM_WRITE:
936 return bs->size;
937
938 default:
939 if (bs->buffer_io)
940 bs_flush_cache(bs);
941 offset = gf_ftell(bs->stream);
942 gf_fseek(bs->stream, 0, SEEK_END);
943 bs->size = gf_ftell(bs->stream);
944 gf_fseek(bs->stream, offset, SEEK_SET);
945 return bs->size;
946 }
947 }
948
949 GF_EXPORT
gf_bs_get_size(GF_BitStream * bs)950 u64 gf_bs_get_size(GF_BitStream *bs)
951 {
952 if (bs->buffer_io)
953 return bs->size + bs->buffer_written;
954 return bs->size;
955 }
956
957 GF_EXPORT
gf_bs_get_position(GF_BitStream * bs)958 u64 gf_bs_get_position(GF_BitStream *bs)
959 {
960 if (bs->buffer_io)
961 return bs->position + bs->buffer_written;
962 return bs->position;
963 }
964
965 GF_EXPORT
gf_bs_bits_available(GF_BitStream * bs)966 u8 gf_bs_bits_available(GF_BitStream *bs)
967 {
968 if (bs->size > bs->position) return 8;
969 if (bs->nbBits < 8) return (8 - bs->nbBits);
970 return 0;
971 }
972
973 GF_EXPORT
gf_bs_set_eos_callback(GF_BitStream * bs,void (* EndOfStream)(void * par),void * par)974 void gf_bs_set_eos_callback(GF_BitStream *bs, void(*EndOfStream)(void *par), void *par)
975 {
976 bs->EndOfStream = EndOfStream;
977 bs->par = par;
978 }
979
980
981 GF_EXPORT
gf_bs_read_u32_le(GF_BitStream * bs)982 u32 gf_bs_read_u32_le(GF_BitStream *bs)
983 {
984 u32 ret, v;
985 ret = gf_bs_read_int(bs, 8);
986 v = gf_bs_read_int(bs, 8);
987 v <<= 8;
988 ret |= v;
989 v = gf_bs_read_int(bs, 8);
990 v <<= 16;
991 ret |= v;
992 v = gf_bs_read_int(bs, 8);
993 v <<= 24;
994 ret |= v;
995 return ret;
996 }
997
998 GF_EXPORT
gf_bs_read_u16_le(GF_BitStream * bs)999 u16 gf_bs_read_u16_le(GF_BitStream *bs)
1000 {
1001 u32 ret, v;
1002 ret = gf_bs_read_int(bs, 8);
1003 v = gf_bs_read_int(bs, 8);
1004 v <<= 8;
1005 ret |= v;
1006 return ret;
1007 }
1008
1009 GF_EXPORT
gf_bs_write_u32_le(GF_BitStream * bs,u32 val)1010 void gf_bs_write_u32_le(GF_BitStream *bs, u32 val)
1011 {
1012 gf_bs_write_int(bs, val & 0xFF, 8);
1013 gf_bs_write_int(bs, val >> 8, 8);
1014 gf_bs_write_int(bs, val >> 16, 8);
1015 gf_bs_write_int(bs, val >> 24, 8);
1016 }
1017
1018 GF_EXPORT
gf_bs_write_u16_le(GF_BitStream * bs,u32 val)1019 void gf_bs_write_u16_le(GF_BitStream *bs, u32 val)
1020 {
1021 gf_bs_write_int(bs, val & 0xFF, 8);
1022 gf_bs_write_int(bs, val >> 8, 8);
1023 }
1024
1025 GF_EXPORT
gf_bs_get_bit_offset(GF_BitStream * bs)1026 u32 gf_bs_get_bit_offset(GF_BitStream *bs)
1027 {
1028 if (bs->stream) return 0;
1029 if (bs->bsmode == GF_BITSTREAM_READ) return (u32)((bs->position - 1) * 8 + bs->nbBits);
1030 return (u32)((bs->position) * 8 + bs->nbBits);
1031 }
1032
1033 GF_EXPORT
gf_bs_get_bit_position(GF_BitStream * bs)1034 u32 gf_bs_get_bit_position(GF_BitStream *bs)
1035 {
1036 if (bs->stream) return 0;
1037 return bs->nbBits;
1038 }
1039
gf_bs_read_vluimsbf5(GF_BitStream * bs)1040 u32 gf_bs_read_vluimsbf5(GF_BitStream *bs)
1041 {
1042 u32 nb_words = 0;
1043 while (gf_bs_read_int(bs, 1)) nb_words++;
1044 nb_words++;
1045 return gf_bs_read_int(bs, 4 * nb_words);
1046 }
1047
1048 GF_EXPORT
gf_bs_truncate(GF_BitStream * bs)1049 void gf_bs_truncate(GF_BitStream *bs)
1050 {
1051 bs->size = bs->position;
1052 if (bs->stream) return;
1053 }
1054
1055
1056 GF_EXPORT
gf_bs_transfer(GF_BitStream * dst,GF_BitStream * src)1057 GF_Err gf_bs_transfer(GF_BitStream *dst, GF_BitStream *src)
1058 {
1059 char *data;
1060 u32 data_len, written;
1061
1062 data = NULL;
1063 data_len = 0;
1064 gf_bs_get_content(src, &data, &data_len);
1065 if (!data || !data_len)
1066 {
1067 if (data) {
1068 gf_free(data);
1069 return GF_IO_ERR;
1070 }
1071 return GF_OK;
1072 }
1073 written = gf_bs_write_data(dst, data, data_len);
1074 gf_free(data);
1075 if (written<data_len) return GF_IO_ERR;
1076 return GF_OK;
1077 }
1078
1079 GF_EXPORT
gf_bs_flush(GF_BitStream * bs)1080 void gf_bs_flush(GF_BitStream *bs)
1081 {
1082 if (bs->buffer_io)
1083 bs_flush_cache(bs);
1084
1085 if (!bs->stream) return;
1086
1087 if (bs->bsmode != GF_BITSTREAM_FILE_WRITE) return;
1088 fflush(bs->stream);
1089 }
1090
gf_bs_reassign(GF_BitStream * bs,FILE * stream)1091 void gf_bs_reassign(GF_BitStream *bs, FILE *stream)
1092 {
1093 if (!bs) return;
1094 switch (bs->bsmode) {
1095 case GF_BITSTREAM_FILE_WRITE:
1096 case GF_BITSTREAM_FILE_READ:
1097 bs->stream = stream;
1098 if (gf_ftell(stream) != bs->position)
1099 gf_bs_seek(bs, bs->position);
1100 break;
1101 }
1102 }
1103