Created by the British Broadcasting Corporation.
00001 /* ***** BEGIN LICENSE BLOCK ***** 00002 * 00003 * $Id: arith_codec.h,v 1.38 2007/04/11 14:36:45 tjdwave Exp $ $Name: Dirac_0_7_0 $ 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 /* 00096 void Context::Update( bool symbol ) 00097 { 00098 // if ( !symbol ) 00099 // ++m_count0; 00100 // else 00101 // ++m_count1; 00102 // 00103 // if ( (m_count0+m_count1)%8==0) 00104 // { 00105 // if ( (m_count0+m_count1) == 256 ) 00106 // { 00107 // m_count0++; 00108 // m_count0 >>= 1; 00109 // m_count1++; 00110 // m_count1 >>= 1; 00111 // } 00112 // m_prob0 = m_count0*lookup( m_count0+m_count1 ); 00113 // } 00114 00115 if (symbol) m_prob0 -= lut[m_prob0>>8]; 00116 else m_prob0 += lut[255-(m_prob0>>8)]; 00117 00118 } 00119 */ 00120 00121 class ArithCodecBase { 00122 00123 public: 00124 00126 00132 ArithCodecBase(ByteIO* p_byteio, size_t number_of_contexts); 00133 00135 00138 virtual ~ArithCodecBase(); 00139 00140 protected: 00141 00142 //core encode functions 00144 00146 void InitEncoder(); 00147 00149 void EncodeSymbol(const bool symbol, const int context_num); 00150 00151 void EncodeUInt(const unsigned int value, const int bin1, const int max_bin); 00152 00153 void EncodeSInt(const int value, const int bin1, const int max_bin); 00154 00156 void FlushEncoder(); 00157 00158 int ByteCount() const; 00159 00160 // core decode functions 00162 00164 void InitDecoder(int num_bytes); 00165 00167 bool DecodeSymbol( int context_num ); 00168 00169 unsigned int DecodeUInt(const int bin1, const int max_bin); 00170 00171 int DecodeSInt(const int bin1, const int max_bin); 00172 00174 std::vector<Context> m_context_list; 00175 00176 private: 00177 00179 ArithCodecBase(const ArithCodecBase & cpy); 00180 00182 ArithCodecBase & operator = (const ArithCodecBase & rhs); 00183 00184 00185 // Decode functions 00187 00189 void ReadAllData(int num_bytes); 00190 00192 inline bool InputBit(); 00193 00194 // Codec data 00196 00197 unsigned int m_scount; 00198 00200 unsigned int m_low_code; 00201 00203 unsigned int m_range; 00204 00206 ByteIO *m_byteio; 00207 00208 // For encoder only 00209 00211 int m_underflow; 00212 00214 char* m_decode_data_ptr; 00215 00217 char* m_data_ptr; 00218 00220 int m_input_bits_left; 00221 00223 unsigned int m_code; 00224 00225 }; 00226 00227 00228 inline bool ArithCodecBase::DecodeSymbol( int context_num ) 00229 { 00230 00231 // Determine the next symbol value by placing code within 00232 // the [low,high] interval. 00233 00234 // Fetch the statistical context to be used 00235 Context& ctx = m_context_list[context_num]; 00236 00237 // Decode as per updated specification 00238 const unsigned int count = m_code - m_low_code ; 00239 const unsigned int range_x_prob = ( m_range* ctx.GetScaledProb0())>>16; 00240 const bool symbol = ( count >= range_x_prob ); 00241 00242 // Rescale the interval 00243 if( symbol ) //symbol is 1 00244 { 00245 m_low_code += range_x_prob; 00246 m_range -= range_x_prob; 00247 } 00248 else //symbol is 0, so m_low_code unchanged 00249 { 00250 m_range = range_x_prob; 00251 } 00252 00253 // Update the statistical context 00254 ctx.Update( symbol ); 00255 00256 while ( m_range<=0x4000 ) 00257 { 00258 if( ( (m_low_code+m_range-1)^m_low_code)>=0x8000 ) 00259 { 00260 // Straddle condition 00261 // We must have an underflow situation with 00262 // low = 0x01... and high = 0x10... 00263 // Flip 2nd bit prior to rescaling 00264 m_code ^= 0x4000; 00265 m_low_code ^= 0x4000; 00266 } 00267 00268 // Double low and range, throw away top bit of low 00269 m_low_code <<= 1; 00270 m_range <<= 1; 00271 m_low_code &= 0xFFFF; 00272 00273 // Shift in another bit of code 00274 m_code <<= 1; 00275 m_code += InputBit(); 00276 m_code &= 0xFFFF; 00277 00278 } 00279 00280 return symbol; 00281 } 00282 00283 inline unsigned int ArithCodecBase::DecodeUInt(const int bin1, const int max_bin) { 00284 const int info_ctx = (max_bin+1); 00285 int bin = bin1; 00286 unsigned int value = 1; 00287 while (!DecodeSymbol(bin)) { 00288 value <<= 1; 00289 if (DecodeSymbol(info_ctx)) value+=1; 00290 if (bin<max_bin) bin+=1; 00291 } 00292 value -= 1; 00293 return value; 00294 } 00295 00296 inline int ArithCodecBase::DecodeSInt(const int bin1, const int max_bin) { 00297 int value = 0; 00298 const int magnitude = DecodeUInt(bin1, max_bin); 00299 if (magnitude!=0) { 00300 if (DecodeSymbol(max_bin+2)) value=-magnitude; 00301 else value=magnitude; 00302 } 00303 return value; 00304 } 00305 00306 inline void ArithCodecBase::EncodeSymbol(const bool symbol, const int context_num) 00307 { 00308 00309 // Adjust high and low (rescale interval) based on the symbol we are encoding 00310 00311 Context& ctx = m_context_list[context_num]; 00312 00313 const unsigned int range_x_prob = ( m_range* ctx.GetScaledProb0())>>16; 00314 00315 if ( symbol ) //symbol is 1 00316 { 00317 m_low_code += range_x_prob; 00318 m_range -= range_x_prob; 00319 } 00320 else // symbol is 0, so m_low_code unchanged 00321 { 00322 m_range = range_x_prob; 00323 } 00324 00325 // Update the statistical context 00326 ctx.Update( symbol ); 00327 00328 while ( m_range <= 0x4000 ) 00329 { 00330 if ( ( (m_low_code+m_range-1)^m_low_code)>=0x8000 ) 00331 { 00332 // Straddle condition 00333 // We must have an underflow situation with 00334 // low = 0x01... and high = 0x10... 00335 00336 m_low_code ^= 0x4000; 00337 m_underflow++; 00338 00339 } 00340 else 00341 { 00342 // Bits agree - output them 00343 m_byteio->OutputBit( m_low_code & 0x8000); 00344 for (; m_underflow > 0; m_underflow-- ) 00345 m_byteio->OutputBit(~m_low_code & 0x8000); 00346 } 00347 00348 // Double low value and range 00349 m_low_code <<= 1; 00350 m_range <<= 1; 00351 00352 // keep low to 16 bits - throw out top bit 00353 m_low_code &= 0xFFFF; 00354 00355 } 00356 00357 } 00358 00359 inline void ArithCodecBase::EncodeUInt(const unsigned int the_int, 00360 const int bin1, const int max_bin) { 00361 const int value = (the_int+1); 00362 const int info_ctx = (max_bin+1); 00363 int bin = bin1; 00364 int top_bit = 1; 00365 { 00366 int max_value = 1; 00367 while (value>max_value) { 00368 top_bit <<= 1; 00369 max_value <<= 1; 00370 max_value += 1; 00371 } 00372 } 00373 bool stop = (top_bit==1); 00374 EncodeSymbol(stop, bin); 00375 while (!stop) { 00376 top_bit >>= 1; 00377 EncodeSymbol( (value&top_bit), info_ctx); 00378 if ( bin < max_bin) bin+=1; 00379 stop = (top_bit==1); 00380 EncodeSymbol(stop, bin); 00381 } 00382 } 00383 00384 inline void ArithCodecBase::EncodeSInt(const int value, 00385 const int bin1, const int max_bin) { 00386 EncodeUInt(std::abs(value), bin1, max_bin); 00387 if (value != 0) { 00388 EncodeSymbol( (value < 0), max_bin+2 ); 00389 } 00390 } 00391 00392 00394 00400 template<class T> //T is container/array type 00401 class ArithCodec 00402 : public ArithCodecBase 00403 { 00404 public: 00405 00407 00413 ArithCodec(ByteIO* p_byteio, size_t number_of_contexts); 00414 00415 00417 00420 virtual ~ArithCodec() {} 00421 00423 00431 int Compress(T & in_data); 00432 00434 00442 void Decompress(T & out_data, const int num_bytes); 00443 00444 protected: 00445 00446 //virtual encode-only functions 00448 00450 virtual void DoWorkCode(T & in_data) = 0; 00451 00454 virtual void DoWorkDecode(T & out_data)=0; 00455 }; 00456 00457 //Implementation - core functions 00459 00460 template<class T> 00461 ArithCodec<T>::ArithCodec(ByteIO* p_byteio, size_t number_of_contexts): 00462 ArithCodecBase(p_byteio, number_of_contexts) {} 00463 00464 00465 00466 template<class T> 00467 int ArithCodec<T>::Compress(T &in_data) 00468 { 00469 InitEncoder(); 00470 DoWorkCode(in_data); 00471 FlushEncoder(); 00472 return ByteCount(); 00473 } 00474 00475 template<class T> 00476 void ArithCodec<T>::Decompress( T &out_data, const int num_bytes ) 00477 { 00478 InitDecoder(num_bytes); 00479 DoWorkDecode( out_data ); 00480 } 00481 00482 inline bool ArithCodecBase::InputBit() 00483 { 00484 if (m_input_bits_left == 0) 00485 { 00486 m_data_ptr++; 00487 m_input_bits_left = 8; 00488 } 00489 m_input_bits_left--; 00490 // MSB to LSB 00491 return bool( ( (*m_data_ptr) >> m_input_bits_left ) & 1 ); 00492 } 00493 00494 }// namespace dirac 00495 #endif 00496
© 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.