diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-08-22 03:57:45 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-08-22 16:52:07 +0200 |
commit | 3f943fe6815b493741ff65f6c25ca856c38cdafc (patch) | |
tree | 9ba7524625f8a7e4421ee47da9fac192a552a381 /libavcodec/huffman.c | |
parent | 4fced11df73fb1921f60660b5b0f319bb4e723ec (diff) | |
download | ffmpeg-3f943fe6815b493741ff65f6c25ca856c38cdafc.tar.gz |
huffman/huffyuv: move lorens huffman table generation code to huffman.c/h
Reviewed-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/huffman.c')
-rw-r--r-- | libavcodec/huffman.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/libavcodec/huffman.c b/libavcodec/huffman.c index cd1d0d754e..8b336dc7ff 100644 --- a/libavcodec/huffman.c +++ b/libavcodec/huffman.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2006 Konstantin Shishkov + * Copyright (c) 2007 Loren Merritt * * This file is part of FFmpeg. * @@ -111,3 +112,60 @@ int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, } return 0; } + +typedef struct { + uint64_t val; + int name; +} HeapElem; + +static void heap_sift(HeapElem *h, int root, int size) +{ + while(root*2+1 < size) { + int child = root*2+1; + if(child < size-1 && h[child].val > h[child+1].val) + child++; + if(h[root].val > h[child].val) { + FFSWAP(HeapElem, h[root], h[child]); + root = child; + } else + break; + } +} + +void ff_generate_len_table(uint8_t *dst, const uint64_t *stats){ + HeapElem h[256]; + int up[2*256]; + int len[2*256]; + int offset, i, next; + int size = 256; + + for(offset=1; ; offset<<=1){ + for(i=0; i<size; i++){ + h[i].name = i; + h[i].val = (stats[i] << 8) + offset; + } + for(i=size/2-1; i>=0; i--) + heap_sift(h, i, size); + + for(next=size; next<size*2-1; next++){ + // merge the two smallest entries, and put it back in the heap + uint64_t min1v = h[0].val; + up[h[0].name] = next; + h[0].val = INT64_MAX; + heap_sift(h, 0, size); + up[h[0].name] = next; + h[0].name = next; + h[0].val += min1v; + heap_sift(h, 0, size); + } + + len[2*size-2] = 0; + for(i=2*size-3; i>=size; i--) + len[i] = len[up[i]] + 1; + for(i=0; i<size; i++) { + dst[i] = len[up[i]] + 1; + if(dst[i] >= 32) break; + } + if(i==size) break; + } +} |