Mercurial > libavcodec.hg
comparison fraps.c @ 5820:ffac546a3861 libavcodec
moves fraps huffman decoder to its own file, making it more generic
author | aurel |
---|---|
date | Sun, 14 Oct 2007 21:19:40 +0000 |
parents | 2b72f9bc4f06 |
children | d2af52426ef7 |
comparison
equal
deleted
inserted
replaced
5819:88e131c2d3f8 | 5820:ffac546a3861 |
---|---|
31 * Version 2 files support by Konstantin Shishkov | 31 * Version 2 files support by Konstantin Shishkov |
32 */ | 32 */ |
33 | 33 |
34 #include "avcodec.h" | 34 #include "avcodec.h" |
35 #include "bitstream.h" | 35 #include "bitstream.h" |
36 #include "huffman.h" | |
37 #include "bytestream.h" | |
36 #include "dsputil.h" | 38 #include "dsputil.h" |
37 | 39 |
38 #define FPS_TAG MKTAG('F', 'P', 'S', 'x') | 40 #define FPS_TAG MKTAG('F', 'P', 'S', 'x') |
39 | |
40 /* symbol for Huffman tree node */ | |
41 #define HNODE -1 | |
42 | |
43 /** | |
44 * Huffman node | |
45 * FIXME one day this should belong to one general framework | |
46 */ | |
47 typedef struct Node{ | |
48 int16_t sym; | |
49 int16_t n0; | |
50 int count; | |
51 }Node; | |
52 | 41 |
53 /** | 42 /** |
54 * local variable storage | 43 * local variable storage |
55 */ | 44 */ |
56 typedef struct FrapsContext{ | 45 typedef struct FrapsContext{ |
57 AVCodecContext *avctx; | 46 AVCodecContext *avctx; |
58 AVFrame frame; | 47 AVFrame frame; |
59 Node nodes[512]; | |
60 uint8_t *tmpbuf; | 48 uint8_t *tmpbuf; |
61 DSPContext dsp; | 49 DSPContext dsp; |
62 } FrapsContext; | 50 } FrapsContext; |
63 | 51 |
64 | 52 |
89 */ | 77 */ |
90 static int huff_cmp(const void *va, const void *vb){ | 78 static int huff_cmp(const void *va, const void *vb){ |
91 const Node *a = va, *b = vb; | 79 const Node *a = va, *b = vb; |
92 return (a->count - b->count)*256 + a->sym - b->sym; | 80 return (a->count - b->count)*256 + a->sym - b->sym; |
93 } | 81 } |
94 | |
95 static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat, Node *nodes, int node, uint32_t pfx, int pl, int *pos) | |
96 { | |
97 int s; | |
98 | |
99 s = nodes[node].sym; | |
100 if(s != HNODE || !nodes[node].count){ | |
101 bits[*pos] = pfx; | |
102 lens[*pos] = pl; | |
103 xlat[*pos] = s; | |
104 (*pos)++; | |
105 }else{ | |
106 pfx <<= 1; | |
107 pl++; | |
108 get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0, pfx, pl, pos); | |
109 pfx |= 1; | |
110 get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0+1, pfx, pl, pos); | |
111 } | |
112 } | |
113 | |
114 static int build_huff_tree(VLC *vlc, Node *nodes, uint8_t *xlat) | |
115 { | |
116 uint32_t bits[256]; | |
117 int16_t lens[256]; | |
118 int pos = 0; | |
119 | |
120 get_tree_codes(bits, lens, xlat, nodes, 510, 0, 0, &pos); | |
121 return init_vlc(vlc, 9, pos, lens, 2, 2, bits, 4, 4, 0); | |
122 } | |
123 | |
124 | 82 |
125 /** | 83 /** |
126 * decode Fraps v2 packed plane | 84 * decode Fraps v2 packed plane |
127 */ | 85 */ |
128 static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, | 86 static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, |
129 int h, uint8_t *src, int size, int Uoff) | 87 int h, uint8_t *src, int size, int Uoff) |
130 { | 88 { |
131 int i, j; | 89 int i, j; |
132 int cur_node; | |
133 GetBitContext gb; | 90 GetBitContext gb; |
134 VLC vlc; | 91 VLC vlc; |
135 int64_t sum = 0; | 92 Node nodes[512]; |
136 uint8_t recode[256]; | 93 |
137 | 94 for(i = 0; i < 256; i++) |
138 for(i = 0; i < 256; i++){ | 95 nodes[i].count = bytestream_get_le32(&src); |
139 s->nodes[i].sym = i; | |
140 s->nodes[i].count = AV_RL32(src); | |
141 s->nodes[i].n0 = -2; | |
142 if(s->nodes[i].count < 0) { | |
143 av_log(s->avctx, AV_LOG_ERROR, "Symbol count < 0\n"); | |
144 return -1; | |
145 } | |
146 src += 4; | |
147 sum += s->nodes[i].count; | |
148 } | |
149 size -= 1024; | 96 size -= 1024; |
150 | 97 if (ff_huff_build_tree(s->avctx, &vlc, 256, nodes, huff_cmp, 0) < 0) |
151 if(sum >> 31) { | |
152 av_log(s->avctx, AV_LOG_ERROR, "Too high symbol frequencies. Tree construction is not possible\n"); | |
153 return -1; | 98 return -1; |
154 } | |
155 qsort(s->nodes, 256, sizeof(Node), huff_cmp); | |
156 cur_node = 256; | |
157 for(i = 0; i < 511; i += 2){ | |
158 s->nodes[cur_node].sym = HNODE; | |
159 s->nodes[cur_node].count = s->nodes[i].count + s->nodes[i+1].count; | |
160 s->nodes[cur_node].n0 = i; | |
161 for(j = cur_node; j > 0; j--){ | |
162 if(s->nodes[j].count >= s->nodes[j - 1].count) break; | |
163 FFSWAP(Node, s->nodes[j], s->nodes[j - 1]); | |
164 } | |
165 cur_node++; | |
166 } | |
167 if(build_huff_tree(&vlc, s->nodes, recode) < 0){ | |
168 av_log(s->avctx, AV_LOG_ERROR, "Error building tree\n"); | |
169 return -1; | |
170 } | |
171 /* we have built Huffman table and are ready to decode plane */ | 99 /* we have built Huffman table and are ready to decode plane */ |
172 | 100 |
173 /* convert bits so they may be used by standard bitreader */ | 101 /* convert bits so they may be used by standard bitreader */ |
174 s->dsp.bswap_buf(s->tmpbuf, src, size >> 2); | 102 s->dsp.bswap_buf(s->tmpbuf, src, size >> 2); |
175 | 103 |
176 init_get_bits(&gb, s->tmpbuf, size * 8); | 104 init_get_bits(&gb, s->tmpbuf, size * 8); |
177 for(j = 0; j < h; j++){ | 105 for(j = 0; j < h; j++){ |
178 for(i = 0; i < w; i++){ | 106 for(i = 0; i < w; i++){ |
179 dst[i] = recode[get_vlc2(&gb, vlc.table, 9, 3)]; | 107 dst[i] = get_vlc2(&gb, vlc.table, 9, 3); |
180 /* lines are stored as deltas between previous lines | 108 /* lines are stored as deltas between previous lines |
181 * and we need to add 0x80 to the first lines of chroma planes | 109 * and we need to add 0x80 to the first lines of chroma planes |
182 */ | 110 */ |
183 if(j) dst[i] += dst[i - stride]; | 111 if(j) dst[i] += dst[i - stride]; |
184 else if(Uoff) dst[i] += 0x80; | 112 else if(Uoff) dst[i] += 0x80; |