Added theora to libs
This commit is contained in:
489
project/jni/theora/lib/huffdec.c
Normal file
489
project/jni/theora/lib/huffdec.c
Normal file
@@ -0,0 +1,489 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
|
||||
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: huffdec.c 16503 2009-08-22 18:14:02Z giles $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "huffdec.h"
|
||||
#include "decint.h"
|
||||
|
||||
|
||||
/*The ANSI offsetof macro is broken on some platforms (e.g., older DECs).*/
|
||||
#define _ogg_offsetof(_type,_field)\
|
||||
((size_t)((char *)&((_type *)0)->_field-(char *)0))
|
||||
|
||||
/*The number of internal tokens associated with each of the spec tokens.*/
|
||||
static const unsigned char OC_DCT_TOKEN_MAP_ENTRIES[TH_NDCT_TOKENS]={
|
||||
1,1,1,4,8,1,1,8,1,1,1,1,1,2,2,2,2,4,8,2,2,2,4,2,2,2,2,2,8,2,4,8
|
||||
};
|
||||
|
||||
/*The map from external spec-defined tokens to internal tokens.
|
||||
This is constructed so that any extra bits read with the original token value
|
||||
can be masked off the least significant bits of its internal token index.
|
||||
In addition, all of the tokens which require additional extra bits are placed
|
||||
at the start of the list, and grouped by type.
|
||||
OC_DCT_REPEAT_RUN3_TOKEN is placed first, as it is an extra-special case, so
|
||||
giving it index 0 may simplify comparisons on some architectures.
|
||||
These requirements require some substantial reordering.*/
|
||||
static const unsigned char OC_DCT_TOKEN_MAP[TH_NDCT_TOKENS]={
|
||||
/*OC_DCT_EOB1_TOKEN (0 extra bits)*/
|
||||
15,
|
||||
/*OC_DCT_EOB2_TOKEN (0 extra bits)*/
|
||||
16,
|
||||
/*OC_DCT_EOB3_TOKEN (0 extra bits)*/
|
||||
17,
|
||||
/*OC_DCT_REPEAT_RUN0_TOKEN (2 extra bits)*/
|
||||
88,
|
||||
/*OC_DCT_REPEAT_RUN1_TOKEN (3 extra bits)*/
|
||||
80,
|
||||
/*OC_DCT_REPEAT_RUN2_TOKEN (4 extra bits)*/
|
||||
1,
|
||||
/*OC_DCT_REPEAT_RUN3_TOKEN (12 extra bits)*/
|
||||
0,
|
||||
/*OC_DCT_SHORT_ZRL_TOKEN (3 extra bits)*/
|
||||
48,
|
||||
/*OC_DCT_ZRL_TOKEN (6 extra bits)*/
|
||||
14,
|
||||
/*OC_ONE_TOKEN (0 extra bits)*/
|
||||
56,
|
||||
/*OC_MINUS_ONE_TOKEN (0 extra bits)*/
|
||||
57,
|
||||
/*OC_TWO_TOKEN (0 extra bits)*/
|
||||
58,
|
||||
/*OC_MINUS_TWO_TOKEN (0 extra bits)*/
|
||||
59,
|
||||
/*OC_DCT_VAL_CAT2 (1 extra bit)*/
|
||||
60,
|
||||
62,
|
||||
64,
|
||||
66,
|
||||
/*OC_DCT_VAL_CAT3 (2 extra bits)*/
|
||||
68,
|
||||
/*OC_DCT_VAL_CAT4 (3 extra bits)*/
|
||||
72,
|
||||
/*OC_DCT_VAL_CAT5 (4 extra bits)*/
|
||||
2,
|
||||
/*OC_DCT_VAL_CAT6 (5 extra bits)*/
|
||||
4,
|
||||
/*OC_DCT_VAL_CAT7 (6 extra bits)*/
|
||||
6,
|
||||
/*OC_DCT_VAL_CAT8 (10 extra bits)*/
|
||||
8,
|
||||
/*OC_DCT_RUN_CAT1A (1 extra bit)*/
|
||||
18,
|
||||
20,
|
||||
22,
|
||||
24,
|
||||
26,
|
||||
/*OC_DCT_RUN_CAT1B (3 extra bits)*/
|
||||
32,
|
||||
/*OC_DCT_RUN_CAT1C (4 extra bits)*/
|
||||
12,
|
||||
/*OC_DCT_RUN_CAT2A (2 extra bits)*/
|
||||
28,
|
||||
/*OC_DCT_RUN_CAT2B (3 extra bits)*/
|
||||
40
|
||||
};
|
||||
|
||||
/*These three functions are really part of the bitpack.c module, but
|
||||
they are only used here.
|
||||
Declaring local static versions so they can be inlined saves considerable
|
||||
function call overhead.*/
|
||||
|
||||
static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){
|
||||
const unsigned char *ptr;
|
||||
const unsigned char *stop;
|
||||
oc_pb_window window;
|
||||
int available;
|
||||
window=_b->window;
|
||||
available=_b->bits;
|
||||
ptr=_b->ptr;
|
||||
stop=_b->stop;
|
||||
/*This version of _refill() doesn't bother setting eof because we won't
|
||||
check for it after we've started decoding DCT tokens.*/
|
||||
if(ptr>=stop)available=OC_LOTS_OF_BITS;
|
||||
while(available<=OC_PB_WINDOW_SIZE-8){
|
||||
available+=8;
|
||||
window|=(oc_pb_window)*ptr++<<OC_PB_WINDOW_SIZE-available;
|
||||
if(ptr>=stop)available=OC_LOTS_OF_BITS;
|
||||
}
|
||||
_b->ptr=ptr;
|
||||
if(_bits>available)window|=*ptr>>(available&7);
|
||||
_b->bits=available;
|
||||
return window;
|
||||
}
|
||||
|
||||
|
||||
/*Read in bits without advancing the bit pointer.
|
||||
Here we assume 0<=_bits&&_bits<=32.*/
|
||||
static long oc_pack_look(oc_pack_buf *_b,int _bits){
|
||||
oc_pb_window window;
|
||||
int available;
|
||||
long result;
|
||||
window=_b->window;
|
||||
available=_b->bits;
|
||||
if(_bits==0)return 0;
|
||||
if(_bits>available)_b->window=window=oc_pack_refill(_b,_bits);
|
||||
result=window>>OC_PB_WINDOW_SIZE-_bits;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*Advance the bit pointer.*/
|
||||
static void oc_pack_adv(oc_pack_buf *_b,int _bits){
|
||||
/*We ignore the special cases for _bits==0 and _bits==32 here, since they are
|
||||
never used actually used.
|
||||
OC_HUFF_SLUSH (defined below) would have to be at least 27 to actually read
|
||||
32 bits in a single go, and would require a 32 GB lookup table (assuming
|
||||
8 byte pointers, since 4 byte pointers couldn't fit such a table).*/
|
||||
_b->window<<=_bits;
|
||||
_b->bits-=_bits;
|
||||
}
|
||||
|
||||
|
||||
/*The log_2 of the size of a lookup table is allowed to grow to relative to
|
||||
the number of unique nodes it contains.
|
||||
E.g., if OC_HUFF_SLUSH is 2, then at most 75% of the space in the tree is
|
||||
wasted (each node will have an amortized cost of at most 20 bytes when using
|
||||
4-byte pointers).
|
||||
Larger numbers can decode tokens with fewer read operations, while smaller
|
||||
numbers may save more space (requiring as little as 8 bytes amortized per
|
||||
node, though there will be more nodes).
|
||||
With a sample file:
|
||||
32233473 read calls are required when no tree collapsing is done (100.0%).
|
||||
19269269 read calls are required when OC_HUFF_SLUSH is 0 (59.8%).
|
||||
11144969 read calls are required when OC_HUFF_SLUSH is 1 (34.6%).
|
||||
10538563 read calls are required when OC_HUFF_SLUSH is 2 (32.7%).
|
||||
10192578 read calls are required when OC_HUFF_SLUSH is 3 (31.6%).
|
||||
Since a value of 1 gets us the vast majority of the speed-up with only a
|
||||
small amount of wasted memory, this is what we use.*/
|
||||
#define OC_HUFF_SLUSH (1)
|
||||
|
||||
|
||||
/*Determines the size in bytes of a Huffman tree node that represents a
|
||||
subtree of depth _nbits.
|
||||
_nbits: The depth of the subtree.
|
||||
If this is 0, the node is a leaf node.
|
||||
Otherwise 1<<_nbits pointers are allocated for children.
|
||||
Return: The number of bytes required to store the node.*/
|
||||
static size_t oc_huff_node_size(int _nbits){
|
||||
size_t size;
|
||||
size=_ogg_offsetof(oc_huff_node,nodes);
|
||||
if(_nbits>0)size+=sizeof(oc_huff_node *)*(1<<_nbits);
|
||||
return size;
|
||||
}
|
||||
|
||||
static oc_huff_node *oc_huff_node_init(char **_storage,size_t _size,int _nbits){
|
||||
oc_huff_node *ret;
|
||||
ret=(oc_huff_node *)*_storage;
|
||||
ret->nbits=(unsigned char)_nbits;
|
||||
(*_storage)+=_size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*Determines the size in bytes of a Huffman tree.
|
||||
_nbits: The depth of the subtree.
|
||||
If this is 0, the node is a leaf node.
|
||||
Otherwise storage for 1<<_nbits pointers are added for children.
|
||||
Return: The number of bytes required to store the tree.*/
|
||||
static size_t oc_huff_tree_size(const oc_huff_node *_node){
|
||||
size_t size;
|
||||
size=oc_huff_node_size(_node->nbits);
|
||||
if(_node->nbits){
|
||||
int nchildren;
|
||||
int i;
|
||||
nchildren=1<<_node->nbits;
|
||||
for(i=0;i<nchildren;i+=1<<_node->nbits-_node->nodes[i]->depth){
|
||||
size+=oc_huff_tree_size(_node->nodes[i]);
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/*Unpacks a sub-tree from the given buffer.
|
||||
_opb: The buffer to unpack from.
|
||||
_binodes: The nodes to store the sub-tree in.
|
||||
_nbinodes: The number of nodes available for the sub-tree.
|
||||
Return: 0 on success, or a negative value on error.*/
|
||||
static int oc_huff_tree_unpack(oc_pack_buf *_opb,
|
||||
oc_huff_node *_binodes,int _nbinodes){
|
||||
oc_huff_node *binode;
|
||||
long bits;
|
||||
int nused;
|
||||
if(_nbinodes<1)return TH_EBADHEADER;
|
||||
binode=_binodes;
|
||||
nused=0;
|
||||
bits=oc_pack_read1(_opb);
|
||||
if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
|
||||
/*Read an internal node:*/
|
||||
if(!bits){
|
||||
int ret;
|
||||
nused++;
|
||||
binode->nbits=1;
|
||||
binode->depth=1;
|
||||
binode->nodes[0]=_binodes+nused;
|
||||
ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused);
|
||||
if(ret>=0){
|
||||
nused+=ret;
|
||||
binode->nodes[1]=_binodes+nused;
|
||||
ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused);
|
||||
}
|
||||
if(ret<0)return ret;
|
||||
nused+=ret;
|
||||
}
|
||||
/*Read a leaf node:*/
|
||||
else{
|
||||
int ntokens;
|
||||
int token;
|
||||
int i;
|
||||
bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
|
||||
if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
|
||||
/*Find out how many internal tokens we translate this external token into.*/
|
||||
ntokens=OC_DCT_TOKEN_MAP_ENTRIES[bits];
|
||||
if(_nbinodes<2*ntokens-1)return TH_EBADHEADER;
|
||||
/*Fill in a complete binary tree pointing to the internal tokens.*/
|
||||
for(i=1;i<ntokens;i<<=1){
|
||||
int j;
|
||||
binode=_binodes+nused;
|
||||
nused+=i;
|
||||
for(j=0;j<i;j++){
|
||||
binode[j].nbits=1;
|
||||
binode[j].depth=1;
|
||||
binode[j].nodes[0]=_binodes+nused+2*j;
|
||||
binode[j].nodes[1]=_binodes+nused+2*j+1;
|
||||
}
|
||||
}
|
||||
/*And now the leaf nodes with those tokens.*/
|
||||
token=OC_DCT_TOKEN_MAP[bits];
|
||||
for(i=0;i<ntokens;i++){
|
||||
binode=_binodes+nused++;
|
||||
binode->nbits=0;
|
||||
binode->depth=1;
|
||||
binode->token=token+i;
|
||||
}
|
||||
}
|
||||
return nused;
|
||||
}
|
||||
|
||||
/*Finds the depth of shortest branch of the given sub-tree.
|
||||
The tree must be binary.
|
||||
_binode: The root of the given sub-tree.
|
||||
_binode->nbits must be 0 or 1.
|
||||
Return: The smallest depth of a leaf node in this sub-tree.
|
||||
0 indicates this sub-tree is a leaf node.*/
|
||||
static int oc_huff_tree_mindepth(oc_huff_node *_binode){
|
||||
int depth0;
|
||||
int depth1;
|
||||
if(_binode->nbits==0)return 0;
|
||||
depth0=oc_huff_tree_mindepth(_binode->nodes[0]);
|
||||
depth1=oc_huff_tree_mindepth(_binode->nodes[1]);
|
||||
return OC_MINI(depth0,depth1)+1;
|
||||
}
|
||||
|
||||
/*Finds the number of internal nodes at a given depth, plus the number of
|
||||
leaves at that depth or shallower.
|
||||
The tree must be binary.
|
||||
_binode: The root of the given sub-tree.
|
||||
_binode->nbits must be 0 or 1.
|
||||
Return: The number of entries that would be contained in a jump table of the
|
||||
given depth.*/
|
||||
static int oc_huff_tree_occupancy(oc_huff_node *_binode,int _depth){
|
||||
if(_binode->nbits==0||_depth<=0)return 1;
|
||||
else{
|
||||
return oc_huff_tree_occupancy(_binode->nodes[0],_depth-1)+
|
||||
oc_huff_tree_occupancy(_binode->nodes[1],_depth-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*Makes a copy of the given Huffman tree.
|
||||
_node: The Huffman tree to copy.
|
||||
Return: The copy of the Huffman tree.*/
|
||||
static oc_huff_node *oc_huff_tree_copy(const oc_huff_node *_node,
|
||||
char **_storage){
|
||||
oc_huff_node *ret;
|
||||
ret=oc_huff_node_init(_storage,oc_huff_node_size(_node->nbits),_node->nbits);
|
||||
ret->depth=_node->depth;
|
||||
if(_node->nbits){
|
||||
int nchildren;
|
||||
int i;
|
||||
int inext;
|
||||
nchildren=1<<_node->nbits;
|
||||
for(i=0;i<nchildren;){
|
||||
ret->nodes[i]=oc_huff_tree_copy(_node->nodes[i],_storage);
|
||||
inext=i+(1<<_node->nbits-ret->nodes[i]->depth);
|
||||
while(++i<inext)ret->nodes[i]=ret->nodes[i-1];
|
||||
}
|
||||
}
|
||||
else ret->token=_node->token;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t oc_huff_tree_collapse_size(oc_huff_node *_binode,int _depth){
|
||||
size_t size;
|
||||
int mindepth;
|
||||
int depth;
|
||||
int loccupancy;
|
||||
int occupancy;
|
||||
if(_binode->nbits!=0&&_depth>0){
|
||||
return oc_huff_tree_collapse_size(_binode->nodes[0],_depth-1)+
|
||||
oc_huff_tree_collapse_size(_binode->nodes[1],_depth-1);
|
||||
}
|
||||
depth=mindepth=oc_huff_tree_mindepth(_binode);
|
||||
occupancy=1<<mindepth;
|
||||
do{
|
||||
loccupancy=occupancy;
|
||||
occupancy=oc_huff_tree_occupancy(_binode,++depth);
|
||||
}
|
||||
while(occupancy>loccupancy&&occupancy>=1<<OC_MAXI(depth-OC_HUFF_SLUSH,0));
|
||||
depth--;
|
||||
size=oc_huff_node_size(depth);
|
||||
if(depth>0){
|
||||
size+=oc_huff_tree_collapse_size(_binode->nodes[0],depth-1);
|
||||
size+=oc_huff_tree_collapse_size(_binode->nodes[1],depth-1);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode,
|
||||
char **_storage);
|
||||
|
||||
/*Fills the given nodes table with all the children in the sub-tree at the
|
||||
given depth.
|
||||
The nodes in the sub-tree with a depth less than that stored in the table
|
||||
are freed.
|
||||
The sub-tree must be binary and complete up until the given depth.
|
||||
_nodes: The nodes table to fill.
|
||||
_binode: The root of the sub-tree to fill it with.
|
||||
_binode->nbits must be 0 or 1.
|
||||
_level: The current level in the table.
|
||||
0 indicates that the current node should be stored, regardless of
|
||||
whether it is a leaf node or an internal node.
|
||||
_depth: The depth of the nodes to fill the table with, relative to their
|
||||
parent.*/
|
||||
static void oc_huff_node_fill(oc_huff_node **_nodes,
|
||||
oc_huff_node *_binode,int _level,int _depth,char **_storage){
|
||||
if(_level<=0||_binode->nbits==0){
|
||||
int i;
|
||||
_binode->depth=(unsigned char)(_depth-_level);
|
||||
_nodes[0]=oc_huff_tree_collapse(_binode,_storage);
|
||||
for(i=1;i<1<<_level;i++)_nodes[i]=_nodes[0];
|
||||
}
|
||||
else{
|
||||
_level--;
|
||||
oc_huff_node_fill(_nodes,_binode->nodes[0],_level,_depth,_storage);
|
||||
_nodes+=1<<_level;
|
||||
oc_huff_node_fill(_nodes,_binode->nodes[1],_level,_depth,_storage);
|
||||
}
|
||||
}
|
||||
|
||||
/*Finds the largest complete sub-tree rooted at the current node and collapses
|
||||
it into a single node.
|
||||
This procedure is then applied recursively to all the children of that node.
|
||||
_binode: The root of the sub-tree to collapse.
|
||||
_binode->nbits must be 0 or 1.
|
||||
Return: The new root of the collapsed sub-tree.*/
|
||||
static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode,
|
||||
char **_storage){
|
||||
oc_huff_node *root;
|
||||
size_t size;
|
||||
int mindepth;
|
||||
int depth;
|
||||
int loccupancy;
|
||||
int occupancy;
|
||||
depth=mindepth=oc_huff_tree_mindepth(_binode);
|
||||
occupancy=1<<mindepth;
|
||||
do{
|
||||
loccupancy=occupancy;
|
||||
occupancy=oc_huff_tree_occupancy(_binode,++depth);
|
||||
}
|
||||
while(occupancy>loccupancy&&occupancy>=1<<OC_MAXI(depth-OC_HUFF_SLUSH,0));
|
||||
depth--;
|
||||
if(depth<=1)return oc_huff_tree_copy(_binode,_storage);
|
||||
size=oc_huff_node_size(depth);
|
||||
root=oc_huff_node_init(_storage,size,depth);
|
||||
root->depth=_binode->depth;
|
||||
oc_huff_node_fill(root->nodes,_binode,depth,depth,_storage);
|
||||
return root;
|
||||
}
|
||||
|
||||
/*Unpacks a set of Huffman trees, and reduces them to a collapsed
|
||||
representation.
|
||||
_opb: The buffer to unpack the trees from.
|
||||
_nodes: The table to fill with the Huffman trees.
|
||||
Return: 0 on success, or a negative value on error.*/
|
||||
int oc_huff_trees_unpack(oc_pack_buf *_opb,
|
||||
oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]){
|
||||
int i;
|
||||
for(i=0;i<TH_NHUFFMAN_TABLES;i++){
|
||||
oc_huff_node nodes[511];
|
||||
char *storage;
|
||||
size_t size;
|
||||
int ret;
|
||||
/*Unpack the full tree into a temporary buffer.*/
|
||||
ret=oc_huff_tree_unpack(_opb,nodes,sizeof(nodes)/sizeof(*nodes));
|
||||
if(ret<0)return ret;
|
||||
/*Figure out how big the collapsed tree will be.*/
|
||||
size=oc_huff_tree_collapse_size(nodes,0);
|
||||
storage=(char *)_ogg_calloc(1,size);
|
||||
if(storage==NULL)return TH_EFAULT;
|
||||
/*And collapse it.*/
|
||||
_nodes[i]=oc_huff_tree_collapse(nodes,&storage);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Makes a copy of the given set of Huffman trees.
|
||||
_dst: The array to store the copy in.
|
||||
_src: The array of trees to copy.*/
|
||||
int oc_huff_trees_copy(oc_huff_node *_dst[TH_NHUFFMAN_TABLES],
|
||||
const oc_huff_node *const _src[TH_NHUFFMAN_TABLES]){
|
||||
int i;
|
||||
for(i=0;i<TH_NHUFFMAN_TABLES;i++){
|
||||
size_t size;
|
||||
char *storage;
|
||||
size=oc_huff_tree_size(_src[i]);
|
||||
storage=(char *)_ogg_calloc(1,size);
|
||||
if(storage==NULL){
|
||||
while(i-->0)_ogg_free(_dst[i]);
|
||||
return TH_EFAULT;
|
||||
}
|
||||
_dst[i]=oc_huff_tree_copy(_src[i],&storage);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Frees the memory used by a set of Huffman trees.
|
||||
_nodes: The array of trees to free.*/
|
||||
void oc_huff_trees_clear(oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]){
|
||||
int i;
|
||||
for(i=0;i<TH_NHUFFMAN_TABLES;i++)_ogg_free(_nodes[i]);
|
||||
}
|
||||
|
||||
/*Unpacks a single token using the given Huffman tree.
|
||||
_opb: The buffer to unpack the token from.
|
||||
_node: The tree to unpack the token with.
|
||||
Return: The token value.*/
|
||||
int oc_huff_token_decode(oc_pack_buf *_opb,const oc_huff_node *_node){
|
||||
long bits;
|
||||
while(_node->nbits!=0){
|
||||
bits=oc_pack_look(_opb,_node->nbits);
|
||||
_node=_node->nodes[bits];
|
||||
oc_pack_adv(_opb,_node->depth);
|
||||
}
|
||||
return _node->token;
|
||||
}
|
||||
Reference in New Issue
Block a user