Mercurial > mplayer.hg
comparison tremor/framing.c @ 15250:e891ff7a7b6c
update to libogg 1.1.2 (needed for Theora)
author | henry |
---|---|
date | Sun, 24 Apr 2005 08:37:48 +0000 |
parents | 8631a3803289 |
children | 052b4ad84883 |
comparison
equal
deleted
inserted
replaced
15249:0deaa53ed5ad | 15250:e891ff7a7b6c |
---|---|
1 /******************************************************************** | 1 /******************************************************************** |
2 * * | 2 * * |
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * | 3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC 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. * | |
4 * * | 7 * * |
5 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * | 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * |
6 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * | 9 * by the Xiph.Org Foundation http://www.xiph.org/ * |
7 * ALL REDISTRIBUTION RIGHTS RESERVED. * | |
8 * * | 10 * * |
9 ******************************************************************** | 11 ******************************************************************** |
10 | 12 |
11 function: code raw [Vorbis] packets into framed OggSquish stream and | 13 function: code raw [Vorbis] packets into framed OggSquish stream and |
12 decode Ogg streams back into raw packets | 14 decode Ogg streams back into raw packets |
15 last mod: $Id$ | |
13 | 16 |
14 note: The CRC code is directly derived from public domain code by | 17 note: The CRC code is directly derived from public domain code by |
15 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html | 18 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html |
16 for details. | 19 for details. |
17 | 20 |
90 for(i=0;i<n;i++) | 93 for(i=0;i<n;i++) |
91 if(og->header[27+i]<255)count++; | 94 if(og->header[27+i]<255)count++; |
92 return(count); | 95 return(count); |
93 } | 96 } |
94 | 97 |
95 static ogg_uint32_t crc_lookup[256]={ | 98 |
99 #if 0 | |
100 /* helper to initialize lookup for direct-table CRC (illustrative; we | |
101 use the static init below) */ | |
102 | |
103 static ogg_uint32_t _ogg_crc_entry(unsigned long index){ | |
104 int i; | |
105 unsigned long r; | |
106 | |
107 r = index << 24; | |
108 for (i=0; i<8; i++) | |
109 if (r & 0x80000000UL) | |
110 r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator | |
111 polynomial, although we use an | |
112 unreflected alg and an init/final | |
113 of 0, not 0xffffffff */ | |
114 else | |
115 r<<=1; | |
116 return (r & 0xffffffffUL); | |
117 } | |
118 #endif | |
119 | |
120 static const ogg_uint32_t crc_lookup[256]={ | |
96 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9, | 121 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9, |
97 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, | 122 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, |
98 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61, | 123 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61, |
99 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd, | 124 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd, |
100 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9, | 125 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9, |
162 | 187 |
163 int ogg_stream_init(ogg_stream_state *os,int serialno){ | 188 int ogg_stream_init(ogg_stream_state *os,int serialno){ |
164 if(os){ | 189 if(os){ |
165 memset(os,0,sizeof(*os)); | 190 memset(os,0,sizeof(*os)); |
166 os->body_storage=16*1024; | 191 os->body_storage=16*1024; |
167 os->body_data=(unsigned char *)_ogg_malloc(os->body_storage*sizeof(*os->body_data)); | 192 os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data)); |
168 | 193 |
169 os->lacing_storage=1024; | 194 os->lacing_storage=1024; |
170 os->lacing_vals=(int *)_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals)); | 195 os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals)); |
171 os->granule_vals=(ogg_int64_t *)_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals)); | 196 os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals)); |
172 | 197 |
173 os->serialno=serialno; | 198 os->serialno=serialno; |
174 | 199 |
175 return(0); | 200 return(0); |
176 } | 201 } |
201 what's happening fairly clear */ | 226 what's happening fairly clear */ |
202 | 227 |
203 static void _os_body_expand(ogg_stream_state *os,int needed){ | 228 static void _os_body_expand(ogg_stream_state *os,int needed){ |
204 if(os->body_storage<=os->body_fill+needed){ | 229 if(os->body_storage<=os->body_fill+needed){ |
205 os->body_storage+=(needed+1024); | 230 os->body_storage+=(needed+1024); |
206 os->body_data=(unsigned char *)_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data)); | 231 os->body_data=_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data)); |
207 } | 232 } |
208 } | 233 } |
209 | 234 |
210 static void _os_lacing_expand(ogg_stream_state *os,int needed){ | 235 static void _os_lacing_expand(ogg_stream_state *os,int needed){ |
211 if(os->lacing_storage<=os->lacing_fill+needed){ | 236 if(os->lacing_storage<=os->lacing_fill+needed){ |
212 os->lacing_storage+=(needed+32); | 237 os->lacing_storage+=(needed+32); |
213 os->lacing_vals=(int *)_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals)); | 238 os->lacing_vals=_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals)); |
214 os->granule_vals=(ogg_int64_t *)_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals)); | 239 os->granule_vals=_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals)); |
215 } | 240 } |
216 } | 241 } |
217 | 242 |
218 /* checksum the page */ | 243 /* checksum the page */ |
219 /* Direct table CRC; note that this will be faster in the future if we | 244 /* Direct table CRC; note that this will be faster in the future if we |
233 for(i=0;i<og->header_len;i++) | 258 for(i=0;i<og->header_len;i++) |
234 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]]; | 259 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]]; |
235 for(i=0;i<og->body_len;i++) | 260 for(i=0;i<og->body_len;i++) |
236 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]]; | 261 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]]; |
237 | 262 |
238 og->header[22]=crc_reg&0xff; | 263 og->header[22]=(unsigned char)(crc_reg&0xff); |
239 og->header[23]=(crc_reg>>8)&0xff; | 264 og->header[23]=(unsigned char)((crc_reg>>8)&0xff); |
240 og->header[24]=(crc_reg>>16)&0xff; | 265 og->header[24]=(unsigned char)((crc_reg>>16)&0xff); |
241 og->header[25]=(crc_reg>>24)&0xff; | 266 og->header[25]=(unsigned char)((crc_reg>>24)&0xff); |
242 } | 267 } |
268 } | |
269 | |
270 /* submit data to the internal buffer of the framing engine */ | |
271 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){ | |
272 int lacing_vals=op->bytes/255+1,i; | |
273 | |
274 if(os->body_returned){ | |
275 /* advance packet data according to the body_returned pointer. We | |
276 had to keep it around to return a pointer into the buffer last | |
277 call */ | |
278 | |
279 os->body_fill-=os->body_returned; | |
280 if(os->body_fill) | |
281 memmove(os->body_data,os->body_data+os->body_returned, | |
282 os->body_fill); | |
283 os->body_returned=0; | |
284 } | |
285 | |
286 /* make sure we have the buffer storage */ | |
287 _os_body_expand(os,op->bytes); | |
288 _os_lacing_expand(os,lacing_vals); | |
289 | |
290 /* Copy in the submitted packet. Yes, the copy is a waste; this is | |
291 the liability of overly clean abstraction for the time being. It | |
292 will actually be fairly easy to eliminate the extra copy in the | |
293 future */ | |
294 | |
295 memcpy(os->body_data+os->body_fill,op->packet,op->bytes); | |
296 os->body_fill+=op->bytes; | |
297 | |
298 /* Store lacing vals for this packet */ | |
299 for(i=0;i<lacing_vals-1;i++){ | |
300 os->lacing_vals[os->lacing_fill+i]=255; | |
301 os->granule_vals[os->lacing_fill+i]=os->granulepos; | |
302 } | |
303 os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255; | |
304 os->granulepos=os->granule_vals[os->lacing_fill+i]=op->granulepos; | |
305 | |
306 /* flag the first segment as the beginning of the packet */ | |
307 os->lacing_vals[os->lacing_fill]|= 0x100; | |
308 | |
309 os->lacing_fill+=lacing_vals; | |
310 | |
311 /* for the sake of completeness */ | |
312 os->packetno++; | |
313 | |
314 if(op->e_o_s)os->e_o_s=1; | |
315 | |
316 return(0); | |
317 } | |
318 | |
319 /* This will flush remaining packets into a page (returning nonzero), | |
320 even if there is not enough data to trigger a flush normally | |
321 (undersized page). If there are no packets or partial packets to | |
322 flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will | |
323 try to flush a normal sized page like ogg_stream_pageout; a call to | |
324 ogg_stream_flush does not guarantee that all packets have flushed. | |
325 Only a return value of 0 from ogg_stream_flush indicates all packet | |
326 data is flushed into pages. | |
327 | |
328 since ogg_stream_flush will flush the last page in a stream even if | |
329 it's undersized, you almost certainly want to use ogg_stream_pageout | |
330 (and *not* ogg_stream_flush) unless you specifically need to flush | |
331 an page regardless of size in the middle of a stream. */ | |
332 | |
333 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){ | |
334 int i; | |
335 int vals=0; | |
336 int maxvals=(os->lacing_fill>255?255:os->lacing_fill); | |
337 int bytes=0; | |
338 long acc=0; | |
339 ogg_int64_t granule_pos=os->granule_vals[0]; | |
340 | |
341 if(maxvals==0)return(0); | |
342 | |
343 /* construct a page */ | |
344 /* decide how many segments to include */ | |
345 | |
346 /* If this is the initial header case, the first page must only include | |
347 the initial header packet */ | |
348 if(os->b_o_s==0){ /* 'initial header page' case */ | |
349 granule_pos=0; | |
350 for(vals=0;vals<maxvals;vals++){ | |
351 if((os->lacing_vals[vals]&0x0ff)<255){ | |
352 vals++; | |
353 break; | |
354 } | |
355 } | |
356 }else{ | |
357 for(vals=0;vals<maxvals;vals++){ | |
358 if(acc>4096)break; | |
359 acc+=os->lacing_vals[vals]&0x0ff; | |
360 granule_pos=os->granule_vals[vals]; | |
361 } | |
362 } | |
363 | |
364 /* construct the header in temp storage */ | |
365 memcpy(os->header,"OggS",4); | |
366 | |
367 /* stream structure version */ | |
368 os->header[4]=0x00; | |
369 | |
370 /* continued packet flag? */ | |
371 os->header[5]=0x00; | |
372 if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01; | |
373 /* first page flag? */ | |
374 if(os->b_o_s==0)os->header[5]|=0x02; | |
375 /* last page flag? */ | |
376 if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04; | |
377 os->b_o_s=1; | |
378 | |
379 /* 64 bits of PCM position */ | |
380 for(i=6;i<14;i++){ | |
381 os->header[i]=(unsigned char)(granule_pos&0xff); | |
382 granule_pos>>=8; | |
383 } | |
384 | |
385 /* 32 bits of stream serial number */ | |
386 { | |
387 long serialno=os->serialno; | |
388 for(i=14;i<18;i++){ | |
389 os->header[i]=(unsigned char)(serialno&0xff); | |
390 serialno>>=8; | |
391 } | |
392 } | |
393 | |
394 /* 32 bits of page counter (we have both counter and page header | |
395 because this val can roll over) */ | |
396 if(os->pageno==-1)os->pageno=0; /* because someone called | |
397 stream_reset; this would be a | |
398 strange thing to do in an | |
399 encode stream, but it has | |
400 plausible uses */ | |
401 { | |
402 long pageno=os->pageno++; | |
403 for(i=18;i<22;i++){ | |
404 os->header[i]=(unsigned char)(pageno&0xff); | |
405 pageno>>=8; | |
406 } | |
407 } | |
408 | |
409 /* zero for computation; filled in later */ | |
410 os->header[22]=0; | |
411 os->header[23]=0; | |
412 os->header[24]=0; | |
413 os->header[25]=0; | |
414 | |
415 /* segment table */ | |
416 os->header[26]=(unsigned char)(vals&0xff); | |
417 for(i=0;i<vals;i++) | |
418 bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff); | |
419 | |
420 /* set pointers in the ogg_page struct */ | |
421 og->header=os->header; | |
422 og->header_len=os->header_fill=vals+27; | |
423 og->body=os->body_data+os->body_returned; | |
424 og->body_len=bytes; | |
425 | |
426 /* advance the lacing data and set the body_returned pointer */ | |
427 | |
428 os->lacing_fill-=vals; | |
429 memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals)); | |
430 memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals)); | |
431 os->body_returned+=bytes; | |
432 | |
433 /* calculate the checksum */ | |
434 | |
435 ogg_page_checksum_set(og); | |
436 | |
437 /* done */ | |
438 return(1); | |
439 } | |
440 | |
441 | |
442 /* This constructs pages from buffered packet segments. The pointers | |
443 returned are to static buffers; do not free. The returned buffers are | |
444 good only until the next call (using the same ogg_stream_state) */ | |
445 | |
446 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){ | |
447 | |
448 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ | |
449 os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */ | |
450 os->lacing_fill>=255 || /* 'segment table full' case */ | |
451 (os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */ | |
452 | |
453 return(ogg_stream_flush(os,og)); | |
454 } | |
455 | |
456 /* not enough data to construct a page and not end of stream */ | |
457 return(0); | |
458 } | |
459 | |
460 int ogg_stream_eos(ogg_stream_state *os){ | |
461 return os->e_o_s; | |
243 } | 462 } |
244 | 463 |
245 /* DECODING PRIMITIVES: packet streaming layer **********************/ | 464 /* DECODING PRIMITIVES: packet streaming layer **********************/ |
246 | 465 |
247 /* This has two layers to place more of the multi-serialno and paging | 466 /* This has two layers to place more of the multi-serialno and paging |
284 } | 503 } |
285 | 504 |
286 char *ogg_sync_buffer(ogg_sync_state *oy, long size){ | 505 char *ogg_sync_buffer(ogg_sync_state *oy, long size){ |
287 | 506 |
288 /* first, clear out any space that has been previously returned */ | 507 /* first, clear out any space that has been previously returned */ |
289 if(oy->returned>8192){ | 508 if(oy->returned){ |
290 oy->fill-=oy->returned; | 509 oy->fill-=oy->returned; |
291 if(oy->fill>0) | 510 if(oy->fill>0) |
292 memmove(oy->data,oy->data+oy->returned,oy->fill); | 511 memmove(oy->data,oy->data+oy->returned,oy->fill); |
293 oy->returned=0; | 512 oy->returned=0; |
294 } | 513 } |
296 if(size>oy->storage-oy->fill){ | 515 if(size>oy->storage-oy->fill){ |
297 /* We need to extend the internal buffer */ | 516 /* We need to extend the internal buffer */ |
298 long newsize=size+oy->fill+4096; /* an extra page to be nice */ | 517 long newsize=size+oy->fill+4096; /* an extra page to be nice */ |
299 | 518 |
300 if(oy->data) | 519 if(oy->data) |
301 oy->data=(unsigned char *)_ogg_realloc(oy->data,newsize); | 520 oy->data=_ogg_realloc(oy->data,newsize); |
302 else | 521 else |
303 oy->data=(unsigned char *)_ogg_malloc(newsize); | 522 oy->data=_ogg_malloc(newsize); |
304 oy->storage=newsize; | 523 oy->storage=newsize; |
305 } | 524 } |
306 | 525 |
307 /* expose a segment at least as large as requested at the fill mark */ | 526 /* expose a segment at least as large as requested at the fill mark */ |
308 return((char *)oy->data+oy->fill); | 527 return((char *)oy->data+oy->fill); |
399 | 618 |
400 oy->headerbytes=0; | 619 oy->headerbytes=0; |
401 oy->bodybytes=0; | 620 oy->bodybytes=0; |
402 | 621 |
403 /* search for possible capture */ | 622 /* search for possible capture */ |
404 next=(unsigned char *)memchr(page+1,'O',bytes-1); | 623 next=memchr(page+1,'O',bytes-1); |
405 if(!next) | 624 if(!next) |
406 next=oy->data+oy->fill; | 625 next=oy->data+oy->fill; |
407 | 626 |
408 oy->returned=next-oy->data; | 627 oy->returned=next-oy->data; |
409 return(-(next-page)); | 628 return(-(next-page)); |
424 | 643 |
425 /* all we need to do is verify a page at the head of the stream | 644 /* all we need to do is verify a page at the head of the stream |
426 buffer. If it doesn't verify, we look for the next potential | 645 buffer. If it doesn't verify, we look for the next potential |
427 frame */ | 646 frame */ |
428 | 647 |
429 while(1){ | 648 for(;;){ |
430 long ret=ogg_sync_pageseek(oy,og); | 649 long ret=ogg_sync_pageseek(oy,og); |
431 if(ret>0){ | 650 if(ret>0){ |
432 /* have a page */ | 651 /* have a page */ |
433 return(1); | 652 return(1); |
434 } | 653 } |
470 { | 689 { |
471 long lr=os->lacing_returned; | 690 long lr=os->lacing_returned; |
472 long br=os->body_returned; | 691 long br=os->body_returned; |
473 | 692 |
474 /* body data */ | 693 /* body data */ |
475 if(br>8192){ | 694 if(br){ |
476 os->body_fill-=br; | 695 os->body_fill-=br; |
477 if(os->body_fill) | 696 if(os->body_fill) |
478 memmove(os->body_data,os->body_data+br,os->body_fill); | 697 memmove(os->body_data,os->body_data+br,os->body_fill); |
479 os->body_returned=0; | 698 os->body_returned=0; |
480 } | 699 } |
481 | 700 |
482 if(lr>8192){ | 701 if(lr){ |
483 /* segment table */ | 702 /* segment table */ |
484 if(os->lacing_fill-lr){ | 703 if(os->lacing_fill-lr){ |
485 memmove(os->lacing_vals,os->lacing_vals+lr, | 704 memmove(os->lacing_vals,os->lacing_vals+lr, |
486 (os->lacing_fill-lr)*sizeof(*os->lacing_vals)); | 705 (os->lacing_fill-lr)*sizeof(*os->lacing_vals)); |
487 memmove(os->granule_vals,os->granule_vals+lr, | 706 memmove(os->granule_vals,os->granule_vals+lr, |
511 /* make a note of dropped data in segment table */ | 730 /* make a note of dropped data in segment table */ |
512 if(os->pageno!=-1){ | 731 if(os->pageno!=-1){ |
513 os->lacing_vals[os->lacing_fill++]=0x400; | 732 os->lacing_vals[os->lacing_fill++]=0x400; |
514 os->lacing_packet++; | 733 os->lacing_packet++; |
515 } | 734 } |
516 | 735 } |
517 /* are we a 'continued packet' page? If so, we'll need to skip | 736 |
518 some segments */ | 737 /* are we a 'continued packet' page? If so, we may need to skip |
519 if(continued){ | 738 some segments */ |
739 if(continued){ | |
740 if(os->lacing_fill<1 || | |
741 os->lacing_vals[os->lacing_fill-1]==0x400){ | |
520 bos=0; | 742 bos=0; |
521 for(;segptr<segments;segptr++){ | 743 for(;segptr<segments;segptr++){ |
522 int val=header[27+segptr]; | 744 int val=header[27+segptr]; |
523 body+=val; | 745 body+=val; |
524 bodysize-=val; | 746 bodysize-=val; |
601 os->granulepos=0; | 823 os->granulepos=0; |
602 | 824 |
603 return(0); | 825 return(0); |
604 } | 826 } |
605 | 827 |
828 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){ | |
829 ogg_stream_reset(os); | |
830 os->serialno=serialno; | |
831 return(0); | |
832 } | |
833 | |
606 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){ | 834 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){ |
607 | 835 |
608 /* The last part of decode. We have the stream broken into packet | 836 /* The last part of decode. We have the stream broken into packet |
609 segments. Now we need to group them into packets (or return the | 837 segments. Now we need to group them into packets (or return the |
610 out of sync markers) */ | 838 out of sync markers) */ |