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 10 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 /* helper to initialize lookup for direct-table CRC */
33 static unsigned size32 _vorbis_crc_entry(unsigned long index){
40 r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
41 polynomial, although we use an
42 unreflected alg and an init/final
43 of 0, not 0xffffffff */
46 return (r & 0xffffffffUL);
49 int vorbis_stream_init(vorbis_stream_state *vs,int serialno){
52 memset(vs,0,sizeof(vorbis_stream_state));
53 vs->body_storage=16*1024;
54 vs->body_data=malloc(vs->body_storage*sizeof(char));
56 vs->lacing_storage=1024;
57 vs->lacing_vals=malloc(vs->lacing_storage*sizeof(int));
58 vs->pcm_vals=malloc(vs->lacing_storage*sizeof(size64));
60 /* initialize the crc_lookup table */
62 vs->crc_lookup[i]=_vorbis_crc_entry((unsigned long)i);
64 vs->serialno=serialno;
71 /* _clear does not free vs, only the non-flat storage within */
72 int vorbis_stream_clear(vorbis_stream_state *vs){
74 if(vs->body_data)free(vs->body_data);
75 if(vs->lacing_vals)free(vs->lacing_vals);
76 if(vs->pcm_vals)free(vs->pcm_vals);
78 memset(vs,0,sizeof(vorbis_stream_state));
83 int vorbis_stream_destroy(vorbis_stream_state *vs){
85 vorbis_stream_clear(vs);
91 /* Helpers for vorbis_stream_encode; this keeps the structure and
92 what's happening fairly clear */
94 /* checksum the page */
95 /* Direct table CRC; note that this will be faster in the future if we
96 perform the checksum silmultaneously with other copies */
98 static void _vs_checksum(vorbis_stream_state *vs,vorbis_page *vg){
99 unsigned size32 crc_reg=0;
100 unsigned size32 *lookup=vs->crc_lookup;
103 for(i=0;i<vg->header_len;i++)
104 crc_reg=(crc_reg<<8)^lookup[((crc_reg >> 24)&0xff)^vg->header[i]];
105 for(i=0;i<vg->body_len;i++)
106 crc_reg=(crc_reg<<8)^lookup[((crc_reg >> 24)&0xff)^vg->body[i]];
108 vg->header[22]=crc_reg&0xff;
109 vg->header[23]=(crc_reg>>8)&0xff;
110 vg->header[24]=(crc_reg>>16)&0xff;
111 vg->header[25]=(crc_reg>>24)&0xff;
114 /* submit data to the internal buffer of the framing engine */
115 int vorbis_stream_encode(vorbis_stream_state *vs,vorbis_packet *vp){
116 int lacing_vals=vp->bytes/255+1,i;
118 /* make sure we have the buffer storage */
119 if(vs->body_storage<=vs->body_fill+vp->bytes){
120 vs->body_storage+=(vp->bytes+1024);
121 vs->body_data=realloc(vs->body_data,vs->body_storage);
123 if(vs->lacing_storage<=vs->lacing_fill+lacing_vals){
124 vs->lacing_storage+=(lacing_vals+32);
125 vs->lacing_vals=realloc(vs->lacing_vals,vs->lacing_storage*sizeof(int));
126 vs->pcm_vals=realloc(vs->pcm_vals,vs->lacing_storage*sizeof(size64));
129 /* Copy in the submitted packet. Yes, the copy is a waste; this is
130 the liability of overly clean abstraction for the time being. It
131 will actually be fairly easy to eliminate the extra copy in the
134 memcpy(vs->body_data+vs->body_fill,vp->packet,vp->bytes);
135 vs->body_fill+=vp->bytes;
137 /* Store lacing vals for this packet */
138 for(i=0;i<lacing_vals-1;i++){
139 vs->lacing_vals[vs->lacing_fill+i]=255;
140 vs->pcm_vals[vs->lacing_fill+i]=vp->pcm_pos;
142 vs->lacing_vals[vs->lacing_fill+i]=(vp->bytes)%255;
143 vs->pcm_vals[vs->lacing_fill+i]=vp->pcm_pos;
145 /* flag the first segment as the beginning of the packet */
146 vs->lacing_vals[vs->lacing_fill]|= 0x100;
148 vs->lacing_fill+=lacing_vals;
150 if(vp->e_o_s)vs->e_o_s=1;
155 /* This constructs pages from buffered packet segments. The pointers
156 returned are to static buffers; do not free. The returned buffers are
157 good only until the next call (using the same vs) */
159 int vorbis_stream_page(vorbis_stream_state *vs, vorbis_page *vg){
162 if(vs->body_returned){
163 /* advance packet data according to the body_returned pointer. We
164 had to keep it around to return a pointer into the buffer last
167 vs->body_fill-=vs->body_returned;
168 memmove(vs->body_data,vs->body_data+vs->body_returned,
169 vs->body_fill*sizeof(char));
173 if((vs->e_o_s&&vs->lacing_fill) ||
174 vs->body_fill > 4096 ||
175 vs->lacing_fill>=255){
177 int maxvals=(vs->lacing_fill>255?255:vs->lacing_fill);
180 /* construct a page */
181 /* decide how many segments to include */
182 for(vals=0;vals<maxvals;vals++){
184 acc+=vs->lacing_vals[vals]&0x0ff;
187 /* construct the header in temp storage */
188 memcpy(vs->header,"OggS",4);
190 /* stream structure version */
194 /* Ah, this is the first page */
197 if(vs->lacing_vals[0]&0x100){
198 /* The first packet segment is the beginning of a packet */
206 /* 64 bits of PCM position */
208 size64 pcm_pos=vs->pcm_vals[vals-1];
211 vs->header[i]=(pcm_pos&0xff);
216 /* 32 bits of stream serial number */
218 long serialno=vs->serialno;
220 vs->header[i]=(serialno&0xff);
225 /* 32 bits of page counter (we have both counter and page header
226 because this val can roll over) */
228 long pageno=vs->pageno++;
230 vs->header[i]=(pageno&0xff);
235 /* zero for computation; filled in later */
242 vs->header[26]=vals&0xff;
244 bytes+=vs->header[i+27]=(vs->lacing_vals[i]&0xff);
246 /* advance the lacing data and set the body_returned pointer */
248 vs->lacing_fill-=vals;
249 memmove(vs->lacing_vals,vs->lacing_vals+vals,vs->lacing_fill*sizeof(int));
250 memmove(vs->pcm_vals,vs->pcm_vals+vals,vs->lacing_fill*sizeof(size64));
251 vs->body_returned=bytes;
253 /* set pointers in the vorbis_page struct */
254 vg->header=vs->header;
255 vg->header_len=vs->headerbytes=vals+27;
256 vg->body=vs->body_data;
259 /* calculate the checksum */
266 /* not enough data to construct a page and not end of stream */
270 int vorbis_stream_eof(vorbis_stream_state *vs){
274 /* DECODING PRIMITIVES: packet streaming layer **********************/
276 /* Accepts data for decoding; syncs and frames the bitstream, then
277 decodes pages into packets. Works through errors and dropouts,
278 reporting holes/errors in the bitstream when the missing/corrupt
279 packet is requested by vorbis_stream_packet(). Call with size=-1
282 /* all below: <0 error, 0 not enough data, >0 success */
284 int vorbis_stream_decode(vorbis_stream_state *vs,char *stream,int size){
285 /* beginning a page? ie, no header started yet?*/
293 size64 vorbis_stream_pcmpos(vorbis_stream_state *vs){
296 size64 vorbis_stream_pageno(vorbis_stream_state *vs){
299 int vorbis_stream_skippage(vorbis_stream_state *vs){
302 int vorbis_stream_clearbuf(vorbis_stream_state *vs){
305 int vorbis_stream_packet(vorbis_stream_state *vs,vorbis_packet *vp){
311 void test_pack(vorbis_stream_state *vs,int *pl, int **headers){
312 unsigned char *data=malloc(1024*1024); /* for scripted test cases only */
316 int i,j,packets,pageno=0;
318 for(packets=0;;packets++)if(pl[packets]==-1)break;
320 for(i=0;i<packets;i++){
321 /* construct a test packet */
325 vp.packet=data+inptr;
327 vp.e_o_s=(pl[i+1]<0?1:0);
332 for(j=0;j<len;j++)data[inptr++]=i+j;
334 /* submit the test packet */
335 vorbis_stream_encode(vs,&vp);
337 /* retrieve any finished pages */
341 while(vorbis_stream_page(vs,&vg)){
342 /* We have a page. Check it carefully */
344 fprintf(stderr,"%d, ",pageno);
346 if(headers[pageno]==NULL){
347 fprintf(stderr,"coded too many pages!\n");
352 for(j=0;j<vg.body_len;j++)
353 if(vg.body[j]!=(data+outptr)[j]){
354 fprintf(stderr,"body data mismatch at pos %ld: %x!=%x!\n\n",
355 outptr+j,(data+outptr)[j],vg.body[j]);
361 for(j=0;j<vg.header_len;j++){
362 if(vg.header[j]!=headers[pageno][j]){
363 fprintf(stderr,"header content mismatch at pos %ld:\n",j);
364 for(j=0;j<headers[pageno][26]+27;j++)
365 fprintf(stderr," (%d)%02x:%02x",j,headers[pageno][j],vg.header[j]);
366 fprintf(stderr,"\n");
370 if(vg.header_len!=headers[pageno][26]+27){
371 fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
372 vg.header_len,headers[pageno][26]+27);
380 if(headers[pageno]!=NULL){
381 fprintf(stderr,"did not write last page!\n");
385 fprintf(stderr,"packet data incomplete!\n");
388 fprintf(stderr,"ok.\n");
392 vorbis_stream_state vs;
394 /* Exercise each code path in the framing code. Also verify that
395 the checksums are working. */
398 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
399 int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
400 int head1[] = {0x4f,0x67,0x67,0x53,0,0,
401 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
402 0x01,0x02,0x03,0x04,0,0,0,0,
405 17,254,255,0,255,1,255,245,255,255,0,
407 int *headret[]={head1,NULL};
409 vorbis_stream_init(&vs,0x04030201);
410 fprintf(stderr,"testing basic page encoding... ");
411 test_pack(&vs,packets,headret);
412 vorbis_stream_clear(&vs);
416 /* nil packets; beginning,middle,end */
417 int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
419 int head1[] = {0x4f,0x67,0x67,0x53,0,0,
420 0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
421 0x01,0x02,0x03,0x04,0,0,0,0,
424 0,17,254,255,0,0,255,1,0,255,245,255,255,0,
426 int *headret[]={head1,NULL};
428 vorbis_stream_init(&vs,0x04030201);
429 fprintf(stderr,"testing basic nil packets... ");
430 test_pack(&vs,packets,headret);
431 vorbis_stream_clear(&vs);
435 /* starting new page with first segment */
436 int packets[]={4345,259,255,-1};
438 int head1[] = {0x4f,0x67,0x67,0x53,0,0,
439 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
440 0x01,0x02,0x03,0x04,0,0,0,0,
443 255,255,255,255,255,255,255,255,
444 255,255,255,255,255,255,255,255,255};
446 int head2[] = {0x4f,0x67,0x67,0x53,0,0x02,
447 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
448 0x01,0x02,0x03,0x04,1,0,0,0,
452 int *headret[]={head1,head2,NULL};
454 vorbis_stream_init(&vs,0x04030201);
455 fprintf(stderr,"testing single-packet page span... ");
456 test_pack(&vs,packets,headret);
457 vorbis_stream_clear(&vs);
461 /* starting new page with first segment */
462 int packets[]={100,4345,259,255,-1};
464 int head1[] = {0x4f,0x67,0x67,0x53,0,0x00,
465 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
466 0x01,0x02,0x03,0x04,0,0,0,0,
469 100,255,255,255,255,255,255,255,255,
470 255,255,255,255,255,255,255,255};
472 int head2[] = {0x4f,0x67,0x67,0x53,0,0x02,
473 0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
474 0x01,0x02,0x03,0x04,1,0,0,0,
478 int *headret[]={head1,head2,NULL};
480 vorbis_stream_init(&vs,0x04030201);
481 fprintf(stderr,"testing multi-packet page span... ");
482 test_pack(&vs,packets,headret);
483 vorbis_stream_clear(&vs);
487 /* page with the 255 segment limit */
490 int packets[]={10,10,10,10,10,10,10,10,
491 10,10,10,10,10,10,10,10,
492 10,10,10,10,10,10,10,10,
493 10,10,10,10,10,10,10,10,
494 10,10,10,10,10,10,10,10,
495 10,10,10,10,10,10,10,10,
496 10,10,10,10,10,10,10,10,
497 10,10,10,10,10,10,10,10,
498 10,10,10,10,10,10,10,10,
499 10,10,10,10,10,10,10,10,
500 10,10,10,10,10,10,10,10,
501 10,10,10,10,10,10,10,10,
502 10,10,10,10,10,10,10,10,
503 10,10,10,10,10,10,10,10,
504 10,10,10,10,10,10,10,10,
505 10,10,10,10,10,10,10,10,
506 10,10,10,10,10,10,10,10,
507 10,10,10,10,10,10,10,10,
508 10,10,10,10,10,10,10,10,
509 10,10,10,10,10,10,10,10,
510 10,10,10,10,10,10,10,10,
511 10,10,10,10,10,10,10,10,
512 10,10,10,10,10,10,10,10,
513 10,10,10,10,10,10,10,10,
514 10,10,10,10,10,10,10,10,
515 10,10,10,10,10,10,10,10,
516 10,10,10,10,10,10,10,10,
517 10,10,10,10,10,10,10,10,
518 10,10,10,10,10,10,10,10,
519 10,10,10,10,10,10,10,10,
520 10,10,10,10,10,10,10,10,
521 10,10,10,10,10,10,10,50,-1};
523 int head1[] = {0x4f,0x67,0x67,0x53,0,0x00,
524 0x00,0xf8,0x03,0x00,0x00,0x00,0x00,0x00,
525 0x01,0x02,0x03,0x04,0,0,0,0,
528 10,10,10,10,10,10,10,10,
529 10,10,10,10,10,10,10,10,
530 10,10,10,10,10,10,10,10,
531 10,10,10,10,10,10,10,10,
532 10,10,10,10,10,10,10,10,
533 10,10,10,10,10,10,10,10,
534 10,10,10,10,10,10,10,10,
535 10,10,10,10,10,10,10,10,
536 10,10,10,10,10,10,10,10,
537 10,10,10,10,10,10,10,10,
538 10,10,10,10,10,10,10,10,
539 10,10,10,10,10,10,10,10,
540 10,10,10,10,10,10,10,10,
541 10,10,10,10,10,10,10,10,
542 10,10,10,10,10,10,10,10,
543 10,10,10,10,10,10,10,10,
544 10,10,10,10,10,10,10,10,
545 10,10,10,10,10,10,10,10,
546 10,10,10,10,10,10,10,10,
547 10,10,10,10,10,10,10,10,
548 10,10,10,10,10,10,10,10,
549 10,10,10,10,10,10,10,10,
550 10,10,10,10,10,10,10,10,
551 10,10,10,10,10,10,10,10,
552 10,10,10,10,10,10,10,10,
553 10,10,10,10,10,10,10,10,
554 10,10,10,10,10,10,10,10,
555 10,10,10,10,10,10,10,10,
556 10,10,10,10,10,10,10,10,
557 10,10,10,10,10,10,10,10,
558 10,10,10,10,10,10,10,10,
559 10,10,10,10,10,10,10};
561 int head2[] = {0x4f,0x67,0x67,0x53,0,0x01,
562 0x00,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
563 0x01,0x02,0x03,0x04,1,0,0,0,
567 int *headret[]={head1,head2,NULL};
569 vorbis_stream_init(&vs,0x04030201);
570 fprintf(stderr,"testing max packet segments... ");
571 test_pack(&vs,packets,headret);
572 vorbis_stream_clear(&vs);
576 /* packet that overspans over an entire page */
578 int packets[]={100,9000,259,255,-1};
580 int head1[] = {0x4f,0x67,0x67,0x53,0,0x00,
581 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
582 0x01,0x02,0x03,0x04,0,0,0,0,
585 100,255,255,255,255,255,255,255,255,
586 255,255,255,255,255,255,255,255};
588 int head2[] = {0x4f,0x67,0x67,0x53,0,0x02,
589 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
590 0x01,0x02,0x03,0x04,1,0,0,0,
593 255,255,255,255,255,255,255,255,
594 255,255,255,255,255,255,255,255,255};
596 int head3[] = {0x4f,0x67,0x67,0x53,0,0x02,
597 0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
598 0x01,0x02,0x03,0x04,2,0,0,0,
601 255,255,75,255,4,255,0};
602 int *headret[]={head1,head2,head3,NULL};
604 vorbis_stream_init(&vs,0x04030201);
605 fprintf(stderr,"testing very large packets... ");
606 test_pack(&vs,packets,headret);
607 vorbis_stream_clear(&vs);
611 /* nil page. why not? */
613 int packets[]={100,4080,-1};
615 int head1[] = {0x4f,0x67,0x67,0x53,0,0x00,
616 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
617 0x01,0x02,0x03,0x04,0,0,0,0,
620 100,255,255,255,255,255,255,255,255,
621 255,255,255,255,255,255,255,255};
623 int head2[] = {0x4f,0x67,0x67,0x53,0,0x02,
624 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
625 0x01,0x02,0x03,0x04,1,0,0,0,
629 int *headret[]={head1,head2,NULL};
631 vorbis_stream_init(&vs,0x04030201);
632 fprintf(stderr,"testing nil page... ");
633 test_pack(&vs,packets,headret);
634 vorbis_stream_clear(&vs);