1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS DISTRIBUTING. *
8 * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999 *
9 * by 1999 Monty <monty@xiph.org> and the XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 function: code raw Vorbis packets into framed vorbis stream and
15 decode vorbis streams back into raw packets
16 author: Monty <xiphmont@mit.edu>
17 modifications by: Monty
18 last modification date: Jul 13 1999
20 note: The CRC code is directly derived from public domain code by
21 Ross Williams (ross@guest.adelaide.edu.au). See framing.txt for
24 ********************************************************************/
30 /* A complete description of Vorbis framing exists in docs/framing.txt */
32 int vorbis_page_version(vorbis_page *vg){
33 return((int)(vg->header[4]));
36 int vorbis_page_continued(vorbis_page *vg){
37 return((int)(vg->header[5]&0x01));
40 int vorbis_page_bos(vorbis_page *vg){
41 return((int)(vg->header[5]&0x02));
44 int vorbis_page_eos(vorbis_page *vg){
45 return((int)(vg->header[5]&0x04));
48 size64 vorbis_page_pcmpos(vorbis_page *vg){
49 char *page=vg->header;
50 size64 pcmpos=page[13];
51 pcmpos= (pcmpos<<8)|page[12];
52 pcmpos= (pcmpos<<8)|page[11];
53 pcmpos= (pcmpos<<8)|page[10];
54 pcmpos= (pcmpos<<8)|page[9];
55 pcmpos= (pcmpos<<8)|page[8];
56 pcmpos= (pcmpos<<8)|page[7];
57 pcmpos= (pcmpos<<8)|page[6];
61 int vorbis_page_serialno(vorbis_page *vg){
62 return(vg->header[14] |
64 (vg->header[16]<<16) |
65 (vg->header[17]<<24));
68 int vorbis_page_pageno(vorbis_page *vg){
69 return(vg->header[18] |
71 (vg->header[20]<<16) |
72 (vg->header[21]<<24));
75 /* helper to initialize lookup for direct-table CRC */
77 static unsigned size32 crc_lookup[256];
78 static int crc_ready=0;
80 static unsigned size32 _vorbis_crc_entry(unsigned long index){
87 r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
88 polynomial, although we use an
89 unreflected alg and an init/final
90 of 0, not 0xffffffff */
93 return (r & 0xffffffffUL);
96 /* mind this in threaded code; sync_init and stream_init call it.
97 It's thread safe only after the first time it returns */
99 static void _vorbis_crc_init(void){
101 /* initialize the crc_lookup table */
104 crc_lookup[i]=_vorbis_crc_entry((unsigned long)i);
109 /* init the encode/decode logical stream state */
111 int vorbis_stream_init(vorbis_stream_state *vs,int serialno){
113 memset(vs,0,sizeof(vorbis_stream_state));
114 vs->body_storage=16*1024;
115 vs->body_data=malloc(vs->body_storage*sizeof(char));
117 vs->lacing_storage=1024;
118 vs->lacing_vals=malloc(vs->lacing_storage*sizeof(int));
119 vs->pcm_vals=malloc(vs->lacing_storage*sizeof(size64));
121 /* initialize the crc_lookup table if not done */
124 vs->serialno=serialno;
131 /* _clear does not free vs, only the non-flat storage within */
132 int vorbis_stream_clear(vorbis_stream_state *vs){
134 if(vs->body_data)free(vs->body_data);
135 if(vs->lacing_vals)free(vs->lacing_vals);
136 if(vs->pcm_vals)free(vs->pcm_vals);
138 memset(vs,0,sizeof(vorbis_stream_state));
143 int vorbis_stream_destroy(vorbis_stream_state *vs){
145 vorbis_stream_clear(vs);
151 /* Helpers for vorbis_stream_encode; this keeps the structure and
152 what's happening fairly clear */
154 static void _vs_body_expand(vorbis_stream_state *vs,int needed){
155 if(vs->body_storage<=vs->body_fill+needed){
156 vs->body_storage+=(needed+1024);
157 vs->body_data=realloc(vs->body_data,vs->body_storage);
161 static void _vs_lacing_expand(vorbis_stream_state *vs,int needed){
162 if(vs->lacing_storage<=vs->lacing_fill+needed){
163 vs->lacing_storage+=(needed+32);
164 vs->lacing_vals=realloc(vs->lacing_vals,vs->lacing_storage*sizeof(int));
165 vs->pcm_vals=realloc(vs->pcm_vals,vs->lacing_storage*sizeof(size64));
169 /* checksum the page */
170 /* Direct table CRC; note that this will be faster in the future if we
171 perform the checksum silmultaneously with other copies */
173 static void _vs_checksum(vorbis_page *vg){
174 unsigned size32 crc_reg=0;
177 for(i=0;i<vg->header_len;i++)
178 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^vg->header[i]];
179 for(i=0;i<vg->body_len;i++)
180 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^vg->body[i]];
182 vg->header[22]=crc_reg&0xff;
183 vg->header[23]=(crc_reg>>8)&0xff;
184 vg->header[24]=(crc_reg>>16)&0xff;
185 vg->header[25]=(crc_reg>>24)&0xff;
188 /* submit data to the internal buffer of the framing engine */
189 int vorbis_stream_encode(vorbis_stream_state *vs,vorbis_packet *vp){
190 int lacing_vals=vp->bytes/255+1,i;
192 /* make sure we have the buffer storage */
193 _vs_body_expand(vs,vp->bytes);
194 _vs_lacing_expand(vs,lacing_vals);
196 /* Copy in the submitted packet. Yes, the copy is a waste; this is
197 the liability of overly clean abstraction for the time being. It
198 will actually be fairly easy to eliminate the extra copy in the
201 memcpy(vs->body_data+vs->body_fill,vp->packet,vp->bytes);
202 vs->body_fill+=vp->bytes;
204 /* Store lacing vals for this packet */
205 for(i=0;i<lacing_vals-1;i++){
206 vs->lacing_vals[vs->lacing_fill+i]=255;
207 vs->pcm_vals[vs->lacing_fill+i]=vp->pcm_pos;
209 vs->lacing_vals[vs->lacing_fill+i]=(vp->bytes)%255;
210 vs->pcm_vals[vs->lacing_fill+i]=vp->pcm_pos;
212 /* flag the first segment as the beginning of the packet */
213 vs->lacing_vals[vs->lacing_fill]|= 0x100;
215 vs->lacing_fill+=lacing_vals;
217 if(vp->e_o_s)vs->e_o_s=1;
222 /* This constructs pages from buffered packet segments. The pointers
223 returned are to static buffers; do not free. The returned buffers are
224 good only until the next call (using the same vs) */
226 int vorbis_stream_page(vorbis_stream_state *vs, vorbis_page *vg){
229 if(vs->body_returned){
230 /* advance packet data according to the body_returned pointer. We
231 had to keep it around to return a pointer into the buffer last
234 vs->body_fill-=vs->body_returned;
235 memmove(vs->body_data,vs->body_data+vs->body_returned,
236 (vs->body_fill-vs->body_returned)*sizeof(char));
240 if((vs->e_o_s&&vs->lacing_fill) ||
241 vs->body_fill > 4096 ||
242 vs->lacing_fill>=255){
244 int maxvals=(vs->lacing_fill>255?255:vs->lacing_fill);
246 size64 pcm_pos=vs->pcm_vals[0];
248 /* construct a page */
249 /* decide how many segments to include */
250 for(vals=0;vals<maxvals;vals++){
252 acc+=vs->lacing_vals[vals]&0x0ff;
253 if((vs->lacing_vals[vals]&0x0ff)<255)pcm_pos=vs->pcm_vals[vals];
256 /* construct the header in temp storage */
257 memcpy(vs->header,"OggS",4);
259 /* stream structure version */
264 /* continued packet flag? */
265 if((vs->lacing_vals[0]&0x100)==0)vs->header[5]|=0x01;
266 /* first page flag? */
267 if(vs->b_o_s==0)vs->header[5]|=0x02;
268 /* last page flag? */
269 if(vs->e_o_s && vs->lacing_fill==vals)vs->header[5]|=0x04;
272 /* 64 bits of PCM position */
274 vs->header[i]=(pcm_pos&0xff);
278 /* 32 bits of stream serial number */
280 long serialno=vs->serialno;
282 vs->header[i]=(serialno&0xff);
287 /* 32 bits of page counter (we have both counter and page header
288 because this val can roll over) */
290 long pageno=vs->pageno++;
292 vs->header[i]=(pageno&0xff);
297 /* zero for computation; filled in later */
304 vs->header[26]=vals&0xff;
306 bytes+=vs->header[i+27]=(vs->lacing_vals[i]&0xff);
308 /* advance the lacing data and set the body_returned pointer */
310 vs->lacing_fill-=vals;
311 memmove(vs->lacing_vals,vs->lacing_vals+vals,vs->lacing_fill*sizeof(int));
312 memmove(vs->pcm_vals,vs->pcm_vals+vals,vs->lacing_fill*sizeof(size64));
313 vs->body_returned=bytes;
315 /* set pointers in the vorbis_page struct */
316 vg->header=vs->header;
317 vg->header_len=vs->header_fill=vals+27;
318 vg->body=vs->body_data;
321 /* calculate the checksum */
328 /* not enough data to construct a page and not end of stream */
332 int vorbis_stream_eof(vorbis_stream_state *vs){
336 /* DECODING PRIMITIVES: packet streaming layer **********************/
338 /* This has two layers to place more of the multi-serialno and paging
339 control in the application's hands. First, we expose a data buffer
340 using vorbis_decode_buffer(). The app either copies into the
341 buffer, or passes it directly to read(), etc. We then call
342 vorbis_decode_wrote() to tell how many bytes we just added.
344 Pages are returned (pointers into the buffer in vorbis_sync_state)
345 by vorbis_decode_stream(). The page is then submitted to
346 vorbis_decode_page() along with the appropriate
347 vorbis_stream_state* (ie, matching serialno). We then get raw
348 packets out calling vorbis_stream_packet() with a
349 vorbis_stream_state. See the 'frame-prog.txt' docs for details and
352 /* initialize the struct to a known state */
353 int vorbis_sync_init(vorbis_sync_state *vs){
355 memset(vs,0,sizeof(vorbis_sync_state));
361 /* clear non-flat storage within */
362 int vorbis_sync_clear(vorbis_sync_state *vs){
364 if(vs->data)free(vs->data);
365 vorbis_sync_init(vs);
370 char *vorbis_decode_buffer(vorbis_sync_state *vs, long size){
372 /* first, clear out any space that has been previously returned */
374 vs->fill-=vs->returned;
375 if(vs->fill-vs->returned>0)
376 memmove(vs->data,vs->data+vs->returned,
377 (vs->fill-vs->returned)*sizeof(char));
381 if(size>vs->storage-vs->fill){
382 /* We need to extend the internal buffer */
383 long newsize=size+vs->fill+4096; /* an extra page to be nice */
386 vs->data=realloc(vs->data,newsize);
388 vs->data=malloc(newsize);
392 /* expose a segment at least as large as requested at the fill mark */
393 return(vs->data+vs->fill);
396 int vorbis_decode_wrote(vorbis_sync_state *vs, long bytes){
397 if(vs->fill+bytes>vs->storage)return(-1);
402 /* sync the stream. If we had to recapture, return -1. If we
403 couldn't capture at all, return 0. If a page was already framed
404 and ready to go, return 1 and fill in the page struct.
406 Returns pointers into buffered data; invalidated by next call to
407 _stream, _clear, _init, or _buffer */
409 int vorbis_decode_stream(vorbis_sync_state *vs, vorbis_page *vg){
411 /* all we need to do is verify a page at the head of the stream
412 buffer. If it doesn't verify, we look for the next potential
416 char *page=vs->data+vs->returned;
417 long bytes=vs->fill-vs->returned;
419 if(vs->headerbytes==0){
421 if(bytes<27)return(0); /* not enough for a header */
423 /* verify capture pattern */
424 if(memcmp(page,"OggS",4))goto sync_fail;
426 headerbytes=page[26]+27;
427 if(bytes<headerbytes)return(0); /* not enough for header + seg table */
429 /* count up body length in the segment table */
431 for(i=0;i<page[26];i++)
432 vs->bodybytes+=page[27+i];
433 vs->headerbytes=headerbytes;
436 if(vs->bodybytes+vs->headerbytes>bytes)return(0);
438 /* The whole test page is buffered. Verify the checksum */
440 /* Grab the checksum bytes, set the header field to zero */
444 memcpy(chksum,page+22,4);
447 /* set up a temp page struct and recompute the checksum */
449 lvg.header_len=vs->headerbytes;
450 lvg.body=page+vs->headerbytes;
451 lvg.body_len=vs->bodybytes;
455 if(memcmp(chksum,page+22,4)){
456 /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
458 /* replace the computed checksum with the one actually read in */
459 memcpy(page+22,chksum,4);
461 /* Bad checksum. Lose sync */
467 vg->header_len=vs->headerbytes;
468 vg->body=page+vs->headerbytes;
469 vg->body_len=vs->bodybytes;
472 vs->returned+=vs->headerbytes+vs->bodybytes;
483 /* search for possible capture */
485 page=memchr(page+1,'O',bytes-1);
487 vs->returned=page-vs->data;
489 vs->returned=vs->fill;
496 /* loop; verifier above will take care of determining capture or not */
501 /* add the incoming page to the stream state; we decompose the page
502 into packet segments here as well. */
504 int vorbis_decode_page(vorbis_stream_state *vs, vorbis_page *vg){
505 unsigned char *header=vg->header;
506 unsigned char *body=vg->body;
507 long bodysize=vg->body_len;
510 int version=vorbis_page_version(vg);
511 int continued=vorbis_page_continued(vg);
512 int bos=vorbis_page_bos(vg);
513 int eos=vorbis_page_eos(vg);
514 size64 pcmpos=vorbis_page_pcmpos(vg);
515 int serialno=vorbis_page_serialno(vg);
516 int pageno=vorbis_page_pageno(vg);
517 int segments=header[26];
519 /* clean up 'returned data' */
521 long lr=vs->lacing_returned;
522 long br=vs->body_returned;
526 memmove(vs->body_data,vs->body_data+br,vs->body_fill-br);
531 if(vs->lacing_fill-lr){
532 memmove(vs->lacing_vals,vs->lacing_vals+lr,
533 (vs->lacing_fill-lr)*sizeof(int));
534 memmove(vs->pcm_vals,vs->pcm_vals+lr,
535 (vs->lacing_fill-lr)*sizeof(size64));
538 vs->lacing_packet-=lr;
539 vs->lacing_returned=0;
542 /* check the serial number */
543 if(serialno!=vs->serialno)return(-1);
544 if(version>0)return(-1);
546 _vs_lacing_expand(vs,segments+1);
548 /* are we in sequence? */
549 if(pageno!=vs->pageno){
552 /* unroll previous partial packet (if any) */
553 for(i=vs->lacing_packet;i<vs->lacing_fill;i++)
554 vs->body_fill-=vs->lacing_vals[i]&0xff;
555 vs->lacing_fill=vs->lacing_packet;
557 /* make a note of dropped data in segment table */
558 vs->lacing_vals[vs->lacing_fill++]=0x400;
561 /* are we a 'continued packet' page? If so, we'll need to skip
565 for(;segptr<segments;segptr++){
566 int val=header[27+segptr];
578 _vs_body_expand(vs,bodysize);
579 memcpy(vs->body_data+vs->body_fill,body,bodysize);
580 vs->body_fill+=bodysize;
583 while(segptr<segments){
584 int val=header[27+segptr];
585 vs->lacing_vals[vs->lacing_fill]=val;
586 vs->pcm_vals[vs->lacing_fill]=pcmpos;
589 vs->lacing_vals[vs->lacing_fill]|=0x100;
596 if(val<255)vs->lacing_packet=vs->lacing_fill;
600 if(vs->lacing_fill>0)
601 vs->lacing_vals[vs->lacing_fill-1]|=0x200;
609 /* clear things to an initial state. Good to call, eg, before seeking */
610 int vorbis_sync_reset(vorbis_sync_state *vs){
619 int vorbis_stream_reset(vorbis_stream_state *vs){
625 vs->lacing_returned=0;
637 int vorbis_stream_packet(vorbis_stream_state *vs,vorbis_packet *vp){
639 /* The last part of decode. We have the stream broken into packet
640 segments. Now we need to group them into packets (or return the
641 out of sync markers) */
643 int ptr=vs->lacing_returned;
645 if(vs->lacing_packet<=ptr)return(0);
646 if(vs->lacing_vals[ptr]&=0x400){
647 /* We lost sync here; let the app know */
648 vs->lacing_returned++;
652 /* Gather the whole packet. We'll have no holes or a partial packet */
654 int size=vs->lacing_vals[ptr]&0xff;
657 vp->packet=vs->body_data+vs->body_returned;
658 vp->e_o_s=vs->lacing_vals[ptr]&0x200; /* last packet of the stream? */
659 vp->b_o_s=vs->lacing_vals[ptr]&0x100; /* first packet of the stream? */
663 int val=vs->lacing_vals[++ptr];
665 if(val&0x200)vp->e_o_s=0x200;
668 vp->pcm_pos=vs->pcm_vals[ptr];
671 vs->body_returned+=bytes;
672 vs->lacing_returned=ptr+1;
680 void test_pack(vorbis_stream_state *vs,int *pl, int **headers){
681 unsigned char *data=malloc(1024*1024); /* for scripted test cases only */
685 int i,j,packets,pageno=0;
687 for(packets=0;;packets++)if(pl[packets]==-1)break;
689 for(i=0;i<packets;i++){
690 /* construct a test packet */
694 vp.packet=data+inptr;
696 vp.e_o_s=(pl[i+1]<0?1:0);
701 for(j=0;j<len;j++)data[inptr++]=i+j;
703 /* submit the test packet */
704 vorbis_stream_encode(vs,&vp);
706 /* retrieve any finished pages */
710 while(vorbis_stream_page(vs,&vg)){
711 /* We have a page. Check it carefully */
713 fprintf(stderr,"%d, ",pageno);
715 if(headers[pageno]==NULL){
716 fprintf(stderr,"coded too many pages!\n");
721 for(j=0;j<vg.body_len;j++)
722 if(vg.body[j]!=(data+outptr)[j]){
723 fprintf(stderr,"body data mismatch at pos %ld: %x!=%x!\n\n",
724 outptr+j,(data+outptr)[j],vg.body[j]);
730 for(j=0;j<vg.header_len;j++){
731 if(vg.header[j]!=headers[pageno][j]){
732 fprintf(stderr,"header content mismatch at pos %ld:\n",j);
733 for(j=0;j<headers[pageno][26]+27;j++)
734 fprintf(stderr," (%d)%02x:%02x",j,headers[pageno][j],vg.header[j]);
735 fprintf(stderr,"\n");
739 if(vg.header_len!=headers[pageno][26]+27){
740 fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
741 vg.header_len,headers[pageno][26]+27);
749 if(headers[pageno]!=NULL){
750 fprintf(stderr,"did not write last page!\n");
754 fprintf(stderr,"packet data incomplete!\n");
757 fprintf(stderr,"ok.\n");
761 vorbis_stream_state vs;
763 /* Exercise each code path in the framing code. Also verify that
764 the checksums are working. */
767 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
768 int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
769 int head1[] = {0x4f,0x67,0x67,0x53,0,0,
770 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
771 0x01,0x02,0x03,0x04,0,0,0,0,
774 17,254,255,0,255,1,255,245,255,255,0,
776 int *headret[]={head1,NULL};
778 vorbis_stream_init(&vs,0x04030201);
779 fprintf(stderr,"testing basic page encoding... ");
780 test_pack(&vs,packets,headret);
781 vorbis_stream_clear(&vs);
785 /* nil packets; beginning,middle,end */
786 int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
788 int head1[] = {0x4f,0x67,0x67,0x53,0,0,
789 0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
790 0x01,0x02,0x03,0x04,0,0,0,0,
793 0,17,254,255,0,0,255,1,0,255,245,255,255,0,
795 int *headret[]={head1,NULL};
797 vorbis_stream_init(&vs,0x04030201);
798 fprintf(stderr,"testing basic nil packets... ");
799 test_pack(&vs,packets,headret);
800 vorbis_stream_clear(&vs);
804 /* starting new page with first segment */
805 int packets[]={4345,259,255,-1};
807 int head1[] = {0x4f,0x67,0x67,0x53,0,0,
808 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
809 0x01,0x02,0x03,0x04,0,0,0,0,
812 255,255,255,255,255,255,255,255,
813 255,255,255,255,255,255,255,255,255};
815 int head2[] = {0x4f,0x67,0x67,0x53,0,0x02,
816 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
817 0x01,0x02,0x03,0x04,1,0,0,0,
821 int *headret[]={head1,head2,NULL};
823 vorbis_stream_init(&vs,0x04030201);
824 fprintf(stderr,"testing single-packet page span... ");
825 test_pack(&vs,packets,headret);
826 vorbis_stream_clear(&vs);
830 /* starting new page with first segment */
831 int packets[]={100,4345,259,255,-1};
833 int head1[] = {0x4f,0x67,0x67,0x53,0,0x00,
834 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
835 0x01,0x02,0x03,0x04,0,0,0,0,
838 100,255,255,255,255,255,255,255,255,
839 255,255,255,255,255,255,255,255};
841 int head2[] = {0x4f,0x67,0x67,0x53,0,0x02,
842 0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
843 0x01,0x02,0x03,0x04,1,0,0,0,
847 int *headret[]={head1,head2,NULL};
849 vorbis_stream_init(&vs,0x04030201);
850 fprintf(stderr,"testing multi-packet page span... ");
851 test_pack(&vs,packets,headret);
852 vorbis_stream_clear(&vs);
856 /* page with the 255 segment limit */
859 int packets[]={10,10,10,10,10,10,10,10,
860 10,10,10,10,10,10,10,10,
861 10,10,10,10,10,10,10,10,
862 10,10,10,10,10,10,10,10,
863 10,10,10,10,10,10,10,10,
864 10,10,10,10,10,10,10,10,
865 10,10,10,10,10,10,10,10,
866 10,10,10,10,10,10,10,10,
867 10,10,10,10,10,10,10,10,
868 10,10,10,10,10,10,10,10,
869 10,10,10,10,10,10,10,10,
870 10,10,10,10,10,10,10,10,
871 10,10,10,10,10,10,10,10,
872 10,10,10,10,10,10,10,10,
873 10,10,10,10,10,10,10,10,
874 10,10,10,10,10,10,10,10,
875 10,10,10,10,10,10,10,10,
876 10,10,10,10,10,10,10,10,
877 10,10,10,10,10,10,10,10,
878 10,10,10,10,10,10,10,10,
879 10,10,10,10,10,10,10,10,
880 10,10,10,10,10,10,10,10,
881 10,10,10,10,10,10,10,10,
882 10,10,10,10,10,10,10,10,
883 10,10,10,10,10,10,10,10,
884 10,10,10,10,10,10,10,10,
885 10,10,10,10,10,10,10,10,
886 10,10,10,10,10,10,10,10,
887 10,10,10,10,10,10,10,10,
888 10,10,10,10,10,10,10,10,
889 10,10,10,10,10,10,10,10,
890 10,10,10,10,10,10,10,50,-1};
892 int head1[] = {0x4f,0x67,0x67,0x53,0,0x00,
893 0x00,0xf8,0x03,0x00,0x00,0x00,0x00,0x00,
894 0x01,0x02,0x03,0x04,0,0,0,0,
897 10,10,10,10,10,10,10,10,
898 10,10,10,10,10,10,10,10,
899 10,10,10,10,10,10,10,10,
900 10,10,10,10,10,10,10,10,
901 10,10,10,10,10,10,10,10,
902 10,10,10,10,10,10,10,10,
903 10,10,10,10,10,10,10,10,
904 10,10,10,10,10,10,10,10,
905 10,10,10,10,10,10,10,10,
906 10,10,10,10,10,10,10,10,
907 10,10,10,10,10,10,10,10,
908 10,10,10,10,10,10,10,10,
909 10,10,10,10,10,10,10,10,
910 10,10,10,10,10,10,10,10,
911 10,10,10,10,10,10,10,10,
912 10,10,10,10,10,10,10,10,
913 10,10,10,10,10,10,10,10,
914 10,10,10,10,10,10,10,10,
915 10,10,10,10,10,10,10,10,
916 10,10,10,10,10,10,10,10,
917 10,10,10,10,10,10,10,10,
918 10,10,10,10,10,10,10,10,
919 10,10,10,10,10,10,10,10,
920 10,10,10,10,10,10,10,10,
921 10,10,10,10,10,10,10,10,
922 10,10,10,10,10,10,10,10,
923 10,10,10,10,10,10,10,10,
924 10,10,10,10,10,10,10,10,
925 10,10,10,10,10,10,10,10,
926 10,10,10,10,10,10,10,10,
927 10,10,10,10,10,10,10,10,
928 10,10,10,10,10,10,10};
930 int head2[] = {0x4f,0x67,0x67,0x53,0,0x01,
931 0x00,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
932 0x01,0x02,0x03,0x04,1,0,0,0,
936 int *headret[]={head1,head2,NULL};
938 vorbis_stream_init(&vs,0x04030201);
939 fprintf(stderr,"testing max packet segments... ");
940 test_pack(&vs,packets,headret);
941 vorbis_stream_clear(&vs);
945 /* packet that overspans over an entire page */
947 int packets[]={100,9000,259,255,-1};
949 int head1[] = {0x4f,0x67,0x67,0x53,0,0x00,
950 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
951 0x01,0x02,0x03,0x04,0,0,0,0,
954 100,255,255,255,255,255,255,255,255,
955 255,255,255,255,255,255,255,255};
957 int head2[] = {0x4f,0x67,0x67,0x53,0,0x02,
958 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
959 0x01,0x02,0x03,0x04,1,0,0,0,
962 255,255,255,255,255,255,255,255,
963 255,255,255,255,255,255,255,255,255};
965 int head3[] = {0x4f,0x67,0x67,0x53,0,0x02,
966 0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
967 0x01,0x02,0x03,0x04,2,0,0,0,
970 255,255,75,255,4,255,0};
971 int *headret[]={head1,head2,head3,NULL};
973 vorbis_stream_init(&vs,0x04030201);
974 fprintf(stderr,"testing very large packets... ");
975 test_pack(&vs,packets,headret);
976 vorbis_stream_clear(&vs);
980 /* nil page. why not? */
982 int packets[]={100,4080,-1};
984 int head1[] = {0x4f,0x67,0x67,0x53,0,0x00,
985 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
986 0x01,0x02,0x03,0x04,0,0,0,0,
989 100,255,255,255,255,255,255,255,255,
990 255,255,255,255,255,255,255,255};
992 int head2[] = {0x4f,0x67,0x67,0x53,0,0x02,
993 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
994 0x01,0x02,0x03,0x04,1,0,0,0,
998 int *headret[]={head1,head2,NULL};
1000 vorbis_stream_init(&vs,0x04030201);
1001 fprintf(stderr,"testing nil page... ");
1002 test_pack(&vs,packets,headret);
1003 vorbis_stream_clear(&vs);