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