1 
2 
3 /********************************************************************
4 *                                                                  *
5 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
6 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
7 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
8 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
9 *                                                                  *
10 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
11 * by the Xiph.Org Foundation http://www.xiph.org/                  *
12 *                                                                  *
13 ********************************************************************
14 
15 function: code raw [Vorbis] packets into framed OggSquish stream and
16 decode Ogg streams back into raw packets
17 
18 note: The CRC code is directly derived from public domain code by
19 Ross Williams (ross@guest.adelaide.edu.au).  See docs/framing.html
20 for details.
21 
22 ********************************************************************/
23 
24 
25 #include <gpac/internal/ogg.h>
26 
27 #ifndef GPAC_DISABLE_OGG
28 
29 #define BUFFER_INCREMENT 256
30 
31 static u32 mask[] =
32 { 0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
33 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
34 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
35 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
36 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
37 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
38 0x3fffffff,0x7fffffff,0xffffffff
39 };
40 
41 static u32 mask8B[] =
42 { 0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
43 
oggpack_writeinit(oggpack_buffer * b)44 void oggpack_writeinit(oggpack_buffer *b) {
45 	memset(b, 0, sizeof(*b));
46 	b->ptr = b->buffer = (unsigned char *)gf_malloc(BUFFER_INCREMENT);
47 	b->buffer[0] = '\0';
48 	b->storage = BUFFER_INCREMENT;
49 }
50 
oggpackB_writeinit(oggpack_buffer * b)51 void oggpackB_writeinit(oggpack_buffer *b) {
52 	oggpack_writeinit(b);
53 }
54 
oggpack_writetrunc(oggpack_buffer * b,s32 bits)55 void oggpack_writetrunc(oggpack_buffer *b, s32 bits) {
56 	s32 bytes = bits >> 3;
57 	bits -= bytes * 8;
58 	b->ptr = b->buffer + bytes;
59 	b->endbit = bits;
60 	b->endbyte = bytes;
61 	*b->ptr &= mask[bits];
62 }
63 
oggpackB_writetrunc(oggpack_buffer * b,s32 bits)64 void oggpackB_writetrunc(oggpack_buffer *b, s32 bits) {
65 	s32 bytes = bits >> 3;
66 	bits -= bytes * 8;
67 	b->ptr = b->buffer + bytes;
68 	b->endbit = bits;
69 	b->endbyte = bytes;
70 	*b->ptr &= mask8B[bits];
71 }
72 
73 /* Takes only up to 32 bits. */
oggpack_write(oggpack_buffer * b,u32 value,s32 bits)74 void oggpack_write(oggpack_buffer *b, u32 value, s32 bits) {
75 	if (b->endbyte + 4 >= b->storage) {
76 		b->buffer = (unsigned char *)gf_realloc(b->buffer, b->storage + BUFFER_INCREMENT);
77 		b->storage += BUFFER_INCREMENT;
78 		b->ptr = b->buffer + b->endbyte;
79 	}
80 
81 	value &= mask[bits];
82 	bits += b->endbit;
83 
84 	b->ptr[0] |= value << b->endbit;
85 
86 	if (bits >= 8) {
87 		b->ptr[1] = value >> (8 - b->endbit);
88 		if (bits >= 16) {
89 			b->ptr[2] = value >> (16 - b->endbit);
90 			if (bits >= 24) {
91 				b->ptr[3] = value >> (24 - b->endbit);
92 				if (bits >= 32) {
93 					if (b->endbit)
94 						b->ptr[4] = value >> (32 - b->endbit);
95 					else
96 						b->ptr[4] = 0;
97 				}
98 			}
99 		}
100 	}
101 
102 	b->endbyte += bits / 8;
103 	b->ptr += bits / 8;
104 	b->endbit = bits & 7;
105 }
106 
107 /* Takes only up to 32 bits. */
oggpackB_write(oggpack_buffer * b,u32 value,s32 bits)108 void oggpackB_write(oggpack_buffer *b, u32 value, s32 bits) {
109 	if (b->endbyte + 4 >= b->storage) {
110 		b->buffer = (unsigned char *)gf_realloc(b->buffer, b->storage + BUFFER_INCREMENT);
111 		b->storage += BUFFER_INCREMENT;
112 		b->ptr = b->buffer + b->endbyte;
113 	}
114 
115 	value = (value&mask[bits]) << (32 - bits);
116 	bits += b->endbit;
117 
118 	b->ptr[0] |= value >> (24 + b->endbit);
119 
120 	if (bits >= 8) {
121 		b->ptr[1] = value >> (16 + b->endbit);
122 		if (bits >= 16) {
123 			b->ptr[2] = value >> (8 + b->endbit);
124 			if (bits >= 24) {
125 				b->ptr[3] = value >> (b->endbit);
126 				if (bits >= 32) {
127 					if (b->endbit)
128 						b->ptr[4] = value << (8 - b->endbit);
129 					else
130 						b->ptr[4] = 0;
131 				}
132 			}
133 		}
134 	}
135 
136 	b->endbyte += bits / 8;
137 	b->ptr += bits / 8;
138 	b->endbit = bits & 7;
139 }
140 
oggpack_writealign(oggpack_buffer * b)141 void oggpack_writealign(oggpack_buffer *b) {
142 	s32 bits = 8 - b->endbit;
143 	if (bits<8)
144 		oggpack_write(b, 0, bits);
145 }
146 
oggpackB_writealign(oggpack_buffer * b)147 void oggpackB_writealign(oggpack_buffer *b) {
148 	s32 bits = 8 - b->endbit;
149 	if (bits<8)
150 		oggpackB_write(b, 0, bits);
151 }
152 
oggpack_writecopy_helper(oggpack_buffer * b,void * source,s32 bits,void (* w)(oggpack_buffer *,u32,s32),s32 msb)153 static void oggpack_writecopy_helper(oggpack_buffer *b,
154 	void *source,
155 	s32 bits,
156 	void(*w)(oggpack_buffer *,
157 		u32,
158 		s32),
159 	s32 msb) {
160 	unsigned char *ptr = (unsigned char *)source;
161 
162 	s32 bytes = bits / 8;
163 	bits -= bytes * 8;
164 
165 	if (b->endbit) {
166 		s32 i;
167 		/* unaligned copy.  Do it the hard way. */
168 		for (i = 0; i<bytes; i++)
169 			w(b, (u32)(ptr[i]), 8);
170 	}
171 	else {
172 		/* aligned block copy */
173 		if (b->endbyte + bytes + 1 >= b->storage) {
174 			b->storage = b->endbyte + bytes + BUFFER_INCREMENT;
175 			b->buffer = (unsigned char *)gf_realloc(b->buffer, b->storage);
176 			b->ptr = b->buffer + b->endbyte;
177 		}
178 
179 		memmove(b->ptr, source, bytes);
180 		b->ptr += bytes;
181 		b->buffer += bytes;
182 		*b->ptr = 0;
183 
184 	}
185 	if (bits) {
186 		if (msb)
187 			w(b, (u32)(ptr[bytes] >> (8 - bits)), bits);
188 		else
189 			w(b, (u32)(ptr[bytes]), bits);
190 	}
191 }
192 
oggpack_writecopy(oggpack_buffer * b,void * source,s32 bits)193 void oggpack_writecopy(oggpack_buffer *b, void *source, s32 bits) {
194 	oggpack_writecopy_helper(b, source, bits, oggpack_write, 0);
195 }
196 
oggpackB_writecopy(oggpack_buffer * b,void * source,s32 bits)197 void oggpackB_writecopy(oggpack_buffer *b, void *source, s32 bits) {
198 	oggpack_writecopy_helper(b, source, bits, oggpackB_write, 1);
199 }
200 
oggpack_reset(oggpack_buffer * b)201 void oggpack_reset(oggpack_buffer *b) {
202 	b->ptr = b->buffer;
203 	b->buffer[0] = 0;
204 	b->endbit = b->endbyte = 0;
205 }
206 
oggpackB_reset(oggpack_buffer * b)207 void oggpackB_reset(oggpack_buffer *b) {
208 	oggpack_reset(b);
209 }
210 
oggpack_writeclear(oggpack_buffer * b)211 void oggpack_writeclear(oggpack_buffer *b) {
212 	gf_free(b->buffer);
213 	memset(b, 0, sizeof(*b));
214 }
215 
oggpackB_writeclear(oggpack_buffer * b)216 void oggpackB_writeclear(oggpack_buffer *b) {
217 	oggpack_writeclear(b);
218 }
219 
oggpack_readinit(oggpack_buffer * b,unsigned char * buf,s32 bytes)220 void oggpack_readinit(oggpack_buffer *b, unsigned char *buf, s32 bytes) {
221 	memset(b, 0, sizeof(*b));
222 	b->buffer = b->ptr = buf;
223 	b->storage = bytes;
224 }
225 
oggpackB_readinit(oggpack_buffer * b,unsigned char * buf,s32 bytes)226 void oggpackB_readinit(oggpack_buffer *b, unsigned char *buf, s32 bytes) {
227 	oggpack_readinit(b, buf, bytes);
228 }
229 
230 /* Read in bits without advancing the bitptr; bits <= 32 */
oggpack_look(oggpack_buffer * b,s32 bits)231 s32 oggpack_look(oggpack_buffer *b, s32 bits) {
232 	u32 ret;
233 	u32 m = mask[bits];
234 
235 	bits += b->endbit;
236 
237 	if (b->endbyte + 4 >= b->storage) {
238 		/* not the main path */
239 		if (b->endbyte * 8 + bits>b->storage * 8)return(-1);
240 	}
241 
242 	ret = b->ptr[0] >> b->endbit;
243 	if (bits>8) {
244 		ret |= b->ptr[1] << (8 - b->endbit);
245 		if (bits>16) {
246 			ret |= b->ptr[2] << (16 - b->endbit);
247 			if (bits>24) {
248 				ret |= b->ptr[3] << (24 - b->endbit);
249 				if (bits>32 && b->endbit)
250 					ret |= b->ptr[4] << (32 - b->endbit);
251 			}
252 		}
253 	}
254 	return(m&ret);
255 }
256 
257 /* Read in bits without advancing the bitptr; bits <= 32 */
oggpackB_look(oggpack_buffer * b,s32 bits)258 s32 oggpackB_look(oggpack_buffer *b, s32 bits) {
259 	u32 ret;
260 	s32 m = 32 - bits;
261 
262 	bits += b->endbit;
263 
264 	if (b->endbyte + 4 >= b->storage) {
265 		/* not the main path */
266 		if (b->endbyte * 8 + bits>b->storage * 8)return(-1);
267 	}
268 
269 	ret = b->ptr[0] << (24 + b->endbit);
270 	if (bits>8) {
271 		ret |= b->ptr[1] << (16 + b->endbit);
272 		if (bits>16) {
273 			ret |= b->ptr[2] << (8 + b->endbit);
274 			if (bits>24) {
275 				ret |= b->ptr[3] << (b->endbit);
276 				if (bits>32 && b->endbit)
277 					ret |= b->ptr[4] >> (8 - b->endbit);
278 			}
279 		}
280 	}
281 	return (ret >> (m >> 1)) >> ((m + 1) >> 1);
282 }
283 
oggpack_look1(oggpack_buffer * b)284 s32 oggpack_look1(oggpack_buffer *b) {
285 	if (b->endbyte >= b->storage)return(-1);
286 	return((b->ptr[0] >> b->endbit) & 1);
287 }
288 
oggpackB_look1(oggpack_buffer * b)289 s32 oggpackB_look1(oggpack_buffer *b) {
290 	if (b->endbyte >= b->storage)return(-1);
291 	return((b->ptr[0] >> (7 - b->endbit)) & 1);
292 }
293 
oggpack_adv(oggpack_buffer * b,s32 bits)294 void oggpack_adv(oggpack_buffer *b, s32 bits) {
295 	bits += b->endbit;
296 	b->ptr += bits / 8;
297 	b->endbyte += bits / 8;
298 	b->endbit = bits & 7;
299 }
300 
oggpackB_adv(oggpack_buffer * b,s32 bits)301 void oggpackB_adv(oggpack_buffer *b, s32 bits) {
302 	oggpack_adv(b, bits);
303 }
304 
oggpack_adv1(oggpack_buffer * b)305 void oggpack_adv1(oggpack_buffer *b) {
306 	if (++(b->endbit)>7) {
307 		b->endbit = 0;
308 		b->ptr++;
309 		b->endbyte++;
310 	}
311 }
312 
oggpackB_adv1(oggpack_buffer * b)313 void oggpackB_adv1(oggpack_buffer *b) {
314 	oggpack_adv1(b);
315 }
316 
317 /* bits <= 32 */
oggpack_read(oggpack_buffer * b,s32 bits)318 s32 oggpack_read(oggpack_buffer *b, s32 bits) {
319 	u32 ret;
320 	u32 m = mask[bits];
321 
322 	bits += b->endbit;
323 
324 	if (b->endbyte + 4 >= b->storage) {
325 		/* not the main path */
326 		ret = (u32)(-1);
327 		if (b->endbyte * 8 + bits>b->storage * 8)goto overflow;
328 	}
329 
330 	ret = b->ptr[0] >> b->endbit;
331 	if (bits>8) {
332 		ret |= b->ptr[1] << (8 - b->endbit);
333 		if (bits>16) {
334 			ret |= b->ptr[2] << (16 - b->endbit);
335 			if (bits>24) {
336 				ret |= b->ptr[3] << (24 - b->endbit);
337 				if (bits>32 && b->endbit) {
338 					ret |= b->ptr[4] << (32 - b->endbit);
339 				}
340 			}
341 		}
342 	}
343 	ret &= m;
344 
345 overflow:
346 
347 	b->ptr += bits / 8;
348 	b->endbyte += bits / 8;
349 	b->endbit = bits & 7;
350 	return(ret);
351 }
352 
353 /* bits <= 32 */
oggpackB_read(oggpack_buffer * b,s32 bits)354 s32 oggpackB_read(oggpack_buffer *b, s32 bits) {
355 	u32 ret;
356 	s32 m = 32 - bits;
357 
358 	bits += b->endbit;
359 
360 	if (b->endbyte + 4 >= b->storage) {
361 		/* not the main path */
362 		ret = (u32)(-1);
363 		if (b->endbyte * 8 + bits>b->storage * 8)goto overflow;
364 	}
365 
366 	ret = b->ptr[0] << (24 + b->endbit);
367 	if (bits>8) {
368 		ret |= b->ptr[1] << (16 + b->endbit);
369 		if (bits>16) {
370 			ret |= b->ptr[2] << (8 + b->endbit);
371 			if (bits>24) {
372 				ret |= b->ptr[3] << (b->endbit);
373 				if (bits>32 && b->endbit)
374 					ret |= b->ptr[4] >> (8 - b->endbit);
375 			}
376 		}
377 	}
378 	ret = (ret >> (m >> 1)) >> ((m + 1) >> 1);
379 
380 overflow:
381 
382 	b->ptr += bits / 8;
383 	b->endbyte += bits / 8;
384 	b->endbit = bits & 7;
385 	return(ret);
386 }
387 
oggpack_read1(oggpack_buffer * b)388 s32 oggpack_read1(oggpack_buffer *b) {
389 	u32 ret;
390 
391 	if (b->endbyte >= b->storage) {
392 		/* not the main path */
393 		ret = (u32)(-1);
394 		goto overflow;
395 	}
396 
397 	ret = (b->ptr[0] >> b->endbit) & 1;
398 
399 overflow:
400 
401 	b->endbit++;
402 	if (b->endbit>7) {
403 		b->endbit = 0;
404 		b->ptr++;
405 		b->endbyte++;
406 	}
407 	return(ret);
408 }
409 
oggpackB_read1(oggpack_buffer * b)410 s32 oggpackB_read1(oggpack_buffer *b) {
411 	u32 ret;
412 
413 	if (b->endbyte >= b->storage) {
414 		/* not the main path */
415 		ret = (u32)(-1);
416 		goto overflow;
417 	}
418 
419 	ret = (b->ptr[0] >> (7 - b->endbit)) & 1;
420 
421 overflow:
422 
423 	b->endbit++;
424 	if (b->endbit>7) {
425 		b->endbit = 0;
426 		b->ptr++;
427 		b->endbyte++;
428 	}
429 	return(ret);
430 }
431 
oggpack_bytes(oggpack_buffer * b)432 s32 oggpack_bytes(oggpack_buffer *b) {
433 	return(b->endbyte + (b->endbit + 7) / 8);
434 }
435 
oggpack_bits(oggpack_buffer * b)436 s32 oggpack_bits(oggpack_buffer *b) {
437 	return(b->endbyte * 8 + b->endbit);
438 }
439 
oggpackB_bytes(oggpack_buffer * b)440 s32 oggpackB_bytes(oggpack_buffer *b) {
441 	return oggpack_bytes(b);
442 }
443 
oggpackB_bits(oggpack_buffer * b)444 s32 oggpackB_bits(oggpack_buffer *b) {
445 	return oggpack_bits(b);
446 }
447 
oggpack_get_buffer(oggpack_buffer * b)448 unsigned char *oggpack_get_buffer(oggpack_buffer *b) {
449 	return(b->buffer);
450 }
451 
oggpackB_get_buffer(oggpack_buffer * b)452 unsigned char *oggpackB_get_buffer(oggpack_buffer *b) {
453 	return oggpack_get_buffer(b);
454 }
455 
456 
457 #undef BUFFER_INCREMENT
458 
459 /* A complete description of Ogg framing exists in docs/framing.html */
460 
ogg_page_version(ogg_page * og)461 s32 ogg_page_version(ogg_page *og) {
462 	return((s32)(og->header[4]));
463 }
464 
ogg_page_continued(ogg_page * og)465 s32 ogg_page_continued(ogg_page *og) {
466 	return((s32)(og->header[5] & 0x01));
467 }
468 
ogg_page_bos(ogg_page * og)469 s32 ogg_page_bos(ogg_page *og) {
470 	return((s32)(og->header[5] & 0x02));
471 }
472 
ogg_page_eos(ogg_page * og)473 s32 ogg_page_eos(ogg_page *og) {
474 	return((s32)(og->header[5] & 0x04));
475 }
476 
ogg_page_granulepos(ogg_page * og)477 s64 ogg_page_granulepos(ogg_page *og) {
478 	unsigned char *page = og->header;
479 	s64 granulepos = page[13] & (0xff);
480 	granulepos = (granulepos << 8) | (page[12] & 0xff);
481 	granulepos = (granulepos << 8) | (page[11] & 0xff);
482 	granulepos = (granulepos << 8) | (page[10] & 0xff);
483 	granulepos = (granulepos << 8) | (page[9] & 0xff);
484 	granulepos = (granulepos << 8) | (page[8] & 0xff);
485 	granulepos = (granulepos << 8) | (page[7] & 0xff);
486 	granulepos = (granulepos << 8) | (page[6] & 0xff);
487 	return(granulepos);
488 }
489 
ogg_page_serialno(ogg_page * og)490 s32 ogg_page_serialno(ogg_page *og) {
491 	return(og->header[14] |
492 		(og->header[15] << 8) |
493 		(og->header[16] << 16) |
494 		(og->header[17] << 24));
495 }
496 
ogg_page_pageno(ogg_page * og)497 s32 ogg_page_pageno(ogg_page *og) {
498 	return(og->header[18] |
499 		(og->header[19] << 8) |
500 		(og->header[20] << 16) |
501 		(og->header[21] << 24));
502 }
503 
504 
505 
506 /* returns the number of packets that are completed on this page (if
507 the leading packet is begun on a previous page, but ends on this
508 page, it's counted */
509 
510 /* NOTE:
511 If a page consists of a packet begun on a previous page, and a new
512 packet begun (but not completed) on this page, the return will be:
513 ogg_page_packets(page)   ==1,
514 ogg_page_continued(page) !=0
515 
516 If a page happens to be a single packet that was begun on a
517 previous page, and spans to the next page (in the case of a three or
518 more page packet), the return will be:
519 ogg_page_packets(page)   ==0,
520 ogg_page_continued(page) !=0
521 */
522 
ogg_page_packets(ogg_page * og)523 s32 ogg_page_packets(ogg_page *og) {
524 	s32 i, n = og->header[26], count = 0;
525 	for (i = 0; i<n; i++)
526 		if (og->header[27 + i]<255)count++;
527 	return(count);
528 }
529 
530 
531 #if 0
532 /* helper to initialize lookup for direct-table CRC (illustrative; we
533 use the static init below) */
534 
535 static u32 _ogg_crc_entry(u32 index) {
536 	s32           i;
537 	u32 r;
538 
539 	r = index << 24;
540 	for (i = 0; i<8; i++)
541 		if (r & 0x80000000UL)
542 			r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
543 									   polynomial, although we use an
544 									   unreflected alg and an init/final
545 									   of 0, not 0xffffffff */
546 		else
547 			r <<= 1;
548 	return (r & 0xffffffffUL);
549 }
550 #endif
551 
552 static u32 crc_lookup[256] = {
553 	0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
554 	0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
555 	0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
556 	0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
557 	0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
558 	0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
559 	0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
560 	0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
561 	0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
562 	0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
563 	0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
564 	0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
565 	0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
566 	0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
567 	0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
568 	0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
569 	0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
570 	0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
571 	0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
572 	0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
573 	0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
574 	0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
575 	0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
576 	0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
577 	0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
578 	0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
579 	0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
580 	0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
581 	0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
582 	0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
583 	0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
584 	0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
585 	0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
586 	0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
587 	0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
588 	0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
589 	0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
590 	0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
591 	0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
592 	0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
593 	0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
594 	0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
595 	0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
596 	0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
597 	0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
598 	0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
599 	0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
600 	0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
601 	0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
602 	0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
603 	0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
604 	0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
605 	0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
606 	0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
607 	0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
608 	0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
609 	0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
610 	0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
611 	0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
612 	0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
613 	0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
614 	0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
615 	0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
616 	0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4
617 };
618 
619 /* init the encode/decode logical stream state */
620 
ogg_stream_init(ogg_stream_state * os,s32 serialno)621 s32 ogg_stream_init(ogg_stream_state *os, s32 serialno) {
622 	if (os) {
623 		memset(os, 0, sizeof(*os));
624 		os->body_storage = 16 * 1024;
625 		os->body_data = (unsigned char *)gf_malloc(os->body_storage * sizeof(*os->body_data));
626 
627 		os->lacing_storage = 1024;
628 		os->lacing_vals = (s32 *)gf_malloc(os->lacing_storage * sizeof(*os->lacing_vals));
629 		os->granule_vals = (s64*)gf_malloc(os->lacing_storage * sizeof(*os->granule_vals));
630 
631 		os->serialno = serialno;
632 
633 		return(0);
634 	}
635 	return(-1);
636 }
637 
638 /* _clear does not free os, only the non-flat storage within */
ogg_stream_clear(ogg_stream_state * os)639 s32 ogg_stream_clear(ogg_stream_state *os) {
640 	if (os) {
641 		if (os->body_data)gf_free(os->body_data);
642 		if (os->lacing_vals)gf_free(os->lacing_vals);
643 		if (os->granule_vals)gf_free(os->granule_vals);
644 
645 		memset(os, 0, sizeof(*os));
646 	}
647 	return(0);
648 }
649 
ogg_stream_destroy(ogg_stream_state * os)650 s32 ogg_stream_destroy(ogg_stream_state *os) {
651 	if (os) {
652 		ogg_stream_clear(os);
653 		gf_free(os);
654 	}
655 	return(0);
656 }
657 
658 /* Helpers for ogg_stream_encode; this keeps the structure and
659 what's happening fairly clear */
660 
_os_body_expand(ogg_stream_state * os,s32 needed)661 static void _os_body_expand(ogg_stream_state *os, s32 needed) {
662 	if (os->body_storage <= os->body_fill + needed) {
663 		os->body_storage += (needed + 1024);
664 		os->body_data = (unsigned char *)gf_realloc(os->body_data, os->body_storage * sizeof(*os->body_data));
665 	}
666 }
667 
_os_lacing_expand(ogg_stream_state * os,s32 needed)668 static void _os_lacing_expand(ogg_stream_state *os, s32 needed) {
669 	if (os->lacing_storage <= os->lacing_fill + needed) {
670 		os->lacing_storage += (needed + 32);
671 		os->lacing_vals = (s32*)gf_realloc(os->lacing_vals, os->lacing_storage * sizeof(*os->lacing_vals));
672 		os->granule_vals = (s64*)gf_realloc(os->granule_vals, os->lacing_storage * sizeof(*os->granule_vals));
673 	}
674 }
675 
676 /* checksum the page */
677 /* Direct table CRC; note that this will be faster in the future if we
678 perform the checksum silmultaneously with other copies */
679 
ogg_page_checksum_set(ogg_page * og)680 void ogg_page_checksum_set(ogg_page *og) {
681 	if (og) {
682 		u32 crc_reg = 0;
683 		s32 i;
684 
685 		/* safety; needed for API behavior, but not framing code */
686 		og->header[22] = 0;
687 		og->header[23] = 0;
688 		og->header[24] = 0;
689 		og->header[25] = 0;
690 
691 		for (i = 0; i<og->header_len; i++)
692 			crc_reg = (crc_reg << 8) ^ crc_lookup[((crc_reg >> 24) & 0xff) ^ og->header[i]];
693 		for (i = 0; i<og->body_len; i++)
694 			crc_reg = (crc_reg << 8) ^ crc_lookup[((crc_reg >> 24) & 0xff) ^ og->body[i]];
695 
696 		og->header[22] = crc_reg & 0xff;
697 		og->header[23] = (crc_reg >> 8) & 0xff;
698 		og->header[24] = (crc_reg >> 16) & 0xff;
699 		og->header[25] = (crc_reg >> 24) & 0xff;
700 	}
701 }
702 
703 /* submit data to the internal buffer of the framing engine */
ogg_stream_packetin(ogg_stream_state * os,ogg_packet * op)704 s32 ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op) {
705 	s32 lacing_vals = op->bytes / 255 + 1, i;
706 
707 	if (os->body_returned) {
708 		/* advance packet data according to the body_returned pointer. We
709 		had to keep it around to return a pointer into the buffer last
710 		call */
711 
712 		os->body_fill -= os->body_returned;
713 		if (os->body_fill)
714 			memmove(os->body_data, os->body_data + os->body_returned,
715 				os->body_fill);
716 		os->body_returned = 0;
717 	}
718 
719 	/* make sure we have the buffer storage */
720 	_os_body_expand(os, op->bytes);
721 	_os_lacing_expand(os, lacing_vals);
722 
723 	/* Copy in the submitted packet.  Yes, the copy is a waste; this is
724 	the liability of overly clean abstraction for the time being.  It
725 	will actually be fairly easy to eliminate the extra copy in the
726 	future */
727 
728 	memcpy(os->body_data + os->body_fill, op->packet, op->bytes);
729 	os->body_fill += op->bytes;
730 
731 	/* Store lacing vals for this packet */
732 	for (i = 0; i<lacing_vals - 1; i++) {
733 		os->lacing_vals[os->lacing_fill + i] = 255;
734 		os->granule_vals[os->lacing_fill + i] = os->granulepos;
735 	}
736 	os->lacing_vals[os->lacing_fill + i] = (op->bytes) % 255;
737 	os->granulepos = os->granule_vals[os->lacing_fill + i] = op->granulepos;
738 
739 	/* flag the first segment as the beginning of the packet */
740 	os->lacing_vals[os->lacing_fill] |= 0x100;
741 
742 	os->lacing_fill += lacing_vals;
743 
744 	/* for the sake of completeness */
745 	os->packetno++;
746 
747 	if (op->e_o_s)os->e_o_s = 1;
748 
749 	return(0);
750 }
751 
752 /* This will flush remaining packets into a page (returning nonzero),
753 even if there is not enough data to trigger a flush normally
754 (undersized page). If there are no packets or partial packets to
755 flush, ogg_stream_flush returns 0.  Note that ogg_stream_flush will
756 try to flush a normal sized page like ogg_stream_pageout; a call to
757 ogg_stream_flush does not guarantee that all packets have flushed.
758 Only a return value of 0 from ogg_stream_flush indicates all packet
759 data is flushed into pages.
760 
761 since ogg_stream_flush will flush the last page in a stream even if
762 it's undersized, you almost certainly want to use ogg_stream_pageout
763 (and *not* ogg_stream_flush) unless you specifically need to flush
764 an page regardless of size in the middle of a stream. */
765 
ogg_stream_flush(ogg_stream_state * os,ogg_page * og)766 s32 ogg_stream_flush(ogg_stream_state *os, ogg_page *og) {
767 	s32 i;
768 	s32 vals = 0;
769 	s32 maxvals = (os->lacing_fill>255 ? 255 : os->lacing_fill);
770 	s32 bytes = 0;
771 	s32 acc = 0;
772 	s64 granule_pos = os->granule_vals[0];
773 
774 	if (maxvals == 0)return(0);
775 
776 	/* construct a page */
777 	/* decide how many segments to include */
778 
779 	/* If this is the initial header case, the first page must only include
780 	the initial header packet */
781 	if (os->b_o_s == 0) { /* 'initial header page' case */
782 		granule_pos = 0;
783 		for (vals = 0; vals<maxvals; vals++) {
784 			if ((os->lacing_vals[vals] & 0x0ff)<255) {
785 				vals++;
786 				break;
787 			}
788 		}
789 	}
790 	else {
791 		for (vals = 0; vals<maxvals; vals++) {
792 			if (acc>4096)break;
793 			acc += os->lacing_vals[vals] & 0x0ff;
794 			granule_pos = os->granule_vals[vals];
795 		}
796 	}
797 
798 	/* construct the header in temp storage */
799 	memcpy(os->header, "OggS", 4);
800 
801 	/* stream structure version */
802 	os->header[4] = 0x00;
803 
804 	/* continued packet flag? */
805 	os->header[5] = 0x00;
806 	if ((os->lacing_vals[0] & 0x100) == 0)os->header[5] |= 0x01;
807 	/* first page flag? */
808 	if (os->b_o_s == 0)os->header[5] |= 0x02;
809 	/* last page flag? */
810 	if (os->e_o_s && os->lacing_fill == vals)os->header[5] |= 0x04;
811 	os->b_o_s = 1;
812 
813 	/* 64 bits of PCM position */
814 	for (i = 6; i<14; i++) {
815 		os->header[i] = (u8)(granule_pos & 0xff);
816 		granule_pos >>= 8;
817 	}
818 
819 	/* 32 bits of stream serial number */
820 	{
821 		s32 serialno = os->serialno;
822 		for (i = 14; i<18; i++) {
823 			os->header[i] = (serialno & 0xff);
824 			serialno >>= 8;
825 		}
826 	}
827 
828 	/* 32 bits of page counter (we have both counter and page header
829 	because this val can roll over) */
830 	if (os->pageno == -1)os->pageno = 0; /* because someone called
831 										 stream_reset; this would be a
832 										 strange thing to do in an
833 										 encode stream, but it has
834 										 plausible uses */
835 	{
836 		s32 pageno = os->pageno++;
837 		for (i = 18; i<22; i++) {
838 			os->header[i] = (pageno & 0xff);
839 			pageno >>= 8;
840 		}
841 	}
842 
843 	/* zero for computation; filled in later */
844 	os->header[22] = 0;
845 	os->header[23] = 0;
846 	os->header[24] = 0;
847 	os->header[25] = 0;
848 
849 	/* segment table */
850 	os->header[26] = vals & 0xff;
851 	for (i = 0; i<vals; i++)
852 		bytes += os->header[i + 27] = (os->lacing_vals[i] & 0xff);
853 
854 	/* set pointers in the ogg_page struct */
855 	og->header = os->header;
856 	og->header_len = os->header_fill = vals + 27;
857 	og->body = os->body_data + os->body_returned;
858 	og->body_len = bytes;
859 
860 	/* advance the lacing data and set the body_returned pointer */
861 
862 	os->lacing_fill -= vals;
863 	memmove(os->lacing_vals, os->lacing_vals + vals, os->lacing_fill * sizeof(*os->lacing_vals));
864 	memmove(os->granule_vals, os->granule_vals + vals, os->lacing_fill * sizeof(*os->granule_vals));
865 	os->body_returned += bytes;
866 
867 	/* calculate the checksum */
868 
869 	ogg_page_checksum_set(og);
870 
871 	/* done */
872 	return(1);
873 }
874 
875 
876 /* This constructs pages from buffered packet segments.  The pointers
877 returned are to static buffers; do not free. The returned buffers are
878 good only until the next call (using the same ogg_stream_state) */
879 
ogg_stream_pageout(ogg_stream_state * os,ogg_page * og)880 s32 ogg_stream_pageout(ogg_stream_state *os, ogg_page *og) {
881 
882 	if ((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
883 		os->body_fill - os->body_returned > 4096 ||/* 'page nominal size' case */
884 		os->lacing_fill >= 255 ||                  /* 'segment table full' case */
885 		(os->lacing_fill && !os->b_o_s)) {         /* 'initial header page' case */
886 
887 		return(ogg_stream_flush(os, og));
888 	}
889 
890 	/* not enough data to construct a page and not end of stream */
891 	return(0);
892 }
893 
ogg_stream_eos(ogg_stream_state * os)894 s32 ogg_stream_eos(ogg_stream_state *os) {
895 	return os->e_o_s;
896 }
897 
898 /* DECODING PRIMITIVES: packet streaming layer **********************/
899 
900 /* This has two layers to place more of the multi-serialno and paging
901 control in the application's hands.  First, we expose a data buffer
902 using ogg_sync_buffer().  The app either copies into the
903 buffer, or passes it directly to read(), etc.  We then call
904 ogg_sync_wrote() to tell how many bytes we just added.
905 
906 Pages are returned (pointers into the buffer in ogg_sync_state)
907 by ogg_sync_pageout().  The page is then submitted to
908 ogg_stream_pagein() along with the appropriate
909 ogg_stream_state* (ie, matching serialno).  We then get raw
910 packets out calling ogg_stream_packetout() with a
911 ogg_stream_state.  See the 'frame-prog.txt' docs for details and
912 example code. */
913 
914 /* initialize the struct to a known state */
ogg_sync_init(ogg_sync_state * oy)915 s32 ogg_sync_init(ogg_sync_state *oy) {
916 	if (oy) {
917 		memset(oy, 0, sizeof(*oy));
918 	}
919 	return(0);
920 }
921 
922 /* clear non-flat storage within */
ogg_sync_clear(ogg_sync_state * oy)923 s32 ogg_sync_clear(ogg_sync_state *oy) {
924 	if (oy) {
925 		if (oy->data)gf_free(oy->data);
926 		ogg_sync_init(oy);
927 	}
928 	return(0);
929 }
930 
ogg_sync_destroy(ogg_sync_state * oy)931 s32 ogg_sync_destroy(ogg_sync_state *oy) {
932 	if (oy) {
933 		ogg_sync_clear(oy);
934 		gf_free(oy);
935 	}
936 	return(0);
937 }
938 
ogg_sync_buffer(ogg_sync_state * oy,s32 size)939 char *ogg_sync_buffer(ogg_sync_state *oy, s32 size) {
940 
941 	/* first, clear out any space that has been previously returned */
942 	if (oy->returned) {
943 		oy->fill -= oy->returned;
944 		if (oy->fill>0)
945 			memmove(oy->data, oy->data + oy->returned, oy->fill);
946 		oy->returned = 0;
947 	}
948 
949 	if (size>oy->storage - oy->fill) {
950 		/* We need to extend the internal buffer */
951 		s32 newsize = size + oy->fill + 4096; /* an extra page to be nice */
952 
953 		if (oy->data)
954 			oy->data = (unsigned char *)gf_realloc(oy->data, newsize);
955 		else
956 			oy->data = (unsigned char *)gf_malloc(newsize);
957 		oy->storage = newsize;
958 	}
959 
960 	/* expose a segment at least as large as requested at the fill mark */
961 	return((char *)oy->data + oy->fill);
962 }
963 
ogg_sync_wrote(ogg_sync_state * oy,s32 bytes)964 s32 ogg_sync_wrote(ogg_sync_state *oy, s32 bytes) {
965 	if (oy->fill + bytes>oy->storage)return(-1);
966 	oy->fill += bytes;
967 	return(0);
968 }
969 
970 /* sync the stream.  This is meant to be useful for finding page
971 boundaries.
972 
973 return values for this:
974 -n) skipped n bytes
975 0) page not ready; more data (no bytes skipped)
976 n) page synced at current location; page length n bytes
977 
978 */
979 
ogg_sync_pageseek(ogg_sync_state * oy,ogg_page * og)980 s32 ogg_sync_pageseek(ogg_sync_state *oy, ogg_page *og) {
981 	unsigned char *page = oy->data + oy->returned;
982 	unsigned char *next;
983 	s32 bytes = oy->fill - oy->returned;
984 
985 	if (oy->headerbytes == 0) {
986 		s32 headerbytes, i;
987 		if (bytes<27)return(0); /* not enough for a header */
988 
989 								/* verify capture pattern */
990 		if (memcmp(page, "OggS", 4))goto sync_fail;
991 
992 		headerbytes = page[26] + 27;
993 		if (bytes<headerbytes)return(0); /* not enough for header + seg table */
994 
995 										 /* count up body length in the segment table */
996 
997 		for (i = 0; i<page[26]; i++)
998 			oy->bodybytes += page[27 + i];
999 		oy->headerbytes = headerbytes;
1000 	}
1001 
1002 	if (oy->bodybytes + oy->headerbytes>bytes)return(0);
1003 
1004 	/* The whole test page is buffered.  Verify the checksum */
1005 	{
1006 		/* Grab the checksum bytes, set the header field to zero */
1007 		char chksum[4];
1008 		ogg_page log;
1009 
1010 		memcpy(chksum, page + 22, 4);
1011 		memset(page + 22, 0, 4);
1012 
1013 		/* set up a temp page struct and recompute the checksum */
1014 		log.header = page;
1015 		log.header_len = oy->headerbytes;
1016 		log.body = page + oy->headerbytes;
1017 		log.body_len = oy->bodybytes;
1018 		ogg_page_checksum_set(&log);
1019 
1020 		/* Compare */
1021 		if (memcmp(chksum, page + 22, 4)) {
1022 			/* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
1023 			at all) */
1024 			/* replace the computed checksum with the one actually read in */
1025 			memcpy(page + 22, chksum, 4);
1026 
1027 			/* Bad checksum. Lose sync */
1028 			goto sync_fail;
1029 		}
1030 	}
1031 
1032 	/* yes, have a whole page all ready to go */
1033 	{
1034 		unsigned char *page = oy->data + oy->returned;
1035 		s32 bytes;
1036 
1037 		if (og) {
1038 			og->header = page;
1039 			og->header_len = oy->headerbytes;
1040 			og->body = page + oy->headerbytes;
1041 			og->body_len = oy->bodybytes;
1042 		}
1043 
1044 		oy->unsynced = 0;
1045 		oy->returned += (bytes = oy->headerbytes + oy->bodybytes);
1046 		oy->headerbytes = 0;
1047 		oy->bodybytes = 0;
1048 		return(bytes);
1049 	}
1050 
1051 sync_fail:
1052 
1053 	oy->headerbytes = 0;
1054 	oy->bodybytes = 0;
1055 
1056 	/* search for possible capture */
1057 	next = (unsigned char *)memchr(page + 1, 'O', bytes - 1);
1058 	if (!next)
1059 		next = oy->data + oy->fill;
1060 
1061 	oy->returned = (s32)(next - oy->data);
1062 	return (s32)(-(next - page));
1063 }
1064 
1065 /* sync the stream and get a page.  Keep trying until we find a page.
1066 Supress 'sync errors' after reporting the first.
1067 
1068 return values:
1069 -1) recapture (hole in data)
1070 0) need more data
1071 1) page returned
1072 
1073 Returns pointers into buffered data; invalidated by next call to
1074 _stream, _clear, _init, or _buffer */
1075 
ogg_sync_pageout(ogg_sync_state * oy,ogg_page * og)1076 s32 ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og) {
1077 
1078 	/* all we need to do is verify a page at the head of the stream
1079 	buffer.  If it doesn't verify, we look for the next potential
1080 	frame */
1081 
1082 	while (1) {
1083 		s32 ret = ogg_sync_pageseek(oy, og);
1084 		if (ret>0) {
1085 			/* have a page */
1086 			return(1);
1087 		}
1088 		if (ret == 0) {
1089 			/* need more data */
1090 			return(0);
1091 		}
1092 
1093 		/* head did not start a synced page... skipped some bytes */
1094 		if (!oy->unsynced) {
1095 			oy->unsynced = 1;
1096 			return(-1);
1097 		}
1098 
1099 		/* loop. keep looking */
1100 
1101 	}
1102 }
1103 
1104 /* add the incoming page to the stream state; we decompose the page
1105 into packet segments here as well. */
1106 
ogg_stream_pagein(ogg_stream_state * os,ogg_page * og)1107 s32 ogg_stream_pagein(ogg_stream_state *os, ogg_page *og) {
1108 	unsigned char *header = og->header;
1109 	unsigned char *body = og->body;
1110 	s32           bodysize = og->body_len;
1111 	s32            segptr = 0;
1112 
1113 	s32 version = ogg_page_version(og);
1114 	s32 continued = ogg_page_continued(og);
1115 	s32 bos = ogg_page_bos(og);
1116 	s32 eos = ogg_page_eos(og);
1117 	s64 granulepos = ogg_page_granulepos(og);
1118 	s32 serialno = ogg_page_serialno(og);
1119 	s32 pageno = ogg_page_pageno(og);
1120 	s32 segments = header[26];
1121 
1122 	/* clean up 'returned data' */
1123 	{
1124 		s32 lr = os->lacing_returned;
1125 		s32 br = os->body_returned;
1126 
1127 		/* body data */
1128 		if (br) {
1129 			os->body_fill -= br;
1130 			if (os->body_fill)
1131 				memmove(os->body_data, os->body_data + br, os->body_fill);
1132 			os->body_returned = 0;
1133 		}
1134 
1135 		if (lr) {
1136 			/* segment table */
1137 			if (os->lacing_fill - lr) {
1138 				memmove(os->lacing_vals, os->lacing_vals + lr,
1139 					(os->lacing_fill - lr) * sizeof(*os->lacing_vals));
1140 				memmove(os->granule_vals, os->granule_vals + lr,
1141 					(os->lacing_fill - lr) * sizeof(*os->granule_vals));
1142 			}
1143 			os->lacing_fill -= lr;
1144 			os->lacing_packet -= lr;
1145 			os->lacing_returned = 0;
1146 		}
1147 	}
1148 
1149 	/* check the serial number */
1150 	if (serialno != os->serialno)return(-1);
1151 	if (version>0)return(-1);
1152 
1153 	_os_lacing_expand(os, segments + 1);
1154 
1155 	/* are we in sequence? */
1156 	if (pageno != os->pageno) {
1157 		s32 i;
1158 
1159 		/* unroll previous partial packet (if any) */
1160 		for (i = os->lacing_packet; i<os->lacing_fill; i++)
1161 			os->body_fill -= os->lacing_vals[i] & 0xff;
1162 		os->lacing_fill = os->lacing_packet;
1163 
1164 		/* make a note of dropped data in segment table */
1165 		if (os->pageno != -1) {
1166 			os->lacing_vals[os->lacing_fill++] = 0x400;
1167 			os->lacing_packet++;
1168 		}
1169 
1170 		/* are we a 'continued packet' page?  If so, we'll need to skip
1171 		some segments */
1172 		if (continued) {
1173 			bos = 0;
1174 			for (; segptr<segments; segptr++) {
1175 				s32 val = header[27 + segptr];
1176 				body += val;
1177 				bodysize -= val;
1178 				if (val<255) {
1179 					segptr++;
1180 					break;
1181 				}
1182 			}
1183 		}
1184 	}
1185 
1186 	if (bodysize) {
1187 		_os_body_expand(os, bodysize);
1188 		memcpy(os->body_data + os->body_fill, body, bodysize);
1189 		os->body_fill += bodysize;
1190 	}
1191 
1192 	{
1193 		s32 saved = -1;
1194 		while (segptr<segments) {
1195 			s32 val = header[27 + segptr];
1196 			os->lacing_vals[os->lacing_fill] = val;
1197 			os->granule_vals[os->lacing_fill] = -1;
1198 
1199 			if (bos) {
1200 				os->lacing_vals[os->lacing_fill] |= 0x100;
1201 				bos = 0;
1202 			}
1203 
1204 			if (val<255)saved = os->lacing_fill;
1205 
1206 			os->lacing_fill++;
1207 			segptr++;
1208 
1209 			if (val<255)os->lacing_packet = os->lacing_fill;
1210 		}
1211 
1212 		/* set the granulepos on the last granuleval of the last full packet */
1213 		if (saved != -1) {
1214 			os->granule_vals[saved] = granulepos;
1215 		}
1216 
1217 	}
1218 
1219 	if (eos) {
1220 		os->e_o_s = 1;
1221 		if (os->lacing_fill>0)
1222 			os->lacing_vals[os->lacing_fill - 1] |= 0x200;
1223 	}
1224 
1225 	os->pageno = pageno + 1;
1226 
1227 	return(0);
1228 }
1229 
1230 /* clear things to an initial state.  Good to call, eg, before seeking */
ogg_sync_reset(ogg_sync_state * oy)1231 s32 ogg_sync_reset(ogg_sync_state *oy) {
1232 	oy->fill = 0;
1233 	oy->returned = 0;
1234 	oy->unsynced = 0;
1235 	oy->headerbytes = 0;
1236 	oy->bodybytes = 0;
1237 	return(0);
1238 }
1239 
ogg_stream_reset(ogg_stream_state * os)1240 s32 ogg_stream_reset(ogg_stream_state *os) {
1241 	os->body_fill = 0;
1242 	os->body_returned = 0;
1243 
1244 	os->lacing_fill = 0;
1245 	os->lacing_packet = 0;
1246 	os->lacing_returned = 0;
1247 
1248 	os->header_fill = 0;
1249 
1250 	os->e_o_s = 0;
1251 	os->b_o_s = 0;
1252 	os->pageno = -1;
1253 	os->packetno = 0;
1254 	os->granulepos = 0;
1255 
1256 	return(0);
1257 }
1258 
ogg_stream_reset_serialno(ogg_stream_state * os,s32 serialno)1259 s32 ogg_stream_reset_serialno(ogg_stream_state *os, s32 serialno) {
1260 	ogg_stream_reset(os);
1261 	os->serialno = serialno;
1262 	return(0);
1263 }
1264 
_packetout(ogg_stream_state * os,ogg_packet * op,s32 adv)1265 static s32 _packetout(ogg_stream_state *os, ogg_packet *op, s32 adv) {
1266 
1267 	/* The last part of decode. We have the stream broken into packet
1268 	segments.  Now we need to group them into packets (or return the
1269 	out of sync markers) */
1270 
1271 	s32 ptr = os->lacing_returned;
1272 
1273 	if (os->lacing_packet <= ptr)return(0);
1274 
1275 	if (os->lacing_vals[ptr] & 0x400) {
1276 		/* we need to tell the codec there's a gap; it might need to
1277 		handle previous packet dependencies. */
1278 		os->lacing_returned++;
1279 		os->packetno++;
1280 		return(-1);
1281 	}
1282 
1283 	if (!op && !adv)return(1); /* just using peek as an inexpensive way
1284 							   to ask if there's a whole packet
1285 							   waiting */
1286 
1287 							   /* Gather the whole packet. We'll have no holes or a partial packet */
1288 	{
1289 		s32 size = os->lacing_vals[ptr] & 0xff;
1290 		s32 bytes = size;
1291 		s32 eos = os->lacing_vals[ptr] & 0x200; /* last packet of the stream? */
1292 		s32 bos = os->lacing_vals[ptr] & 0x100; /* first packet of the stream? */
1293 
1294 		while (size == 255) {
1295 			s32 val = os->lacing_vals[++ptr];
1296 			size = val & 0xff;
1297 			if (val & 0x200)eos = 0x200;
1298 			bytes += size;
1299 		}
1300 
1301 		if (op) {
1302 			op->e_o_s = eos;
1303 			op->b_o_s = bos;
1304 			op->packet = os->body_data + os->body_returned;
1305 			op->packetno = os->packetno;
1306 			op->granulepos = os->granule_vals[ptr];
1307 			op->bytes = bytes;
1308 		}
1309 
1310 		if (adv) {
1311 			os->body_returned += bytes;
1312 			os->lacing_returned = ptr + 1;
1313 			os->packetno++;
1314 		}
1315 	}
1316 	return(1);
1317 }
1318 
ogg_stream_packetout(ogg_stream_state * os,ogg_packet * op)1319 s32 ogg_stream_packetout(ogg_stream_state *os, ogg_packet *op) {
1320 	return _packetout(os, op, 1);
1321 }
1322 
ogg_stream_packetpeek(ogg_stream_state * os,ogg_packet * op)1323 s32 ogg_stream_packetpeek(ogg_stream_state *os, ogg_packet *op) {
1324 	return _packetout(os, op, 0);
1325 }
1326 
ogg_packet_clear(ogg_packet * op)1327 void ogg_packet_clear(ogg_packet *op) {
1328 	gf_free(op->packet);
1329 	memset(op, 0, sizeof(*op));
1330 }
1331 
1332 #endif /*GPAC_DISABLE_OGG*/
1333