BltBitStream.h

Go to the documentation of this file.
00001 /*****************************************************************
00002 |
00003 |   BlueTune - Bit Streams
00004 |
00005 |   (c) 2002-2007 Gilles Boccon-Gibod
00006 |   Author: Gilles Boccon-Gibod (bok@bok.net)
00007 |
00008  ****************************************************************/
00013 #ifndef _BLT_BIT_STREAM_H_
00014 #define _BLT_BIT_STREAM_H_
00015 
00016 /*----------------------------------------------------------------------
00017 |       includes
00018 +---------------------------------------------------------------------*/
00019 #include "BltConfig.h"
00020 #include "BltTypes.h"
00021 #include "BltErrors.h"
00022 
00023 /*----------------------------------------------------------------------
00024 |       types helpers
00025 +---------------------------------------------------------------------*/
00026 /* use long by default */
00027 typedef BLT_UInt32 BLT_BitsWord;
00028 #define BLT_WORD_BITS  32
00029 #define BLT_WORD_BYTES 4
00030 
00031 /*----------------------------------------------------------------------
00032 |       types
00033 +---------------------------------------------------------------------*/
00034 typedef struct BLT_BitStream
00035 {
00036     unsigned char* buffer;
00037     BLT_Size       buffer_size;
00038     BLT_Size       data_size;
00039     unsigned int   pos;
00040     BLT_BitsWord   cache;
00041     unsigned int   bits_cached;
00042 } BLT_BitStream;
00043 
00044 /*----------------------------------------------------------------------
00045 |       prototypes
00046 +---------------------------------------------------------------------*/
00047 #ifdef __cplusplus
00048 extern "C" {
00049 #endif /* __cplusplus */
00050     
00051 BLT_Result BLT_BitStream_Construct(BLT_BitStream* bits, BLT_Size size);
00052 BLT_Result BLT_BitStream_Destruct(BLT_BitStream* bits);
00053 BLT_Result BLT_BitStream_SetData(BLT_BitStream*       bits, 
00054                                  const unsigned char* data, 
00055                                  BLT_Size             data_size);
00056 BLT_Result BLT_BitStream_ByteAlign(BLT_BitStream* bits);
00057 BLT_Result BLT_BitStream_Reset(BLT_BitStream* bits);
00058 BLT_Size   BLT_BitStream_GetBitsLeft(BLT_BitStream* bits);
00059 
00060 #ifdef __cplusplus
00061 }
00062 #endif /* __cplusplus */
00063     
00064 /*----------------------------------------------------------------------
00065 |       macros
00066 +---------------------------------------------------------------------*/
00067 #define BLT_BIT_MASK(_n) ((1<<(_n))-1)
00068 
00069 /*
00070 ==============================================================================
00071 Name: BLT_BitStream_ReadCache
00072 Description:
00073    This is a private function, for internal use.
00074    Reads bytes to get cached bits.
00075 Input parameters:
00076     - bits_ptr: Pointer on the BitStream structure
00077 Returns: The cached bits
00078 ==============================================================================
00079 */
00080 
00081 static inline BLT_BitsWord
00082 BLT_BitStream_ReadCache (const BLT_BitStream* bits_ptr)
00083 {
00084    unsigned int   pos = bits_ptr->pos;
00085 
00086 #if BLT_WORD_BITS != 32
00087 #error unsupported word size /* 64 and other word size not yet implemented */
00088 #endif
00089 
00090    if (pos > bits_ptr->buffer_size - BLT_WORD_BYTES) return 0;
00091 
00092    {
00093       unsigned char *in = &bits_ptr->buffer[pos];
00094       return    (((BLT_BitsWord) in[0]) << 24)
00095               | (((BLT_BitsWord) in[1]) << 16)
00096               | (((BLT_BitsWord) in[2]) <<  8)
00097               | (((BLT_BitsWord) in[3])      );
00098    }
00099 }
00100 
00101 /*----------------------------------------------------------------------
00102 |       BLT_BitStream_ReadBits
00103 +---------------------------------------------------------------------*/
00104 static inline unsigned int
00105 BLT_BitStream_ReadBits(BLT_BitStream* bits, unsigned int n)
00106 {
00107     BLT_BitsWord  result;
00108     if (bits->bits_cached >= n) {
00109         /* we have enough bits in the cache to satisfy the request */
00110         bits->bits_cached -= n;
00111         result = (bits->cache >> bits->bits_cached) & BLT_BIT_MASK(n);
00112     } else {
00113         /* not enough bits in the cache */
00114         BLT_BitsWord word;
00115 
00116         /* read the next word */
00117         word = BLT_BitStream_ReadCache (bits);
00118         bits->pos +=  BLT_WORD_BYTES;
00119 
00120         /* combine the new word and the cache, and update the state */
00121         {
00122             BLT_BitsWord cache = bits->cache & BLT_BIT_MASK(bits->bits_cached);
00123             n -= bits->bits_cached;
00124             bits->bits_cached = BLT_WORD_BITS - n;
00125             result = (word >> bits->bits_cached) | (cache << n);
00126             bits->cache = word;
00127         }
00128     }
00129 
00130     return result;
00131 }
00132 
00133 /*----------------------------------------------------------------------
00134 |       BLT_BitStream_ReadBit
00135 +---------------------------------------------------------------------*/
00136 static inline unsigned int
00137 BLT_BitStream_ReadBit(BLT_BitStream* bits)
00138 {
00139     BLT_BitsWord result;
00140     if (bits->bits_cached == 0) {
00141         /* the cache is empty */
00142 
00143         /* read the next word into the cache */
00144         bits->cache = BLT_BitStream_ReadCache (bits);
00145         bits->pos +=  BLT_WORD_BYTES;
00146         bits->bits_cached = BLT_WORD_BITS - 1;
00147 
00148         /* return the first bit */
00149         result = bits->cache >> (BLT_WORD_BITS - 1);
00150     } else {
00151         /* get the bit from the cache */
00152         result = (bits->cache >> (--bits->bits_cached)) & 1;
00153     }
00154     return result;
00155 }
00156 
00157 /*----------------------------------------------------------------------
00158 |       BLT_BitStream_PeekBits
00159 +---------------------------------------------------------------------*/
00160 static inline unsigned int
00161 BLT_BitStream_PeekBits(const BLT_BitStream* bits, unsigned int n)
00162 {
00163    /* we have enough bits in the cache to satisfy the request */
00164    if (bits->bits_cached >= n) {
00165       return (bits->cache >> (bits->bits_cached - n)) & BLT_BIT_MASK(n);
00166    } else {
00167       /* not enough bits in the cache */
00168       /* read the next word */
00169       BLT_BitsWord word = BLT_BitStream_ReadCache (bits);
00170 
00171       /* combine the new word and the cache, and update the state */
00172       BLT_BitsWord   cache = bits->cache & BLT_BIT_MASK(bits->bits_cached);
00173       n -= bits->bits_cached;
00174       return (word >> (BLT_WORD_BITS - n)) | (cache << n);
00175    }
00176 }
00177 
00178 /*----------------------------------------------------------------------
00179 |       BLT_BitStream_PeekBit
00180 +---------------------------------------------------------------------*/
00181 static inline unsigned int
00182 BLT_BitStream_PeekBit(const BLT_BitStream* bits)
00183 {
00184    /* the cache is empty */
00185    if (bits->bits_cached == 0) {
00186       /* read the next word into the cache */
00187       BLT_BitsWord   cache = BLT_BitStream_ReadCache (bits);
00188 
00189       /* return the first bit */
00190       return cache >> (BLT_WORD_BITS - 1);
00191    } else {
00192       /* get the bit from the cache */
00193       return (bits->cache >> (bits->bits_cached-1)) & 1;
00194    }
00195 }
00196 
00197 /*----------------------------------------------------------------------
00198 |       BLT_BitStream_SkipBits
00199 +---------------------------------------------------------------------*/
00200 static inline void
00201 BLT_BitStream_SkipBits(BLT_BitStream* bits, unsigned int n)
00202 {
00203    if (n <= bits->bits_cached) {
00204       bits->bits_cached -= n;
00205    } else {
00206       n -= bits->bits_cached;
00207       while (n >= BLT_WORD_BITS) {
00208          bits->pos +=  BLT_WORD_BYTES;
00209          n -= BLT_WORD_BITS;
00210       }
00211       if (n) {
00212          bits->cache = BLT_BitStream_ReadCache (bits);
00213          bits->bits_cached = BLT_WORD_BITS-n;
00214          bits->pos +=  BLT_WORD_BYTES;
00215       } else {
00216          bits->bits_cached = 0;
00217          bits->cache = 0;
00218       }
00219    }
00220 }
00221 
00222 /*----------------------------------------------------------------------
00223 |       BLT_BitStream_SkipBit
00224 +---------------------------------------------------------------------*/
00225 static inline void
00226 BLT_BitStream_SkipBit(BLT_BitStream* bits)
00227 {
00228    if (bits->bits_cached == 0) {
00229       bits->cache = BLT_BitStream_ReadCache (bits);
00230       bits->pos +=  BLT_WORD_BYTES;
00231       bits->bits_cached = BLT_WORD_BITS - 1;
00232    } else {
00233       --bits->bits_cached;
00234    }
00235 }
00236 
00237 
00238 #endif /* _BLT_BIT_STREAM_H_ */