summaryrefslogtreecommitdiff
path: root/thirdparty/libtheora/huffenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/libtheora/huffenc.c')
-rw-r--r--thirdparty/libtheora/huffenc.c112
1 files changed, 84 insertions, 28 deletions
diff --git a/thirdparty/libtheora/huffenc.c b/thirdparty/libtheora/huffenc.c
index bf624e0523..77ab584a19 100644
--- a/thirdparty/libtheora/huffenc.c
+++ b/thirdparty/libtheora/huffenc.c
@@ -859,9 +859,10 @@ int oc_huff_codes_pack(oggpack_buffer *_opb,
/*First, find the maximum code length so we can align all the bit
patterns.*/
maxlen=_codes[i][0].nbits;
- for(j=1;j<TH_NDCT_TOKENS;j++){
- maxlen=OC_MAXI(_codes[i][j].nbits,maxlen);
- }
+ for(j=1;j<TH_NDCT_TOKENS;j++)maxlen=OC_MAXI(_codes[i][j].nbits,maxlen);
+ /*It's improbable that a code with more than 32 bits could pass the
+ validation below, but abort early in any case.*/
+ if(maxlen>32)return TH_EINVAL;
mask=(1<<(maxlen>>1)<<(maxlen+1>>1))-1;
/*Copy over the codes into our temporary workspace.
The bit patterns are aligned, and the original entry each code is from
@@ -877,34 +878,89 @@ int oc_huff_codes_pack(oggpack_buffer *_opb,
/*For each leaf of the tree:*/
bpos=maxlen;
for(j=0;j<TH_NDCT_TOKENS;j++){
- int bit;
- /*If this code has any bits at all.*/
- if(entries[j].shift<maxlen){
- /*Descend into the tree, writing a bit for each branch.*/
- for(;bpos>entries[j].shift;bpos--)oggpackB_write(_opb,0,1);
- /*Mark this as a leaf node, and write its value.*/
- oggpackB_write(_opb,1,1);
- oggpackB_write(_opb,entries[j].token,5);
- /*For each 1 branch we've descended, back up the tree until we reach a
- 0 branch.*/
- bit=1<<bpos;
- for(;entries[j].pattern&bit;bpos++)bit<<=1;
- /*Validate the code.*/
- if(j+1<TH_NDCT_TOKENS){
- mask=~(bit-1)<<1;
- /*The next entry should have a 1 bit where we had a 0, and should
- match our code above that bit.
- This verifies both fullness and prefix-freeness simultaneously.*/
- if(!(entries[j+1].pattern&bit)||
- (entries[j].pattern&mask)!=(entries[j+1].pattern&mask)){
- return TH_EINVAL;
- }
+ ogg_uint32_t bit;
+ /*Fail if this code has no bits at all.
+ Technically a codebook with a single 0-bit entry is legal, but the
+ encoder currently does not support codebooks which do not contain all
+ the tokens.*/
+ if(entries[j].shift>=maxlen)return TH_EINVAL;
+ /*Descend into the tree, writing a bit for each branch.*/
+ for(;bpos>entries[j].shift;bpos--)oggpackB_write(_opb,0,1);
+ /*Mark this as a leaf node, and write its value.*/
+ oggpackB_write(_opb,1,1);
+ oggpackB_write(_opb,entries[j].token,5);
+ /*For each 1 branch we've descended, back up the tree until we reach a
+ 0 branch.*/
+ bit=(ogg_uint32_t)1<<bpos;
+ for(;entries[j].pattern&bit;bpos++)bit<<=1;
+ /*Validate the code.*/
+ if(j+1<TH_NDCT_TOKENS){
+ mask=~(bit-1)<<1;
+ /*The next entry should have a 1 bit where we had a 0, and should
+ match our code above that bit.
+ This verifies both fullness and prefix-freeness simultaneously.*/
+ if(!(entries[j+1].pattern&bit)||
+ (entries[j].pattern&mask)!=(entries[j+1].pattern&mask)){
+ return TH_EINVAL;
+ }
+ }
+ /*If there are no more codes, we should have ascended back to the top
+ of the tree.*/
+ else if(bpos<maxlen)return TH_EINVAL;
+ }
+ }
+ return 0;
+}
+
+/*This is used to copy the configuration of an existing setup header for use by
+ the encoder.
+ The decoder uses a completely different data structure for the Huffman
+ codebooks.*/
+int oc_huff_codes_unpack(oc_pack_buf *_opb,
+ th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]){
+ int i;
+ for(i=0;i<TH_NHUFFMAN_TABLES;i++){
+ ogg_uint32_t code;
+ int len;
+ int nleaves;
+ code=0;
+ len=nleaves=0;
+ memset(_codes[i],0,TH_NDCT_TOKENS*sizeof(*_codes[i]));
+ for(;;){
+ long bits;
+ bits=oc_pack_read1(_opb);
+ /*Only process nodes so long as there's more bits in the buffer.*/
+ if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
+ /*Read an internal node:*/
+ if(!bits){
+ len++;
+ /*Don't allow codewords longer than 32 bits.*/
+ if(len>32)return TH_EBADHEADER;
+ }
+ /*Read a leaf node:*/
+ else{
+ ogg_uint32_t code_bit;
+ /*Don't allow more than 32 tokens per codebook.*/
+ if(++nleaves>32)return TH_EBADHEADER;
+ bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
+ /*The current encoder does not support codebooks that do not contain
+ all of the tokens.*/
+ if(_codes[i][bits].nbits>0)return TH_EINVAL;
+ _codes[i][bits].pattern=code>>32-len;
+ _codes[i][bits].nbits=len;
+ code_bit=0x80000000U>>len-1;
+ while(len>0&&(code&code_bit)){
+ code^=code_bit;
+ code_bit<<=1;
+ len--;
}
- /*If there are no more codes, we should have ascended back to the top
- of the tree.*/
- else if(bpos<maxlen)return TH_EINVAL;
+ if(len<=0)break;
+ code|=code_bit;
}
}
+ /*The current encoder does not support codebooks that do not contain all of
+ the tokens.*/
+ if(nleaves<32)return TH_EINVAL;
}
return 0;
}