Fix the bug that was causing the last byte of the stream to be returned incorrectly, as well as undo jm's reversion, which can cause ec_dec_tell() to operate incorrectly at the end of the stream.
A few other minor updates are included as well. git-svn-id: http://svn.xiph.org/trunk/ghost@14427 0101bb08-14d6-0310-b084-bc0e0c8e3800
This commit is contained in:
parent
77ff83a28c
commit
7e3293f713
5 changed files with 85 additions and 55 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "probenc.h"
|
#include "probenc.h"
|
||||||
|
@ -139,6 +140,32 @@ int main(int _argc,char **_argv){
|
||||||
ldexp(nbits2,-4),ldexp(nbits,-4));
|
ldexp(nbits2,-4),ldexp(nbits,-4));
|
||||||
}
|
}
|
||||||
ec_byte_writeclear(&buf);
|
ec_byte_writeclear(&buf);
|
||||||
fprintf(stderr,"All tests passed.\n");
|
fprintf(stderr,"Testing random streams...\n");
|
||||||
|
srand(0);
|
||||||
|
for(i=0;i<1024;i++){
|
||||||
|
unsigned *data;
|
||||||
|
int j;
|
||||||
|
ft=rand()/((RAND_MAX>>9)+1)+512;
|
||||||
|
sz=rand()/((RAND_MAX>>9)+1);
|
||||||
|
data=(unsigned *)malloc(sz*sizeof(*data));
|
||||||
|
ec_byte_writeinit(&buf);
|
||||||
|
ec_enc_init(&enc,&buf);
|
||||||
|
for(j=0;j<sz;j++){
|
||||||
|
data[j]=rand()%ft;
|
||||||
|
ec_enc_uint(&enc,data[j],ft);
|
||||||
|
}
|
||||||
|
ec_enc_done(&enc);
|
||||||
|
ec_byte_readinit(&buf,ec_byte_get_buffer(&buf),ec_byte_bytes(&buf));
|
||||||
|
ec_dec_init(&dec,&buf);
|
||||||
|
for(j=0;j<sz;j++){
|
||||||
|
sym=ec_dec_uint(&dec,ft);
|
||||||
|
if(sym!=data[j]){
|
||||||
|
fprintf(stderr,
|
||||||
|
"Decoded %i instead of %i with ft of %i at position %i of %i.\n",
|
||||||
|
sym,data[j],ft,j,sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ec_byte_writeclear(&buf);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,25 +138,26 @@ static int ec_dec_in(ec_dec *_this){
|
||||||
ret=ec_byte_read1(_this->buf);
|
ret=ec_byte_read1(_this->buf);
|
||||||
if(ret<0){
|
if(ret<0){
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
long bytes;
|
long i;
|
||||||
bytes=ec_byte_bytes(_this->buf);
|
i=ec_byte_bytes(_this->buf);
|
||||||
buf=ec_byte_get_buffer(_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==i&&i>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 i--;
|
||||||
zero, return an extra EC_FOF_RSV1 byte.*/
|
while(i>0&&buf[i]==EC_FOF_RSV1);
|
||||||
do p--;
|
if(!buf[i])ret=EC_FOF_RSV1;
|
||||||
while(p>buf&&p[0]==EC_FOF_RSV1);
|
else ret=0;
|
||||||
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
|
||||||
|
|
|
@ -169,25 +169,26 @@ void ec_enc_done(ec_enc *_this){
|
||||||
}
|
}
|
||||||
/*If we have a buffered byte...*/
|
/*If we have a buffered byte...*/
|
||||||
if(_this->rem>=0){
|
if(_this->rem>=0){
|
||||||
unsigned char *p;
|
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
|
long i;
|
||||||
/*Flush it into the output buffer.*/
|
/*Flush it into the output buffer.*/
|
||||||
ec_enc_carry_out(_this,0);
|
ec_enc_carry_out(_this,0);
|
||||||
_this->rem=-1;
|
_this->rem=-1;
|
||||||
/*We may be able to drop some redundant bytes from the end.*/
|
/*We may be able to drop some redundant bytes from the end.*/
|
||||||
buf=ec_byte_get_buffer(_this->buf);
|
buf=ec_byte_get_buffer(_this->buf);
|
||||||
p=buf+ec_byte_bytes(_this->buf)-1;
|
i=ec_byte_bytes(_this->buf);
|
||||||
/*Strip trailing zeros.*/
|
/*Strip trailing zeros.*/
|
||||||
while(p>=buf&&!p[0])p--;
|
do i--;
|
||||||
|
while(i>0&&!buf[i]);
|
||||||
/*Strip one trailing EC_FOF_RSV1 byte if the buffer ends in a string of
|
/*Strip one trailing EC_FOF_RSV1 byte if the buffer ends in a string of
|
||||||
consecutive EC_FOF_RSV1 bytes preceded by one (or more) zeros.*/
|
consecutive EC_FOF_RSV1 bytes preceded by one (or more) zeros.*/
|
||||||
if(p>buf&&p[0]==EC_FOF_RSV1){
|
if(i>0&&buf[i]==EC_FOF_RSV1){
|
||||||
unsigned char *q;
|
long j;
|
||||||
q=p;
|
j=i;
|
||||||
do q--;
|
do j--;
|
||||||
while(q>buf&&q[0]==EC_FOF_RSV1);
|
while(j>0&&buf[j]==EC_FOF_RSV1);
|
||||||
if(!q[0])p--;
|
if(!buf[j])i--;
|
||||||
}
|
}
|
||||||
ec_byte_writetrunc(_this->buf,p+1-buf);
|
ec_byte_writetrunc(_this->buf,i+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,7 @@
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/*Gets the next byte of input.
|
/*Gets the next byte of input.
|
||||||
After all the bytes in the current packet have been consumed, and the extra
|
After all the bytes in the current packet have been consumed, and the extra
|
||||||
|
@ -121,25 +122,26 @@ static int ec_dec_in(ec_dec *_this){
|
||||||
ret=ec_byte_read1(_this->buf);
|
ret=ec_byte_read1(_this->buf);
|
||||||
if(ret<0){
|
if(ret<0){
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
long bytes;
|
long i;
|
||||||
bytes=ec_byte_bytes(_this->buf);
|
i=ec_byte_bytes(_this->buf);
|
||||||
buf=ec_byte_get_buffer(_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==i&&i>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 i--;
|
||||||
zero, return an extra EC_FOF_RSV1 byte.*/
|
while(i>0&&buf[i]==EC_FOF_RSV1);
|
||||||
do p--;
|
if(!buf[i])ret=EC_FOF_RSV1;
|
||||||
while(p>buf&&p[0]==EC_FOF_RSV1);
|
else ret=0;
|
||||||
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
|
||||||
|
|
|
@ -79,12 +79,10 @@ void ec_enc_init(ec_enc *_this,ec_byte_buffer *_buf){
|
||||||
}
|
}
|
||||||
|
|
||||||
void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
|
void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
|
||||||
unsigned r;
|
ec_uint32 r;
|
||||||
unsigned s;
|
|
||||||
r=_this->rng/_ft;
|
r=_this->rng/_ft;
|
||||||
if(_fl>0){
|
if(_fl>0){
|
||||||
s=r*(_ft-_fl);
|
_this->low+=_this->rng-r*(_ft-_fl);
|
||||||
_this->low+=_this->rng-s;
|
|
||||||
_this->rng=r*(_fh-_fl);
|
_this->rng=r*(_fh-_fl);
|
||||||
}
|
}
|
||||||
else _this->rng-=r*(_ft-_fh);
|
else _this->rng-=r*(_ft-_fh);
|
||||||
|
@ -141,25 +139,26 @@ void ec_enc_done(ec_enc *_this){
|
||||||
}
|
}
|
||||||
/*If we have a buffered byte...*/
|
/*If we have a buffered byte...*/
|
||||||
if(_this->rem>=0){
|
if(_this->rem>=0){
|
||||||
unsigned char *p;
|
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
|
long i;
|
||||||
/*Flush it into the output buffer.*/
|
/*Flush it into the output buffer.*/
|
||||||
ec_enc_carry_out(_this,0);
|
ec_enc_carry_out(_this,0);
|
||||||
_this->rem=-1;
|
_this->rem=-1;
|
||||||
/*We may be able to drop some redundant bytes from the end.*/
|
/*We may be able to drop some redundant bytes from the end.*/
|
||||||
buf=ec_byte_get_buffer(_this->buf);
|
buf=ec_byte_get_buffer(_this->buf);
|
||||||
p=buf+ec_byte_bytes(_this->buf)-1;
|
i=ec_byte_bytes(_this->buf);
|
||||||
/*Strip trailing zeros.*/
|
/*Strip trailing zeros.*/
|
||||||
while(p>=buf&&!p[0])p--;
|
do i--;
|
||||||
|
while(i>0&&!buf[i]);
|
||||||
/*Strip one trailing EC_FOF_RSV1 byte if the buffer ends in a string of
|
/*Strip one trailing EC_FOF_RSV1 byte if the buffer ends in a string of
|
||||||
consecutive EC_FOF_RSV1 bytes preceded by one (or more) zeros.*/
|
consecutive EC_FOF_RSV1 bytes preceded by one (or more) zeros.*/
|
||||||
if(p>buf&&p[0]==EC_FOF_RSV1){
|
if(i>0&&buf[i]==EC_FOF_RSV1){
|
||||||
unsigned char *q;
|
long j;
|
||||||
q=p;
|
j=i;
|
||||||
do q--;
|
do j--;
|
||||||
while(q>buf&&q[0]==EC_FOF_RSV1);
|
while(j>0&&buf[j]==EC_FOF_RSV1);
|
||||||
if(!q[0])p--;
|
if(!buf[j])i--;
|
||||||
}
|
}
|
||||||
ec_byte_writetrunc(_this->buf,p+1-buf);
|
ec_byte_writetrunc(_this->buf,i+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue