comparison tremor/framing.c @ 15250:e891ff7a7b6c

update to libogg 1.1.2 (needed for Theora)
author henry
date Sun, 24 Apr 2005 08:37:48 +0000
parents 8631a3803289
children 052b4ad84883
comparison
equal deleted inserted replaced
15249:0deaa53ed5ad 15250:e891ff7a7b6c
1 /******************************************************************** 1 /********************************************************************
2 * * 2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
4 * * 7 * *
5 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
6 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 9 * by the Xiph.Org Foundation http://www.xiph.org/ *
7 * ALL REDISTRIBUTION RIGHTS RESERVED. *
8 * * 10 * *
9 ******************************************************************** 11 ********************************************************************
10 12
11 function: code raw [Vorbis] packets into framed OggSquish stream and 13 function: code raw [Vorbis] packets into framed OggSquish stream and
12 decode Ogg streams back into raw packets 14 decode Ogg streams back into raw packets
15 last mod: $Id$
13 16
14 note: The CRC code is directly derived from public domain code by 17 note: The CRC code is directly derived from public domain code by
15 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html 18 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
16 for details. 19 for details.
17 20
90 for(i=0;i<n;i++) 93 for(i=0;i<n;i++)
91 if(og->header[27+i]<255)count++; 94 if(og->header[27+i]<255)count++;
92 return(count); 95 return(count);
93 } 96 }
94 97
95 static ogg_uint32_t crc_lookup[256]={ 98
99 #if 0
100 /* helper to initialize lookup for direct-table CRC (illustrative; we
101 use the static init below) */
102
103 static ogg_uint32_t _ogg_crc_entry(unsigned long index){
104 int i;
105 unsigned long r;
106
107 r = index << 24;
108 for (i=0; i<8; i++)
109 if (r & 0x80000000UL)
110 r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
111 polynomial, although we use an
112 unreflected alg and an init/final
113 of 0, not 0xffffffff */
114 else
115 r<<=1;
116 return (r & 0xffffffffUL);
117 }
118 #endif
119
120 static const ogg_uint32_t crc_lookup[256]={
96 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9, 121 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
97 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, 122 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
98 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61, 123 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
99 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd, 124 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
100 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9, 125 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
162 187
163 int ogg_stream_init(ogg_stream_state *os,int serialno){ 188 int ogg_stream_init(ogg_stream_state *os,int serialno){
164 if(os){ 189 if(os){
165 memset(os,0,sizeof(*os)); 190 memset(os,0,sizeof(*os));
166 os->body_storage=16*1024; 191 os->body_storage=16*1024;
167 os->body_data=(unsigned char *)_ogg_malloc(os->body_storage*sizeof(*os->body_data)); 192 os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
168 193
169 os->lacing_storage=1024; 194 os->lacing_storage=1024;
170 os->lacing_vals=(int *)_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals)); 195 os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
171 os->granule_vals=(ogg_int64_t *)_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals)); 196 os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
172 197
173 os->serialno=serialno; 198 os->serialno=serialno;
174 199
175 return(0); 200 return(0);
176 } 201 }
201 what's happening fairly clear */ 226 what's happening fairly clear */
202 227
203 static void _os_body_expand(ogg_stream_state *os,int needed){ 228 static void _os_body_expand(ogg_stream_state *os,int needed){
204 if(os->body_storage<=os->body_fill+needed){ 229 if(os->body_storage<=os->body_fill+needed){
205 os->body_storage+=(needed+1024); 230 os->body_storage+=(needed+1024);
206 os->body_data=(unsigned char *)_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data)); 231 os->body_data=_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data));
207 } 232 }
208 } 233 }
209 234
210 static void _os_lacing_expand(ogg_stream_state *os,int needed){ 235 static void _os_lacing_expand(ogg_stream_state *os,int needed){
211 if(os->lacing_storage<=os->lacing_fill+needed){ 236 if(os->lacing_storage<=os->lacing_fill+needed){
212 os->lacing_storage+=(needed+32); 237 os->lacing_storage+=(needed+32);
213 os->lacing_vals=(int *)_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals)); 238 os->lacing_vals=_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals));
214 os->granule_vals=(ogg_int64_t *)_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals)); 239 os->granule_vals=_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals));
215 } 240 }
216 } 241 }
217 242
218 /* checksum the page */ 243 /* checksum the page */
219 /* Direct table CRC; note that this will be faster in the future if we 244 /* Direct table CRC; note that this will be faster in the future if we
233 for(i=0;i<og->header_len;i++) 258 for(i=0;i<og->header_len;i++)
234 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]]; 259 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
235 for(i=0;i<og->body_len;i++) 260 for(i=0;i<og->body_len;i++)
236 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]]; 261 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
237 262
238 og->header[22]=crc_reg&0xff; 263 og->header[22]=(unsigned char)(crc_reg&0xff);
239 og->header[23]=(crc_reg>>8)&0xff; 264 og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
240 og->header[24]=(crc_reg>>16)&0xff; 265 og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
241 og->header[25]=(crc_reg>>24)&0xff; 266 og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
242 } 267 }
268 }
269
270 /* submit data to the internal buffer of the framing engine */
271 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
272 int lacing_vals=op->bytes/255+1,i;
273
274 if(os->body_returned){
275 /* advance packet data according to the body_returned pointer. We
276 had to keep it around to return a pointer into the buffer last
277 call */
278
279 os->body_fill-=os->body_returned;
280 if(os->body_fill)
281 memmove(os->body_data,os->body_data+os->body_returned,
282 os->body_fill);
283 os->body_returned=0;
284 }
285
286 /* make sure we have the buffer storage */
287 _os_body_expand(os,op->bytes);
288 _os_lacing_expand(os,lacing_vals);
289
290 /* Copy in the submitted packet. Yes, the copy is a waste; this is
291 the liability of overly clean abstraction for the time being. It
292 will actually be fairly easy to eliminate the extra copy in the
293 future */
294
295 memcpy(os->body_data+os->body_fill,op->packet,op->bytes);
296 os->body_fill+=op->bytes;
297
298 /* Store lacing vals for this packet */
299 for(i=0;i<lacing_vals-1;i++){
300 os->lacing_vals[os->lacing_fill+i]=255;
301 os->granule_vals[os->lacing_fill+i]=os->granulepos;
302 }
303 os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255;
304 os->granulepos=os->granule_vals[os->lacing_fill+i]=op->granulepos;
305
306 /* flag the first segment as the beginning of the packet */
307 os->lacing_vals[os->lacing_fill]|= 0x100;
308
309 os->lacing_fill+=lacing_vals;
310
311 /* for the sake of completeness */
312 os->packetno++;
313
314 if(op->e_o_s)os->e_o_s=1;
315
316 return(0);
317 }
318
319 /* This will flush remaining packets into a page (returning nonzero),
320 even if there is not enough data to trigger a flush normally
321 (undersized page). If there are no packets or partial packets to
322 flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
323 try to flush a normal sized page like ogg_stream_pageout; a call to
324 ogg_stream_flush does not guarantee that all packets have flushed.
325 Only a return value of 0 from ogg_stream_flush indicates all packet
326 data is flushed into pages.
327
328 since ogg_stream_flush will flush the last page in a stream even if
329 it's undersized, you almost certainly want to use ogg_stream_pageout
330 (and *not* ogg_stream_flush) unless you specifically need to flush
331 an page regardless of size in the middle of a stream. */
332
333 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
334 int i;
335 int vals=0;
336 int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
337 int bytes=0;
338 long acc=0;
339 ogg_int64_t granule_pos=os->granule_vals[0];
340
341 if(maxvals==0)return(0);
342
343 /* construct a page */
344 /* decide how many segments to include */
345
346 /* If this is the initial header case, the first page must only include
347 the initial header packet */
348 if(os->b_o_s==0){ /* 'initial header page' case */
349 granule_pos=0;
350 for(vals=0;vals<maxvals;vals++){
351 if((os->lacing_vals[vals]&0x0ff)<255){
352 vals++;
353 break;
354 }
355 }
356 }else{
357 for(vals=0;vals<maxvals;vals++){
358 if(acc>4096)break;
359 acc+=os->lacing_vals[vals]&0x0ff;
360 granule_pos=os->granule_vals[vals];
361 }
362 }
363
364 /* construct the header in temp storage */
365 memcpy(os->header,"OggS",4);
366
367 /* stream structure version */
368 os->header[4]=0x00;
369
370 /* continued packet flag? */
371 os->header[5]=0x00;
372 if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
373 /* first page flag? */
374 if(os->b_o_s==0)os->header[5]|=0x02;
375 /* last page flag? */
376 if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
377 os->b_o_s=1;
378
379 /* 64 bits of PCM position */
380 for(i=6;i<14;i++){
381 os->header[i]=(unsigned char)(granule_pos&0xff);
382 granule_pos>>=8;
383 }
384
385 /* 32 bits of stream serial number */
386 {
387 long serialno=os->serialno;
388 for(i=14;i<18;i++){
389 os->header[i]=(unsigned char)(serialno&0xff);
390 serialno>>=8;
391 }
392 }
393
394 /* 32 bits of page counter (we have both counter and page header
395 because this val can roll over) */
396 if(os->pageno==-1)os->pageno=0; /* because someone called
397 stream_reset; this would be a
398 strange thing to do in an
399 encode stream, but it has
400 plausible uses */
401 {
402 long pageno=os->pageno++;
403 for(i=18;i<22;i++){
404 os->header[i]=(unsigned char)(pageno&0xff);
405 pageno>>=8;
406 }
407 }
408
409 /* zero for computation; filled in later */
410 os->header[22]=0;
411 os->header[23]=0;
412 os->header[24]=0;
413 os->header[25]=0;
414
415 /* segment table */
416 os->header[26]=(unsigned char)(vals&0xff);
417 for(i=0;i<vals;i++)
418 bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
419
420 /* set pointers in the ogg_page struct */
421 og->header=os->header;
422 og->header_len=os->header_fill=vals+27;
423 og->body=os->body_data+os->body_returned;
424 og->body_len=bytes;
425
426 /* advance the lacing data and set the body_returned pointer */
427
428 os->lacing_fill-=vals;
429 memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
430 memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
431 os->body_returned+=bytes;
432
433 /* calculate the checksum */
434
435 ogg_page_checksum_set(og);
436
437 /* done */
438 return(1);
439 }
440
441
442 /* This constructs pages from buffered packet segments. The pointers
443 returned are to static buffers; do not free. The returned buffers are
444 good only until the next call (using the same ogg_stream_state) */
445
446 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
447
448 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
449 os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */
450 os->lacing_fill>=255 || /* 'segment table full' case */
451 (os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */
452
453 return(ogg_stream_flush(os,og));
454 }
455
456 /* not enough data to construct a page and not end of stream */
457 return(0);
458 }
459
460 int ogg_stream_eos(ogg_stream_state *os){
461 return os->e_o_s;
243 } 462 }
244 463
245 /* DECODING PRIMITIVES: packet streaming layer **********************/ 464 /* DECODING PRIMITIVES: packet streaming layer **********************/
246 465
247 /* This has two layers to place more of the multi-serialno and paging 466 /* This has two layers to place more of the multi-serialno and paging
284 } 503 }
285 504
286 char *ogg_sync_buffer(ogg_sync_state *oy, long size){ 505 char *ogg_sync_buffer(ogg_sync_state *oy, long size){
287 506
288 /* first, clear out any space that has been previously returned */ 507 /* first, clear out any space that has been previously returned */
289 if(oy->returned>8192){ 508 if(oy->returned){
290 oy->fill-=oy->returned; 509 oy->fill-=oy->returned;
291 if(oy->fill>0) 510 if(oy->fill>0)
292 memmove(oy->data,oy->data+oy->returned,oy->fill); 511 memmove(oy->data,oy->data+oy->returned,oy->fill);
293 oy->returned=0; 512 oy->returned=0;
294 } 513 }
296 if(size>oy->storage-oy->fill){ 515 if(size>oy->storage-oy->fill){
297 /* We need to extend the internal buffer */ 516 /* We need to extend the internal buffer */
298 long newsize=size+oy->fill+4096; /* an extra page to be nice */ 517 long newsize=size+oy->fill+4096; /* an extra page to be nice */
299 518
300 if(oy->data) 519 if(oy->data)
301 oy->data=(unsigned char *)_ogg_realloc(oy->data,newsize); 520 oy->data=_ogg_realloc(oy->data,newsize);
302 else 521 else
303 oy->data=(unsigned char *)_ogg_malloc(newsize); 522 oy->data=_ogg_malloc(newsize);
304 oy->storage=newsize; 523 oy->storage=newsize;
305 } 524 }
306 525
307 /* expose a segment at least as large as requested at the fill mark */ 526 /* expose a segment at least as large as requested at the fill mark */
308 return((char *)oy->data+oy->fill); 527 return((char *)oy->data+oy->fill);
399 618
400 oy->headerbytes=0; 619 oy->headerbytes=0;
401 oy->bodybytes=0; 620 oy->bodybytes=0;
402 621
403 /* search for possible capture */ 622 /* search for possible capture */
404 next=(unsigned char *)memchr(page+1,'O',bytes-1); 623 next=memchr(page+1,'O',bytes-1);
405 if(!next) 624 if(!next)
406 next=oy->data+oy->fill; 625 next=oy->data+oy->fill;
407 626
408 oy->returned=next-oy->data; 627 oy->returned=next-oy->data;
409 return(-(next-page)); 628 return(-(next-page));
424 643
425 /* all we need to do is verify a page at the head of the stream 644 /* all we need to do is verify a page at the head of the stream
426 buffer. If it doesn't verify, we look for the next potential 645 buffer. If it doesn't verify, we look for the next potential
427 frame */ 646 frame */
428 647
429 while(1){ 648 for(;;){
430 long ret=ogg_sync_pageseek(oy,og); 649 long ret=ogg_sync_pageseek(oy,og);
431 if(ret>0){ 650 if(ret>0){
432 /* have a page */ 651 /* have a page */
433 return(1); 652 return(1);
434 } 653 }
470 { 689 {
471 long lr=os->lacing_returned; 690 long lr=os->lacing_returned;
472 long br=os->body_returned; 691 long br=os->body_returned;
473 692
474 /* body data */ 693 /* body data */
475 if(br>8192){ 694 if(br){
476 os->body_fill-=br; 695 os->body_fill-=br;
477 if(os->body_fill) 696 if(os->body_fill)
478 memmove(os->body_data,os->body_data+br,os->body_fill); 697 memmove(os->body_data,os->body_data+br,os->body_fill);
479 os->body_returned=0; 698 os->body_returned=0;
480 } 699 }
481 700
482 if(lr>8192){ 701 if(lr){
483 /* segment table */ 702 /* segment table */
484 if(os->lacing_fill-lr){ 703 if(os->lacing_fill-lr){
485 memmove(os->lacing_vals,os->lacing_vals+lr, 704 memmove(os->lacing_vals,os->lacing_vals+lr,
486 (os->lacing_fill-lr)*sizeof(*os->lacing_vals)); 705 (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
487 memmove(os->granule_vals,os->granule_vals+lr, 706 memmove(os->granule_vals,os->granule_vals+lr,
511 /* make a note of dropped data in segment table */ 730 /* make a note of dropped data in segment table */
512 if(os->pageno!=-1){ 731 if(os->pageno!=-1){
513 os->lacing_vals[os->lacing_fill++]=0x400; 732 os->lacing_vals[os->lacing_fill++]=0x400;
514 os->lacing_packet++; 733 os->lacing_packet++;
515 } 734 }
516 735 }
517 /* are we a 'continued packet' page? If so, we'll need to skip 736
518 some segments */ 737 /* are we a 'continued packet' page? If so, we may need to skip
519 if(continued){ 738 some segments */
739 if(continued){
740 if(os->lacing_fill<1 ||
741 os->lacing_vals[os->lacing_fill-1]==0x400){
520 bos=0; 742 bos=0;
521 for(;segptr<segments;segptr++){ 743 for(;segptr<segments;segptr++){
522 int val=header[27+segptr]; 744 int val=header[27+segptr];
523 body+=val; 745 body+=val;
524 bodysize-=val; 746 bodysize-=val;
601 os->granulepos=0; 823 os->granulepos=0;
602 824
603 return(0); 825 return(0);
604 } 826 }
605 827
828 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
829 ogg_stream_reset(os);
830 os->serialno=serialno;
831 return(0);
832 }
833
606 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){ 834 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
607 835
608 /* The last part of decode. We have the stream broken into packet 836 /* The last part of decode. We have the stream broken into packet
609 segments. Now we need to group them into packets (or return the 837 segments. Now we need to group them into packets (or return the
610 out of sync markers) */ 838 out of sync markers) */