Bringing my development in line with CVS now that the repository is set up.
[platform/upstream/libvorbis.git] / lib / framing.c
1 /********************************************************************
2  *                                                                  *
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.                            *
7  *                                                                  *
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/                                             *
11  *                                                                  *
12  ********************************************************************
13
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
19
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
22  details.
23
24  ********************************************************************/
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include "codec.h"
29
30 /* A complete description of Vorbis framing exists in docs/framing.txt */
31
32 int vorbis_page_version(vorbis_page *vg){
33   return((int)(vg->header[4]));
34 }
35
36 int vorbis_page_continued(vorbis_page *vg){
37   return((int)(vg->header[5]&0x01));
38 }
39
40 int vorbis_page_bos(vorbis_page *vg){
41   return((int)(vg->header[5]&0x02));
42 }
43
44 int vorbis_page_eos(vorbis_page *vg){
45   return((int)(vg->header[5]&0x04));
46 }
47
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];
58   return(pcmpos);
59 }
60
61 int vorbis_page_serialno(vorbis_page *vg){
62   return(vg->header[14] |
63          (vg->header[15]<<8) |
64          (vg->header[16]<<16) |
65          (vg->header[17]<<24));
66 }
67  
68 int vorbis_page_pageno(vorbis_page *vg){
69   return(vg->header[18] |
70          (vg->header[19]<<8) |
71          (vg->header[20]<<16) |
72          (vg->header[21]<<24));
73 }
74
75 /* helper to initialize lookup for direct-table CRC */
76
77 static unsigned size32 crc_lookup[256];
78 static int crc_ready=0;
79
80 static unsigned size32 _vorbis_crc_entry(unsigned long index){
81   int           i;
82   unsigned long r;
83
84   r = index << 24;
85   for (i=0; i<8; i++)
86     if (r & 0x80000000UL)
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 */
91     else
92        r<<=1;
93  return (r & 0xffffffffUL);
94 }
95
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 */
98
99 static void _vorbis_crc_init(void){
100   if(!crc_ready){
101     /* initialize the crc_lookup table */
102     int i;
103     for (i=0;i<256;i++)
104       crc_lookup[i]=_vorbis_crc_entry((unsigned long)i);
105     crc_ready=0;
106   }
107 }
108
109 /* init the encode/decode logical stream state */
110
111 int vorbis_stream_init(vorbis_stream_state *vs,int serialno){
112   if(vs){
113     memset(vs,0,sizeof(vorbis_stream_state));
114     vs->body_storage=16*1024;
115     vs->body_data=malloc(vs->body_storage*sizeof(char));
116
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));
120
121     /* initialize the crc_lookup table if not done */
122     _vorbis_crc_init();
123
124     vs->serialno=serialno;
125
126     return(0);
127   }
128   return(-1);
129
130
131 /* _clear does not free vs, only the non-flat storage within */
132 int vorbis_stream_clear(vorbis_stream_state *vs){
133   if(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);
137
138     memset(vs,0,sizeof(vorbis_stream_state));    
139   }
140   return(0);
141
142
143 int vorbis_stream_destroy(vorbis_stream_state *vs){
144   if(vs){
145     vorbis_stream_clear(vs);
146     free(vs);
147   }
148   return(0);
149
150
151 /* Helpers for vorbis_stream_encode; this keeps the structure and
152    what's happening fairly clear */
153
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);
158   }
159 }
160
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));
166   }
167 }
168
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 */
172
173 static void _vs_checksum(vorbis_page *vg){
174   unsigned size32 crc_reg=0;
175   int i;
176
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]];
181   
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;
186 }
187
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;
191
192   /* make sure we have the buffer storage */
193   _vs_body_expand(vs,vp->bytes);
194   _vs_lacing_expand(vs,lacing_vals);
195
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
199      future */
200
201   memcpy(vs->body_data+vs->body_fill,vp->packet,vp->bytes);
202   vs->body_fill+=vp->bytes;
203
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;
208   }
209   vs->lacing_vals[vs->lacing_fill+i]=(vp->bytes)%255;
210   vs->pcm_vals[vs->lacing_fill+i]=vp->pcm_pos;
211
212   /* flag the first segment as the beginning of the packet */
213   vs->lacing_vals[vs->lacing_fill]|= 0x100;
214
215   vs->lacing_fill+=lacing_vals;
216
217   if(vp->e_o_s)vs->e_o_s=1;
218
219   return(0);
220 }
221
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) */
225
226 int vorbis_stream_page(vorbis_stream_state *vs, vorbis_page *vg){
227   int i;
228
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
232        call */
233
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));
237     vs->body_returned=0;
238   }
239
240   if((vs->e_o_s&&vs->lacing_fill) || 
241      vs->body_fill > 4096 || 
242      vs->lacing_fill>=255){
243     int vals=0,bytes=0;
244     int maxvals=(vs->lacing_fill>255?255:vs->lacing_fill);
245     long acc=0;
246     size64 pcm_pos=vs->pcm_vals[0];
247
248     /* construct a page */
249     /* decide how many segments to include */
250     for(vals=0;vals<maxvals;vals++){
251       if(acc>4096)break;
252       acc+=vs->lacing_vals[vals]&0x0ff;
253       if((vs->lacing_vals[vals]&0x0ff)<255)pcm_pos=vs->pcm_vals[vals];
254     }
255
256     /* construct the header in temp storage */
257     memcpy(vs->header,"OggS",4);
258
259     /* stream structure version */
260     vs->header[4]=0x00;
261
262     
263     vs->header[5]=0x00;
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;
270     vs->b_o_s=1;
271
272     /* 64 bits of PCM position */
273     for(i=6;i<14;i++){
274       vs->header[i]=(pcm_pos&0xff);
275       pcm_pos>>=8;
276     }
277
278     /* 32 bits of stream serial number */
279     {
280       long serialno=vs->serialno;
281       for(i=14;i<18;i++){
282         vs->header[i]=(serialno&0xff);
283         serialno>>=8;
284       }
285     }
286
287     /* 32 bits of page counter (we have both counter and page header
288        because this val can roll over) */
289     {
290       long pageno=vs->pageno++;
291       for(i=18;i<22;i++){
292         vs->header[i]=(pageno&0xff);
293         pageno>>=8;
294       }
295     }
296
297     /* zero for computation; filled in later */
298     vs->header[22]=0;
299     vs->header[23]=0;
300     vs->header[24]=0;
301     vs->header[25]=0;
302
303     /* segment table */
304     vs->header[26]=vals&0xff;
305     for(i=0;i<vals;i++)
306       bytes+=vs->header[i+27]=(vs->lacing_vals[i]&0xff);
307       
308     /* advance the lacing data and set the body_returned pointer */
309
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;
314
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;
319     vg->body_len=bytes;
320
321     /* calculate the checksum */
322
323     _vs_checksum(vg);
324
325     return(1);
326   }
327
328   /* not enough data to construct a page and not end of stream */
329   return(0);
330 }
331
332 int vorbis_stream_eof(vorbis_stream_state *vs){
333   return vs->e_o_s;
334 }
335
336 /* DECODING PRIMITIVES: packet streaming layer **********************/
337
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.
343
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
350    example code. */
351
352 /* initialize the struct to a known state */
353 int vorbis_sync_init(vorbis_sync_state *vs){
354   if(vs){
355     memset(vs,0,sizeof(vorbis_sync_state));
356     _vorbis_crc_init();
357   }
358   return(0);
359 }
360
361 /* clear non-flat storage within */
362 int vorbis_sync_clear(vorbis_sync_state *vs){
363   if(vs){
364     if(vs->data)free(vs->data);
365     vorbis_sync_init(vs);
366   }
367   return(0);
368 }
369
370 char *vorbis_decode_buffer(vorbis_sync_state *vs, long size){
371
372   /* first, clear out any space that has been previously returned */
373   if(vs->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));
378     vs->returned=0;
379   }
380
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 */
384
385     if(vs->data)
386       vs->data=realloc(vs->data,newsize);
387     else
388       vs->data=malloc(newsize);
389     vs->storage=newsize;
390   }
391
392   /* expose a segment at least as large as requested at the fill mark */
393   return(vs->data+vs->fill);
394 }
395
396 int vorbis_decode_wrote(vorbis_sync_state *vs, long bytes){
397   if(vs->fill+bytes>vs->storage)return(-1);
398   vs->fill+=bytes;
399   return(0);
400 }
401
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.
405
406    Returns pointers into buffered data; invalidated by next call to
407    _stream, _clear, _init, or _buffer */
408
409 int vorbis_decode_stream(vorbis_sync_state *vs, vorbis_page *vg){
410
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
413      frame */
414
415   while(1){
416     char *page=vs->data+vs->returned;
417     long bytes=vs->fill-vs->returned;
418       
419     if(vs->headerbytes==0){
420       int headerbytes,i;
421       if(bytes<27)return(0); /* not enough for a header */
422
423       /* verify capture pattern */
424       if(memcmp(page,"OggS",4))goto sync_fail;
425       
426       headerbytes=page[26]+27;
427       if(bytes<headerbytes)return(0); /* not enough for header + seg table */
428
429       /* count up body length in the segment table */
430
431       for(i=0;i<page[26];i++)
432         vs->bodybytes+=page[27+i];
433       vs->headerbytes=headerbytes;
434     }
435     
436     if(vs->bodybytes+vs->headerbytes>bytes)return(0);
437
438     /* The whole test page is buffered.  Verify the checksum */
439     {
440       /* Grab the checksum bytes, set the header field to zero */
441       char chksum[4];
442       vorbis_page lvg;
443       
444       memcpy(chksum,page+22,4);
445       memset(page+22,0,4);
446       
447       /* set up a temp page struct and recompute the checksum */
448       lvg.header=page;
449       lvg.header_len=vs->headerbytes;
450       lvg.body=page+vs->headerbytes;
451       lvg.body_len=vs->bodybytes;
452       _vs_checksum(&lvg);
453         
454       /* Compare */
455       if(memcmp(chksum,page+22,4)){
456         /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
457            at all) */
458         /* replace the computed checksum with the one actually read in */
459         memcpy(page+22,chksum,4);
460           
461         /* Bad checksum. Lose sync */
462         goto sync_fail;
463       }
464     }
465         
466     vg->header=page;
467     vg->header_len=vs->headerbytes;
468     vg->body=page+vs->headerbytes;
469     vg->body_len=vs->bodybytes;
470     
471     vs->unsynced=0;
472     vs->returned+=vs->headerbytes+vs->bodybytes;
473     vs->headerbytes=0;
474     vs->bodybytes=0;
475
476     return(1);
477
478   sync_fail:
479     
480     vs->headerbytes=0;
481     vs->bodybytes=0;
482
483     /* search for possible capture */
484     
485     page=memchr(page+1,'O',bytes-1);
486     if(page)
487       vs->returned=page-vs->data;
488     else
489       vs->returned=vs->fill;
490
491     if(!vs->unsynced){
492       vs->unsynced=1;
493       return(-1);
494     }
495
496     /* loop; verifier above will take care of determining capture or not */
497
498   }
499 }
500
501 /* add the incoming page to the stream state; we decompose the page
502    into packet segments here as well. */
503
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;
508   int segptr=0;
509
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];
518   
519   /* clean up 'returned data' */
520   {
521     long lr=vs->lacing_returned;
522     long br=vs->body_returned;
523
524     /* body data */
525     if(vs->body_fill-br)
526       memmove(vs->body_data,vs->body_data+br,vs->body_fill-br);
527     vs->body_fill-=br;
528     vs->body_returned=0;
529
530     /* segment table */
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));
536     }
537     vs->lacing_fill-=lr;
538     vs->lacing_packet-=lr;
539     vs->lacing_returned=0;
540   }
541
542   /* check the serial number */
543   if(serialno!=vs->serialno)return(-1);
544   if(version>0)return(-1);
545
546   _vs_lacing_expand(vs,segments+1);
547
548   /* are we in sequence? */
549   if(pageno!=vs->pageno){
550     int i;
551
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;
556
557     /* make a note of dropped data in segment table */
558     vs->lacing_vals[vs->lacing_fill++]=0x400;
559     vs->lacing_packet++;
560
561     /* are we a 'continued packet' page?  If so, we'll need to skip
562        some segments */
563     if(continued){
564       bos=0;
565       for(;segptr<segments;segptr++){
566         int val=header[27+segptr];
567         body+=val;
568         bodysize-=val;
569         if(val<255){
570           segptr++;
571           break;
572         }
573       }
574     }
575   }
576   
577   if(bodysize){
578     _vs_body_expand(vs,bodysize);
579     memcpy(vs->body_data+vs->body_fill,body,bodysize);
580     vs->body_fill+=bodysize;
581   }
582
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;
587
588     if(bos){
589       vs->lacing_vals[vs->lacing_fill]|=0x100;
590       bos=0;
591     }
592
593     vs->lacing_fill++;
594     segptr++;
595
596     if(val<255)vs->lacing_packet=vs->lacing_fill;
597   }
598   if(eos){
599     vs->e_o_s=1;
600     if(vs->lacing_fill>0)
601       vs->lacing_vals[vs->lacing_fill-1]|=0x200;
602   }
603
604   vs->pageno=pageno;
605
606   return(0);
607 }
608
609 /* clear things to an initial state.  Good to call, eg, before seeking */
610 int vorbis_sync_reset(vorbis_sync_state *vs){
611   vs->fill=0;
612   vs->returned=0;
613   vs->unsynced=0;
614   vs->headerbytes=0;
615   vs->bodybytes=0;
616   return(0);
617 }
618
619 int vorbis_stream_reset(vorbis_stream_state *vs){
620   vs->body_fill=0;
621   vs->body_returned=0;
622
623   vs->lacing_fill=0;
624   vs->lacing_packet=0;
625   vs->lacing_returned=0;
626
627   vs->header_fill=0;
628
629   vs->e_o_s=0;
630   vs->b_o_s=0;
631   vs->pageno=0;
632   vs->pcmpos=0;
633
634   return(0);
635 }
636
637 int vorbis_stream_packet(vorbis_stream_state *vs,vorbis_packet *vp){
638
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) */
642
643   int ptr=vs->lacing_returned;
644
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++;
649     return(-1);
650   }
651
652   /* Gather the whole packet. We'll have no holes or a partial packet */
653   {
654     int size=vs->lacing_vals[ptr]&0xff;
655     int bytes=0;
656
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? */
660     bytes+=size;
661
662     while(size==255){
663       int val=vs->lacing_vals[++ptr];
664       size=val&0xff;
665       if(val&0x200)vp->e_o_s=0x200;
666       bytes+=size;
667     }
668     vp->pcm_pos=vs->pcm_vals[ptr];
669     vp->bytes=bytes;
670
671     vs->body_returned+=bytes;
672     vs->lacing_returned=ptr+1;
673   }
674   return(1);
675 }
676
677 #ifdef _V_SELFTEST
678 #include <stdio.h>
679
680 void test_pack(vorbis_stream_state *vs,int *pl, int **headers){
681   unsigned char *data=malloc(1024*1024); /* for scripted test cases only */
682   long inptr=0;
683   long outptr=0;
684   long pcm_pos=0;
685   int i,j,packets,pageno=0;
686
687   for(packets=0;;packets++)if(pl[packets]==-1)break;
688
689   for(i=0;i<packets;i++){
690     /* construct a test packet */
691     vorbis_packet vp;
692     int len=pl[i];
693     
694     vp.packet=data+inptr;
695     vp.bytes=len;
696     vp.e_o_s=(pl[i+1]<0?1:0);
697     vp.pcm_pos=pcm_pos;
698
699     pcm_pos+=1024;
700
701     for(j=0;j<len;j++)data[inptr++]=i+j;
702
703     /* submit the test packet */
704     vorbis_stream_encode(vs,&vp);
705
706     /* retrieve any finished pages */
707     {
708       vorbis_page vg;
709       
710       while(vorbis_stream_page(vs,&vg)){
711         /* We have a page.  Check it carefully */
712
713         fprintf(stderr,"%d, ",pageno);
714
715         if(headers[pageno]==NULL){
716           fprintf(stderr,"coded too many pages!\n");
717           exit(1);
718         }
719
720         /* Test data */
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]);
725           exit(1);
726         }
727         outptr+=vg.body_len;
728
729         /* Test header */
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");
736             exit(1);
737           }
738         }
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);
742           exit(1);
743         }
744         pageno++;
745       }
746     }
747   }
748   free(data);
749   if(headers[pageno]!=NULL){
750     fprintf(stderr,"did not write last page!\n");
751     exit(1);
752   }
753   if(inptr!=outptr){
754     fprintf(stderr,"packet data incomplete!\n");
755     exit(1);
756   }
757   fprintf(stderr,"ok.\n");
758 }
759
760 int main(void){
761   vorbis_stream_state vs;
762
763   /* Exercise each code path in the framing code.  Also verify that
764      the checksums are working.  */
765
766   {
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,
772                    0x7e,0xea,0x18,0xd0,
773                    14,
774                    17,254,255,0,255,1,255,245,255,255,0,
775                    255,255,90};
776     int *headret[]={head1,NULL};
777     
778     vorbis_stream_init(&vs,0x04030201);
779     fprintf(stderr,"testing basic page encoding... ");
780     test_pack(&vs,packets,headret);
781     vorbis_stream_clear(&vs);
782   }
783
784   {
785     /* nil packets; beginning,middle,end */
786     int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
787
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,
791                    0xcf,0x70,0xa4,0x1b,
792                    18,
793                    0,17,254,255,0,0,255,1,0,255,245,255,255,0,
794                    255,255,90,0};
795     int *headret[]={head1,NULL};
796     
797     vorbis_stream_init(&vs,0x04030201);
798     fprintf(stderr,"testing basic nil packets... ");
799     test_pack(&vs,packets,headret);
800     vorbis_stream_clear(&vs);
801   }
802
803   {
804     /* starting new page with first segment */
805     int packets[]={4345,259,255,-1};
806
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,
810                    0xe7,0xdc,0x6d,0x09,
811                    17,
812                    255,255,255,255,255,255,255,255,
813                    255,255,255,255,255,255,255,255,255};
814
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,
818                    0x5f,0x54,0x07,0x69,
819                    5,
820                    10,255,4,255,0};
821     int *headret[]={head1,head2,NULL};
822     
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);
827   }
828
829   {
830     /* starting new page with first segment */
831     int packets[]={100,4345,259,255,-1};
832
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,
836                    0x6f,0xac,0x43,0x67,
837                    17,
838                    100,255,255,255,255,255,255,255,255,
839                    255,255,255,255,255,255,255,255};
840
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,
844                    0xe7,0xa3,0x34,0x53,
845                    6,
846                    255,10,255,4,255,0};
847     int *headret[]={head1,head2,NULL};
848     
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);
853   }
854
855
856   /* page with the 255 segment limit */
857   {
858
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};
891
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,
895                    0xb1,0xd0,0xab,0xbc,
896                    255,
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};
929
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,
933                    0xb1,0x1e,0x4f,0x41,
934                    1,
935                    50};
936     int *headret[]={head1,head2,NULL};
937     
938     vorbis_stream_init(&vs,0x04030201);
939     fprintf(stderr,"testing max packet segments... ");
940     test_pack(&vs,packets,headret);
941     vorbis_stream_clear(&vs);
942   }
943
944   {
945     /* packet that overspans over an entire page */
946
947     int packets[]={100,9000,259,255,-1};
948
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,
952                    0x6f,0xac,0x43,0x67,
953                    17,
954                    100,255,255,255,255,255,255,255,255,
955                    255,255,255,255,255,255,255,255};
956
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,
960                    0x65,0x4e,0xbd,0x96,
961                    17,
962                    255,255,255,255,255,255,255,255,
963                    255,255,255,255,255,255,255,255,255};
964
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,
968                    0x84,0x86,0x86,0xf4,
969                    7,
970                    255,255,75,255,4,255,0};
971     int *headret[]={head1,head2,head3,NULL};
972     
973     vorbis_stream_init(&vs,0x04030201);
974     fprintf(stderr,"testing very large packets... ");
975     test_pack(&vs,packets,headret);
976     vorbis_stream_clear(&vs);
977   }
978
979   {
980     /* nil page.  why not? */
981
982     int packets[]={100,4080,-1};
983
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,
987                    0x6f,0xac,0x43,0x67,
988                    17,
989                    100,255,255,255,255,255,255,255,255,
990                    255,255,255,255,255,255,255,255};
991
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,
995                    0x71,0xc8,0x17,0x8c,
996                    1,0};
997
998     int *headret[]={head1,head2,NULL};
999     
1000     vorbis_stream_init(&vs,0x04030201);
1001     fprintf(stderr,"testing nil page... ");
1002     test_pack(&vs,packets,headret);
1003     vorbis_stream_clear(&vs);
1004   }
1005
1006   
1007
1008   return(0);
1009 }
1010
1011 #endif
1012
1013
1014
1015