/******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: packing variable sized words into an octet stream ********************************************************************/ /* We're 'LSb' endian; if we write a word but read individual bits, then we'll read the lsb first */ #include "config-tremor.h" #include #include "ogg.h" void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){ memset(b,0,sizeof(*b)); b->tail=b->head=r; b->count=0; b->headptr=b->head->buffer->data+b->head->begin; b->headend=b->head->length; _span(b); } #define _lookspan() while(!end){\ head=head->next;\ if(!head) return -1;\ ptr=head->buffer->data + head->begin;\ end=head->length;\ } /* Read in bits without advancing the bitptr; bits <= 32 */ long oggpack_look_full(oggpack_buffer *b,int bits) ICODE_ATTR; long oggpack_look_full(oggpack_buffer *b,int bits){ unsigned long m=(1<headbit; if(bits >= b->headend<<3){ int end=b->headend; unsigned char *ptr=b->headptr; ogg_reference *head=b->head; if(end<0)return -1; if(bits){ _lookspan(); ret=*ptr++>>b->headbit; if(bits>8){ --end; _lookspan(); ret|=*ptr++<<(8-b->headbit); if(bits>16){ --end; _lookspan(); ret|=*ptr++<<(16-b->headbit); if(bits>24){ --end; _lookspan(); ret|=*ptr++<<(24-b->headbit); if(bits>32 && b->headbit){ --end; _lookspan(); ret|=*ptr<<(32-b->headbit); } } } } } }else{ /* make this a switch jump-table */ ret=b->headptr[0]>>b->headbit; if(bits>8){ ret|=b->headptr[1]<<(8-b->headbit); if(bits>16){ ret|=b->headptr[2]<<(16-b->headbit); if(bits>24){ ret|=b->headptr[3]<<(24-b->headbit); if(bits>32 && b->headbit) ret|=b->headptr[4]<<(32-b->headbit); } } } } ret&=m; return ret; } /* spans forward and finds next byte. Never halts */ static void _span_one(oggpack_buffer *b){ while(b->headend<1){ if(b->head->next){ b->count+=b->head->length; b->head=b->head->next; b->headptr=b->head->buffer->data+b->head->begin; b->headend=b->head->length; }else break; } } static int _halt_one(oggpack_buffer *b){ if(b->headend<1){ _adv_halt(b); return -1; } return 0; } int oggpack_eop(oggpack_buffer *b){ if(b->headend<0)return -1; return 0; } /* bits <= 32 */ long oggpack_read(oggpack_buffer *b,int bits){ unsigned long m=(1<headbit; if(bits >= b->headend<<3){ if(b->headend<0)return -1; if(bits){ if (_halt_one(b)) return -1; ret=*b->headptr>>b->headbit; if(bits>=8){ ++b->headptr; --b->headend; _span_one(b); if(bits>8){ if (_halt_one(b)) return -1; ret|=*b->headptr<<(8-b->headbit); if(bits>=16){ ++b->headptr; --b->headend; _span_one(b); if(bits>16){ if (_halt_one(b)) return -1; ret|=*b->headptr<<(16-b->headbit); if(bits>=24){ ++b->headptr; --b->headend; _span_one(b); if(bits>24){ if (_halt_one(b)) return -1; ret|=*b->headptr<<(24-b->headbit); if(bits>=32){ ++b->headptr; --b->headend; _span_one(b); if(bits>32){ if (_halt_one(b)) return -1; if(b->headbit)ret|=*b->headptr<<(32-b->headbit); } } } } } } } } } }else{ ret=b->headptr[0]>>b->headbit; if(bits>8){ ret|=b->headptr[1]<<(8-b->headbit); if(bits>16){ ret|=b->headptr[2]<<(16-b->headbit); if(bits>24){ ret|=b->headptr[3]<<(24-b->headbit); if(bits>32 && b->headbit){ ret|=b->headptr[4]<<(32-b->headbit); } } } } b->headptr+=bits/8; b->headend-=bits/8; } ret&=m; b->headbit=bits&7; return ret; } long oggpack_bytes(oggpack_buffer *b){ return(b->count+b->headptr-b->head->buffer->data-b->head->begin+ (b->headbit+7)/8); } long oggpack_bits(oggpack_buffer *b){ return((b->count+b->headptr-b->head->buffer->data-b->head->begin)*8+ b->headbit); }