Recognizes if input is ogg or not.
[xiph.git] / ogg2 / src / sync.c
blob9485ffb3a0568ce559adf36298abee699aaa9074
1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE Ogg Reference Library 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. *
7 * *
8 * THE Ogg Reference Library SOURCE CODE IS (C) COPYRIGHT 1994-2004 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
10 * *
11 ********************************************************************
13 function: decode stream sync and memory management foundation code;
14 takes in raw data, spits out packets
15 last mod: $Id$
17 note: The CRC code is directly derived from public domain code by
18 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
19 for details.
21 ********************************************************************/
23 #include <stdlib.h>
24 #include <string.h>
25 #include "ogginternal.h" /* proper way to suck in ogg/ogg.h from a
26 libogg compile */
28 /* A complete description of Ogg framing exists in docs/framing.html */
30 int ogg2_page_version(ogg2_page *og){
31 ogg2byte_buffer ob;
32 ogg2byte_init(&ob,og->header,0);
33 return ogg2byte_read1(&ob,4);
36 int ogg2_page_continued(ogg2_page *og){
37 ogg2byte_buffer ob;
38 ogg2byte_init(&ob,og->header,0);
39 return ogg2byte_read1(&ob,5)&0x01;
42 int ogg2_page_bos(ogg2_page *og){
43 ogg2byte_buffer ob;
44 ogg2byte_init(&ob,og->header,0);
45 return ogg2byte_read1(&ob,5)&0x02;
48 int ogg2_page_eos(ogg2_page *og){
49 ogg2byte_buffer ob;
50 ogg2byte_init(&ob,og->header,0);
51 return ogg2byte_read1(&ob,5)&0x04;
54 ogg_int64_t ogg2_page_granulepos(ogg2_page *og){
55 ogg2byte_buffer ob;
56 ogg2byte_init(&ob,og->header,0);
57 return ogg2byte_read8(&ob,6);
60 ogg_uint32_t ogg2_page_serialno(ogg2_page *og){
61 ogg2byte_buffer ob;
62 ogg2byte_init(&ob,og->header,0);
63 return ogg2byte_read4(&ob,14);
66 ogg_uint32_t ogg2_page_pageno(ogg2_page *og){
67 ogg2byte_buffer ob;
68 ogg2byte_init(&ob,og->header,0);
69 return ogg2byte_read4(&ob,18);
72 /* returns the number of packets that are completed on this page (if
73 the leading packet is begun on a previous page, but ends on this
74 page, it's counted */
76 /* NOTE:
77 If a page consists of a packet begun on a previous page, and a new
78 packet begun (but not completed) on this page, the return will be:
79 ogg2_page_packets(page) ==1,
80 ogg2_page_continued(page) !=0
82 If a page happens to be a single packet that was begun on a
83 previous page, and spans to the next page (in the case of a three or
84 more page packet), the return will be:
85 ogg2_page_packets(page) ==0,
86 ogg2_page_continued(page) !=0
89 int ogg2_page_packets(ogg2_page *og){
90 int i;
91 int n;
92 int count=0;
93 ogg2byte_buffer ob;
94 ogg2byte_init(&ob,og->header,0);
96 n=ogg2byte_read1(&ob,26);
97 for(i=0;i<n;i++)
98 if(ogg2byte_read1(&ob,27+i)<255)count++;
99 return(count);
103 These functions can be used to change some header values of an
104 Ogg Page without having to decode and recompile the stream. This can
105 be very helpful for repairing broken streams, chaining streams which
106 have the same serialno, or intentionally creating broken streams
107 to test how your application will react to the erronious data.
110 void ogg2_page_set_continued(ogg2_page *og, int value){
111 int b;
112 ogg2byte_buffer ob;
113 ogg2byte_init(&ob,og->header,0);
114 b=ogg2byte_read1(&ob,5);
115 if(value)ogg2byte_set1(&ob,b|0x01,5);
116 else ogg2byte_set1(&ob,b&0xFE,5);
117 ogg2_page_checksum_set(og);
120 void ogg2_page_set_bos(ogg2_page *og, int value){
121 int b;
122 ogg2byte_buffer ob;
123 ogg2byte_init(&ob,og->header,0);
124 b=ogg2byte_read1(&ob,5);
125 if(value)ogg2byte_set1(&ob,b|0x02,5);
126 else ogg2byte_set1(&ob,b&0xFD,5);
127 ogg2_page_checksum_set(og);
130 void ogg2_page_set_eos(ogg2_page *og, int value){
131 int b;
132 ogg2byte_buffer ob;
133 ogg2byte_init(&ob,og->header,0);
134 b=ogg2byte_read1(&ob,5);
135 if(value)ogg2byte_set1(&ob,b|0x04,5);
136 else ogg2byte_set1(&ob,b&0xFB,5);
137 ogg2_page_checksum_set(og);
140 void ogg2_page_set_granulepos(ogg2_page *og, ogg_int64_t value){
141 ogg2byte_buffer ob;
142 ogg2byte_init(&ob,og->header,0);
143 ogg2byte_set8(&ob,value,6);
144 ogg2_page_checksum_set(og);
147 void ogg2_page_set_serialno(ogg2_page *og, ogg_uint32_t value){
148 ogg2byte_buffer ob;
149 ogg2byte_init(&ob,og->header,0);
150 ogg2byte_set4(&ob,value,14);
151 ogg2_page_checksum_set(og);
154 void ogg2_page_set_pageno(ogg2_page *og, ogg_uint32_t value){
155 ogg2byte_buffer ob;
156 ogg2byte_init(&ob,og->header,0);
157 ogg2byte_set4(&ob,value,18);
158 ogg2_page_checksum_set(og);
162 /* Static CRC calculation table. See older code in SVN for dead
163 run-time initialization code. */
165 static ogg_uint32_t crc_lookup[256]={
166 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
167 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
168 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
169 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
170 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
171 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
172 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
173 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
174 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
175 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
176 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
177 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
178 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
179 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
180 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
181 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
182 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
183 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
184 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
185 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
186 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
187 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
188 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
189 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
190 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
191 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
192 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
193 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
194 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
195 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
196 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
197 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
198 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
199 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
200 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
201 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
202 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
203 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
204 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
205 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
206 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
207 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
208 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
209 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
210 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
211 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
212 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
213 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
214 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
215 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
216 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
217 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
218 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
219 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
220 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
221 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
222 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
223 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
224 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
225 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
226 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
227 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
228 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
229 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
231 /* DECODING PRIMITIVES: raw stream and page layer *******************/
233 /* This has two layers (split page decode and packet decode) to place
234 more of the multi-serialno and paging control in the hands of
235 higher layers (eg, OggFile). First, we expose a data buffer using
236 ogg2_sync_buffer(). The app either copies into the buffer, or
237 passes it directly to read(), etc. We then call ogg2_sync_wrote()
238 to tell how many bytes we just added.
240 Efficiency note: request the same buffer size each time if at all
241 possible.
243 Pages are returned (pointers into the buffer in ogg2_sync_state)
244 by ogg2_sync_pageout(). */
246 ogg2_sync_state *ogg2_sync_create(void){
247 ogg2_sync_state *oy=_ogg_calloc(1,sizeof(*oy));
248 memset(oy,0,sizeof(*oy));
249 oy->bufferpool=ogg2_buffer_create();
250 return oy;
253 int ogg2_sync_destroy(ogg2_sync_state *oy){
254 if(oy){
255 ogg2_sync_reset(oy);
256 ogg2_buffer_destroy(oy->bufferpool);
257 memset(oy,0,sizeof(*oy));
258 _ogg_free(oy);
260 return OGG2_SUCCESS;
263 unsigned char *ogg2_sync_bufferin(ogg2_sync_state *oy, long bytes){
265 /* [allocate and] expose a buffer for data submission.
267 If there is no head fragment
268 allocate one and expose it
269 else
270 if the current head fragment has sufficient unused space
271 expose it
272 else
273 if the current head fragment is unused
274 resize and expose it
275 else
276 allocate new fragment and expose it
279 /* base case; fifo uninitialized */
280 if(!oy->fifo_head){
281 oy->fifo_head=oy->fifo_tail=ogg2_buffer_alloc(oy->bufferpool,bytes);
282 return oy->fifo_head->buffer->data;
285 /* space left in current fragment case */
286 if(oy->fifo_head->buffer->size-
287 oy->fifo_head->length-
288 oy->fifo_head->begin >= bytes)
289 return oy->fifo_head->buffer->data+
290 oy->fifo_head->length+oy->fifo_head->begin;
292 /* current fragment is unused, but too small */
293 if(!oy->fifo_head->length){
294 ogg2_buffer_realloc(oy->fifo_head,bytes);
295 return oy->fifo_head->buffer->data+oy->fifo_head->begin;
298 /* current fragment used/full; get new fragment */
300 ogg2_reference *new=ogg2_buffer_alloc(oy->bufferpool,bytes);
301 oy->fifo_head->next=new;
302 oy->fifo_head=new;
304 return oy->fifo_head->buffer->data;
307 int ogg2_sync_wrote(ogg2_sync_state *oy, long bytes){
308 if(!oy->fifo_head)return OGG2_EINVAL;
309 if(oy->fifo_head->buffer->size-oy->fifo_head->length-oy->fifo_head->begin <
310 bytes)return OGG2_EINVAL;
311 oy->fifo_head->length+=bytes;
312 oy->fifo_fill+=bytes;
313 return OGG2_SUCCESS;
316 static ogg_uint32_t _checksum(ogg2_reference *or, int bytes){
317 ogg_uint32_t crc_reg=0;
318 int j,post;
320 while(or){
321 unsigned char *data=or->buffer->data+or->begin;
322 post=(bytes<or->length?bytes:or->length);
323 for(j=0;j<post;++j)
324 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^data[j]];
325 bytes-=j;
326 or=or->next;
329 return crc_reg;
333 /* sync the stream. This is meant to be useful for finding page
334 boundaries.
336 return values for this:
337 -n) skipped n bytes
338 0) page not ready; more data (no bytes skipped)
339 n) page synced at current location; page length n bytes
343 long ogg2_sync_pageseek(ogg2_sync_state *oy,ogg2_page *og){
344 ogg2byte_buffer page;
345 long bytes,ret=0;
347 /* don't leak a valid reference */
348 ogg2_page_release(og);
350 bytes=oy->fifo_fill;
351 ogg2byte_init(&page,oy->fifo_tail,0);
353 if(oy->headerbytes==0){
354 if(bytes<27)goto sync_out; /* not enough for even a minimal header */
356 /* verify capture pattern */
357 if(ogg2byte_read1(&page,0)!=(int)'O' ||
358 ogg2byte_read1(&page,1)!=(int)'g' ||
359 ogg2byte_read1(&page,2)!=(int)'g' ||
360 ogg2byte_read1(&page,3)!=(int)'S' ) goto sync_fail;
362 oy->headerbytes=ogg2byte_read1(&page,26)+27;
364 if(bytes<oy->headerbytes)goto sync_out; /* not enough for header +
365 seg table */
366 if(oy->bodybytes==0){
367 int i;
368 /* count up body length in the segment table */
369 for(i=0;i<oy->headerbytes-27;i++)
370 oy->bodybytes+=ogg2byte_read1(&page,27+i);
373 if(oy->bodybytes+oy->headerbytes>bytes)goto sync_out;
375 /* we have what appears to be a complete page; last test: verify
376 checksum */
378 ogg_uint32_t chksum=ogg2byte_read4(&page,22);
379 ogg2byte_set4(&page,0,22);
381 /* Compare checksums; memory continues to be common access */
382 if(chksum!=_checksum(oy->fifo_tail,oy->bodybytes+oy->headerbytes)){
384 /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
385 at all). replace the computed checksum with the one actually
386 read in; remember all the memory is common access */
388 ogg2byte_set4(&page,chksum,22);
389 goto sync_fail;
391 ogg2byte_set4(&page,chksum,22);
394 /* We have a page. Set up page return. */
395 if(og){
396 /* set up page output */
397 og->header=ogg2_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->headerbytes);
398 og->header_len=oy->headerbytes;
399 og->body=ogg2_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->bodybytes);
400 og->body_len=oy->bodybytes;
401 }else{
402 /* simply advance */
403 oy->fifo_tail=
404 ogg2_buffer_pretruncate(oy->fifo_tail,oy->headerbytes+oy->bodybytes);
405 if(!oy->fifo_tail)oy->fifo_head=0;
408 ret=oy->headerbytes+oy->bodybytes;
409 oy->unsynced=0;
410 oy->headerbytes=0;
411 oy->bodybytes=0;
412 oy->fifo_fill-=ret;
414 return ret;
416 sync_fail:
418 oy->headerbytes=0;
419 oy->bodybytes=0;
420 oy->fifo_tail=ogg2_buffer_pretruncate(oy->fifo_tail,1);
421 ret--;
423 /* search forward through fragments for possible capture */
424 while(oy->fifo_tail){
425 /* invariant: fifo_cursor points to a position in fifo_tail */
426 unsigned char *now=oy->fifo_tail->buffer->data+oy->fifo_tail->begin;
427 unsigned char *next=memchr(now, 'O', oy->fifo_tail->length);
429 if(next){
430 /* possible capture in this segment */
431 long bytes=next-now;
432 oy->fifo_tail=ogg2_buffer_pretruncate(oy->fifo_tail,bytes);
433 ret-=bytes;
434 break;
435 }else{
436 /* no capture. advance to next segment */
437 long bytes=oy->fifo_tail->length;
438 ret-=bytes;
439 oy->fifo_tail=ogg2_buffer_pretruncate(oy->fifo_tail,bytes);
442 if(!oy->fifo_tail)oy->fifo_head=0;
443 oy->fifo_fill+=ret;
445 sync_out:
446 return ret;
449 /* sync the stream and get a page. Keep trying until we find a page.
450 Supress 'sync errors' after reporting the first.
452 return values:
453 OGG2_HOLE) recapture (hole in data)
454 0) need more data
455 1) page returned
457 Returns pointers into buffered data; invalidated by next call to
458 _stream, _clear, _init, or _buffer */
460 int ogg2_sync_pageout(ogg2_sync_state *oy, ogg2_page *og){
462 /* all we need to do is verify a page at the head of the stream
463 buffer. If it doesn't verify, we look for the next potential
464 frame */
466 while(1){
467 long ret=ogg2_sync_pageseek(oy,og);
468 if(ret>0){
469 /* have a page */
470 return 1;
472 if(ret==0){
473 /* need more data */
474 return 0;
477 /* head did not start a synced page... skipped some bytes */
478 if(!oy->unsynced){
479 oy->unsynced=1;
480 return OGG2_HOLE;
483 /* loop. keep looking */
488 /* clear things to an initial state. Good to call, eg, before seeking */
489 int ogg2_sync_reset(ogg2_sync_state *oy){
491 ogg2_buffer_release(oy->fifo_tail);
492 oy->fifo_tail=0;
493 oy->fifo_head=0;
494 oy->fifo_fill=0;
496 oy->unsynced=0;
497 oy->headerbytes=0;
498 oy->bodybytes=0;
499 return OGG2_SUCCESS;
502 /* checksum the page; direct table CRC */
504 int ogg2_page_checksum_set(ogg2_page *og){
505 if(og && og->header){
506 ogg2byte_buffer ob;
507 ogg2_reference *or;
508 ogg_uint32_t crc_reg=0;
509 int j;
511 /* safety; needed for API behavior, but not framing code */
512 ogg2byte_init(&ob,og->header,0);
513 ogg2byte_set4(&ob,0,22);
515 or=og->header;
516 while(or){
517 unsigned char *data=or->buffer->data+or->begin;
518 for(j=0;j<or->length;j++)
519 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^data[j]];
520 or=or->next;
523 or=og->body;
524 while(or){
525 unsigned char *data=or->buffer->data+or->begin;
526 for(j=0;j<or->length;j++)
527 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^data[j]];
528 or=or->next;
531 ogg2byte_set4(&ob,crc_reg,22);
533 return OGG2_SUCCESS;
535 return OGG2_EINVAL;
538 /* ENCODING PRIMITIVES: raw stream and page layer *******************/
540 /* On encode side, the sync layer provides centralized memory
541 management, buffering, and and abstraction to deal with fragmented
542 linked buffers as an iteration over flat char buffers.
543 ogg2_sync_encode and ogg2_sync_destroy are as in decode. */
545 int ogg2_sync_pagein(ogg2_sync_state *oy,ogg2_page *og){
546 /* buffer new */
547 if(oy->fifo_head)
548 oy->fifo_head=ogg2_buffer_cat(oy->fifo_head,og->header);
549 else
550 oy->fifo_head=ogg2_buffer_walk(oy->fifo_tail=og->header);
551 oy->fifo_head=ogg2_buffer_cat(oy->fifo_head,og->body);
552 memset(og,0,sizeof(*og));
553 return OGG2_SUCCESS;
556 long ogg2_sync_bufferout(ogg2_sync_state *oy, unsigned char **buffer){
557 long ret=0;
559 /* return next fragment */
561 while(!ret){
563 if(!oy->fifo_tail){
564 *buffer=0;
565 return 0;
568 *buffer=oy->fifo_tail->buffer->data+oy->fifo_tail->begin;
569 ret=oy->fifo_tail->length;
572 return ret;
575 int ogg2_sync_read(ogg2_sync_state *oy, long bytes){
576 if(!oy->fifo_tail)return OGG2_EINVAL;
577 oy->fifo_tail=ogg2_buffer_pretruncate(oy->fifo_tail,bytes);
578 if(!oy->fifo_tail)oy->fifo_head=0;
580 return OGG2_SUCCESS;
583 void ogg2_page_dup(ogg2_page *dup,ogg2_page *orig){
584 dup->header_len=orig->header_len;
585 dup->body_len=orig->body_len;
586 dup->header=ogg2_buffer_dup(orig->header);
587 dup->body=ogg2_buffer_dup(orig->body);
590 void ogg2_packet_dup(ogg2_packet *dup,ogg2_packet *orig){
591 dup->bytes=orig->bytes;
592 dup->b_o_s=orig->b_o_s;
593 dup->e_o_s=orig->e_o_s;
594 dup->top_granule=orig->top_granule;
595 dup->end_granule=orig->end_granule;
596 dup->packetno=orig->packetno;
598 dup->packet=ogg2_buffer_dup(orig->packet);