shithub: opus

Download patch

ref: c08be4485b9e15461578527f568219459db2036c
parent: 8d940a664e14952f3541b6587e367064d9f321bd
author: Jean-Marc Valin <[email protected]>
date: Wed Jun 17 19:23:46 EDT 2009

Implemented "raw bits"

Making it so all the information encoded directly with ec_enc_bits() gets
stored at the end of the stream, without going through the range coder. This
should be both faster and reduce the effects of bit errors.

Conflicts:

	tests/ectest.c

--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -459,11 +459,11 @@
    flag_bits = flaglist[i]&0xf;
    /*printf ("enc %d: %d %d %d %d\n", flag_bits, intra_ener, has_pitch, shortBlocks, has_fold);*/
    if (i<2)
-      ec_enc_bits(enc, flag_bits, 2);
+      ec_enc_uint(enc, flag_bits, 4);
    else if (i<6)
-      ec_enc_bits(enc, flag_bits, 4);
+      ec_enc_uint(enc, flag_bits, 16);
    else
-      ec_enc_bits(enc, flag_bits, 3);
+      ec_enc_uint(enc, flag_bits, 8);
 }
 
 void decode_flags(ec_dec *dec, int *intra_ener, int *has_pitch, int *shortBlocks, int *has_fold)
@@ -470,12 +470,12 @@
 {
    int i;
    int flag_bits;
-   flag_bits = ec_dec_bits(dec, 2);
+   flag_bits = ec_dec_uint(dec, 4);
    /*printf ("(%d) ", flag_bits);*/
    if (flag_bits==2)
-      flag_bits = (flag_bits<<2) | ec_dec_bits(dec, 2);
+      flag_bits = (flag_bits<<2) | ec_dec_uint(dec, 4);
    else if (flag_bits==3)
-      flag_bits = (flag_bits<<1) | ec_dec_bits(dec, 1);
+      flag_bits = (flag_bits<<1) | ec_dec_uint(dec, 2);
    for (i=0;i<8;i++)
       if (flag_bits == (flaglist[i]&0xf))
          break;
--- a/libcelt/entcode.h
+++ b/libcelt/entcode.h
@@ -56,6 +56,7 @@
 struct ec_byte_buffer{
   unsigned char *buf;
   unsigned char *ptr;
+  unsigned char *end_ptr;
   long           storage;
   int            resizable;
 };
@@ -65,6 +66,7 @@
 void ec_byte_writeinit(ec_byte_buffer *_b);
 void ec_byte_writetrunc(ec_byte_buffer *_b,long _bytes);
 void ec_byte_write1(ec_byte_buffer *_b,unsigned _value);
+void ec_byte_write_at_end(ec_byte_buffer *_b,unsigned _value);
 void ec_byte_write4(ec_byte_buffer *_b,ec_uint32 _value);
 void ec_byte_writecopy(ec_byte_buffer *_b,void *_source,long _bytes);
 void ec_byte_writeclear(ec_byte_buffer *_b);
@@ -71,6 +73,7 @@
 /*Decoding functions.*/
 void ec_byte_readinit(ec_byte_buffer *_b,unsigned char *_buf,long _bytes);
 int ec_byte_look1(ec_byte_buffer *_b);
+unsigned char ec_byte_look_at_end(ec_byte_buffer *_b);
 int ec_byte_look4(ec_byte_buffer *_b,ec_uint32 *_val);
 void ec_byte_adv1(ec_byte_buffer *_b);
 void ec_byte_adv4(ec_byte_buffer *_b);
--- a/libcelt/entdec.c
+++ b/libcelt/entdec.c
@@ -38,10 +38,10 @@
 #include "os_support.h"
 #include "arch.h"
 
-
 void ec_byte_readinit(ec_byte_buffer *_b,unsigned char *_buf,long _bytes){
   _b->buf=_b->ptr=_buf;
   _b->storage=_bytes;
+  _b->end_ptr=_b->buf+_bytes-1;
 }
 
 int ec_byte_look1(ec_byte_buffer *_b){
@@ -51,6 +51,14 @@
   else return _b->ptr[0];
 }
 
+unsigned char ec_byte_look_at_end(ec_byte_buffer *_b){
+  if (_b->end_ptr < _b->buf)
+  {
+    celt_fatal("Trying to read raw bits before the beginning of the stream");
+  }
+  return *(_b->end_ptr--);
+}
+
 int ec_byte_look4(ec_byte_buffer *_b,ec_uint32 *_val){
   ptrdiff_t endbyte;
   endbyte=_b->ptr-_b->buf;
@@ -121,13 +129,13 @@
   t=0;
   while(_ftb>EC_UNIT_BITS){
     s=ec_decode_bin(_this,EC_UNIT_BITS);
-    ec_dec_update(_this,s,s+1,EC_UNIT_MASK+1);
+    /*ec_dec_update(_this,s,s+1,EC_UNIT_MASK+1);*/
     t=t<<EC_UNIT_BITS|s;
     _ftb-=EC_UNIT_BITS;
   }
   ft=1U<<_ftb;
   s=ec_decode_bin(_this,_ftb);
-  ec_dec_update(_this,s,s+1,ft);
+  /*ec_dec_update(_this,s,s+1,ft);*/
   t=t<<_ftb|s;
   return t;
 }
--- a/libcelt/entdec.h
+++ b/libcelt/entdec.h
@@ -52,6 +52,11 @@
    ec_uint32       dif;
    /*Normalization factor.*/
    ec_uint32       nrm;
+   /*Byte that will be written at the end*/
+   unsigned char   end_byte;
+   /*Number of valid bits in end_byte*/
+   int             end_bits_left;
+   int             nb_end_bits;
 };
 
 
--- a/libcelt/entenc.c
+++ b/libcelt/entenc.c
@@ -42,14 +42,16 @@
 
 void ec_byte_writeinit_buffer(ec_byte_buffer *_b, unsigned char *_buf, long _size){
   _b->ptr=_b->buf=_buf;
+  _b->end_ptr=_b->buf+_size-1;
   _b->storage=_size;
-  _b->resizable = 0;
+  _b->resizable=0;
 }
 
 void ec_byte_writeinit(ec_byte_buffer *_b){
   _b->ptr=_b->buf=celt_alloc(EC_BUFFER_INCREMENT*sizeof(char));
   _b->storage=EC_BUFFER_INCREMENT;
-  _b->resizable = 1;
+  _b->end_ptr=_b->buf;
+  _b->resizable=1;
 }
 
 void ec_byte_writetrunc(ec_byte_buffer *_b,long _bytes){
@@ -71,6 +73,14 @@
   *(_b->ptr++)=(unsigned char)_value;
 }
 
+void ec_byte_write_at_end(ec_byte_buffer *_b,unsigned _value){
+  if (_b->end_ptr < _b->ptr)
+  {
+    celt_fatal("byte buffer collision");
+  }
+  *(_b->end_ptr--)=(unsigned char)_value;
+}
+
 void ec_byte_write4(ec_byte_buffer *_b,ec_uint32 _value){
   ptrdiff_t endbyte;
   endbyte=_b->ptr-_b->buf;
@@ -109,7 +119,8 @@
 }
 
 void ec_byte_writeclear(ec_byte_buffer *_b){
-  celt_free(_b->buf);
+  if (_b->resizable)
+    celt_free(_b->buf);
 }
 
 
--- a/libcelt/entenc.h
+++ b/libcelt/entenc.h
@@ -52,6 +52,11 @@
    ec_uint32       rng;
    /*The low end of the current range (inclusive).*/
    ec_uint32       low;
+   /*Byte that will be written at the end*/
+   unsigned char   end_byte;
+   /*Number of valid bits in end_byte*/
+   int             end_bits_left;
+   int             nb_end_bits;
 };
 
 
--- a/libcelt/rangedec.c
+++ b/libcelt/rangedec.c
@@ -141,6 +141,9 @@
   _this->dif=_this->rng-(_this->rem>>EC_SYM_BITS-EC_CODE_EXTRA);
   /*Normalize the interval.*/
   ec_dec_normalize(_this);
+  /*_this->end_byte=ec_byte_look_at_end(_this->buf);*/
+  _this->end_bits_left=0;
+  _this->nb_end_bits=0;
 }
 
 
@@ -152,6 +155,7 @@
 }
 
 unsigned ec_decode_bin(ec_dec *_this,unsigned bits){
+#if 0
    unsigned s;
    ec_uint32 ft;
    ft = (ec_uint32)1<<bits;
@@ -158,6 +162,22 @@
    _this->nrm=_this->rng>>bits;
    s=(unsigned)((_this->dif-1)/_this->nrm);
    return ft-EC_MINI(s+1,ft);
+#else
+  unsigned value=0;
+  int count=0;
+  _this->nb_end_bits += bits;
+  while (bits>=_this->end_bits_left)
+  {
+    value |= _this->end_byte>>(8-_this->end_bits_left)<<count;
+    count += _this->end_bits_left;
+    bits -= _this->end_bits_left;
+    _this->end_byte=ec_byte_look_at_end(_this->buf);
+    _this->end_bits_left = 8;
+  }
+  value |= ((_this->end_byte>>(8-_this->end_bits_left))&((1<<bits)-1))<<count;
+  _this->end_bits_left -= bits;
+  return value;
+#endif
 }
 
 void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){
@@ -177,7 +197,7 @@
   /*To handle the non-integral number of bits still left in the decoder state,
      we compute the number of bits of low that must be encoded to ensure that
      the value is inside the range for any possible subsequent bits.*/
-  nbits+=EC_CODE_BITS+1;
+  nbits+=EC_CODE_BITS+1+_this->nb_end_bits;
   nbits<<=_b;
   l=EC_ILOG(_this->rng);
   r=_this->rng>>l-16;
--- a/libcelt/rangeenc.c
+++ b/libcelt/rangeenc.c
@@ -111,6 +111,9 @@
   _this->ext=0;
   _this->low=0;
   _this->rng=EC_CODE_TOP;
+  _this->end_byte=0;
+  _this->end_bits_left=8;
+  _this->nb_end_bits=0;
 }
 
 void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
@@ -125,6 +128,7 @@
 }
 
 void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned bits){
+#if 0
    ec_uint32 r, ft;
    r=_this->rng>>bits;
    ft = (ec_uint32)1<<bits;
@@ -134,6 +138,20 @@
    }
    else _this->rng-=IMUL32(r,(ft-_fh));
    ec_enc_normalize(_this);
+#else
+  _this->nb_end_bits += bits;
+  while (bits >= _this->end_bits_left)
+  {
+    _this->end_byte |= (_fl<<(8-_this->end_bits_left)) & 0xff;
+    _fl >>= _this->end_bits_left;
+    ec_byte_write_at_end(_this->buf, _this->end_byte);
+    _this->end_byte = 0;
+    bits -= _this->end_bits_left;
+    _this->end_bits_left = 8;
+  }
+  _this->end_byte |= (_fl<<(8-_this->end_bits_left)) & 0xff;
+  _this->end_bits_left -= bits;
+#endif
 }
 
 long ec_enc_tell(ec_enc *_this,int _b){
@@ -144,7 +162,7 @@
   /*To handle the non-integral number of bits still left in the encoder state,
      we compute the number of bits of low that must be encoded to ensure that
      the value is inside the range for any possible subsequent bits.*/
-  nbits+=EC_CODE_BITS+1;
+  nbits+=EC_CODE_BITS+1+_this->nb_end_bits;
   nbits<<=_b;
   l=EC_ILOG(_this->rng);
   r=_this->rng>>l-16;
@@ -181,5 +199,12 @@
   if(_this->rem>=0||_this->ext>0){
     ec_enc_carry_out(_this,0);
     _this->rem=-1;
+  }
+  {
+    unsigned char *ptr = _this->buf->ptr;
+    while (ptr<= _this->buf->end_ptr)
+      *ptr++ = 0;
+    if (_this->end_bits_left != 8)
+      *_this->buf->end_ptr |= _this->end_byte;
   }
 }
--- a/tests/ectest.c
+++ b/tests/ectest.c
@@ -11,6 +11,7 @@
 #include "entcode.h"
 #include "entenc.h"
 #include "entdec.h"
+#include <string.h>
 
 #include "../libcelt/rangeenc.c"
 #include "../libcelt/rangedec.c"
@@ -21,6 +22,8 @@
 #ifndef M_LOG2E
 # define M_LOG2E    1.4426950408889634074
 #endif
+#define DATA_SIZE 10000000
+#define DATA_SIZE2 10000
 
 int main(int _argc,char **_argv){
   ec_byte_buffer buf;
@@ -38,7 +41,7 @@
   unsigned int   seed;
   ret=0;
   entropy=0;
-
+  unsigned char *ptr;
     if (_argc > 2) {
 	fprintf(stderr, "Usage: %s [<seed>]\n", _argv[0]);
 	return 1;
@@ -48,7 +51,8 @@
     else
 	seed = (time(NULL) ^ (getpid()%(1<<16) << 16));
   /*Testing encoding of raw bit values.*/
-  ec_byte_writeinit(&buf);
+  ptr = malloc(DATA_SIZE);
+  ec_byte_writeinit_buffer(&buf, ptr, DATA_SIZE);
   ec_enc_init(&enc,&buf);
   for(ft=2;ft<1024;ft++){
     for(i=0;i<ft;i++){
@@ -76,7 +80,7 @@
    "Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n",
    entropy,ldexp(nbits,-4),100*(nbits-ldexp(entropy,4))/nbits);
   fprintf(stderr,"Packed to %li bytes.\n",(long)(buf.ptr-buf.buf));
-  ec_byte_readinit(&buf,ec_byte_get_buffer(&buf),ec_byte_bytes(&buf));
+  ec_byte_readinit(&buf,ptr,DATA_SIZE);
   ec_dec_init(&dec,&buf);
   for(ft=2;ft<1024;ft++){
     for(i=0;i<ft;i++){
@@ -114,7 +118,7 @@
     ft=rand()/((RAND_MAX>>(rand()%11))+1)+10;
     sz=rand()/((RAND_MAX>>(rand()%9))+1);
     data=(unsigned *)malloc(sz*sizeof(*data));
-    ec_byte_writeinit(&buf);
+    ec_byte_writeinit_buffer(&buf, ptr, DATA_SIZE2);
     ec_enc_init(&enc,&buf);
     zeros = rand()%13==0;
     for(j=0;j<sz;j++){
@@ -136,7 +140,7 @@
       ret=-1;
     }
     tell_bits -= 8*ec_byte_bytes(&buf);
-    ec_byte_readinit(&buf,ec_byte_get_buffer(&buf),ec_byte_bytes(&buf));
+    ec_byte_readinit(&buf,ptr,DATA_SIZE2);
     ec_dec_init(&dec,&buf);
     for(j=0;j<sz;j++){
       sym=ec_dec_uint(&dec,ft);
@@ -150,5 +154,6 @@
     ec_byte_writeclear(&buf);
     free(data);
   }
+  free(ptr);
   return ret;
 }