Skip to content
Snippets Groups Projects
Commit 3eff11d8 authored by tterribe's avatar tterribe Committed by Jean-Marc Valin
Browse files

Add ec_dec_tell() to report the same information as ec_enc_tell() decode side....

Add ec_dec_tell() to report the same information as ec_enc_tell() decode side. Remove ec_enc_tell() and replace it with ec_enc_tellf(): just request 0 fractional bits if you want an integer value.

git-svn-id: http://svn.xiph.org/trunk/ghost@14394 0101bb08-14d6-0310-b084-bc0e0c8e3800
parent fad779ca
No related branches found
No related tags found
No related merge requests found
......@@ -11,6 +11,7 @@ int main(int _argc,char **_argv){
ec_probmod mod;
ec_uint64 sym64;
long nbits;
long nbits2;
double entropy;
int ft;
int ftb;
......@@ -33,12 +34,10 @@ int main(int _argc,char **_argv){
/*Testing encoding of raw bit values.*/
for(ftb=0;ftb<16;ftb++){
for(i=0;i<(1<<ftb);i++){
long nbits;
long nbits2;
entropy+=ftb;
nbits=ec_enc_tell(&enc);
nbits=ec_enc_tell(&enc,0);
ec_enc_bits(&enc,i,ftb);
nbits2=ec_enc_tell(&enc);
nbits2=ec_enc_tell(&enc,0);
if(nbits2-nbits!=ftb){
fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
nbits2-nbits,ftb);
......@@ -46,7 +45,7 @@ int main(int _argc,char **_argv){
entropy+=ftb+30;
nbits=nbits2;
ec_enc_bits64(&enc,(ec_uint64)i<<30|i,ftb+30);
nbits2=ec_enc_tell(&enc);
nbits2=ec_enc_tell(&enc,0);
if(nbits2-nbits!=ftb+30){
fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
nbits2-nbits,ftb+30);
......@@ -73,7 +72,7 @@ int main(int _argc,char **_argv){
}
ec_probmod_clear(&mod);
}
nbits=ec_enc_tellf(&enc,4);
nbits=ec_enc_tell(&enc,4);
ec_enc_done(&enc);
fprintf(stderr,
"Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n",
......@@ -133,6 +132,12 @@ int main(int _argc,char **_argv){
}
ec_probmod_clear(&mod);
}
nbits2=ec_dec_tell(&dec,4);
if(nbits!=nbits2){
fprintf(stderr,
"Reported number of bits used was %0.2lf, should be %0.2lf.\n",
ldexp(nbits2,-4),ldexp(nbits,-4));
}
ec_byte_writeclear(&buf);
fprintf(stderr,"All tests passed.\n");
return 0;
......
......@@ -86,4 +86,17 @@ ec_uint32 ec_dec_uint(ec_dec *_this,ec_uint32 _ft);
Return: The decoded bits.*/
ec_uint64 ec_dec_uint64(ec_dec *_this,ec_uint64 _ft);
/*Returns the number of bits "used" by the decoded symbols so far.
The actual number of bits may be larger, due to rounding to whole bytes, or
smaller, due to trailing zeros that were be stripped, so this is not an
estimate of the true packet size.
This same number can be computed by the encoder, and is suitable for making
coding decisions.
_b: The number of extra bits of precision to include.
At most 16 will be accurate.
Return: The number of bits scaled by 2**_b.
This will always be slightly larger than the exact value (e.g., all
rounding error is in the positive direction).*/
long ec_dec_tell(ec_dec *_this,int _b);
#endif
......@@ -65,18 +65,16 @@ void ec_enc_uint64(ec_enc *_this,ec_uint64 _fl,ec_uint64 _ft);
/*Returns the number of bits "used" by the encoded symbols so far.
The actual number of bits may be larger, due to rounding to whole bytes, or
smaller, due to trailing zeros that can be stripped.
Return: The number of bits.*/
long ec_enc_tell(ec_enc *_this);
/*Returns the number of bits "used" by the encoded symbols so far.
The actual number of bits may be larger, due to rounding to whole bytes, or
smaller, due to trailing zeros that can be stripped.
smaller, due to trailing zeros that can be stripped, so this is not an
estimate of the true packet size.
This same number can be computed by the decoder, and is suitable for making
coding decisions.
_b: The number of extra bits of precision to include.
At most 16 will be accurate.
Return: The number of bits scaled by 2**_b.
This will always be slightly larger than the exact value.*/
long ec_enc_tellf(ec_enc *_this,int _b);
This will always be slightly larger than the exact value (e.g., all
rounding error is in the positive direction).*/
long ec_enc_tell(ec_enc *_this,int _b);
/*Indicates that there are no more symbols to encode.
All reamining output bytes are flushed to the output buffer.
......
......@@ -137,26 +137,24 @@ static int ec_dec_in(ec_dec *_this){
int ret;
ret=ec_byte_read1(_this->buf);
if(ret<0){
unsigned char *buf;
long bytes;
long bytes;
bytes=ec_byte_bytes(_this->buf);
buf=ec_byte_get_buffer(_this->buf);
/*Breaking abstraction: don't do this at home, kids.*/
if(_this->buf->storage==bytes){
ec_byte_adv1(_this->buf);
if(bytes>0){
unsigned char *p;
p=buf+bytes;
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
zero, return an extra EC_FOF_RSV1 byte.*/
do p--;
while(p>buf&&p[0]==EC_FOF_RSV1);
if(!p[0])return EC_FOF_RSV1;
}
if(_this->buf->storage==bytes&&bytes>0){
unsigned char *buf;
buf=ec_byte_get_buffer(_this->buf);
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
zero, return an extra EC_FOF_RSV1 byte.*/
do bytes--;
while(bytes>0&&buf[bytes]==EC_FOF_RSV1);
if(!buf[bytes])ret=EC_FOF_RSV1;
}
return 0;
else ret=0;
/*Needed to make sure the above conditional only triggers once, and to keep
oc_dec_tell() operating correctly.*/
ec_byte_adv1(_this->buf);
}
else return ret;
return ret;
}
/*Normalizes the contents of dif and rng so that rng lies entirely in the
......@@ -222,6 +220,31 @@ void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){
ec_dec_normalize(_this);
}
long ec_dec_tell(ec_dec *_this,int _b){
ec_uint32 r;
int l;
long nbits;
nbits=ec_byte_bytes(_this->buf)-(EC_CODE_BITS+EC_SYM_BITS-1)/EC_SYM_BITS<<3;
/*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.
Note that this is subtly different than the actual value we would end the
stream with, which tries to make as many of the trailing bits zeros as
possible.*/
nbits+=EC_CODE_BITS;
nbits<<=_b;
l=EC_ILOG(_this->rng);
r=_this->rng>>l-16;
while(_b-->0){
int b;
r=r*r>>15;
b=(int)(r>>16);
l=l<<1|b;
r>>=b;
}
return nbits-l;
}
#if 0
int ec_dec_done(ec_dec *_this){
unsigned low;
......
......@@ -119,20 +119,7 @@ void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
ec_enc_normalize(_this);
}
long ec_enc_tell(ec_enc *_this){
long nbits;
nbits=ec_byte_bytes(_this->buf)+(_this->rem>=0)+_this->ext<<3;
/*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.
Note that this is subtly different than the actual value we would end the
stream with, which tries to make as many of the trailing bits zeros as
possible.*/
nbits+=EC_CODE_BITS-EC_ILOG(_this->rng);
return nbits;
}
long ec_enc_tellf(ec_enc *_this,int _b){
long ec_enc_tell(ec_enc *_this,int _b){
ec_uint32 r;
int l;
long nbits;
......
......@@ -120,26 +120,24 @@ static int ec_dec_in(ec_dec *_this){
int ret;
ret=ec_byte_read1(_this->buf);
if(ret<0){
unsigned char *buf;
long bytes;
long bytes;
bytes=ec_byte_bytes(_this->buf);
buf=ec_byte_get_buffer(_this->buf);
/*Breaking abstraction: don't do this at home, kids.*/
if(_this->buf->storage==bytes){
ec_byte_adv1(_this->buf);
if(bytes>0){
unsigned char *p;
p=buf+bytes;
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
zero, return an extra EC_FOF_RSV1 byte.*/
do p--;
while(p>buf&&p[0]==EC_FOF_RSV1);
if(!p[0])return EC_FOF_RSV1;
}
if(_this->buf->storage==bytes&&bytes>0){
unsigned char *buf;
buf=ec_byte_get_buffer(_this->buf);
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
zero, return an extra EC_FOF_RSV1 byte.*/
do bytes--;
while(bytes>0&&buf[bytes]==EC_FOF_RSV1);
if(!buf[bytes])ret=EC_FOF_RSV1;
}
return 0;
else ret=0;
/*Needed to make sure the above conditional only triggers once, and to keep
oc_dec_tell() operating correctly.*/
ec_byte_adv1(_this->buf);
}
else return ret;
return ret;
}
/*Normalizes the contents of dif and rng so that rng lies entirely in the
......@@ -188,6 +186,31 @@ void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){
ec_dec_normalize(_this);
}
long ec_dec_tell(ec_dec *_this,int _b){
ec_uint32 r;
int l;
long nbits;
nbits=ec_byte_bytes(_this->buf)-(EC_CODE_BITS+EC_SYM_BITS-1)/EC_SYM_BITS<<3;
/*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.
Note that this is subtly different than the actual value we would end the
stream with, which tries to make as many of the trailing bits zeros as
possible.*/
nbits+=EC_CODE_BITS;
nbits<<=_b;
l=EC_ILOG(_this->rng);
r=_this->rng>>l-16;
while(_b-->0){
int b;
r=r*r>>15;
b=(int)(r>>16);
l=l<<1|b;
r>>=b;
}
return nbits-l;
}
#if 0
int ec_dec_done(ec_dec *_this){
unsigned low;
......
......@@ -91,20 +91,7 @@ void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
ec_enc_normalize(_this);
}
long ec_enc_tell(ec_enc *_this){
long nbits;
nbits=ec_byte_bytes(_this->buf)+(_this->rem>=0)+_this->ext<<3;
/*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.
Note that this is subtly different than the actual value we would end the
stream with, which tries to make as many of the trailing bits zeros as
possible.*/
nbits+=EC_CODE_BITS-EC_ILOG(_this->rng);
return nbits;
}
long ec_enc_tellf(ec_enc *_this,int _b){
long ec_enc_tell(ec_enc *_this,int _b){
ec_uint32 r;
int l;
long nbits;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment