1 /* ***** BEGIN LICENSE BLOCK ***** 2 * 3 * $Id: arith_codec.h,v 1.40 2007/11/16 04:48:44 asuraparaju Exp $ $Name: Dirac_1_0_2 $ 4 * 5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 6 * 7 * The contents of this file are subject to the Mozilla Public License 8 * Version 1.1 (the "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * http://www.mozilla.org/MPL/ 11 * 12 * Software distributed under the License is distributed on an "AS IS" basis, 13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 14 * the specific language governing rights and limitations under the License. 15 * 16 * The Original Code is BBC Research and Development code. 17 * 18 * The Initial Developer of the Original Code is the British Broadcasting 19 * Corporation. 20 * Portions created by the Initial Developer are Copyright (C) 2004. 21 * All Rights Reserved. 22 * 23 * Contributor(s): Richard Felton (Original Author), 24 Thomas Davies, 25 Scott R Ladd, 26 Peter Bleackley, 27 Steve Bearcroft, 28 Anuradha Suraparaju, 29 Tim Borer (major refactor February 2006) 30 Andrew Kennedy 31 * 32 * Alternatively, the contents of this file may be used under the terms of 33 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser 34 * Public License Version 2.1 (the "LGPL"), in which case the provisions of 35 * the GPL or the LGPL are applicable instead of those above. If you wish to 36 * allow use of your version of this file only under the terms of the either 37 * the GPL or LGPL and not to allow others to use your version of this file 38 * under the MPL, indicate your decision by deleting the provisions above 39 * and replace them with the notice and other provisions required by the GPL 40 * or LGPL. If you do not delete the provisions above, a recipient may use 41 * your version of this file under the terms of any one of the MPL, the GPL 42 * or the LGPL. 43 * ***** END LICENSE BLOCK ***** */ 44 45 46 #ifndef _ARITH_CODEC_H_ 47 #define _ARITH_CODEC_H_ 48 49 ///////////////////////////////////////////////////////////////////////// 50 ///////////////////////////////////////////////////////////////////////// 51 //// //// 52 ////-----------Abstract binary arithmetic coding class---------------//// 53 ////subclass this for coding motion vectors, subband residues etc ...//// 54 //// //// 55 ///////////////////////////////////////////////////////////////////////// 56 ///////////////////////////////////////////////////////////////////////// 57 58 #include <libdirac_common/common.h> 59 #include <libdirac_byteio/byteio.h> 60 #include <vector> 61 62 namespace dirac 63 { 64 65 class Context { 66 public: 67 68 //! Default Constructor. 69 /*! 70 Default constructor initialises counts to 1 each of 0 and 1. 71 */ 72 inline Context(); 73 74 //Class is POD 75 //Use built in copy constructor, assignment and destructor. 76 77 //! Returns estimate of probability of 0 (false) scaled to 2**16 78 GetScaledProb0()79 inline unsigned int GetScaledProb0( ) const{ return m_prob0;} 80 81 //! Updates context counts Update(bool symbol)82 inline void Update( bool symbol ) { 83 if (symbol) m_prob0 -= lut[m_prob0>>8]; 84 else m_prob0 += lut[255-(m_prob0>>8)]; 85 } 86 87 private: 88 89 int m_prob0; 90 static const unsigned int lut[256]; //Probability update table 91 }; 92 Context()93 Context::Context(): m_prob0( 0x8000 ) {} 94 95 class ArithCodecBase { 96 97 public: 98 99 //! Constructor 100 /*! 101 Creates an ArithCodec object to decode input based on a set of 102 parameters. 103 \param p_byteio input/output for encoded bits 104 \param number_of_contexts the number of contexts used 105 */ 106 ArithCodecBase(ByteIO* p_byteio, size_t number_of_contexts); 107 108 //! Destructor 109 /*! 110 Destructor is virtual as this class is abstract. 111 */ 112 virtual ~ArithCodecBase(); 113 114 protected: 115 116 //core encode functions 117 //////////////////////////// 118 119 //! Initialises the Encoder 120 void InitEncoder(); 121 122 //! encodes a symbol and writes to output 123 void EncodeSymbol(const bool symbol, const int context_num); 124 125 void EncodeUInt(const unsigned int value, const int bin1, const int max_bin); 126 127 void EncodeSInt(const int value, const int bin1, const int max_bin); 128 129 //! flushes the output of the encoder. 130 void FlushEncoder(); 131 132 int ByteCount() const; 133 134 // core decode functions 135 //////////////////////////// 136 137 //! Initialise the Decoder 138 void InitDecoder(int num_bytes); 139 140 //! Decodes a symbol given a context number 141 bool DecodeSymbol( int context_num ); 142 143 unsigned int DecodeUInt(const int bin1, const int max_bin); 144 145 int DecodeSInt(const int bin1, const int max_bin); 146 147 //! List of contexts 148 std::vector<Context> m_context_list; 149 150 private: 151 152 //! private, bodyless copy constructor: class should not be copied 153 ArithCodecBase(const ArithCodecBase & cpy); 154 155 //! private, bodyless copy operator=: class should not be assigned 156 ArithCodecBase & operator = (const ArithCodecBase & rhs); 157 158 159 // Decode functions 160 //////////////////////////// 161 162 //! Read all the data in 163 void ReadAllData(int num_bytes); 164 165 //! Read in a bit of data 166 inline bool InputBit(); 167 168 // Codec data 169 //////////////////////////// 170 171 unsigned int m_scount; 172 173 //! Start of the current code range 174 unsigned int m_low_code; 175 176 //! Length of the current code range 177 unsigned int m_range; 178 179 //! Input/output stream of Dirac-format bytes 180 ByteIO *m_byteio; 181 182 // For encoder only 183 184 //! Number of underflow bits 185 int m_underflow; 186 187 //! A pointer to the data for reading in 188 char* m_decode_data_ptr; 189 190 //! A point to the byte currently being read 191 char* m_data_ptr; 192 193 //! The index of the bit of the byte being read 194 int m_input_bits_left; 195 196 //! The present input code 197 unsigned int m_code; 198 199 }; 200 201 DecodeSymbol(int context_num)202 inline bool ArithCodecBase::DecodeSymbol( int context_num ) 203 { 204 205 // Determine the next symbol value by placing code within 206 // the [low,high] interval. 207 208 // Fetch the statistical context to be used 209 Context& ctx = m_context_list[context_num]; 210 211 // Decode as per updated specification 212 const unsigned int count = m_code - m_low_code ; 213 const unsigned int range_x_prob = ( m_range* ctx.GetScaledProb0())>>16; 214 const bool symbol = ( count >= range_x_prob ); 215 216 // Rescale the interval 217 if( symbol ) //symbol is 1 218 { 219 m_low_code += range_x_prob; 220 m_range -= range_x_prob; 221 } 222 else //symbol is 0, so m_low_code unchanged 223 { 224 m_range = range_x_prob; 225 } 226 227 // Update the statistical context 228 ctx.Update( symbol ); 229 230 while ( m_range<=0x4000 ) 231 { 232 if( ( (m_low_code+m_range-1)^m_low_code)>=0x8000 ) 233 { 234 // Straddle condition 235 // We must have an underflow situation with 236 // low = 0x01... and high = 0x10... 237 // Flip 2nd bit prior to rescaling 238 m_code ^= 0x4000; 239 m_low_code ^= 0x4000; 240 } 241 242 // Double low and range, throw away top bit of low 243 m_low_code <<= 1; 244 m_range <<= 1; 245 m_low_code &= 0xFFFF; 246 247 // Shift in another bit of code 248 m_code <<= 1; 249 m_code += InputBit(); 250 m_code &= 0xFFFF; 251 252 } 253 254 return symbol; 255 } 256 DecodeUInt(const int bin1,const int max_bin)257 inline unsigned int ArithCodecBase::DecodeUInt(const int bin1, const int max_bin) { 258 const int info_ctx = (max_bin+1); 259 int bin = bin1; 260 unsigned int value = 1; 261 while (!DecodeSymbol(bin)) { 262 value <<= 1; 263 if (DecodeSymbol(info_ctx)) value+=1; 264 if (bin<max_bin) bin+=1; 265 } 266 value -= 1; 267 return value; 268 } 269 DecodeSInt(const int bin1,const int max_bin)270 inline int ArithCodecBase::DecodeSInt(const int bin1, const int max_bin) { 271 int value = 0; 272 const int magnitude = DecodeUInt(bin1, max_bin); 273 if (magnitude!=0) { 274 if (DecodeSymbol(max_bin+2)) value=-magnitude; 275 else value=magnitude; 276 } 277 return value; 278 } 279 EncodeSymbol(const bool symbol,const int context_num)280 inline void ArithCodecBase::EncodeSymbol(const bool symbol, const int context_num) 281 { 282 283 // Adjust high and low (rescale interval) based on the symbol we are encoding 284 285 Context& ctx = m_context_list[context_num]; 286 287 const unsigned int range_x_prob = ( m_range* ctx.GetScaledProb0())>>16; 288 289 if ( symbol ) //symbol is 1 290 { 291 m_low_code += range_x_prob; 292 m_range -= range_x_prob; 293 } 294 else // symbol is 0, so m_low_code unchanged 295 { 296 m_range = range_x_prob; 297 } 298 299 // Update the statistical context 300 ctx.Update( symbol ); 301 302 while ( m_range <= 0x4000 ) 303 { 304 if ( ( (m_low_code+m_range-1)^m_low_code)>=0x8000 ) 305 { 306 // Straddle condition 307 // We must have an underflow situation with 308 // low = 0x01... and high = 0x10... 309 310 m_low_code ^= 0x4000; 311 m_underflow++; 312 313 } 314 else 315 { 316 // Bits agree - output them 317 m_byteio->WriteBit( m_low_code & 0x8000); 318 for (; m_underflow > 0; m_underflow-- ) 319 m_byteio->WriteBit(~m_low_code & 0x8000); 320 } 321 322 // Double low value and range 323 m_low_code <<= 1; 324 m_range <<= 1; 325 326 // keep low to 16 bits - throw out top bit 327 m_low_code &= 0xFFFF; 328 329 } 330 } 331 EncodeUInt(const unsigned int the_int,const int bin1,const int max_bin)332 inline void ArithCodecBase::EncodeUInt(const unsigned int the_int, 333 const int bin1, const int max_bin) { 334 const int value = (the_int+1); 335 const int info_ctx = (max_bin+1); 336 int bin = bin1; 337 int top_bit = 1; 338 { 339 int max_value = 1; 340 while (value>max_value) { 341 top_bit <<= 1; 342 max_value <<= 1; 343 max_value += 1; 344 } 345 } 346 bool stop = (top_bit==1); 347 EncodeSymbol(stop, bin); 348 while (!stop) { 349 top_bit >>= 1; 350 EncodeSymbol( (value&top_bit), info_ctx); 351 if ( bin < max_bin) bin+=1; 352 stop = (top_bit==1); 353 EncodeSymbol(stop, bin); 354 } 355 } 356 EncodeSInt(const int value,const int bin1,const int max_bin)357 inline void ArithCodecBase::EncodeSInt(const int value, 358 const int bin1, const int max_bin) { 359 EncodeUInt(std::abs(value), bin1, max_bin); 360 if (value != 0) { 361 EncodeSymbol( (value < 0), max_bin+2 ); 362 } 363 } 364 365 366 //! Abstract binary arithmetic coding class 367 /*! 368 This is an abtract binary arithmetic encoding class, used as the base 369 for concrete classes that encode motion vectors and subband residues. 370 \param T a container (most probably, or array) type 371 */ 372 373 template<class T> //T is container/array type 374 class ArithCodec 375 : public ArithCodecBase 376 { 377 public: 378 379 //! Constructor for encoding 380 /*! 381 Creates an ArithCodec object to decode input based on a set of 382 parameters. 383 \param p_byteio input/output for encoded bits 384 \param number_of_contexts the number of contexts used 385 */ 386 ArithCodec(ByteIO* p_byteio, size_t number_of_contexts); 387 388 389 //! Destructor 390 /*! 391 Destructor is virtual as this class is abstract. 392 */ ~ArithCodec()393 virtual ~ArithCodec() {} 394 395 //! Compresses the input and returns the number of bits written. 396 /*! 397 Compress takes a type T object (a container or array) and 398 compresses it using the abstract function DoWorkCode() which 399 is overridden in subclasses. It returns the number of 400 bits written. 401 \param in_data the input to be compressed. Non-const, 402 since the compression may be lossy. 403 */ 404 int Compress(T & in_data); 405 406 //! Decompresses the bitstream and writes into the output. 407 /*! 408 Decompresses the bitstream, up to the number of bytes 409 specified and writes into the output subclasses. 410 \param out_data the output into which the decompressed data 411 is written. 412 \param num_bytes the number of bytes to be read from the 413 bitstream. 414 */ 415 void Decompress(T & out_data, const int num_bytes); 416 417 protected: 418 419 //virtual encode-only functions 420 /////////////////////////////// 421 422 //! Does the work of actually coding the data 423 virtual void DoWorkCode(T & in_data) = 0; 424 425 //! virtual decode-only functions 426 /////////////////////////////// 427 virtual void DoWorkDecode(T & out_data)=0; 428 }; 429 430 //Implementation - core functions 431 ///////////////////////////////// 432 433 template<class T> ArithCodec(ByteIO * p_byteio,size_t number_of_contexts)434 ArithCodec<T>::ArithCodec(ByteIO* p_byteio, size_t number_of_contexts): 435 ArithCodecBase(p_byteio, number_of_contexts) {} 436 437 438 439 template<class T> Compress(T & in_data)440 int ArithCodec<T>::Compress(T &in_data) 441 { 442 InitEncoder(); 443 DoWorkCode(in_data); 444 FlushEncoder(); 445 return ByteCount(); 446 } 447 448 template<class T> Decompress(T & out_data,const int num_bytes)449 void ArithCodec<T>::Decompress( T &out_data, const int num_bytes ) 450 { 451 InitDecoder(num_bytes); 452 DoWorkDecode( out_data ); 453 } 454 InputBit()455 inline bool ArithCodecBase::InputBit() 456 { 457 if (m_input_bits_left == 0) 458 { 459 m_data_ptr++; 460 m_input_bits_left = 8; 461 } 462 m_input_bits_left--; 463 // MSB to LSB 464 return bool( ( (*m_data_ptr) >> m_input_bits_left ) & 1 ); 465 } 466 467 }// namespace dirac 468 #endif 469 470