00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include "ogg.h"
00025 #include "misc.h"
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 static ogg_buffer_state *ogg_buffer_create(void){
00036 ogg_buffer_state *bs=(ogg_buffer_state *)_ogg_calloc(1,sizeof(*bs));
00037 return bs;
00038 }
00039
00040
00041
00042
00043
00044
00045
00046
00047 static void _ogg_buffer_destroy(ogg_buffer_state *bs){
00048 ogg_buffer *bt;
00049 ogg_reference *rt;
00050
00051 if(bs->shutdown){
00052
00053 bt=bs->unused_buffers;
00054 rt=bs->unused_references;
00055
00056 while(bt){
00057 ogg_buffer *b=bt;
00058 bt=b->ptr.next;
00059 if(b->data)_ogg_free(b->data);
00060 _ogg_free(b);
00061 }
00062 bs->unused_buffers=0;
00063 while(rt){
00064 ogg_reference *r=rt;
00065 rt=r->next;
00066 _ogg_free(r);
00067 }
00068 bs->unused_references=0;
00069
00070 if(!bs->outstanding){
00071 _ogg_free(bs);
00072 return;
00073 }
00074
00075 }
00076 }
00077
00078 static void ogg_buffer_destroy(ogg_buffer_state *bs){
00079 bs->shutdown=1;
00080 _ogg_buffer_destroy(bs);
00081 }
00082
00083 static ogg_buffer *_fetch_buffer(ogg_buffer_state *bs,long bytes){
00084 ogg_buffer *ob;
00085 bs->outstanding++;
00086
00087
00088 if(bs->unused_buffers){
00089 ob=bs->unused_buffers;
00090 bs->unused_buffers=ob->ptr.next;
00091
00092
00093 if(ob->size<bytes){
00094 ob->data=(unsigned char* )_ogg_realloc(ob->data,bytes);
00095 ob->size=bytes;
00096 }
00097 }else{
00098
00099 ob=(ogg_buffer* )_ogg_malloc(sizeof(*ob));
00100 ob->data=(unsigned char* )_ogg_malloc(bytes<16?16:bytes);
00101 ob->size=bytes;
00102 }
00103
00104 ob->refcount=1;
00105 ob->ptr.owner=bs;
00106 return ob;
00107 }
00108
00109 static ogg_reference *_fetch_ref(ogg_buffer_state *bs){
00110 ogg_reference *oggref;
00111 bs->outstanding++;
00112
00113
00114 if(bs->unused_references){
00115 oggref=bs->unused_references;
00116 bs->unused_references=oggref->next;
00117 }else{
00118
00119 oggref=(ogg_reference *)_ogg_malloc(sizeof(*oggref));
00120 }
00121
00122 oggref->begin=0;
00123 oggref->length=0;
00124 oggref->next=0;
00125 return oggref;
00126 }
00127
00128
00129
00130 static ogg_reference *ogg_buffer_alloc(ogg_buffer_state *bs,long bytes){
00131 ogg_buffer *ob=_fetch_buffer(bs,bytes);
00132 ogg_reference *oggref=_fetch_ref(bs);
00133 oggref->buffer=ob;
00134 return oggref;
00135 }
00136
00137
00138 static void ogg_buffer_realloc(ogg_reference *oggref,long bytes){
00139 ogg_buffer *ob=oggref->buffer;
00140
00141
00142 if(ob->size<bytes){
00143 ob->data=(unsigned char* )_ogg_realloc(ob->data,bytes);
00144 ob->size=bytes;
00145 }
00146 }
00147
00148 static void _ogg_buffer_mark_one(ogg_reference *oggref){
00149 oggref->buffer->refcount++;
00150 }
00151
00152
00153 static void ogg_buffer_mark(ogg_reference *oggref){
00154 while(oggref){
00155 _ogg_buffer_mark_one(oggref);
00156 oggref=oggref->next;
00157 }
00158 }
00159
00160
00161
00162
00163
00164
00165 static ogg_reference *ogg_buffer_sub(ogg_reference *oggref,long begin,long length){
00166 ogg_reference *ret=0,*head=0;
00167
00168
00169 while(oggref && begin>=oggref->length){
00170 begin-=oggref->length;
00171 oggref=oggref->next;
00172 }
00173
00174
00175 while(oggref && length){
00176 ogg_reference *temp=_fetch_ref(oggref->buffer->ptr.owner);
00177 if(head)
00178 head->next=temp;
00179 else
00180 ret=temp;
00181 head=temp;
00182 head->buffer=oggref->buffer;
00183 head->begin=oggref->begin+begin;
00184 head->length=length;
00185 if(head->length>oggref->length-begin)
00186 head->length=oggref->length-begin;
00187
00188 begin=0;
00189 length-=head->length;
00190 oggref=oggref->next;
00191 }
00192
00193 ogg_buffer_mark(ret);
00194 return ret;
00195 }
00196
00197 ogg_reference *ogg_buffer_dup(ogg_reference *oggref){
00198 ogg_reference *ret=0,*head=0;
00199
00200 while(oggref){
00201 ogg_reference *temp=_fetch_ref(oggref->buffer->ptr.owner);
00202 if(head)
00203 head->next=temp;
00204 else
00205 ret=temp;
00206 head=temp;
00207 head->buffer=oggref->buffer;
00208 head->begin=oggref->begin;
00209 head->length=oggref->length;
00210 oggref=oggref->next;
00211 }
00212
00213 ogg_buffer_mark(ret);
00214 return ret;
00215 }
00216
00217
00218
00219
00220
00221 static ogg_reference *ogg_buffer_split(ogg_reference **tail,
00222 ogg_reference **head,long pos){
00223
00224
00225
00226
00227 ogg_reference *ret=*tail;
00228 ogg_reference *oggref=*tail;
00229
00230 while(oggref && pos>oggref->length){
00231 pos-=oggref->length;
00232 oggref=oggref->next;
00233 }
00234
00235 if(!oggref || pos==0){
00236
00237 return 0;
00238
00239 }else{
00240
00241 if(pos>=oggref->length){
00242
00243 if(oggref->next){
00244
00245
00246 *tail=oggref->next;
00247 oggref->next=0;
00248
00249 }else{
00250
00251
00252 *tail=*head=0;
00253
00254 }
00255 }else{
00256
00257
00258 long lengthA=pos;
00259 long beginB=oggref->begin+pos;
00260 long lengthB=oggref->length-pos;
00261
00262
00263 *tail=_fetch_ref(oggref->buffer->ptr.owner);
00264
00265 (*tail)->buffer=oggref->buffer;
00266 (*tail)->begin=beginB;
00267 (*tail)->length=lengthB;
00268 (*tail)->next=oggref->next;
00269 _ogg_buffer_mark_one(*tail);
00270 if(head && oggref==*head)*head=*tail;
00271
00272
00273 oggref->next=0;
00274 oggref->length=lengthA;
00275
00276 }
00277 }
00278 return ret;
00279 }
00280
00281 static void ogg_buffer_release_one(ogg_reference *oggref){
00282 ogg_buffer *ob=oggref->buffer;
00283 ogg_buffer_state *bs=ob->ptr.owner;
00284
00285 ob->refcount--;
00286 if(ob->refcount==0){
00287 bs->outstanding--;
00288 ob->ptr.next=bs->unused_buffers;
00289 bs->unused_buffers=ob;
00290 }
00291
00292 bs->outstanding--;
00293 oggref->next=bs->unused_references;
00294 bs->unused_references=oggref;
00295
00296 _ogg_buffer_destroy(bs);
00297
00298 }
00299
00300
00301
00302 static void ogg_buffer_release(ogg_reference *oggref){
00303 while(oggref){
00304 ogg_reference *next=oggref->next;
00305 ogg_buffer_release_one(oggref);
00306 oggref=next;
00307 }
00308 }
00309
00310 static ogg_reference *ogg_buffer_pretruncate(ogg_reference *oggref,long pos){
00311
00312 while(oggref && pos>=oggref->length){
00313 ogg_reference *next=oggref->next;
00314 pos-=oggref->length;
00315 ogg_buffer_release_one(oggref);
00316 oggref=next;
00317 }
00318 if (oggref) {
00319 oggref->begin+=pos;
00320 oggref->length-=pos;
00321 }
00322 return oggref;
00323 }
00324
00325 static ogg_reference *ogg_buffer_walk(ogg_reference *oggref){
00326 if(!oggref)return NULL;
00327 while(oggref->next){
00328 oggref=oggref->next;
00329 }
00330 return(oggref);
00331 }
00332
00333
00334
00335 static ogg_reference *ogg_buffer_cat(ogg_reference *tail, ogg_reference *head){
00336 if(!tail)return head;
00337
00338 while(tail->next){
00339 tail=tail->next;
00340 }
00341 tail->next=head;
00342 return ogg_buffer_walk(head);
00343 }
00344
00345 static void _positionB(oggbyte_buffer *b,int pos){
00346 if(pos<b->pos){
00347
00348 b->ref=b->baseref;
00349 b->pos=0;
00350 b->end=b->pos+b->ref->length;
00351 b->ptr=b->ref->buffer->data+b->ref->begin;
00352 }
00353 }
00354
00355 static void _positionF(oggbyte_buffer *b,int pos){
00356
00357 while(pos>=b->end){
00358
00359 b->pos+=b->ref->length;
00360 b->ref=b->ref->next;
00361 b->end=b->ref->length+b->pos;
00362 b->ptr=b->ref->buffer->data+b->ref->begin;
00363 }
00364 }
00365
00366 static int oggbyte_init(oggbyte_buffer *b,ogg_reference *oggref){
00367 memset(b,0,sizeof(*b));
00368 if(oggref){
00369 b->ref=b->baseref=oggref;
00370 b->pos=0;
00371 b->end=b->ref->length;
00372 b->ptr=b->ref->buffer->data+b->ref->begin;
00373 return 0;
00374 }else
00375 return -1;
00376 }
00377
00378 static void oggbyte_set4(oggbyte_buffer *b,ogg_uint32_t val,int pos){
00379 int i;
00380 _positionB(b,pos);
00381 for(i=0;i<4;i++){
00382 _positionF(b,pos);
00383 b->ptr[pos-b->pos]=val;
00384 val>>=8;
00385 ++pos;
00386 }
00387 }
00388
00389 static unsigned char oggbyte_read1(oggbyte_buffer *b,int pos){
00390 _positionB(b,pos);
00391 _positionF(b,pos);
00392 return b->ptr[pos-b->pos];
00393 }
00394
00395 static ogg_uint32_t oggbyte_read4(oggbyte_buffer *b,int pos){
00396 ogg_uint32_t ret;
00397 _positionB(b,pos);
00398 _positionF(b,pos);
00399 ret=b->ptr[pos-b->pos];
00400 _positionF(b,++pos);
00401 ret|=b->ptr[pos-b->pos]<<8;
00402 _positionF(b,++pos);
00403 ret|=b->ptr[pos-b->pos]<<16;
00404 _positionF(b,++pos);
00405 ret|=b->ptr[pos-b->pos]<<24;
00406 return ret;
00407 }
00408
00409 static ogg_int64_t oggbyte_read8(oggbyte_buffer *b,int pos){
00410 ogg_int64_t ret;
00411 unsigned char t[7];
00412 int i;
00413 _positionB(b,pos);
00414 for(i=0;i<7;i++){
00415 _positionF(b,pos);
00416 t[i]=b->ptr[pos++ -b->pos];
00417 }
00418
00419 _positionF(b,pos);
00420 ret=b->ptr[pos-b->pos];
00421
00422 for(i=6;i>=0;--i)
00423 ret= ret<<8 | t[i];
00424
00425 return ret;
00426 }
00427
00428
00429
00430 int ogg_page_version(ogg_page *og){
00431 oggbyte_buffer ob;
00432 oggbyte_init(&ob,og->header);
00433 return oggbyte_read1(&ob,4);
00434 }
00435
00436 int ogg_page_continued(ogg_page *og){
00437 oggbyte_buffer ob;
00438 oggbyte_init(&ob,og->header);
00439 return oggbyte_read1(&ob,5)&0x01;
00440 }
00441
00442 int ogg_page_bos(ogg_page *og){
00443 oggbyte_buffer ob;
00444 oggbyte_init(&ob,og->header);
00445 return oggbyte_read1(&ob,5)&0x02;
00446 }
00447
00448 int ogg_page_eos(ogg_page *og){
00449 oggbyte_buffer ob;
00450 oggbyte_init(&ob,og->header);
00451 return oggbyte_read1(&ob,5)&0x04;
00452 }
00453
00454 ogg_int64_t ogg_page_granulepos(ogg_page *og){
00455 oggbyte_buffer ob;
00456 oggbyte_init(&ob,og->header);
00457 return oggbyte_read8(&ob,6);
00458 }
00459
00460 ogg_uint32_t ogg_page_serialno(ogg_page *og){
00461 oggbyte_buffer ob;
00462 oggbyte_init(&ob,og->header);
00463 return oggbyte_read4(&ob,14);
00464 }
00465
00466 ogg_uint32_t ogg_page_pageno(ogg_page *og){
00467 oggbyte_buffer ob;
00468 oggbyte_init(&ob,og->header);
00469 return oggbyte_read4(&ob,18);
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 int ogg_page_packets(ogg_page *og){
00490 int i;
00491 int n;
00492 int count=0;
00493 oggbyte_buffer ob;
00494 oggbyte_init(&ob,og->header);
00495
00496 n=oggbyte_read1(&ob,26);
00497 for(i=0;i<n;i++)
00498 if(oggbyte_read1(&ob,27+i)<255)count++;
00499 return(count);
00500 }
00501
00502
00503
00504
00505 static ogg_uint32_t const crc_lookup[256]={
00506 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
00507 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
00508 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
00509 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
00510 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
00511 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
00512 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
00513 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
00514 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
00515 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
00516 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
00517 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
00518 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
00519 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
00520 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
00521 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
00522 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
00523 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
00524 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
00525 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
00526 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
00527 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
00528 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
00529 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
00530 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
00531 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
00532 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
00533 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
00534 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
00535 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
00536 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
00537 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
00538 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
00539 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
00540 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
00541 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
00542 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
00543 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
00544 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
00545 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
00546 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
00547 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
00548 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
00549 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
00550 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
00551 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
00552 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
00553 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
00554 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
00555 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
00556 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
00557 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
00558 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
00559 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
00560 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
00561 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
00562 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
00563 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
00564 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
00565 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
00566 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
00567 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
00568 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
00569 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
00570
00571 ogg_sync_state *ogg_sync_create(void){
00572 ogg_sync_state *oy=(ogg_sync_state *)_ogg_calloc(1,sizeof(*oy));
00573 memset(oy,0,sizeof(*oy));
00574 oy->bufferpool=ogg_buffer_create();
00575 return oy;
00576 }
00577
00578 int ogg_sync_destroy(ogg_sync_state *oy){
00579 if(oy){
00580 ogg_sync_reset(oy);
00581 ogg_buffer_destroy(oy->bufferpool);
00582 memset(oy,0,sizeof(*oy));
00583 _ogg_free(oy);
00584 }
00585 return OGG_SUCCESS;
00586 }
00587
00588 unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long bytes){
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 if(!oy->fifo_head){
00606 oy->fifo_head=oy->fifo_tail=ogg_buffer_alloc(oy->bufferpool,bytes);
00607 return oy->fifo_head->buffer->data;
00608 }
00609
00610
00611 if(oy->fifo_head->buffer->size-
00612 oy->fifo_head->length-
00613 oy->fifo_head->begin >= bytes)
00614 return oy->fifo_head->buffer->data+
00615 oy->fifo_head->length+oy->fifo_head->begin;
00616
00617
00618 if(!oy->fifo_head->length){
00619 ogg_buffer_realloc(oy->fifo_head,bytes);
00620 return oy->fifo_head->buffer->data+oy->fifo_head->begin;
00621 }
00622
00623
00624 {
00625 ogg_reference *newref=ogg_buffer_alloc(oy->bufferpool,bytes);
00626 oy->fifo_head->next=newref;
00627 oy->fifo_head=newref;
00628 }
00629 return oy->fifo_head->buffer->data;
00630 }
00631
00632 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
00633 if(!oy->fifo_head)return OGG_EINVAL;
00634 if(oy->fifo_head->buffer->size-oy->fifo_head->length-oy->fifo_head->begin <
00635 bytes)return OGG_EINVAL;
00636 oy->fifo_head->length+=bytes;
00637 oy->fifo_fill+=bytes;
00638 return OGG_SUCCESS;
00639 }
00640
00641 static ogg_uint32_t _checksum(ogg_reference *oggref, int bytes){
00642 ogg_uint32_t crc_reg=0;
00643 int j,post;
00644
00645 while(oggref){
00646 unsigned char *data=oggref->buffer->data+oggref->begin;
00647 post=(bytes<oggref->length?bytes:oggref->length);
00648 for(j=0;j<post;++j)
00649 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^data[j]];
00650 bytes-=j;
00651 oggref=oggref->next;
00652 }
00653
00654 return crc_reg;
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
00669 oggbyte_buffer page;
00670 long bytes,ret=0;
00671
00672 ogg_page_release(og);
00673
00674 bytes=oy->fifo_fill;
00675 oggbyte_init(&page,oy->fifo_tail);
00676
00677 if(oy->headerbytes==0){
00678 if(bytes<27)goto sync_out;
00679
00680
00681 if(oggbyte_read1(&page,0)!=(int)'O' ||
00682 oggbyte_read1(&page,1)!=(int)'g' ||
00683 oggbyte_read1(&page,2)!=(int)'g' ||
00684 oggbyte_read1(&page,3)!=(int)'S' ) goto sync_fail;
00685
00686 oy->headerbytes=oggbyte_read1(&page,26)+27;
00687 }
00688 if(bytes<oy->headerbytes)goto sync_out;
00689
00690 if(oy->bodybytes==0){
00691 int i;
00692
00693 for(i=0;i<oy->headerbytes-27;i++)
00694 oy->bodybytes+=oggbyte_read1(&page,27+i);
00695 }
00696
00697 if(oy->bodybytes+oy->headerbytes>bytes)goto sync_out;
00698
00699
00700
00701 {
00702 ogg_uint32_t chksum=oggbyte_read4(&page,22);
00703 oggbyte_set4(&page,0,22);
00704
00705
00706 if(chksum!=_checksum(oy->fifo_tail,oy->bodybytes+oy->headerbytes)){
00707
00708
00709
00710
00711
00712 oggbyte_set4(&page,chksum,22);
00713 goto sync_fail;
00714 }
00715 oggbyte_set4(&page,chksum,22);
00716 }
00717
00718
00719 if(og){
00720
00721 og->header=ogg_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->headerbytes);
00722 og->header_len=oy->headerbytes;
00723 og->body=ogg_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->bodybytes);
00724 og->body_len=oy->bodybytes;
00725 }else{
00726
00727 oy->fifo_tail=
00728 ogg_buffer_pretruncate(oy->fifo_tail,oy->headerbytes+oy->bodybytes);
00729 if(!oy->fifo_tail)oy->fifo_head=0;
00730 }
00731
00732 ret=oy->headerbytes+oy->bodybytes;
00733 oy->unsynced=0;
00734 oy->headerbytes=0;
00735 oy->bodybytes=0;
00736 oy->fifo_fill-=ret;
00737
00738 return ret;
00739
00740 sync_fail:
00741
00742 oy->headerbytes=0;
00743 oy->bodybytes=0;
00744 oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,1);
00745 ret--;
00746
00747
00748 while(oy->fifo_tail){
00749
00750 unsigned char *now=oy->fifo_tail->buffer->data+oy->fifo_tail->begin;
00751 unsigned char *next=(unsigned char *)memchr(now, 'O', oy->fifo_tail->length);
00752
00753 if(next){
00754
00755 long bytes=next-now;
00756 oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,bytes);
00757 ret-=bytes;
00758 break;
00759 }else{
00760
00761 long bytes=oy->fifo_tail->length;
00762 ret-=bytes;
00763 oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,bytes);
00764 }
00765 }
00766 if(!oy->fifo_tail)oy->fifo_head=0;
00767 oy->fifo_fill+=ret;
00768
00769 sync_out:
00770 return ret;
00771 }
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
00785
00786
00787
00788
00789
00790 while(1){
00791 long ret=ogg_sync_pageseek(oy,og);
00792 if(ret>0){
00793
00794 return 1;
00795 }
00796 if(ret==0){
00797
00798 return 0;
00799 }
00800
00801
00802 if(!oy->unsynced){
00803 oy->unsynced=1;
00804 return OGG_HOLE;
00805 }
00806
00807
00808
00809 }
00810 }
00811
00812
00813 int ogg_sync_reset(ogg_sync_state *oy){
00814 ogg_buffer_release(oy->fifo_tail);
00815 oy->fifo_tail=0;
00816 oy->fifo_head=0;
00817 oy->fifo_fill=0;
00818
00819 oy->unsynced=0;
00820 oy->headerbytes=0;
00821 oy->bodybytes=0;
00822 return OGG_SUCCESS;
00823 }
00824
00825 ogg_stream_state *ogg_stream_create(int serialno){
00826 ogg_stream_state *os=(ogg_stream_state *)_ogg_calloc(1,sizeof(*os));
00827 os->serialno=serialno;
00828 os->pageno=-1;
00829 return os;
00830 }
00831
00832 int ogg_stream_destroy(ogg_stream_state *os){
00833 if(os){
00834 ogg_buffer_release(os->header_tail);
00835 ogg_buffer_release(os->body_tail);
00836 memset(os,0,sizeof(*os));
00837 _ogg_free(os);
00838 }
00839 return OGG_SUCCESS;
00840 }
00841
00842
00843 #define FINFLAG 0x80000000UL
00844 #define FINMASK 0x7fffffffUL
00845
00846 static void _next_lace(oggbyte_buffer *ob,ogg_stream_state *os){
00847
00848 os->body_fill_next=0;
00849 while(os->laceptr<os->lacing_fill){
00850 int val=oggbyte_read1(ob,27+os->laceptr++);
00851 os->body_fill_next+=val;
00852 if(val<255){
00853 os->body_fill_next|=FINFLAG;
00854 os->clearflag=1;
00855 break;
00856 }
00857 }
00858 }
00859
00860 static void _span_queued_page(ogg_stream_state *os){
00861 while( !(os->body_fill&FINFLAG) ){
00862
00863 if(!os->header_tail)break;
00864
00865
00866
00867
00868 if(os->lacing_fill>=0)
00869 os->header_tail=ogg_buffer_pretruncate(os->header_tail,
00870 os->lacing_fill+27);
00871 os->lacing_fill=0;
00872 os->laceptr=0;
00873 os->clearflag=0;
00874
00875 if(!os->header_tail){
00876 os->header_head=0;
00877 break;
00878 }else{
00879
00880
00881
00882 long pageno;
00883 oggbyte_buffer ob;
00884 ogg_page og;
00885 og.header=os->header_tail;
00886 pageno=ogg_page_pageno(&og);
00887
00888 oggbyte_init(&ob,os->header_tail);
00889 os->lacing_fill=oggbyte_read1(&ob,26);
00890
00891
00892 if(pageno!=os->pageno){
00893 if(os->pageno==-1)
00894 os->holeflag=1;
00895 else
00896 os->holeflag=2;
00897
00898 os->body_tail=ogg_buffer_pretruncate(os->body_tail,
00899 os->body_fill);
00900 if(os->body_tail==0)os->body_head=0;
00901 os->body_fill=0;
00902
00903 }
00904
00905 if(ogg_page_continued(&og)){
00906 if(os->body_fill==0){
00907
00908
00909 _next_lace(&ob,os);
00910 os->body_tail=
00911 ogg_buffer_pretruncate(os->body_tail,os->body_fill_next&FINMASK);
00912 if(os->body_tail==0)os->body_head=0;
00913
00914 if(!os->spanflag && !os->holeflag)os->spanflag=2;
00915 }
00916 }else{
00917 if(os->body_fill>0){
00918
00919
00920 os->body_tail=ogg_buffer_pretruncate(os->body_tail,
00921 os->body_fill);
00922 if(os->body_tail==0)os->body_head=0;
00923 os->body_fill=0;
00924
00925
00926 if(!os->spanflag && !os->holeflag)os->spanflag=2;
00927 }
00928 }
00929
00930 if(os->laceptr<os->lacing_fill){
00931 os->granulepos=ogg_page_granulepos(&og);
00932
00933
00934 _next_lace(&ob,os);
00935 os->body_fill+=os->body_fill_next;
00936
00937
00938 _next_lace(&ob,os);
00939
00940 }
00941
00942 os->pageno=pageno+1;
00943 os->e_o_s=ogg_page_eos(&og);
00944 os->b_o_s=ogg_page_bos(&og);
00945
00946 }
00947 }
00948 }
00949
00950
00951
00952
00953 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
00954
00955 int serialno=ogg_page_serialno(og);
00956 int version=ogg_page_version(og);
00957
00958
00959 if(serialno!=os->serialno){
00960 ogg_page_release(og);
00961 return OGG_ESERIAL;
00962 }
00963 if(version>0){
00964 ogg_page_release(og);
00965 return OGG_EVERSION;
00966 }
00967
00968
00969 if(!os->body_tail){
00970 os->body_tail=og->body;
00971 os->body_head=ogg_buffer_walk(og->body);
00972 }else{
00973 os->body_head=ogg_buffer_cat(os->body_head,og->body);
00974 }
00975 if(!os->header_tail){
00976 os->header_tail=og->header;
00977 os->header_head=ogg_buffer_walk(og->header);
00978 os->lacing_fill=-27;
00979 }else{
00980 os->header_head=ogg_buffer_cat(os->header_head,og->header);
00981 }
00982
00983 memset(og,0,sizeof(*og));
00984 return OGG_SUCCESS;
00985 }
00986
00987 int ogg_stream_reset(ogg_stream_state *os){
00988
00989 ogg_buffer_release(os->header_tail);
00990 ogg_buffer_release(os->body_tail);
00991 os->header_tail=os->header_head=0;
00992 os->body_tail=os->body_head=0;
00993
00994 os->e_o_s=0;
00995 os->b_o_s=0;
00996 os->pageno=-1;
00997 os->packetno=0;
00998 os->granulepos=0;
00999
01000 os->body_fill=0;
01001 os->lacing_fill=0;
01002
01003 os->holeflag=0;
01004 os->spanflag=0;
01005 os->clearflag=0;
01006 os->laceptr=0;
01007 os->body_fill_next=0;
01008
01009 return OGG_SUCCESS;
01010 }
01011
01012 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
01013 ogg_stream_reset(os);
01014 os->serialno=serialno;
01015 return OGG_SUCCESS;
01016 }
01017
01018 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
01019
01020 ogg_packet_release(op);
01021 _span_queued_page(os);
01022
01023 if(os->holeflag){
01024 int temp=os->holeflag;
01025 if(os->clearflag)
01026 os->holeflag=0;
01027 else
01028 os->holeflag=1;
01029 if(temp==2){
01030 os->packetno++;
01031 return OGG_HOLE;
01032 }
01033 }
01034 if(os->spanflag){
01035 int temp=os->spanflag;
01036 if(os->clearflag)
01037 os->spanflag=0;
01038 else
01039 os->spanflag=1;
01040 if(temp==2){
01041 os->packetno++;
01042 return OGG_SPAN;
01043 }
01044 }
01045
01046 if(!(os->body_fill&FINFLAG)) return 0;
01047 if(!op && !adv)return 1;
01048
01049
01050 if(op){
01051 op->b_o_s=os->b_o_s;
01052 if(os->e_o_s && os->body_fill_next==0)
01053 op->e_o_s=os->e_o_s;
01054 else
01055 op->e_o_s=0;
01056 if( (os->body_fill&FINFLAG) && !(os->body_fill_next&FINFLAG) )
01057 op->granulepos=os->granulepos;
01058 else
01059 op->granulepos=-1;
01060 op->packetno=os->packetno;
01061 }
01062
01063 if(adv){
01064 oggbyte_buffer ob;
01065 oggbyte_init(&ob,os->header_tail);
01066
01067
01068 if(op){
01069 op->packet=ogg_buffer_split(&os->body_tail,&os->body_head,
01070 os->body_fill&FINMASK);
01071 op->bytes=os->body_fill&FINMASK;
01072 }else{
01073 os->body_tail=ogg_buffer_pretruncate(os->body_tail,
01074 os->body_fill&FINMASK);
01075 if(os->body_tail==0)os->body_head=0;
01076 }
01077
01078
01079 os->body_fill=os->body_fill_next;
01080 _next_lace(&ob,os);
01081 }else{
01082 if(op){
01083 op->packet=ogg_buffer_sub(os->body_tail,0,os->body_fill&FINMASK);
01084 op->bytes=os->body_fill&FINMASK;
01085 }
01086 }
01087
01088 if(adv){
01089 os->packetno++;
01090 os->b_o_s=0;
01091 }
01092
01093 return 1;
01094 }
01095
01096 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
01097 return _packetout(os,op,1);
01098 }
01099
01100 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
01101 return _packetout(os,op,0);
01102 }
01103
01104 int ogg_packet_release(ogg_packet *op) {
01105 if(op){
01106 ogg_buffer_release(op->packet);
01107 memset(op, 0, sizeof(*op));
01108 }
01109 return OGG_SUCCESS;
01110 }
01111
01112 int ogg_page_release(ogg_page *og) {
01113 if(og){
01114 ogg_buffer_release(og->header);
01115 ogg_buffer_release(og->body);
01116 memset(og, 0, sizeof(*og));
01117 }
01118 return OGG_SUCCESS;
01119 }
01120
01121 void ogg_page_dup(ogg_page *dup,ogg_page *orig){
01122 dup->header_len=orig->header_len;
01123 dup->body_len=orig->body_len;
01124 dup->header=ogg_buffer_dup(orig->header);
01125 dup->body=ogg_buffer_dup(orig->body);
01126 }
01127