Commit 30df6cf3 authored by Timothy B. Terriberry's avatar Timothy B. Terriberry Committed by Jean-Marc Valin
Browse files

Entropy coder clean-up.

This simplifies a good bit of the error handling, and should make it
 impossible to overrun the buffer in the encoder or decoder, while
 still allowing tell() to operate correctly after a bust.
The encoder now tries to keep the range coder data intact after a
 bust instead of corrupting it with extra bits data, though this is
 not a guarantee (too many extra bits may have already been flushed).
It also now correctly reports errors when the bust occurs merging the
 last byte of range coder and extra bits.

A number of abstraction barrier violations were cleaned up, as well.
This patch also includes a number of minor performance improvements:
 ec_{enc|dec}_bits() in particular should be much faster.

Finally, tf_select was changed to be coded with the range coder
 rather than extra bits, so that it is at the front of the packet
 (for unequal error protection robustness).
parent 59858633
...@@ -600,7 +600,7 @@ static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM, ...@@ -600,7 +600,7 @@ static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM,
curr = tf_res[i]; curr = tf_res[i];
} }
if (LM!=0) if (LM!=0)
ec_enc_bits(enc, tf_select, 1); ec_enc_bit_logp(enc, tf_select, 1);
for (i=start;i<end;i++) for (i=start;i<end;i++)
tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]]; tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
/*printf("%d %d ", isTransient, tf_select); for(i=0;i<end;i++)printf("%d ", tf_res[i]);printf("\n");*/ /*printf("%d %d ", isTransient, tf_select); for(i=0;i<end;i++)printf("%d ", tf_res[i]);printf("\n");*/
...@@ -617,7 +617,7 @@ static void tf_decode(int start, int end, int C, int isTransient, int *tf_res, i ...@@ -617,7 +617,7 @@ static void tf_decode(int start, int end, int C, int isTransient, int *tf_res, i
curr = tf_res[i]; curr = tf_res[i];
} }
if (LM!=0) if (LM!=0)
tf_select = ec_dec_bits(dec, 1); tf_select = ec_dec_bit_logp(dec, 1);
else else
tf_select = 0; tf_select = 0;
for (i=start;i<end;i++) for (i=start;i<end;i++)
...@@ -1953,7 +1953,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da ...@@ -1953,7 +1953,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
deemphasis(out_syn, pcm, N, C, st->mode->preemph, st->preemph_memD); deemphasis(out_syn, pcm, N, C, st->mode->preemph, st->preemph_memD);
st->loss_count = 0; st->loss_count = 0;
RESTORE_STACK; RESTORE_STACK;
if (ec_dec_get_error(dec)) if (ec_dec_tell(dec,0) > 8*len || ec_dec_get_error(dec))
return CELT_CORRUPTED_DATA; return CELT_CORRUPTED_DATA;
else else
return CELT_OK; return CELT_OK;
......
...@@ -34,54 +34,56 @@ ...@@ -34,54 +34,56 @@
#if !defined(_entcode_H) #if !defined(_entcode_H)
# define _entcode_H (1) # define _entcode_H (1)
# include <limits.h> # include <limits.h>
# include <stddef.h>
# include "ecintrin.h" # include "ecintrin.h"
typedef celt_int32 ec_int32; typedef celt_int32 ec_int32;
typedef celt_uint32 ec_uint32; typedef celt_uint32 ec_uint32;
typedef size_t ec_window;
typedef struct ec_byte_buffer ec_byte_buffer; typedef struct ec_byte_buffer ec_byte_buffer;
/*The number of bits to code at a time when coding bits directly.*/ /*This must be at least 32 bits.*/
# define EC_UNIT_BITS (8) # define EC_WINDOW_SIZE ((int)sizeof(ec_window)*CHAR_BIT)
/*The mask for the given bits.*/
# define EC_UNIT_MASK ((1U<<EC_UNIT_BITS)-1) /*The number of bits to use for the range-coded part of unsigned integers.*/
# define EC_UINT_BITS (8)
/*Simple libogg1-style buffer.*/ /*Simple libogg1-style buffer.*/
struct ec_byte_buffer{ struct ec_byte_buffer{
unsigned char *buf; unsigned char *buf;
unsigned char *ptr; ec_uint32 offs;
unsigned char *end_ptr; ec_uint32 end_offs;
ec_uint32 storage; ec_uint32 storage;
}; };
/*Encoding functions.*/ /*Encoding functions.*/
void ec_byte_writeinit_buffer(ec_byte_buffer *_b, unsigned char *_buf, ec_uint32 _size); void ec_byte_writeinit_buffer(ec_byte_buffer *_b, unsigned char *_buf, ec_uint32 _size);
void ec_byte_shrink(ec_byte_buffer *_b, ec_uint32 _size); void ec_byte_shrink(ec_byte_buffer *_b, ec_uint32 _size);
int ec_byte_write1(ec_byte_buffer *_b,unsigned _value); int ec_byte_write(ec_byte_buffer *_b,unsigned _value);
int ec_byte_write_at_end(ec_byte_buffer *_b,unsigned _value); int ec_byte_write_at_end(ec_byte_buffer *_b,unsigned _value);
int ec_byte_write_done(ec_byte_buffer *_b,int _start_bits_available,
unsigned _end_byte,int _end_bits_used);
/*Decoding functions.*/ /*Decoding functions.*/
void ec_byte_readinit(ec_byte_buffer *_b,unsigned char *_buf,ec_uint32 _bytes); void ec_byte_readinit(ec_byte_buffer *_b,unsigned char *_buf,ec_uint32 _bytes);
unsigned char ec_byte_look_at_end(ec_byte_buffer *_b); int ec_byte_read(ec_byte_buffer *_b);
int ec_byte_look4(ec_byte_buffer *_b,ec_uint32 *_val); unsigned char ec_byte_read_from_end(ec_byte_buffer *_b);
void ec_byte_adv1(ec_byte_buffer *_b);
void ec_byte_adv4(ec_byte_buffer *_b);
int ec_byte_read1(ec_byte_buffer *_b);
/*Shared functions.*/ /*Shared functions.*/
static inline void ec_byte_reset(ec_byte_buffer *_b){ static inline void ec_byte_reset(ec_byte_buffer *_b){
_b->ptr=_b->buf; _b->offs=_b->end_offs=0;
} }
static inline ec_uint32 ec_byte_bytes(ec_byte_buffer *_b){ static inline ec_uint32 ec_byte_bytes(ec_byte_buffer *_b){
return _b->ptr-_b->buf; return _b->offs;
} }
static inline unsigned char *ec_byte_get_buffer(ec_byte_buffer *_b){ static inline unsigned char *ec_byte_get_buffer(ec_byte_buffer *_b){
return _b->buf; return _b->buf;
} }
int ec_ilog(ec_uint32 _v); int ec_ilog(ec_uint32 _v);
......
...@@ -39,50 +39,39 @@ ...@@ -39,50 +39,39 @@
#include "arch.h" #include "arch.h"
void ec_byte_readinit(ec_byte_buffer *_b,unsigned char *_buf,ec_uint32 _bytes){ void ec_byte_readinit(ec_byte_buffer *_b,unsigned char *_buf,ec_uint32 _bytes){
_b->buf=_b->ptr=_buf; _b->buf=_buf;
_b->offs=_b->end_offs=0;
_b->storage=_bytes; _b->storage=_bytes;
_b->end_ptr=_b->buf+_bytes-1;
} }
unsigned char ec_byte_look_at_end(ec_byte_buffer *_b){ int ec_byte_read(ec_byte_buffer *_b){
celt_assert2 (_b->end_ptr >= _b->buf, "Trying to read raw bits before the beginning of the stream"); return _b->offs<_b->storage?_b->buf[_b->offs++]:0;
return *(_b->end_ptr--);
} }
void ec_byte_adv1(ec_byte_buffer *_b){ unsigned char ec_byte_read_from_end(ec_byte_buffer *_b){
_b->ptr++; return _b->end_offs<_b->storage?_b->buf[_b->storage-++(_b->end_offs)]:0;
}
int ec_byte_read1(ec_byte_buffer *_b){
ptrdiff_t endbyte;
endbyte=_b->ptr-_b->buf;
if(endbyte>=_b->storage)return -1;
else return *(_b->ptr++);
} }
ec_uint32 ec_dec_uint(ec_dec *_this,ec_uint32 _ft){ ec_uint32 ec_dec_uint(ec_dec *_this,ec_uint32 _ft){
unsigned ft; unsigned ft;
unsigned s; unsigned s;
int ftb; int ftb;
/*In order to optimize EC_ILOG(), it is undefined for the value 0.*/ /*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
celt_assert(_ft>1); celt_assert(_ft>1);
_ft--; _ft--;
ftb=EC_ILOG(_ft); ftb=EC_ILOG(_ft);
if(ftb>EC_UNIT_BITS){ if(ftb>EC_UINT_BITS){
ec_uint32 t; ec_uint32 t;
ftb-=EC_UNIT_BITS; ftb-=EC_UINT_BITS;
ft=(unsigned)(_ft>>ftb)+1; ft=(unsigned)(_ft>>ftb)+1;
s=ec_decode(_this,ft); s=ec_decode(_this,ft);
ec_dec_update(_this,s,s+1,ft); ec_dec_update(_this,s,s+1,ft);
t=s; t=s<<ftb|ec_dec_bits(_this,ftb);
t = t<<ftb|ec_dec_bits(_this,ftb&(1<<ftb)-1); if(t<=_ft)return t;
if (t>_ft) _this->error=1;
{ return _ft;
_this->error |= 1; }
t = _ft; else{
}
return t;
} else {
_ft++; _ft++;
s=ec_decode(_this,(unsigned)_ft); s=ec_decode(_this,(unsigned)_ft);
ec_dec_update(_this,s,s+1,(unsigned)_ft); ec_dec_update(_this,s,s+1,(unsigned)_ft);
...@@ -90,7 +79,6 @@ ec_uint32 ec_dec_uint(ec_dec *_this,ec_uint32 _ft){ ...@@ -90,7 +79,6 @@ ec_uint32 ec_dec_uint(ec_dec *_this,ec_uint32 _ft){
} }
} }
int ec_dec_get_error(ec_dec *_this) int ec_dec_get_error(ec_dec *_this){
{ return _this->error;
return _this->error || (ec_dec_tell(_this,0) > 8*_this->buf->storage);
} }
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#if !defined(_entdec_H) #if !defined(_entdec_H)
# define _entdec_H (1) # define _entdec_H (1)
# include <limits.h>
# include "entcode.h" # include "entcode.h"
...@@ -52,12 +53,13 @@ struct ec_dec{ ...@@ -52,12 +53,13 @@ struct ec_dec{
ec_uint32 dif; ec_uint32 dif;
/*Normalization factor.*/ /*Normalization factor.*/
ec_uint32 nrm; ec_uint32 nrm;
/*Byte that will be written at the end*/ /*Bits that were written at the end.*/
unsigned char end_byte; ec_window end_window;
/*Number of valid bits in end_byte*/ /*Number of valid bits in end_window.*/
int end_bits_left; int nend_bits;
int nb_end_bits; /*The total number of whole bits read.*/
/*Nonzero if an error occurred*/ int nbits_total;
/*Nonzero if an error occurred.*/
int error; int error;
}; };
...@@ -101,7 +103,7 @@ void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh, ...@@ -101,7 +103,7 @@ void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,
The bits must have been encoded with ec_enc_bits(). The bits must have been encoded with ec_enc_bits().
No call to ec_dec_update() is necessary after this call. No call to ec_dec_update() is necessary after this call.
_ftb: The number of bits to extract. _ftb: The number of bits to extract.
This must be at least one, and no more than 32. This must be between 0 and 25, inclusive.
Return: The decoded bits.*/ Return: The decoded bits.*/
ec_uint32 ec_dec_bits(ec_dec *_this,unsigned _ftb); ec_uint32 ec_dec_bits(ec_dec *_this,unsigned _ftb);
/*Extracts a raw unsigned integer with a non-power-of-2 range from the stream. /*Extracts a raw unsigned integer with a non-power-of-2 range from the stream.
...@@ -137,7 +139,7 @@ int ec_dec_bit_logp(ec_dec *_this,unsigned _logp); ...@@ -137,7 +139,7 @@ int ec_dec_bit_logp(ec_dec *_this,unsigned _logp);
rounding error is in the positive direction).*/ rounding error is in the positive direction).*/
ec_uint32 ec_dec_tell(ec_dec *_this,int _b); ec_uint32 ec_dec_tell(ec_dec *_this,int _b);
/*Returns a nonzero value if any error has been detected during decoding*/ /*Return: A nonzero value if any error has been detected during decoding.*/
int ec_dec_get_error(ec_dec *_this); int ec_dec_get_error(ec_dec *_this);
#endif #endif
...@@ -29,53 +29,60 @@ ...@@ -29,53 +29,60 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifdef HAVE_CONFIG_H #if defined(HAVE_CONFIG_H)
#include "config.h" # include "config.h"
#endif #endif
#include "os_support.h" #include "os_support.h"
#include "entenc.h" #include "entenc.h"
#include "arch.h" #include "arch.h"
void ec_byte_writeinit_buffer(ec_byte_buffer *_b, unsigned char *_buf, ec_uint32 _size){ void ec_byte_writeinit_buffer(ec_byte_buffer *_b,
_b->ptr=_b->buf=_buf; unsigned char *_buf,ec_uint32 _size){
_b->end_ptr=_b->buf+_size-1; _b->buf=_buf;
_b->end_offs=_b->offs=0;
_b->storage=_size; _b->storage=_size;
} }
void ec_byte_shrink(ec_byte_buffer *_b, ec_uint32 _size){ void ec_byte_shrink(ec_byte_buffer *_b,ec_uint32 _size){
int i; celt_assert(_b->offs+_b->end_offs<=_size);
int d; CELT_MOVE(_b->buf+_size-_b->end_offs,
int N; _b->buf+_b->storage-_b->end_offs,_b->end_offs);
d = _b->storage-_size; _b->storage=_size;
N = _b->storage-(_b->end_ptr-_b->buf)-1;
/* Copy "raw bytes" */
_b->end_ptr=_b->buf+_size-1-N;
for (i=0;i<N;i++)
_b->end_ptr[i+1] = _b->end_ptr[i+1+d];
_b->storage=_size;
} }
int ec_byte_write1(ec_byte_buffer *_b,unsigned _value){ int ec_byte_write(ec_byte_buffer *_b,unsigned _value){
ptrdiff_t endbyte; if(_b->offs+_b->end_offs>=_b->storage)return -1;
endbyte=_b->ptr-_b->buf; _b->buf[_b->offs++]=(unsigned char)_value;
if(endbyte>=_b->storage){ return 0;
return 1;
} else {
*(_b->ptr++)=(unsigned char)_value;
return 0;
}
} }
int ec_byte_write_at_end(ec_byte_buffer *_b,unsigned _value){ int ec_byte_write_at_end(ec_byte_buffer *_b,unsigned _value){
if (_b->end_ptr < _b->ptr) if(_b->offs+_b->end_offs>=_b->storage)return -1;
{ _b->buf[_b->storage-++(_b->end_offs)]=(unsigned char)_value;
return 1; return 0;
} else { }
*(_b->end_ptr--)=(unsigned char)_value;
return 0; int ec_byte_write_done(ec_byte_buffer *_b,int _start_bits_available,
unsigned _end_byte,int _end_bits_used){
int ret;
CELT_MEMSET(_b->buf+_b->offs,0,_b->storage-_b->offs-_b->end_offs);
ret=0;
if(_end_bits_used>0){
if(_b->offs+_b->end_offs>=_b->storage){
/*If there's no range coder data at all, give up.*/
if(_b->end_offs>=_b->storage)return -1;
/*If we've busted, don't add too many extra bits to the last byte; it
would corrupt the range coder data, and that's more important.*/
if(_start_bits_available<_end_bits_used){
_end_bits_used=_start_bits_available;
_end_byte&=(1<_start_bits_available)-1;
ret=-1;
}
}
_b->buf[_b->storage-_b->end_offs-1]|=_end_byte;
} }
return ret;
} }
void ec_enc_uint(ec_enc *_this,ec_uint32 _fl,ec_uint32 _ft){ void ec_enc_uint(ec_enc *_this,ec_uint32 _fl,ec_uint32 _ft){
...@@ -86,18 +93,16 @@ void ec_enc_uint(ec_enc *_this,ec_uint32 _fl,ec_uint32 _ft){ ...@@ -86,18 +93,16 @@ void ec_enc_uint(ec_enc *_this,ec_uint32 _fl,ec_uint32 _ft){
celt_assert(_ft>1); celt_assert(_ft>1);
_ft--; _ft--;
ftb=EC_ILOG(_ft); ftb=EC_ILOG(_ft);
if(ftb>EC_UNIT_BITS){ if(ftb>EC_UINT_BITS){
ftb-=EC_UNIT_BITS; ftb-=EC_UINT_BITS;
ft=(_ft>>ftb)+1; ft=(_ft>>ftb)+1;
fl=(unsigned)(_fl>>ftb); fl=(unsigned)(_fl>>ftb);
ec_encode(_this,fl,fl+1,ft); ec_encode(_this,fl,fl+1,ft);
ec_enc_bits(_this,_fl&(1<<ftb)-1,ftb); ec_enc_bits(_this,_fl&((ec_uint32)1<<ftb)-1,ftb);
} else {
ec_encode(_this,_fl,_fl+1,_ft+1);
} }
else ec_encode(_this,_fl,_fl+1,_ft+1);
} }
int ec_enc_get_error(ec_enc *_this) int ec_enc_get_error(ec_enc *_this){
{
return _this->error; return _this->error;
} }
...@@ -52,12 +52,13 @@ struct ec_enc{ ...@@ -52,12 +52,13 @@ struct ec_enc{
ec_uint32 rng; ec_uint32 rng;
/*The low end of the current range (inclusive).*/ /*The low end of the current range (inclusive).*/
ec_uint32 low; ec_uint32 low;
/*Byte that will be written at the end*/ /*Bits that will be written at the end.*/
unsigned char end_byte; ec_window end_window;
/*Number of valid bits in end_byte*/ /*Number of valid bits in end_window.*/
int end_bits_left; int nend_bits;
int nb_end_bits; /*The total number of whole bits written.*/
/*Nonzero if an error occurred*/ int nbits_total;
/*Nonzero if an error occurred.*/
int error; int error;
}; };
...@@ -84,7 +85,7 @@ void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits); ...@@ -84,7 +85,7 @@ void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits);
/*Encodes a sequence of raw bits in the stream. /*Encodes a sequence of raw bits in the stream.
_fl: The bits to encode. _fl: The bits to encode.
_ftb: The number of bits to encode. _ftb: The number of bits to encode.
This must be at least one, and no more than 32.*/ This must be between 0 and 25, inclusive.*/
void ec_enc_bits(ec_enc *_this,ec_uint32 _fl,unsigned _ftb); void ec_enc_bits(ec_enc *_this,ec_uint32 _fl,unsigned _ftb);
/*Encodes a raw unsigned integer in the stream. /*Encodes a raw unsigned integer in the stream.
......
...@@ -207,7 +207,6 @@ static void quant_coarse_energy_impl(const CELTMode *m, int start, int end, ...@@ -207,7 +207,6 @@ static void quant_coarse_energy_impl(const CELTMode *m, int start, int end,
bits_left = budget-(int)ec_enc_tell(enc, 0)-3*C*(end-i); bits_left = budget-(int)ec_enc_tell(enc, 0)-3*C*(end-i);
if (i!=start && bits_left < 30) if (i!=start && bits_left < 30)
{ {
qi = IMAX(-1,qi);
if (bits_left < 24) if (bits_left < 24)
qi = IMIN(1, qi); qi = IMIN(1, qi);
if (bits_left < 16) if (bits_left < 16)
...@@ -274,6 +273,8 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, ...@@ -274,6 +273,8 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
ec_enc enc_intra_state; ec_enc enc_intra_state;
ec_byte_buffer buf_intra_state; ec_byte_buffer buf_intra_state;
int tell_intra; int tell_intra;
ec_uint32 nstart_bytes;
ec_uint32 nintra_bytes;
VARDECL(unsigned char, intra_bits); VARDECL(unsigned char, intra_bits);
tell_intra = ec_enc_tell(enc, 3); tell_intra = ec_enc_tell(enc, 3);
...@@ -281,9 +282,13 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, ...@@ -281,9 +282,13 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
enc_intra_state = *enc; enc_intra_state = *enc;
buf_intra_state = *(enc->buf); buf_intra_state = *(enc->buf);
ALLOC(intra_bits, buf_intra_state.ptr-buf_start_state.ptr, unsigned char); nstart_bytes = ec_byte_bytes(&buf_start_state);
nintra_bytes = ec_byte_bytes(&buf_intra_state);
ALLOC(intra_bits, nintra_bytes-nstart_bytes, unsigned char);
/* Copy bits from intra bit-stream */ /* Copy bits from intra bit-stream */
CELT_COPY(intra_bits, buf_start_state.ptr, buf_intra_state.ptr-buf_start_state.ptr); CELT_COPY(intra_bits,
ec_byte_get_buffer(&buf_intra_state) + nstart_bytes,
nintra_bytes - nstart_bytes);
*enc = enc_start_state; *enc = enc_start_state;
*(enc->buf) = buf_start_state; *(enc->buf) = buf_start_state;
...@@ -295,8 +300,9 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, ...@@ -295,8 +300,9 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
{ {
*enc = enc_intra_state; *enc = enc_intra_state;
*(enc->buf) = buf_intra_state; *(enc->buf) = buf_intra_state;
/* Copy bits from to bit-stream */ /* Copy intra bits to bit-stream */
CELT_COPY(buf_start_state.ptr, intra_bits, buf_intra_state.ptr-buf_start_state.ptr); CELT_COPY(ec_byte_get_buffer(&buf_intra_state) + nstart_bytes,
intra_bits, nintra_bytes - nstart_bytes);
CELT_COPY(oldEBands, oldEBands_intra, C*end); CELT_COPY(oldEBands, oldEBands_intra, C*end);
CELT_COPY(error, error_intra, C*end); CELT_COPY(error, error_intra, C*end);
} }
......
...@@ -97,35 +97,20 @@ ...@@ -97,35 +97,20 @@
}*/ }*/
/*Gets the next byte of input.
After all the bytes in the current packet have been consumed, and the extra
end code returned if needed, this function will continue to return zero each
time it is called.
Return: The next byte of input.*/
static int ec_dec_in(ec_dec *_this){
int ret;
ret=ec_byte_read1(_this->buf);
if(ret<0){
ret=0;
/*Needed to keep oc_dec_tell() operating correctly.*/
ec_byte_adv1(_this->buf);
}
return ret;
}
/*Normalizes the contents of dif and rng so that rng lies entirely in the /*Normalizes the contents of dif and rng so that rng lies entirely in the
high-order symbol.*/ high-order symbol.*/
static inline void ec_dec_normalize(ec_dec *_this){ static inline void ec_dec_normalize(ec_dec *_this){
/*If the range is too small, rescale it and input some bits.*/ /*If the range is too small, rescale it and input some bits.*/
while(_this->rng<=EC_CODE_BOT){ while(_this->rng<=EC_CODE_BOT){
int sym; int sym;
_this->nbits_total+=EC_SYM_BITS;
_this->rng<<=EC_SYM_BITS; _this->rng<<=EC_SYM_BITS;
/*Use up the remaining bits from our last symbol.*/ /*Use up the remaining bits from our last symbol.*/
sym=_this->rem<<EC_CODE_EXTRA; sym=_this->rem;
/*Read the next value from the input.*/ /*Read the next value from the input.*/
_this->rem=ec_dec_in(_this); _this->rem=ec_byte_read(_this->buf);
/*Take the rest of the bits we need from this new symbol.*/ /*Take the rest of the bits we need from this new symbol.*/
sym|=_this->rem>>EC_SYM_BITS-EC_CODE_EXTRA; sym=(sym<<EC_SYM_BITS|_this->rem)>>EC_SYM_BITS-EC_CODE_EXTRA;
/*And subtract them from dif, capped to be less than EC_CODE_TOP.*/ /*And subtract them from dif, capped to be less than EC_CODE_TOP.*/
_this->dif=(_this->dif<<EC_SYM_BITS)+(EC_SYM_MAX&~sym)&EC_CODE_TOP-1; _this->dif=(_this->dif<<EC_SYM_BITS)+(EC_SYM_MAX&~sym)&EC_CODE_TOP-1;
} }
...@@ -133,14 +118,17 @@ static inline void ec_dec_normalize(ec_dec *_this){ ...@@ -133,14 +118,17 @@ static inline void ec_dec_normalize(ec_dec *_this){
void ec_dec_init(ec_dec *_this,ec_byte_buffer *_buf){ void ec_dec_init(ec_dec *_this,ec_byte_buffer *_buf){
_this->buf=_buf; _this->buf=_buf;
_this->rem=ec_dec_in(_this); _this->rem=ec_byte_read(_buf);
_this->rng=1U<<EC_CODE_EXTRA; _this->rng=1U<<EC_CODE_EXTRA;
_this->dif=_this->rng-1-(_this->rem>>EC_SYM_BITS-EC_CODE_EXTRA); _this->dif=_this->rng-1-(_this->rem>>EC_SYM_BITS-EC_CODE_EXTRA);
/*Normalize the interval.*/ /*Normalize the interval.*/
ec_dec_normalize(_this); ec_dec_normalize(_this);
_this->end_byte=0; /* Required for platforms that have chars > 8 bits */ _this->end_window=0;
_this->end_bits_left=0; _this->nend_bits=0;
_this->nb_end_bits=0; /*This is the offset from which ec_enc_tell() will subtract partial bits.
This must be after the initial ec_dec_normalize(), or you will have to
compensate for the bits that are read there.*/
_this->nbits_total=EC_CODE_BITS+1;