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