/***************************************************************************** * * This program is free software ; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: bitstrm.h 292 2005-10-14 20:30:00Z picard $ * * The Core Pocket Media Player * Copyright (c) 2004-2005 Gabor Kovacs * ****************************************************************************/ #ifndef __BITSTRM_H #define __BITSTRM_H typedef struct bitstream { int bits; int bitpos; const uint8_t *bitptr; const uint8_t *bitend; } bitstream; // n=1..24 (or ..32 after bytealign) #define bitshow(p,n) ((uint32_t)((p)->bits << (p)->bitpos) >> (32-(n))) // n=9..32 static INLINE int bitshowlarge(bitstream* p, int n) { int i = bitshow(p,n); i |= *p->bitptr >> (40-n-p->bitpos); return i; } static INLINE void bitrewind(bitstream* p,int n) { p->bitpos += 32 - (n & 7); p->bitptr -= 4 + (n >> 3); } #define bitflush(p,n) (p)->bitpos += n; // use this only in boolean expression. to get a 1 bit value use getbits(p,1) #define bitget1(p) (((p)->bits << (p)->bitpos++) < 0) static INLINE int bitget(bitstream* p,int n) { int i = bitshow(p,n); bitflush(p,n); return i; } static INLINE const uint8_t* bitendptr(bitstream* p) { return p->bitend-4; } static INLINE uintptr_t bitendbookmark(bitstream* p) { return (uintptr_t)p->bitend*8; } static INLINE uintptr_t bitbookmark(bitstream* p) { return (uintptr_t)p->bitptr*8 + p->bitpos; } // non-exact eof, just for error checking static INLINE int biteof(bitstream* p) { return p->bitptr >= p->bitend; } static INLINE void bitbytealign(bitstream* p) { p->bitpos = ALIGN8(p->bitpos); } static INLINE int bittonextbyte(bitstream* p) { return 8-(p->bitpos & 7); } static INLINE const uint8_t *bitbytepos(bitstream* p) { return p->bitptr - 4 + ((p->bitpos+7) >> 3); } //************************************************************************ // optimized reader using one local variable #define bitload_pos(p, bitpos) \ bitpos -= 8; \ if (bitpos >= 0) { \ int bits = (p)->bits; \ const uint8_t* bitptr = (p)->bitptr; \ do { \ bits = (bits << 8) | *bitptr++; \ bitpos -= 8; \ } while (bitpos>=0); \ (p)->bits = bits; \ (p)->bitptr = bitptr; \ } \ bitpos += 8; #define bitbookmark_pos(p,bitpos) ((int)(p)->bitptr*8 + bitpos) #define bitshow_pos(p,bitpos,n) ((uint32_t)((p)->bits << bitpos) >> (32-(n))) #define bitflush_pos(p,bitpos,n) bitpos += n; #define bitget1_pos(p,bitpos) (((p)->bits << bitpos++) < 0) #define bitbytealign_pos(p,bitpos) bitpos = ALIGN8(bitpos); #define bitrewind_pos(p,bitpos,n) bitpos += 32 - ((n) & 7); (p)->bitptr -= 4 + ((n) >> 3); #define bitgetx_pos(p,bitpos,n,tmp) \ { \ tmp = (p)->bits << bitpos; \ bitflush_pos(p,bitpos,n); \ tmp >>= 1; \ tmp ^= 0x80000000; \ tmp >>= 31-n; \ n = tmp - (tmp >> 31); \ } //************************************************************************ // optimized reader using two prenamed local variables #define bitbegin_pos2(p) \ int bitpos = (p)->bitpos; \ int bits = (p)->bits; #define bitend_pos2(p) \ (p)->bitpos = bitpos; #define bitload_pos2(p) \ if (bitpos >= 8) { \ const uint8_t* bitptr = (p)->bitptr;\ do { \ bits = (bits << 8) | *bitptr++; \ bitpos -= 8; \ } while (bitpos >= 8); \ (p)->bits = bits; \ (p)->bitptr = bitptr; \ } #define bitshow_pos2(p,n) ((uint32_t)(bits << bitpos) >> (32-(n))) #define bitflush_pos2(p,n) bitpos += n #define bitget1_pos2(p) ((bits << bitpos++) < 0) #define bitsign_pos2(p) (((bits << bitpos++) >> 31)|1) //************************************************************************ #define bitloadcond(p) if ((p)->bitpos >= 8) bitload(p); #define DECLARE_BITLOAD \ static NOINLINE void bitload(bitstream* p) \ { \ bitbegin_pos2(p); \ bitload_pos2(p); \ bitend_pos2(p); \ } #define DECLARE_BITINIT \ static void bitinit(bitstream* p,const uint8_t *stream, int len) \ { \ p->bits = 0; \ p->bitpos = 32; \ p->bitptr = stream; \ p->bitend = stream+len+4; \ } static INLINE void bitsetpos(bitstream* p,const uint8_t *stream) { p->bitpos = 32; p->bitptr = stream; } #ifdef MIPS static INLINE void bitloadinline(bitstream* p) { int n = p->bitpos-8; if (n>=0) { const uint8_t* bitptr = p->bitptr; int bits = p->bits; do { bits = (bits << 8) | *bitptr++; n -= 8; } while (n>=0); p->bits = bits; p->bitptr = bitptr; p->bitpos = n+8; } } #else #define bitloadinline(p) if ((p)->bitpos >= 8) bitload(p) #endif #endif