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
This commit is contained in:
parent
fad779ca56
commit
3eff11d8d4
7 changed files with 111 additions and 75 deletions
|
@ -11,6 +11,7 @@ int main(int _argc,char **_argv){
|
||||||
ec_probmod mod;
|
ec_probmod mod;
|
||||||
ec_uint64 sym64;
|
ec_uint64 sym64;
|
||||||
long nbits;
|
long nbits;
|
||||||
|
long nbits2;
|
||||||
double entropy;
|
double entropy;
|
||||||
int ft;
|
int ft;
|
||||||
int ftb;
|
int ftb;
|
||||||
|
@ -33,12 +34,10 @@ int main(int _argc,char **_argv){
|
||||||
/*Testing encoding of raw bit values.*/
|
/*Testing encoding of raw bit values.*/
|
||||||
for(ftb=0;ftb<16;ftb++){
|
for(ftb=0;ftb<16;ftb++){
|
||||||
for(i=0;i<(1<<ftb);i++){
|
for(i=0;i<(1<<ftb);i++){
|
||||||
long nbits;
|
|
||||||
long nbits2;
|
|
||||||
entropy+=ftb;
|
entropy+=ftb;
|
||||||
nbits=ec_enc_tell(&enc);
|
nbits=ec_enc_tell(&enc,0);
|
||||||
ec_enc_bits(&enc,i,ftb);
|
ec_enc_bits(&enc,i,ftb);
|
||||||
nbits2=ec_enc_tell(&enc);
|
nbits2=ec_enc_tell(&enc,0);
|
||||||
if(nbits2-nbits!=ftb){
|
if(nbits2-nbits!=ftb){
|
||||||
fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
|
fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
|
||||||
nbits2-nbits,ftb);
|
nbits2-nbits,ftb);
|
||||||
|
@ -46,7 +45,7 @@ int main(int _argc,char **_argv){
|
||||||
entropy+=ftb+30;
|
entropy+=ftb+30;
|
||||||
nbits=nbits2;
|
nbits=nbits2;
|
||||||
ec_enc_bits64(&enc,(ec_uint64)i<<30|i,ftb+30);
|
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){
|
if(nbits2-nbits!=ftb+30){
|
||||||
fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
|
fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
|
||||||
nbits2-nbits,ftb+30);
|
nbits2-nbits,ftb+30);
|
||||||
|
@ -73,7 +72,7 @@ int main(int _argc,char **_argv){
|
||||||
}
|
}
|
||||||
ec_probmod_clear(&mod);
|
ec_probmod_clear(&mod);
|
||||||
}
|
}
|
||||||
nbits=ec_enc_tellf(&enc,4);
|
nbits=ec_enc_tell(&enc,4);
|
||||||
ec_enc_done(&enc);
|
ec_enc_done(&enc);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n",
|
"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);
|
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);
|
ec_byte_writeclear(&buf);
|
||||||
fprintf(stderr,"All tests passed.\n");
|
fprintf(stderr,"All tests passed.\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -86,4 +86,17 @@ ec_uint32 ec_dec_uint(ec_dec *_this,ec_uint32 _ft);
|
||||||
Return: The decoded bits.*/
|
Return: The decoded bits.*/
|
||||||
ec_uint64 ec_dec_uint64(ec_dec *_this,ec_uint64 _ft);
|
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
|
#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.
|
/*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
|
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
|
||||||
Return: The number of bits.*/
|
estimate of the true packet size.
|
||||||
long ec_enc_tell(ec_enc *_this);
|
This same number can be computed by the decoder, and is suitable for making
|
||||||
|
coding decisions.
|
||||||
/*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.
|
|
||||||
_b: The number of extra bits of precision to include.
|
_b: The number of extra bits of precision to include.
|
||||||
At most 16 will be accurate.
|
At most 16 will be accurate.
|
||||||
Return: The number of bits scaled by 2**_b.
|
Return: The number of bits scaled by 2**_b.
|
||||||
This will always be slightly larger than the exact value.*/
|
This will always be slightly larger than the exact value (e.g., all
|
||||||
long ec_enc_tellf(ec_enc *_this,int _b);
|
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.
|
/*Indicates that there are no more symbols to encode.
|
||||||
All reamining output bytes are flushed to the output buffer.
|
All reamining output bytes are flushed to the output buffer.
|
||||||
|
|
|
@ -137,26 +137,24 @@ static int ec_dec_in(ec_dec *_this){
|
||||||
int ret;
|
int ret;
|
||||||
ret=ec_byte_read1(_this->buf);
|
ret=ec_byte_read1(_this->buf);
|
||||||
if(ret<0){
|
if(ret<0){
|
||||||
unsigned char *buf;
|
long bytes;
|
||||||
long bytes;
|
|
||||||
bytes=ec_byte_bytes(_this->buf);
|
bytes=ec_byte_bytes(_this->buf);
|
||||||
buf=ec_byte_get_buffer(_this->buf);
|
|
||||||
/*Breaking abstraction: don't do this at home, kids.*/
|
/*Breaking abstraction: don't do this at home, kids.*/
|
||||||
if(_this->buf->storage==bytes){
|
if(_this->buf->storage==bytes&&bytes>0){
|
||||||
ec_byte_adv1(_this->buf);
|
unsigned char *buf;
|
||||||
if(bytes>0){
|
buf=ec_byte_get_buffer(_this->buf);
|
||||||
unsigned char *p;
|
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
|
||||||
p=buf+bytes;
|
zero, return an extra EC_FOF_RSV1 byte.*/
|
||||||
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
|
do bytes--;
|
||||||
zero, return an extra EC_FOF_RSV1 byte.*/
|
while(bytes>0&&buf[bytes]==EC_FOF_RSV1);
|
||||||
do p--;
|
if(!buf[bytes])ret=EC_FOF_RSV1;
|
||||||
while(p>buf&&p[0]==EC_FOF_RSV1);
|
|
||||||
if(!p[0])return 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
|
/*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);
|
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
|
#if 0
|
||||||
int ec_dec_done(ec_dec *_this){
|
int ec_dec_done(ec_dec *_this){
|
||||||
unsigned low;
|
unsigned low;
|
||||||
|
|
|
@ -119,20 +119,7 @@ void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
|
||||||
ec_enc_normalize(_this);
|
ec_enc_normalize(_this);
|
||||||
}
|
}
|
||||||
|
|
||||||
long ec_enc_tell(ec_enc *_this){
|
long ec_enc_tell(ec_enc *_this,int _b){
|
||||||
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){
|
|
||||||
ec_uint32 r;
|
ec_uint32 r;
|
||||||
int l;
|
int l;
|
||||||
long nbits;
|
long nbits;
|
||||||
|
|
|
@ -120,26 +120,24 @@ static int ec_dec_in(ec_dec *_this){
|
||||||
int ret;
|
int ret;
|
||||||
ret=ec_byte_read1(_this->buf);
|
ret=ec_byte_read1(_this->buf);
|
||||||
if(ret<0){
|
if(ret<0){
|
||||||
unsigned char *buf;
|
long bytes;
|
||||||
long bytes;
|
|
||||||
bytes=ec_byte_bytes(_this->buf);
|
bytes=ec_byte_bytes(_this->buf);
|
||||||
buf=ec_byte_get_buffer(_this->buf);
|
|
||||||
/*Breaking abstraction: don't do this at home, kids.*/
|
/*Breaking abstraction: don't do this at home, kids.*/
|
||||||
if(_this->buf->storage==bytes){
|
if(_this->buf->storage==bytes&&bytes>0){
|
||||||
ec_byte_adv1(_this->buf);
|
unsigned char *buf;
|
||||||
if(bytes>0){
|
buf=ec_byte_get_buffer(_this->buf);
|
||||||
unsigned char *p;
|
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
|
||||||
p=buf+bytes;
|
zero, return an extra EC_FOF_RSV1 byte.*/
|
||||||
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
|
do bytes--;
|
||||||
zero, return an extra EC_FOF_RSV1 byte.*/
|
while(bytes>0&&buf[bytes]==EC_FOF_RSV1);
|
||||||
do p--;
|
if(!buf[bytes])ret=EC_FOF_RSV1;
|
||||||
while(p>buf&&p[0]==EC_FOF_RSV1);
|
|
||||||
if(!p[0])return 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
|
/*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);
|
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
|
#if 0
|
||||||
int ec_dec_done(ec_dec *_this){
|
int ec_dec_done(ec_dec *_this){
|
||||||
unsigned low;
|
unsigned low;
|
||||||
|
|
|
@ -91,20 +91,7 @@ void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
|
||||||
ec_enc_normalize(_this);
|
ec_enc_normalize(_this);
|
||||||
}
|
}
|
||||||
|
|
||||||
long ec_enc_tell(ec_enc *_this){
|
long ec_enc_tell(ec_enc *_this,int _b){
|
||||||
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){
|
|
||||||
ec_uint32 r;
|
ec_uint32 r;
|
||||||
int l;
|
int l;
|
||||||
long nbits;
|
long nbits;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue