Created by the British Broadcasting Corporation.
00001 /* ***** BEGIN LICENSE BLOCK ***** 00002 * 00003 * $Id: arith_codec.h,v 1.40 2007/11/16 04:48:44 asuraparaju Exp $ $Name: Dirac_1_0_2 $ 00004 * 00005 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 00006 * 00007 * The contents of this file are subject to the Mozilla Public License 00008 * Version 1.1 (the "License"); you may not use this file except in compliance 00009 * with the License. You may obtain a copy of the License at 00010 * http://www.mozilla.org/MPL/ 00011 * 00012 * Software distributed under the License is distributed on an "AS IS" basis, 00013 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 00014 * the specific language governing rights and limitations under the License. 00015 * 00016 * The Original Code is BBC Research and Development code. 00017 * 00018 * The Initial Developer of the Original Code is the British Broadcasting 00019 * Corporation. 00020 * Portions created by the Initial Developer are Copyright (C) 2004. 00021 * All Rights Reserved. 00022 * 00023 * Contributor(s): Richard Felton (Original Author), 00024 Thomas Davies, 00025 Scott R Ladd, 00026 Peter Bleackley, 00027 Steve Bearcroft, 00028 Anuradha Suraparaju, 00029 Tim Borer (major refactor February 2006) 00030 Andrew Kennedy 00031 * 00032 * Alternatively, the contents of this file may be used under the terms of 00033 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser 00034 * Public License Version 2.1 (the "LGPL"), in which case the provisions of 00035 * the GPL or the LGPL are applicable instead of those above. If you wish to 00036 * allow use of your version of this file only under the terms of the either 00037 * the GPL or LGPL and not to allow others to use your version of this file 00038 * under the MPL, indicate your decision by deleting the provisions above 00039 * and replace them with the notice and other provisions required by the GPL 00040 * or LGPL. If you do not delete the provisions above, a recipient may use 00041 * your version of this file under the terms of any one of the MPL, the GPL 00042 * or the LGPL. 00043 * ***** END LICENSE BLOCK ***** */ 00044 00045 00046 #ifndef _ARITH_CODEC_H_ 00047 #define _ARITH_CODEC_H_ 00048 00057 00058 #include <libdirac_common/common.h> 00059 #include <libdirac_byteio/byteio.h> 00060 #include <vector> 00061 00062 namespace dirac 00063 { 00064 00065 class Context { 00066 public: 00067 00069 00072 inline Context(); 00073 00074 //Class is POD 00075 //Use built in copy constructor, assignment and destructor. 00076 00078 00079 inline unsigned int GetScaledProb0( ) const{ return m_prob0;} 00080 00082 inline void Update( bool symbol ) { 00083 if (symbol) m_prob0 -= lut[m_prob0>>8]; 00084 else m_prob0 += lut[255-(m_prob0>>8)]; 00085 } 00086 00087 private: 00088 00089 int m_prob0; 00090 static const unsigned int lut[256]; //Probability update table 00091 }; 00092 00093 Context::Context(): m_prob0( 0x8000 ) {} 00094 00095 class ArithCodecBase { 00096 00097 public: 00098 00100 00106 ArithCodecBase(ByteIO* p_byteio, size_t number_of_contexts); 00107 00109 00112 virtual ~ArithCodecBase(); 00113 00114 protected: 00115 00116 //core encode functions 00118 00120 void InitEncoder(); 00121 00123 void EncodeSymbol(const bool symbol, const int context_num); 00124 00125 void EncodeUInt(const unsigned int value, const int bin1, const int max_bin); 00126 00127 void EncodeSInt(const int value, const int bin1, const int max_bin); 00128 00130 void FlushEncoder(); 00131 00132 int ByteCount() const; 00133 00134 // core decode functions 00136 00138 void InitDecoder(int num_bytes); 00139 00141 bool DecodeSymbol( int context_num ); 00142 00143 unsigned int DecodeUInt(const int bin1, const int max_bin); 00144 00145 int DecodeSInt(const int bin1, const int max_bin); 00146 00148 std::vector<Context> m_context_list; 00149 00150 private: 00151 00153 ArithCodecBase(const ArithCodecBase & cpy); 00154 00156 ArithCodecBase & operator = (const ArithCodecBase & rhs); 00157 00158 00159 // Decode functions 00161 00163 void ReadAllData(int num_bytes); 00164 00166 inline bool InputBit(); 00167 00168 // Codec data 00170 00171 unsigned int m_scount; 00172 00174 unsigned int m_low_code; 00175 00177 unsigned int m_range; 00178 00180 ByteIO *m_byteio; 00181 00182 // For encoder only 00183 00185 int m_underflow; 00186 00188 char* m_decode_data_ptr; 00189 00191 char* m_data_ptr; 00192 00194 int m_input_bits_left; 00195 00197 unsigned int m_code; 00198 00199 }; 00200 00201 00202 inline bool ArithCodecBase::DecodeSymbol( int context_num ) 00203 { 00204 00205 // Determine the next symbol value by placing code within 00206 // the [low,high] interval. 00207 00208 // Fetch the statistical context to be used 00209 Context& ctx = m_context_list[context_num]; 00210 00211 // Decode as per updated specification 00212 const unsigned int count = m_code - m_low_code ; 00213 const unsigned int range_x_prob = ( m_range* ctx.GetScaledProb0())>>16; 00214 const bool symbol = ( count >= range_x_prob ); 00215 00216 // Rescale the interval 00217 if( symbol ) //symbol is 1 00218 { 00219 m_low_code += range_x_prob; 00220 m_range -= range_x_prob; 00221 } 00222 else //symbol is 0, so m_low_code unchanged 00223 { 00224 m_range = range_x_prob; 00225 } 00226 00227 // Update the statistical context 00228 ctx.Update( symbol ); 00229 00230 while ( m_range<=0x4000 ) 00231 { 00232 if( ( (m_low_code+m_range-1)^m_low_code)>=0x8000 ) 00233 { 00234 // Straddle condition 00235 // We must have an underflow situation with 00236 // low = 0x01... and high = 0x10... 00237 // Flip 2nd bit prior to rescaling 00238 m_code ^= 0x4000; 00239 m_low_code ^= 0x4000; 00240 } 00241 00242 // Double low and range, throw away top bit of low 00243 m_low_code <<= 1; 00244 m_range <<= 1; 00245 m_low_code &= 0xFFFF; 00246 00247 // Shift in another bit of code 00248 m_code <<= 1; 00249 m_code += InputBit(); 00250 m_code &= 0xFFFF; 00251 00252 } 00253 00254 return symbol; 00255 } 00256 00257 inline unsigned int ArithCodecBase::DecodeUInt(const int bin1, const int max_bin) { 00258 const int info_ctx = (max_bin+1); 00259 int bin = bin1; 00260 unsigned int value = 1; 00261 while (!DecodeSymbol(bin)) { 00262 value <<= 1; 00263 if (DecodeSymbol(info_ctx)) value+=1; 00264 if (bin<max_bin) bin+=1; 00265 } 00266 value -= 1; 00267 return value; 00268 } 00269 00270 inline int ArithCodecBase::DecodeSInt(const int bin1, const int max_bin) { 00271 int value = 0; 00272 const int magnitude = DecodeUInt(bin1, max_bin); 00273 if (magnitude!=0) { 00274 if (DecodeSymbol(max_bin+2)) value=-magnitude; 00275 else value=magnitude; 00276 } 00277 return value; 00278 } 00279 00280 inline void ArithCodecBase::EncodeSymbol(const bool symbol, const int context_num) 00281 { 00282 00283 // Adjust high and low (rescale interval) based on the symbol we are encoding 00284 00285 Context& ctx = m_context_list[context_num]; 00286 00287 const unsigned int range_x_prob = ( m_range* ctx.GetScaledProb0())>>16; 00288 00289 if ( symbol ) //symbol is 1 00290 { 00291 m_low_code += range_x_prob; 00292 m_range -= range_x_prob; 00293 } 00294 else // symbol is 0, so m_low_code unchanged 00295 { 00296 m_range = range_x_prob; 00297 } 00298 00299 // Update the statistical context 00300 ctx.Update( symbol ); 00301 00302 while ( m_range <= 0x4000 ) 00303 { 00304 if ( ( (m_low_code+m_range-1)^m_low_code)>=0x8000 ) 00305 { 00306 // Straddle condition 00307 // We must have an underflow situation with 00308 // low = 0x01... and high = 0x10... 00309 00310 m_low_code ^= 0x4000; 00311 m_underflow++; 00312 00313 } 00314 else 00315 { 00316 // Bits agree - output them 00317 m_byteio->WriteBit( m_low_code & 0x8000); 00318 for (; m_underflow > 0; m_underflow-- ) 00319 m_byteio->WriteBit(~m_low_code & 0x8000); 00320 } 00321 00322 // Double low value and range 00323 m_low_code <<= 1; 00324 m_range <<= 1; 00325 00326 // keep low to 16 bits - throw out top bit 00327 m_low_code &= 0xFFFF; 00328 00329 } 00330 } 00331 00332 inline void ArithCodecBase::EncodeUInt(const unsigned int the_int, 00333 const int bin1, const int max_bin) { 00334 const int value = (the_int+1); 00335 const int info_ctx = (max_bin+1); 00336 int bin = bin1; 00337 int top_bit = 1; 00338 { 00339 int max_value = 1; 00340 while (value>max_value) { 00341 top_bit <<= 1; 00342 max_value <<= 1; 00343 max_value += 1; 00344 } 00345 } 00346 bool stop = (top_bit==1); 00347 EncodeSymbol(stop, bin); 00348 while (!stop) { 00349 top_bit >>= 1; 00350 EncodeSymbol( (value&top_bit), info_ctx); 00351 if ( bin < max_bin) bin+=1; 00352 stop = (top_bit==1); 00353 EncodeSymbol(stop, bin); 00354 } 00355 } 00356 00357 inline void ArithCodecBase::EncodeSInt(const int value, 00358 const int bin1, const int max_bin) { 00359 EncodeUInt(std::abs(value), bin1, max_bin); 00360 if (value != 0) { 00361 EncodeSymbol( (value < 0), max_bin+2 ); 00362 } 00363 } 00364 00365 00367 00373 template<class T> //T is container/array type 00374 class ArithCodec 00375 : public ArithCodecBase 00376 { 00377 public: 00378 00380 00386 ArithCodec(ByteIO* p_byteio, size_t number_of_contexts); 00387 00388 00390 00393 virtual ~ArithCodec() {} 00394 00396 00404 int Compress(T & in_data); 00405 00407 00415 void Decompress(T & out_data, const int num_bytes); 00416 00417 protected: 00418 00419 //virtual encode-only functions 00421 00423 virtual void DoWorkCode(T & in_data) = 0; 00424 00427 virtual void DoWorkDecode(T & out_data)=0; 00428 }; 00429 00430 //Implementation - core functions 00432 00433 template<class T> 00434 ArithCodec<T>::ArithCodec(ByteIO* p_byteio, size_t number_of_contexts): 00435 ArithCodecBase(p_byteio, number_of_contexts) {} 00436 00437 00438 00439 template<class T> 00440 int ArithCodec<T>::Compress(T &in_data) 00441 { 00442 InitEncoder(); 00443 DoWorkCode(in_data); 00444 FlushEncoder(); 00445 return ByteCount(); 00446 } 00447 00448 template<class T> 00449 void ArithCodec<T>::Decompress( T &out_data, const int num_bytes ) 00450 { 00451 InitDecoder(num_bytes); 00452 DoWorkDecode( out_data ); 00453 } 00454 00455 inline bool ArithCodecBase::InputBit() 00456 { 00457 if (m_input_bits_left == 0) 00458 { 00459 m_data_ptr++; 00460 m_input_bits_left = 8; 00461 } 00462 m_input_bits_left--; 00463 // MSB to LSB 00464 return bool( ( (*m_data_ptr) >> m_input_bits_left ) & 1 ); 00465 } 00466 00467 }// namespace dirac 00468 #endif 00469
© 2004 British Broadcasting Corporation.
Dirac code licensed under the Mozilla Public License (MPL) Version 1.1.
HTML documentation generated by Dimitri van Heesch's
excellent Doxygen tool.