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