MloBitStream.h

Go to the documentation of this file.
00001 /*****************************************************************
00002 |
00003 |    Melo - Bit Streams
00004 |
00005 |    Copyright 2004-2006 Axiomatic Systems LLC
00006 |
00007 |    This file is part of Melo (Melo AAC Decoder).
00008 |
00009 |    Unless you have obtained Melo under a difference license,
00010 |    this version of Melo is Melo|GPL.
00011 |    Melo|GPL is free software; you can redistribute it and/or modify
00012 |    it under the terms of the GNU General Public License as published by
00013 |    the Free Software Foundation; either version 2, or (at your option)
00014 |    any later version.
00015 |
00016 |    Melo|GPL is distributed in the hope that it will be useful,
00017 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 |    GNU General Public License for more details.
00020 |
00021 |    You should have received a copy of the GNU General Public License
00022 |    along with Melo|GPL; see the file COPYING.  If not, write to the
00023 |    Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
00024 |    02111-1307, USA.
00025 |
00026  ****************************************************************/
00031 #ifndef _MLO_BIT_STREAM_H_
00032 #define _MLO_BIT_STREAM_H_
00033 
00034 /*----------------------------------------------------------------------
00035 |       includes
00036 +---------------------------------------------------------------------*/
00037 #include "MloConfig.h"
00038 #include "MloTypes.h"
00039 #include "MloResults.h"
00040 
00041 /*----------------------------------------------------------------------
00042 |       constants
00043 +---------------------------------------------------------------------*/
00044 
00045 /* error codes */
00046 #define MLO_ERROR_NOT_ENOUGH_DATA        (MLO_ERROR_BASE_BITSTREAM - 0)
00047 #define MLO_ERROR_CORRUPTED_BITSTREAM    (MLO_ERROR_BASE_BITSTREAM - 1)
00048 #define MLO_ERROR_NOT_ENOUGH_FREE_BUFFER (MLO_ERROR_BASE_BITSTREAM - 2)
00049 
00050 /*----------------------------------------------------------------------
00051 |       types helpers
00052 +---------------------------------------------------------------------*/
00053 /* use long by default */
00054 typedef unsigned int MLO_BitsWord;
00055 #define MLO_WORD_BITS  32
00056 #define MLO_WORD_BYTES 4
00057 
00058 /*----------------------------------------------------------------------
00059 |       types
00060 +---------------------------------------------------------------------*/
00061 typedef struct MLO_BitStream
00062 {
00063     unsigned char* buffer;
00064     MLO_Size       buffer_size;
00065     MLO_Size       data_size;
00066     unsigned int   pos;
00067     MLO_BitsWord   cache;
00068     unsigned int   bits_cached;
00069 } MLO_BitStream;
00070 
00071 /*----------------------------------------------------------------------
00072 |       prototypes
00073 +---------------------------------------------------------------------*/
00074 #ifdef __cplusplus
00075 extern "C" {
00076 #endif /* __cplusplus */
00077     
00078 MLO_Result MLO_BitStream_Construct(MLO_BitStream* bits, MLO_Size size);
00079 MLO_Result MLO_BitStream_Destruct(MLO_BitStream* bits);
00080 MLO_Result MLO_BitStream_SetData(MLO_BitStream*  bits, 
00081                                  const MLO_Byte* data, 
00082                                  MLO_Size        data_size);
00083 MLO_Result MLO_BitStream_ByteAlign(MLO_BitStream* bits);
00084 MLO_Result MLO_BitStream_Reset(MLO_BitStream* bits);
00085 MLO_Size   MLO_BitStream_GetBitsLeft(MLO_BitStream* bits);
00086 
00087 #ifdef __cplusplus
00088 }
00089 #endif /* __cplusplus */
00090     
00091 /*----------------------------------------------------------------------
00092 |       macros
00093 +---------------------------------------------------------------------*/
00094 #define MLO_BIT_MASK(_n) ((1<<(_n))-1)
00095 
00096 /*
00097 ==============================================================================
00098 Name: MLO_BitStream_ReadCache
00099 Description:
00100    This is a private function, for internal use.
00101    Reads bytes to get cached bits.
00102 Input parameters:
00103     - bits_ptr: Pointer on the BitStream structure
00104 Returns: The cached bits
00105 ==============================================================================
00106 */
00107 
00108 static inline MLO_BitsWord
00109 MLO_BitStream_ReadCache (const MLO_BitStream* bits_ptr)
00110 {
00111    unsigned int   pos = bits_ptr->pos;
00112 
00113 #if MLO_WORD_BITS != 32
00114 #error unsupported word size /* 64 and other word size not yet implemented */
00115 #endif
00116 
00117    if (pos > bits_ptr->buffer_size - MLO_WORD_BYTES) return 0;
00118 
00119    {
00120       unsigned char *   out_ptr = &bits_ptr->buffer [pos];
00121       return    (((MLO_BitsWord) out_ptr [0]) << 24)
00122               | (((MLO_BitsWord) out_ptr [1]) << 16)
00123               | (((MLO_BitsWord) out_ptr [2]) <<  8)
00124               | (((MLO_BitsWord) out_ptr [3])      );
00125    }
00126 }
00127 
00128 /*----------------------------------------------------------------------
00129 |       MLO_BitStream_ReadBits
00130 +---------------------------------------------------------------------*/
00131 static inline unsigned int
00132 MLO_BitStream_ReadBits(MLO_BitStream* bits, unsigned int n)
00133 {
00134     MLO_BitsWord  result;
00135     if (bits->bits_cached >= n) {
00136         /* we have enough bits in the cache to satisfy the request */
00137         bits->bits_cached -= n;
00138         result = (bits->cache >> bits->bits_cached) & MLO_BIT_MASK(n);
00139     } else {
00140         /* not enough bits in the cache */
00141         MLO_BitsWord word;
00142 
00143         /* read the next word */
00144         word = MLO_BitStream_ReadCache (bits);
00145         bits->pos +=  MLO_WORD_BYTES;
00146 
00147         /* combine the new word and the cache, and update the state */
00148         {
00149             MLO_BitsWord cache = bits->cache & MLO_BIT_MASK(bits->bits_cached);
00150             n -= bits->bits_cached;
00151             bits->bits_cached = MLO_WORD_BITS - n;
00152             result = (word >> bits->bits_cached) | (cache << n);
00153             bits->cache = word;
00154         }
00155     }
00156 
00157     return result;
00158 }
00159 
00160 /*----------------------------------------------------------------------
00161 |       MLO_BitStream_ReadBit
00162 +---------------------------------------------------------------------*/
00163 static inline unsigned int
00164 MLO_BitStream_ReadBit(MLO_BitStream* bits)
00165 {
00166     MLO_BitsWord   result;
00167     if (bits->bits_cached == 0) {
00168         /* the cache is empty */
00169 
00170         /* read the next word into the cache */
00171         bits->cache = MLO_BitStream_ReadCache (bits);
00172         bits->pos +=  MLO_WORD_BYTES;
00173         bits->bits_cached = MLO_WORD_BITS - 1;
00174 
00175         /* return the first bit */
00176         result = bits->cache >> (MLO_WORD_BITS - 1);
00177     } else {
00178         /* get the bit from the cache */
00179         result = (bits->cache >> (--bits->bits_cached)) & 1;
00180     }
00181     return result;
00182 }
00183 
00184 /*----------------------------------------------------------------------
00185 |       MLO_BitStream_PeekBits
00186 +---------------------------------------------------------------------*/
00187 static inline unsigned int
00188 MLO_BitStream_PeekBits(const MLO_BitStream* bits, unsigned int n)
00189 {
00190    /* we have enough bits in the cache to satisfy the request */
00191    if (bits->bits_cached >= n) {
00192       return (bits->cache >> (bits->bits_cached - n)) & MLO_BIT_MASK(n);
00193    } else {
00194       /* not enough bits in the cache */
00195       /* read the next word */
00196       MLO_BitsWord word = MLO_BitStream_ReadCache (bits);
00197 
00198       /* combine the new word and the cache, and update the state */
00199       MLO_BitsWord   cache = bits->cache & MLO_BIT_MASK(bits->bits_cached);
00200       n -= bits->bits_cached;
00201       return (word >> (MLO_WORD_BITS - n)) | (cache << n);
00202    }
00203 }
00204 
00205 /*----------------------------------------------------------------------
00206 |       MLO_BitStream_PeekBit
00207 +---------------------------------------------------------------------*/
00208 static inline unsigned int
00209 MLO_BitStream_PeekBit(const MLO_BitStream* bits)
00210 {
00211    /* the cache is empty */
00212    if (bits->bits_cached == 0) {
00213       /* read the next word into the cache */
00214       MLO_BitsWord   cache = MLO_BitStream_ReadCache (bits);
00215 
00216       /* return the first bit */
00217       return cache >> (MLO_WORD_BITS - 1);
00218    } else {
00219       /* get the bit from the cache */
00220       return (bits->cache >> (bits->bits_cached-1)) & 1;
00221    }
00222 }
00223 
00224 /*----------------------------------------------------------------------
00225 |       MLO_BitStream_SkipBits
00226 +---------------------------------------------------------------------*/
00227 static inline void
00228 MLO_BitStream_SkipBits(MLO_BitStream* bits, unsigned int n)
00229 {
00230    if (n <= bits->bits_cached) {
00231       bits->bits_cached -= n;
00232    } else {
00233       n -= bits->bits_cached;
00234       while (n >= MLO_WORD_BITS) {
00235          bits->pos +=  MLO_WORD_BYTES;
00236          n -= MLO_WORD_BITS;
00237       }
00238       if (n) {
00239          bits->cache = MLO_BitStream_ReadCache (bits);
00240          bits->bits_cached = MLO_WORD_BITS-n;
00241          bits->pos +=  MLO_WORD_BYTES;
00242       } else {
00243          bits->bits_cached = 0;
00244          bits->cache = 0;
00245       }
00246    }
00247 }
00248 
00249 /*----------------------------------------------------------------------
00250 |       MLO_BitStream_SkipBit
00251 +---------------------------------------------------------------------*/
00252 static inline void
00253 MLO_BitStream_SkipBit(MLO_BitStream* bits)
00254 {
00255    if (bits->bits_cached == 0) {
00256       bits->cache = MLO_BitStream_ReadCache (bits);
00257       bits->pos +=  MLO_WORD_BYTES;
00258       bits->bits_cached = MLO_WORD_BITS - 1;
00259    } else {
00260       --bits->bits_cached;
00261    }
00262 }
00263 
00264 
00265 #endif /* _MLO_BIT_STREAM_H_ */