diff options
author | Loren Merritt <lorenm@u.washington.edu> | 2007-05-19 02:32:59 +0000 |
---|---|---|
committer | Loren Merritt <lorenm@u.washington.edu> | 2007-05-19 02:32:59 +0000 |
commit | 98ef8c324cbab46521fc08fc0483de91e156093e (patch) | |
tree | 3b5fa6e53ebabcc809012d7f37e857c766fcfd18 | |
parent | d2f43ca998bc0c92e798078d11e30ca34b5e8144 (diff) | |
download | ffmpeg-98ef8c324cbab46521fc08fc0483de91e156093e.tar.gz |
change brute force search to min-heap. 3.6x faster generate_len_table, 8% faster ffvhuff encoding.
Originally committed as revision 9069 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavcodec/huffyuv.c | 84 |
1 files changed, 42 insertions, 42 deletions
diff --git a/libavcodec/huffyuv.c b/libavcodec/huffyuv.c index 3a252f6824..21bf176e83 100644 --- a/libavcodec/huffyuv.c +++ b/libavcodec/huffyuv.c @@ -261,57 +261,57 @@ static int generate_bits_table(uint32_t *dst, uint8_t *len_table){ } #ifdef CONFIG_ENCODERS +typedef struct { + uint64_t val; + int name; +} heap_elem_t; + +static void heap_sift(heap_elem_t *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(heap_elem_t, h[root], h[child]); + root = child; + } else + break; + } +} + static void generate_len_table(uint8_t *dst, uint64_t *stats, int size){ - uint64_t counts[2*size]; + heap_elem_t h[size]; int up[2*size]; + int len[2*size]; int offset, i, next; for(offset=1; ; offset<<=1){ for(i=0; i<size; i++){ - counts[i]= stats[i] + offset - 1; + h[i].name = i; + h[i].val = (stats[i] << 8) + offset; } - - for(next=size; next<size*2; next++){ - uint64_t min1, min2; - int min1_i, min2_i; - - min1=min2= INT64_MAX; - min1_i= min2_i=-1; - - for(i=0; i<next; i++){ - if(min2 > counts[i]){ - if(min1 > counts[i]){ - min2= min1; - min2_i= min1_i; - min1= counts[i]; - min1_i= i; - }else{ - min2= counts[i]; - min2_i= i; - } - } - } - - if(min2==INT64_MAX) break; - - counts[next]= min1 + min2; - counts[min1_i]= - counts[min2_i]= INT64_MAX; - up[min1_i]= - up[min2_i]= next; - up[next]= -1; + 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); } - for(i=0; i<size; i++){ - int len; - int index=i; - - for(len=0; up[index] != -1; len++) - index= up[index]; - - if(len >= 32) break; - - dst[i]= len; + 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; } |