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