Home | History | Annotate | Download | only in Tremolo
      1 /************************************************************************
      2  * Copyright (C) 2002-2009, Xiph.org Foundation
      3  * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  *
     10  *     * Redistributions of source code must retain the above copyright
     11  * notice, this list of conditions and the following disclaimer.
     12  *     * Redistributions in binary form must reproduce the above
     13  * copyright notice, this list of conditions and the following disclaimer
     14  * in the documentation and/or other materials provided with the
     15  * distribution.
     16  *     * Neither the names of the Xiph.org Foundation nor Pinknoise
     17  * Productions Ltd nor the names of its contributors may be used to
     18  * endorse or promote products derived from this software without
     19  * specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  ************************************************************************
     33 
     34  function: decode Ogg streams back into raw packets
     35 
     36  note: The CRC code is directly derived from public domain code by
     37  Ross Williams (ross (at) guest.adelaide.edu.au).  See docs/framing.html
     38  for details.
     39 
     40  ************************************************************************/
     41 
     42 #include <stdlib.h>
     43 #include <string.h>
     44 #include "ogg.h"
     45 #include "misc.h"
     46 
     47 
     48 /* A complete description of Ogg framing exists in docs/framing.html */
     49 
     50 /* basic, centralized Ogg memory management based on linked lists of
     51    references to refcounted memory buffers.  References and buffers
     52    are both recycled.  Buffers are passed around and consumed in
     53    reference form. */
     54 
     55 static ogg_buffer_state *ogg_buffer_create(void){
     56   ogg_buffer_state *bs=_ogg_calloc(1,sizeof(*bs));
     57   return bs;
     58 }
     59 
     60 /* destruction is 'lazy'; there may be memory references outstanding,
     61    and yanking the buffer state out from underneath would be
     62    antisocial.  Dealloc what is currently unused and have
     63    _release_one watch for the stragglers to come in.  When they do,
     64    finish destruction. */
     65 
     66 /* call the helper while holding lock */
     67 static void _ogg_buffer_destroy(ogg_buffer_state *bs){
     68   ogg_buffer *bt;
     69   ogg_reference *rt;
     70 
     71   if(bs->shutdown){
     72 
     73     bt=bs->unused_buffers;
     74     rt=bs->unused_references;
     75 
     76     while(bt){
     77       ogg_buffer *b=bt;
     78       bt=b->ptr.next;
     79       if(b->data)_ogg_free(b->data);
     80       _ogg_free(b);
     81     }
     82     bs->unused_buffers=0;
     83     while(rt){
     84       ogg_reference *r=rt;
     85       rt=r->next;
     86       _ogg_free(r);
     87     }
     88     bs->unused_references=0;
     89 
     90     if(!bs->outstanding)
     91       _ogg_free(bs);
     92 
     93   }
     94 }
     95 
     96 static void ogg_buffer_destroy(ogg_buffer_state *bs){
     97   bs->shutdown=1;
     98   _ogg_buffer_destroy(bs);
     99 }
    100 
    101 static ogg_buffer *_fetch_buffer(ogg_buffer_state *bs,long bytes){
    102   ogg_buffer    *ob;
    103   bs->outstanding++;
    104 
    105   /* do we have an unused buffer sitting in the pool? */
    106   if(bs->unused_buffers){
    107     ob=bs->unused_buffers;
    108     bs->unused_buffers=ob->ptr.next;
    109 
    110     /* if the unused buffer is too small, grow it */
    111     if(ob->size<bytes){
    112       ob->data=_ogg_realloc(ob->data,bytes);
    113       ob->size=bytes;
    114     }
    115   }else{
    116     /* allocate a new buffer */
    117     ob=_ogg_malloc(sizeof(*ob));
    118     ob->data=_ogg_malloc(bytes<16?16:bytes);
    119     ob->size=bytes;
    120   }
    121 
    122   ob->refcount=1;
    123   ob->ptr.owner=bs;
    124   return ob;
    125 }
    126 
    127 static ogg_reference *_fetch_ref(ogg_buffer_state *bs){
    128   ogg_reference *or;
    129   bs->outstanding++;
    130 
    131   /* do we have an unused reference sitting in the pool? */
    132   if(bs->unused_references){
    133     or=bs->unused_references;
    134     bs->unused_references=or->next;
    135   }else{
    136     /* allocate a new reference */
    137     or=_ogg_malloc(sizeof(*or));
    138   }
    139 
    140   or->begin=0;
    141   or->length=0;
    142   or->next=0;
    143   return or;
    144 }
    145 
    146 /* fetch a reference pointing to a fresh, initially continguous buffer
    147    of at least [bytes] length */
    148 static ogg_reference *ogg_buffer_alloc(ogg_buffer_state *bs,long bytes){
    149   ogg_buffer    *ob=_fetch_buffer(bs,bytes);
    150   ogg_reference *or=_fetch_ref(bs);
    151   or->buffer=ob;
    152   return or;
    153 }
    154 
    155 /* enlarge the data buffer in the current link */
    156 static void ogg_buffer_realloc(ogg_reference *or,long bytes){
    157   ogg_buffer    *ob=or->buffer;
    158 
    159   /* if the unused buffer is too small, grow it */
    160   if(ob->size<bytes){
    161     ob->data=_ogg_realloc(ob->data,bytes);
    162     ob->size=bytes;
    163   }
    164 }
    165 
    166 static void _ogg_buffer_mark_one(ogg_reference *or){
    167   or->buffer->refcount++;
    168 }
    169 
    170 /* increase the refcount of the buffers to which the reference points */
    171 static void ogg_buffer_mark(ogg_reference *or){
    172   while(or){
    173     _ogg_buffer_mark_one(or);
    174     or=or->next;
    175   }
    176 }
    177 
    178 /* duplicate a reference (pointing to the same actual buffer memory)
    179    and increment buffer refcount.  If the desired segment is zero
    180    length, a zero length ref is returned. */
    181 static ogg_reference *ogg_buffer_sub(ogg_reference *or,long length){
    182   ogg_reference *ret=0,*head=0;
    183 
    184   /* duplicate the reference chain; increment refcounts */
    185   while(or && length){
    186     ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner);
    187     if(head)
    188       head->next=temp;
    189     else
    190       ret=temp;
    191     head=temp;
    192     head->buffer=or->buffer;
    193     head->begin=or->begin;
    194     head->length=length;
    195     if(head->length>or->length)
    196       head->length=or->length;
    197 
    198     length-=head->length;
    199     or=or->next;
    200   }
    201 
    202   ogg_buffer_mark(ret);
    203   return ret;
    204 }
    205 
    206 ogg_reference *ogg_buffer_dup(ogg_reference *or){
    207   ogg_reference *ret=0,*head=0;
    208   /* duplicate the reference chain; increment refcounts */
    209   while(or){
    210     ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner);
    211     if(head)
    212       head->next=temp;
    213     else
    214       ret=temp;
    215     head=temp;
    216     head->buffer=or->buffer;
    217     head->begin=or->begin;
    218     head->length=or->length;
    219     or=or->next;
    220   }
    221 
    222   ogg_buffer_mark(ret);
    223   return ret;
    224 }
    225 
    226 /* split a reference into two references; 'return' is a reference to
    227    the buffer preceeding pos and 'head'/'tail' are the buffer past the
    228    split.  If pos is at or past the end of the passed in segment,
    229    'head/tail' are NULL */
    230 static ogg_reference *ogg_buffer_split(ogg_reference **tail,
    231                                 ogg_reference **head,long pos){
    232 
    233   /* walk past any preceeding fragments to one of:
    234      a) the exact boundary that seps two fragments
    235      b) the fragment that needs split somewhere in the middle */
    236   ogg_reference *ret=*tail;
    237   ogg_reference *or=*tail;
    238 
    239   while(or && pos>or->length){
    240     pos-=or->length;
    241     or=or->next;
    242   }
    243 
    244   if(!or || pos==0){
    245 
    246     return 0;
    247 
    248   }else{
    249 
    250     if(pos>=or->length){
    251       /* exact split, or off the end? */
    252       if(or->next){
    253 
    254         /* a split */
    255         *tail=or->next;
    256         or->next=0;
    257 
    258       }else{
    259 
    260         /* off or at the end */
    261         *tail=*head=0;
    262 
    263       }
    264     }else{
    265 
    266       /* split within a fragment */
    267       long lengthA=pos;
    268       long beginB=or->begin+pos;
    269       long lengthB=or->length-pos;
    270 
    271       /* make a new reference to tail the second piece */
    272       *tail=_fetch_ref(or->buffer->ptr.owner);
    273 
    274       (*tail)->buffer=or->buffer;
    275       (*tail)->begin=beginB;
    276       (*tail)->length=lengthB;
    277       (*tail)->next=or->next;
    278       _ogg_buffer_mark_one(*tail);
    279       if(head && or==*head)*head=*tail;
    280 
    281       /* update the first piece */
    282       or->next=0;
    283       or->length=lengthA;
    284 
    285     }
    286   }
    287   return ret;
    288 }
    289 
    290 static void ogg_buffer_release_one(ogg_reference *or){
    291   ogg_buffer *ob=or->buffer;
    292   ogg_buffer_state *bs=ob->ptr.owner;
    293 
    294   ob->refcount--;
    295   if(ob->refcount==0){
    296     bs->outstanding--; /* for the returned buffer */
    297     ob->ptr.next=bs->unused_buffers;
    298     bs->unused_buffers=ob;
    299   }
    300 
    301   bs->outstanding--; /* for the returned reference */
    302   or->next=bs->unused_references;
    303   bs->unused_references=or;
    304 
    305   _ogg_buffer_destroy(bs); /* lazy cleanup (if needed) */
    306 
    307 }
    308 
    309 /* release the references, decrease the refcounts of buffers to which
    310    they point, release any buffers with a refcount that drops to zero */
    311 static void ogg_buffer_release(ogg_reference *or){
    312   while(or){
    313     ogg_reference *next=or->next;
    314     ogg_buffer_release_one(or);
    315     or=next;
    316   }
    317 }
    318 
    319 static ogg_reference *ogg_buffer_pretruncate(ogg_reference *or,long pos){
    320   /* release preceeding fragments we don't want */
    321   while(or && pos>=or->length){
    322     ogg_reference *next=or->next;
    323     pos-=or->length;
    324     ogg_buffer_release_one(or);
    325     or=next;
    326   }
    327   if (or) {
    328     or->begin+=pos;
    329     or->length-=pos;
    330   }
    331   return or;
    332 }
    333 
    334 static ogg_reference *ogg_buffer_walk(ogg_reference *or){
    335   if(!or)return NULL;
    336   while(or->next){
    337     or=or->next;
    338   }
    339   return(or);
    340 }
    341 
    342 /* *head is appended to the front end (head) of *tail; both continue to
    343    be valid pointers, with *tail at the tail and *head at the head */
    344 static ogg_reference *ogg_buffer_cat(ogg_reference *tail, ogg_reference *head){
    345   if(!tail)return head;
    346 
    347   while(tail->next){
    348     tail=tail->next;
    349   }
    350   tail->next=head;
    351   return ogg_buffer_walk(head);
    352 }
    353 
    354 static void _positionB(oggbyte_buffer *b,int pos){
    355   if(pos<b->pos){
    356     /* start at beginning, scan forward */
    357     b->ref=b->baseref;
    358     b->pos=0;
    359     b->end=b->pos+b->ref->length;
    360     b->ptr=b->ref->buffer->data+b->ref->begin;
    361   }
    362 }
    363 
    364 static void _positionF(oggbyte_buffer *b,int pos){
    365   /* scan forward for position */
    366   while(pos>=b->end){
    367     /* just seek forward */
    368     b->pos+=b->ref->length;
    369     b->ref=b->ref->next;
    370     b->end=b->ref->length+b->pos;
    371     b->ptr=b->ref->buffer->data+b->ref->begin;
    372   }
    373 }
    374 
    375 static int oggbyte_init(oggbyte_buffer *b,ogg_reference *or){
    376   memset(b,0,sizeof(*b));
    377   if(or){
    378     b->ref=b->baseref=or;
    379     b->pos=0;
    380     b->end=b->ref->length;
    381     b->ptr=b->ref->buffer->data+b->ref->begin;
    382     return 0;
    383   }else
    384     return -1;
    385 }
    386 
    387 static void oggbyte_set4(oggbyte_buffer *b,ogg_uint32_t val,int pos){
    388   int i;
    389   _positionB(b,pos);
    390   for(i=0;i<4;i++){
    391     _positionF(b,pos);
    392     b->ptr[pos-b->pos]=val;
    393     val>>=8;
    394     ++pos;
    395   }
    396 }
    397 
    398 static unsigned char oggbyte_read1(oggbyte_buffer *b,int pos){
    399   _positionB(b,pos);
    400   _positionF(b,pos);
    401   return b->ptr[pos-b->pos];
    402 }
    403 
    404 static ogg_uint32_t oggbyte_read4(oggbyte_buffer *b,int pos){
    405   ogg_uint32_t ret;
    406   _positionB(b,pos);
    407   _positionF(b,pos);
    408   ret=b->ptr[pos-b->pos];
    409   _positionF(b,++pos);
    410   ret|=b->ptr[pos-b->pos]<<8;
    411   _positionF(b,++pos);
    412   ret|=b->ptr[pos-b->pos]<<16;
    413   _positionF(b,++pos);
    414   ret|=b->ptr[pos-b->pos]<<24;
    415   return ret;
    416 }
    417 
    418 static ogg_int64_t oggbyte_read8(oggbyte_buffer *b,int pos){
    419   ogg_int64_t ret;
    420   unsigned char t[7];
    421   int i;
    422   _positionB(b,pos);
    423   for(i=0;i<7;i++){
    424     _positionF(b,pos);
    425     t[i]=b->ptr[pos++ -b->pos];
    426   }
    427 
    428   _positionF(b,pos);
    429   ret=b->ptr[pos-b->pos];
    430 
    431   for(i=6;i>=0;--i)
    432     ret= ret<<8 | t[i];
    433 
    434   return ret;
    435 }
    436 
    437 /* Now we get to the actual framing code */
    438 
    439 int ogg_page_version(ogg_page *og){
    440   oggbyte_buffer ob;
    441   if(oggbyte_init(&ob,og->header))return -1;
    442   return oggbyte_read1(&ob,4);
    443 }
    444 
    445 int ogg_page_continued(ogg_page *og){
    446   oggbyte_buffer ob;
    447   if(oggbyte_init(&ob,og->header))return -1;
    448   return oggbyte_read1(&ob,5)&0x01;
    449 }
    450 
    451 int ogg_page_bos(ogg_page *og){
    452   oggbyte_buffer ob;
    453   if(oggbyte_init(&ob,og->header))return -1;
    454   return oggbyte_read1(&ob,5)&0x02;
    455 }
    456 
    457 int ogg_page_eos(ogg_page *og){
    458   oggbyte_buffer ob;
    459   if(oggbyte_init(&ob,og->header))return -1;
    460   return oggbyte_read1(&ob,5)&0x04;
    461 }
    462 
    463 ogg_int64_t ogg_page_granulepos(ogg_page *og){
    464   oggbyte_buffer ob;
    465   if(oggbyte_init(&ob,og->header))return -1;
    466   return oggbyte_read8(&ob,6);
    467 }
    468 
    469 ogg_uint32_t ogg_page_serialno(ogg_page *og){
    470   oggbyte_buffer ob;
    471   if(oggbyte_init(&ob,og->header)) return 0xffffffffUL;
    472   return oggbyte_read4(&ob,14);
    473 }
    474 
    475 ogg_uint32_t ogg_page_pageno(ogg_page *og){
    476   oggbyte_buffer ob;
    477   if(oggbyte_init(&ob,og->header))return 0xffffffffUL;
    478   return oggbyte_read4(&ob,18);
    479 }
    480 
    481 /* returns the number of packets that are completed on this page (if
    482    the leading packet is begun on a previous page, but ends on this
    483    page, it's counted */
    484 
    485 /* NOTE:
    486 If a page consists of a packet begun on a previous page, and a new
    487 packet begun (but not completed) on this page, the return will be:
    488   ogg_page_packets(page)   ==1,
    489   ogg_page_continued(page) !=0
    490 
    491 If a page happens to be a single packet that was begun on a
    492 previous page, and spans to the next page (in the case of a three or
    493 more page packet), the return will be:
    494   ogg_page_packets(page)   ==0,
    495   ogg_page_continued(page) !=0
    496 */
    497 
    498 int ogg_page_packets(ogg_page *og){
    499   int i;
    500   int n;
    501   int count=0;
    502   oggbyte_buffer ob;
    503   oggbyte_init(&ob,og->header);
    504 
    505   n=oggbyte_read1(&ob,26);
    506   for(i=0;i<n;i++)
    507     if(oggbyte_read1(&ob,27+i)<255)count++;
    508   return(count);
    509 }
    510 
    511 /* Static CRC calculation table.  See older code in CVS for dead
    512    run-time initialization code. */
    513 
    514 ogg_uint32_t crc_lookup[256]={
    515   0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
    516   0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
    517   0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
    518   0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
    519   0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
    520   0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
    521   0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
    522   0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
    523   0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
    524   0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
    525   0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
    526   0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
    527   0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
    528   0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
    529   0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
    530   0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
    531   0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
    532   0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
    533   0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
    534   0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
    535   0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
    536   0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
    537   0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
    538   0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
    539   0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
    540   0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
    541   0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
    542   0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
    543   0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
    544   0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
    545   0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
    546   0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
    547   0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
    548   0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
    549   0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
    550   0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
    551   0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
    552   0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
    553   0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
    554   0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
    555   0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
    556   0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
    557   0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
    558   0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
    559   0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
    560   0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
    561   0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
    562   0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
    563   0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
    564   0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
    565   0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
    566   0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
    567   0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
    568   0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
    569   0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
    570   0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
    571   0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
    572   0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
    573   0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
    574   0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
    575   0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
    576   0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
    577   0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
    578   0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
    579 
    580 void ogg_sync_init(ogg_sync_state *oy){
    581   memset(oy,0,sizeof(*oy));
    582   oy->bufferpool=ogg_buffer_create();
    583 }
    584 
    585 ogg_sync_state *ogg_sync_create(void){
    586   ogg_sync_state *oy=_ogg_calloc(1,sizeof(*oy));
    587   memset(oy,0,sizeof(*oy));
    588   oy->bufferpool=ogg_buffer_create();
    589   return oy;
    590 }
    591 
    592 int ogg_sync_clear(ogg_sync_state *oy){
    593   if(oy){
    594     ogg_sync_reset(oy);
    595     ogg_buffer_destroy(oy->bufferpool);
    596     memset(oy,0,sizeof(*oy));
    597   }
    598   return OGG_SUCCESS;
    599 }
    600 
    601 int ogg_sync_destroy(ogg_sync_state *oy){
    602   if(oy){
    603     ogg_sync_reset(oy);
    604     ogg_buffer_destroy(oy->bufferpool);
    605     memset(oy,0,sizeof(*oy));
    606     _ogg_free(oy);
    607   }
    608   return OGG_SUCCESS;
    609 }
    610 
    611 unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long bytes){
    612 
    613   /* [allocate and] expose a buffer for data submission.
    614 
    615      If there is no head fragment
    616        allocate one and expose it
    617      else
    618        if the current head fragment has sufficient unused space
    619          expose it
    620        else
    621          if the current head fragment is unused
    622            resize and expose it
    623          else
    624            allocate new fragment and expose it
    625   */
    626 
    627   /* base case; fifo uninitialized */
    628   if(!oy->fifo_head){
    629     oy->fifo_head=oy->fifo_tail=ogg_buffer_alloc(oy->bufferpool,bytes);
    630     return oy->fifo_head->buffer->data;
    631   }
    632 
    633   /* space left in current fragment case */
    634   if(oy->fifo_head->buffer->size-
    635      oy->fifo_head->length-
    636      oy->fifo_head->begin >= bytes)
    637     return oy->fifo_head->buffer->data+
    638       oy->fifo_head->length+oy->fifo_head->begin;
    639 
    640   /* current fragment is unused, but too small */
    641   if(!oy->fifo_head->length){
    642     ogg_buffer_realloc(oy->fifo_head,bytes);
    643     return oy->fifo_head->buffer->data+oy->fifo_head->begin;
    644   }
    645 
    646   /* current fragment used/full; get new fragment */
    647   {
    648     ogg_reference *new=ogg_buffer_alloc(oy->bufferpool,bytes);
    649     oy->fifo_head->next=new;
    650     oy->fifo_head=new;
    651   }
    652   return oy->fifo_head->buffer->data;
    653 }
    654 
    655 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
    656   if(!oy->fifo_head)return OGG_EINVAL;
    657   if(oy->fifo_head->buffer->size-oy->fifo_head->length-oy->fifo_head->begin <
    658      bytes)return OGG_EINVAL;
    659   oy->fifo_head->length+=bytes;
    660   oy->fifo_fill+=bytes;
    661   return OGG_SUCCESS;
    662 }
    663 
    664 #ifndef ONLY_C
    665 ogg_uint32_t _checksum(ogg_reference *or, int bytes);
    666 #else
    667 static ogg_uint32_t _checksum(ogg_reference *or, int bytes){
    668   ogg_uint32_t crc_reg=0;
    669   int j,post;
    670 
    671   while(or){
    672     unsigned char *data=or->buffer->data+or->begin;
    673     post=(bytes<or->length?bytes:or->length);
    674     for(j=0;j<post;++j)
    675       crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^data[j]];
    676     bytes-=j;
    677     or=or->next;
    678   }
    679 
    680   return crc_reg;
    681 }
    682 #endif
    683 
    684 /* sync the stream.  This is meant to be useful for finding page
    685    boundaries.
    686 
    687    return values for this:
    688   -n) skipped n bytes
    689    0) page not ready; more data (no bytes skipped)
    690    n) page synced at current location; page length n bytes
    691 
    692 */
    693 
    694 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
    695   oggbyte_buffer page;
    696   long           bytes,ret=0;
    697 
    698   ogg_page_release(og);
    699 
    700   bytes=oy->fifo_fill;
    701   oggbyte_init(&page,oy->fifo_tail);
    702 
    703   if(oy->headerbytes==0){
    704     if(bytes<27)goto sync_out; /* not enough for even a minimal header */
    705 
    706     /* verify capture pattern */
    707     if(oggbyte_read1(&page,0)!=(int)'O' ||
    708        oggbyte_read1(&page,1)!=(int)'g' ||
    709        oggbyte_read1(&page,2)!=(int)'g' ||
    710        oggbyte_read1(&page,3)!=(int)'S'    ) goto sync_fail;
    711 
    712     oy->headerbytes=oggbyte_read1(&page,26)+27;
    713   }
    714   if(bytes<oy->headerbytes)goto sync_out; /* not enough for header +
    715                                              seg table */
    716   if(oy->bodybytes==0){
    717     int i;
    718     /* count up body length in the segment table */
    719     for(i=0;i<oy->headerbytes-27;i++)
    720       oy->bodybytes+=oggbyte_read1(&page,27+i);
    721   }
    722 
    723   if(oy->bodybytes+oy->headerbytes>bytes)goto sync_out;
    724 
    725   /* we have what appears to be a complete page; last test: verify
    726      checksum */
    727   {
    728     ogg_uint32_t chksum=oggbyte_read4(&page,22);
    729     oggbyte_set4(&page,0,22);
    730 
    731     /* Compare checksums; memory continues to be common access */
    732     if(chksum!=_checksum(oy->fifo_tail,oy->bodybytes+oy->headerbytes)){
    733 
    734       /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
    735          at all). replace the computed checksum with the one actually
    736          read in; remember all the memory is common access */
    737 
    738       oggbyte_set4(&page,chksum,22);
    739       goto sync_fail;
    740     }
    741     oggbyte_set4(&page,chksum,22);
    742   }
    743 
    744   /* We have a page.  Set up page return. */
    745   if(og){
    746     /* set up page output */
    747     og->header=ogg_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->headerbytes);
    748     og->header_len=oy->headerbytes;
    749     og->body=ogg_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->bodybytes);
    750     og->body_len=oy->bodybytes;
    751   }else{
    752     /* simply advance */
    753     oy->fifo_tail=
    754       ogg_buffer_pretruncate(oy->fifo_tail,oy->headerbytes+oy->bodybytes);
    755     if(!oy->fifo_tail)oy->fifo_head=0;
    756   }
    757 
    758   ret=oy->headerbytes+oy->bodybytes;
    759   oy->unsynced=0;
    760   oy->headerbytes=0;
    761   oy->bodybytes=0;
    762   oy->fifo_fill-=ret;
    763 
    764   return ret;
    765 
    766  sync_fail:
    767 
    768   oy->headerbytes=0;
    769   oy->bodybytes=0;
    770   oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,1);
    771   ret--;
    772 
    773   /* search forward through fragments for possible capture */
    774   while(oy->fifo_tail){
    775     /* invariant: fifo_cursor points to a position in fifo_tail */
    776     unsigned char *now=oy->fifo_tail->buffer->data+oy->fifo_tail->begin;
    777     unsigned char *next=memchr(now, 'O', oy->fifo_tail->length);
    778 
    779     if(next){
    780       /* possible capture in this segment */
    781       long bytes=next-now;
    782       oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,bytes);
    783       ret-=bytes;
    784       break;
    785     }else{
    786       /* no capture.  advance to next segment */
    787       long bytes=oy->fifo_tail->length;
    788       ret-=bytes;
    789       oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,bytes);
    790     }
    791   }
    792   if(!oy->fifo_tail)oy->fifo_head=0;
    793   oy->fifo_fill+=ret;
    794 
    795  sync_out:
    796   return ret;
    797 }
    798 
    799 /* sync the stream and get a page.  Keep trying until we find a page.
    800    Supress 'sync errors' after reporting the first.
    801 
    802    return values:
    803    OGG_HOLE) recapture (hole in data)
    804           0) need more data
    805           1) page returned
    806 
    807    Returns pointers into buffered data; invalidated by next call to
    808    _stream, _clear, _init, or _buffer */
    809 
    810 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
    811 
    812   /* all we need to do is verify a page at the head of the stream
    813      buffer.  If it doesn't verify, we look for the next potential
    814      frame */
    815 
    816   while(1){
    817     long ret=ogg_sync_pageseek(oy,og);
    818     if(ret>0){
    819       /* have a page */
    820       return 1;
    821     }
    822     if(ret==0){
    823       /* need more data */
    824       return 0;
    825     }
    826 
    827     /* head did not start a synced page... skipped some bytes */
    828     if(!oy->unsynced){
    829       oy->unsynced=1;
    830       return OGG_HOLE;
    831     }
    832 
    833     /* loop. keep looking */
    834 
    835   }
    836 }
    837 
    838 /* clear things to an initial state.  Good to call, eg, before seeking */
    839 int ogg_sync_reset(ogg_sync_state *oy){
    840 
    841   ogg_buffer_release(oy->fifo_tail);
    842   oy->fifo_tail=0;
    843   oy->fifo_head=0;
    844   oy->fifo_fill=0;
    845 
    846   oy->unsynced=0;
    847   oy->headerbytes=0;
    848   oy->bodybytes=0;
    849   return OGG_SUCCESS;
    850 }
    851 
    852 void ogg_stream_init(ogg_stream_state *os, int serialno){
    853   memset(os, 0, sizeof(*os));
    854   os->serialno=serialno;
    855   os->pageno=-1;
    856 }
    857 
    858 ogg_stream_state *ogg_stream_create(int serialno){
    859   ogg_stream_state *os=_ogg_calloc(1,sizeof(*os));
    860   os->serialno=serialno;
    861   os->pageno=-1;
    862   return os;
    863 }
    864 
    865 int ogg_stream_clear(ogg_stream_state *os){
    866   if(os){
    867     ogg_buffer_release(os->header_tail);
    868     ogg_buffer_release(os->body_tail);
    869     memset(os,0,sizeof(*os));
    870   }
    871   return OGG_SUCCESS;
    872 }
    873 
    874 int ogg_stream_destroy(ogg_stream_state *os){
    875   if(os){
    876     ogg_buffer_release(os->header_tail);
    877     ogg_buffer_release(os->body_tail);
    878     memset(os,0,sizeof(*os));
    879     _ogg_free(os);
    880   }
    881   return OGG_SUCCESS;
    882 }
    883 
    884 
    885 #define FINFLAG 0x80000000UL
    886 #define FINMASK 0x7fffffffUL
    887 
    888 static void _next_lace(oggbyte_buffer *ob,ogg_stream_state *os){
    889   /* search ahead one lace */
    890   os->body_fill_next=0;
    891   while(os->laceptr<os->lacing_fill){
    892     int val=oggbyte_read1(ob,27+os->laceptr++);
    893     os->body_fill_next+=val;
    894     if(val<255){
    895       os->body_fill_next|=FINFLAG;
    896       os->clearflag=1;
    897       break;
    898     }
    899   }
    900 }
    901 
    902 static void _span_queued_page(ogg_stream_state *os){
    903   while( !(os->body_fill&FINFLAG) ){
    904 
    905     if(!os->header_tail)break;
    906 
    907     /* first flush out preceeding page header (if any).  Body is
    908        flushed as it's consumed, so that's not done here. */
    909 
    910     if(os->lacing_fill>=0)
    911       os->header_tail=ogg_buffer_pretruncate(os->header_tail,
    912                                              os->lacing_fill+27);
    913     os->lacing_fill=0;
    914     os->laceptr=0;
    915     os->clearflag=0;
    916 
    917     if(!os->header_tail){
    918       os->header_head=0;
    919       break;
    920     }else{
    921 
    922       /* process/prepare next page, if any */
    923 
    924       long pageno;
    925       oggbyte_buffer ob;
    926       ogg_page og;               /* only for parsing header values */
    927       og.header=os->header_tail; /* only for parsing header values */
    928       pageno=ogg_page_pageno(&og);
    929 
    930       oggbyte_init(&ob,os->header_tail);
    931       os->lacing_fill=oggbyte_read1(&ob,26);
    932 
    933       /* are we in sequence? */
    934       if(pageno!=os->pageno){
    935         if(os->pageno==-1) /* indicates seek or reset */
    936           os->holeflag=1;  /* set for internal use */
    937         else
    938           os->holeflag=2;  /* set for external reporting */
    939 
    940         os->body_tail=ogg_buffer_pretruncate(os->body_tail,
    941                                              os->body_fill);
    942         if(os->body_tail==0)os->body_head=0;
    943         os->body_fill=0;
    944 
    945       }
    946 
    947       if(ogg_page_continued(&og)){
    948         if(os->body_fill==0){
    949           /* continued packet, but no preceeding data to continue */
    950           /* dump the first partial packet on the page */
    951           _next_lace(&ob,os);
    952           os->body_tail=
    953             ogg_buffer_pretruncate(os->body_tail,os->body_fill_next&FINMASK);
    954           if(os->body_tail==0)os->body_head=0;
    955           /* set span flag */
    956           if(!os->spanflag && !os->holeflag)os->spanflag=2;
    957         }
    958       }else{
    959         if(os->body_fill>0){
    960           /* preceeding data to continue, but not a continued page */
    961           /* dump body_fill */
    962           os->body_tail=ogg_buffer_pretruncate(os->body_tail,
    963                                                os->body_fill);
    964           if(os->body_tail==0)os->body_head=0;
    965           os->body_fill=0;
    966 
    967           /* set espan flag */
    968           if(!os->spanflag && !os->holeflag)os->spanflag=2;
    969         }
    970       }
    971 
    972       if(os->laceptr<os->lacing_fill){
    973         os->granulepos=ogg_page_granulepos(&og);
    974 
    975         /* get current packet size & flag */
    976         _next_lace(&ob,os);
    977         os->body_fill+=os->body_fill_next; /* addition handles the flag fine;
    978                                              unsigned on purpose */
    979         /* ...and next packet size & flag */
    980         _next_lace(&ob,os);
    981 
    982       }
    983 
    984       os->pageno=pageno+1;
    985       os->e_o_s=ogg_page_eos(&og);
    986       os->b_o_s=ogg_page_bos(&og);
    987 
    988     }
    989   }
    990 }
    991 
    992 /* add the incoming page to the stream state; we decompose the page
    993    into packet segments here as well. */
    994 
    995 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
    996 
    997   int serialno=ogg_page_serialno(og);
    998   int version=ogg_page_version(og);
    999 
   1000   /* check the serial number */
   1001   if(serialno!=os->serialno){
   1002     //ogg_page_release(og);
   1003     return OGG_ESERIAL;
   1004   }
   1005   if(version>0){
   1006     //ogg_page_release(og);
   1007     return OGG_EVERSION;
   1008   }
   1009 
   1010   /* add to fifos */
   1011   if(!os->body_tail){
   1012     os->body_tail=og->body;
   1013     os->body_head=ogg_buffer_walk(og->body);
   1014   }else{
   1015     os->body_head=ogg_buffer_cat(os->body_head,og->body);
   1016   }
   1017   if(!os->header_tail){
   1018     os->header_tail=og->header;
   1019     os->header_head=ogg_buffer_walk(og->header);
   1020     os->lacing_fill=-27;
   1021   }else{
   1022     os->header_head=ogg_buffer_cat(os->header_head,og->header);
   1023   }
   1024 
   1025   memset(og,0,sizeof(*og));
   1026   return OGG_SUCCESS;
   1027 }
   1028 
   1029 int ogg_stream_reset(ogg_stream_state *os){
   1030 
   1031   ogg_buffer_release(os->header_tail);
   1032   ogg_buffer_release(os->body_tail);
   1033   os->header_tail=os->header_head=0;
   1034   os->body_tail=os->body_head=0;
   1035 
   1036   os->e_o_s=0;
   1037   os->b_o_s=0;
   1038   os->pageno=-1;
   1039   os->packetno=0;
   1040   os->granulepos=0;
   1041 
   1042   os->body_fill=0;
   1043   os->lacing_fill=0;
   1044 
   1045   os->holeflag=0;
   1046   os->spanflag=0;
   1047   os->clearflag=0;
   1048   os->laceptr=0;
   1049   os->body_fill_next=0;
   1050 
   1051   return OGG_SUCCESS;
   1052 }
   1053 
   1054 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
   1055   ogg_stream_reset(os);
   1056   os->serialno=serialno;
   1057   return OGG_SUCCESS;
   1058 }
   1059 
   1060 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
   1061 
   1062   ogg_packet_release(op);
   1063   _span_queued_page(os);
   1064 
   1065   if(os->holeflag){
   1066     int temp=os->holeflag;
   1067     if(os->clearflag)
   1068       os->holeflag=0;
   1069     else
   1070       os->holeflag=1;
   1071     if(temp==2){
   1072       os->packetno++;
   1073       return OGG_HOLE;
   1074     }
   1075   }
   1076   if(os->spanflag){
   1077     int temp=os->spanflag;
   1078     if(os->clearflag)
   1079       os->spanflag=0;
   1080     else
   1081       os->spanflag=1;
   1082     if(temp==2){
   1083       os->packetno++;
   1084       return OGG_SPAN;
   1085     }
   1086   }
   1087 
   1088   if(!(os->body_fill&FINFLAG)) return 0;
   1089   if(!op && !adv)return 1; /* just using peek as an inexpensive way
   1090                                to ask if there's a whole packet
   1091                                waiting */
   1092   if(op){
   1093     op->b_o_s=os->b_o_s;
   1094     if(os->e_o_s && os->body_fill_next==0)
   1095       op->e_o_s=os->e_o_s;
   1096     else
   1097       op->e_o_s=0;
   1098     if( (os->body_fill&FINFLAG) && !(os->body_fill_next&FINFLAG) )
   1099       op->granulepos=os->granulepos;
   1100     else
   1101       op->granulepos=-1;
   1102     op->packetno=os->packetno;
   1103   }
   1104 
   1105   if(adv){
   1106     oggbyte_buffer ob;
   1107     oggbyte_init(&ob,os->header_tail);
   1108 
   1109     /* split the body contents off */
   1110     if(op){
   1111       op->packet=ogg_buffer_split(&os->body_tail,&os->body_head,
   1112 				  os->body_fill&FINMASK);
   1113       op->bytes=os->body_fill&FINMASK;
   1114     }else{
   1115       os->body_tail=ogg_buffer_pretruncate(os->body_tail,
   1116 					   os->body_fill&FINMASK);
   1117       if(os->body_tail==0)os->body_head=0;
   1118     }
   1119 
   1120     /* update lacing pointers */
   1121     os->body_fill=os->body_fill_next;
   1122     _next_lace(&ob,os);
   1123   }else{
   1124     if(op){
   1125       op->packet=ogg_buffer_sub(os->body_tail,os->body_fill&FINMASK);
   1126       op->bytes=os->body_fill&FINMASK;
   1127     }
   1128   }
   1129 
   1130   if(adv){
   1131     os->packetno++;
   1132     os->b_o_s=0;
   1133   }
   1134 
   1135   return 1;
   1136 }
   1137 
   1138 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
   1139   return _packetout(os,op,1);
   1140 }
   1141 
   1142 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
   1143   return _packetout(os,op,0);
   1144 }
   1145 
   1146 int ogg_packet_release(ogg_packet *op) {
   1147   if(op){
   1148     ogg_buffer_release(op->packet);
   1149     memset(op, 0, sizeof(*op));
   1150   }
   1151   return OGG_SUCCESS;
   1152 }
   1153 
   1154 int ogg_page_release(ogg_page *og) {
   1155   if(og){
   1156     ogg_buffer_release(og->header);
   1157     ogg_buffer_release(og->body);
   1158     memset(og, 0, sizeof(*og));
   1159   }
   1160   return OGG_SUCCESS;
   1161 }
   1162 
   1163 void ogg_page_dup(ogg_page *dup,ogg_page *orig){
   1164   dup->header_len=orig->header_len;
   1165   dup->body_len=orig->body_len;
   1166   dup->header=ogg_buffer_dup(orig->header);
   1167   dup->body=ogg_buffer_dup(orig->body);
   1168 }
   1169 
   1170