Dirac - A Video Codec

Created by the British Broadcasting Corporation.


arith_codec.h
Go to the documentation of this file.
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
57
60#include <vector>
61
62namespace dirac
63{
64
65 class Context {
66 public:
67
69
72 inline Context();
73
74 //Class is POD
75 //Use built in copy constructor, assignment and destructor.
76
78
79 inline unsigned int GetScaledProb0( ) const{ return m_prob0;}
80
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
90 static const unsigned int lut[256]; //Probability update table
91 };
92
93 Context::Context(): m_prob0( 0x8000 ) {}
94
96
97 public:
98
100
106 ArithCodecBase(ByteIO* p_byteio, size_t number_of_contexts);
107
109
113
114 protected:
115
116 //core encode functions
118
121
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
131
132 int ByteCount() const;
133
134 // core decode functions
136
138 void InitDecoder(int num_bytes);
139
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
148 std::vector<Context> m_context_list;
149
150 private:
151
154
157
158
159 // Decode functions
161
163 void ReadAllData(int num_bytes);
164
166 inline bool InputBit();
167
168 // Codec data
170
171 unsigned int m_scount;
172
174 unsigned int m_low_code;
175
177 unsigned int m_range;
178
181
182 // For encoder only
183
186
189
192
195
197 unsigned int m_code;
198
199 };
200
201
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
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
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
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
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
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
367
372
373 template<class T> //T is container/array type
375 : public ArithCodecBase
376 {
377 public:
378
380
386 ArithCodec(ByteIO* p_byteio, size_t number_of_contexts);
387
388
390
393 virtual ~ArithCodec() {}
394
396
404 int Compress(T & in_data);
405
407
415 void Decompress(T & out_data, const int num_bytes);
416
417 protected:
418
419 //virtual encode-only functions
421
423 virtual void DoWorkCode(T & in_data) = 0;
424
427 virtual void DoWorkDecode(T & out_data)=0;
428 };
429
430 //Implementation - core functions
432
433 template<class T>
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>
441 {
442 InitEncoder();
443 DoWorkCode(in_data);
444 FlushEncoder();
445 return ByteCount();
446 }
447
448 template<class T>
449 void ArithCodec<T>::Decompress( T &out_data, const int num_bytes )
450 {
451 InitDecoder(num_bytes);
452 DoWorkDecode( out_data );
453 }
454
456 {
457 if (m_input_bits_left == 0)
458 {
459 m_data_ptr++;
461 }
463 // MSB to LSB
464 return bool( ( (*m_data_ptr) >> m_input_bits_left ) & 1 );
465 }
466
467}// namespace dirac
468#endif
469
Definition of class SequenceHeaderByteIO.
Definition accessunit_byteio.h:52
Class ByteIO - top-level class for reading/writing bytes to a stream.
Definition byteio.h:73
Definition arith_codec.h:65
void Update(bool symbol)
Updates context counts.
Definition arith_codec.h:82
Context()
Default Constructor.
Definition arith_codec.h:93
int m_prob0
Definition arith_codec.h:89
unsigned int GetScaledProb0() const
Returns estimate of probability of 0 (false) scaled to 2**16.
Definition arith_codec.h:79
static const unsigned int lut[256]
Definition arith_codec.h:90
char * m_data_ptr
A point to the byte currently being read.
Definition arith_codec.h:191
unsigned int m_range
Length of the current code range.
Definition arith_codec.h:177
std::vector< Context > m_context_list
List of contexts.
Definition arith_codec.h:148
void InitEncoder()
Initialises the Encoder.
bool InputBit()
Read in a bit of data.
Definition arith_codec.h:455
unsigned int m_low_code
Start of the current code range.
Definition arith_codec.h:174
ByteIO * m_byteio
Input/output stream of Dirac-format bytes.
Definition arith_codec.h:180
char * m_decode_data_ptr
A pointer to the data for reading in.
Definition arith_codec.h:188
int m_input_bits_left
The index of the bit of the byte being read.
Definition arith_codec.h:194
unsigned int m_scount
Definition arith_codec.h:171
ArithCodecBase(const ArithCodecBase &cpy)
private, bodyless copy constructor: class should not be copied
ArithCodecBase(ByteIO *p_byteio, size_t number_of_contexts)
Constructor.
int DecodeSInt(const int bin1, const int max_bin)
Definition arith_codec.h:270
int m_underflow
Number of underflow bits.
Definition arith_codec.h:185
void EncodeSInt(const int value, const int bin1, const int max_bin)
Definition arith_codec.h:357
void ReadAllData(int num_bytes)
Read all the data in.
virtual ~ArithCodecBase()
Destructor.
ArithCodecBase & operator=(const ArithCodecBase &rhs)
private, bodyless copy operator=: class should not be assigned
unsigned int m_code
The present input code.
Definition arith_codec.h:197
void EncodeSymbol(const bool symbol, const int context_num)
encodes a symbol and writes to output
Definition arith_codec.h:280
void InitDecoder(int num_bytes)
Initialise the Decoder.
unsigned int DecodeUInt(const int bin1, const int max_bin)
Definition arith_codec.h:257
void FlushEncoder()
flushes the output of the encoder.
void EncodeUInt(const unsigned int value, const int bin1, const int max_bin)
Definition arith_codec.h:332
bool DecodeSymbol(int context_num)
Decodes a symbol given a context number.
Definition arith_codec.h:202
int Compress(T &in_data)
Compresses the input and returns the number of bits written.
Definition arith_codec.h:440
virtual void DoWorkCode(T &in_data)=0
Does the work of actually coding the data.
virtual ~ArithCodec()
Destructor.
Definition arith_codec.h:393
virtual void DoWorkDecode(T &out_data)=0
virtual decode-only functions
void Decompress(T &out_data, const int num_bytes)
Decompresses the bitstream and writes into the output.
Definition arith_codec.h:449
ArithCodec(ByteIO *p_byteio, size_t number_of_contexts)
Constructor for encoding.
Definition arith_codec.h:434

© 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.