comparison fraps.c @ 4140:a2247f4db5aa libavcodec

Fraps v2 and v4 support
author kostya
date Sun, 05 Nov 2006 04:57:14 +0000
parents c8c591fe26f8
children b03f19bc1698
comparison
equal deleted inserted replaced
4139:8772709e26d0 4140:a2247f4db5aa
1 /* 1 /*
2 * Fraps FPS1 decoder 2 * Fraps FPS1 decoder
3 * Copyright (c) 2005 Roine Gustafsson 3 * Copyright (c) 2005 Roine Gustafsson
4 * Copyright (c) 2006 Konstantin Shishkov
4 * 5 *
5 * This file is part of FFmpeg. 6 * This file is part of FFmpeg.
6 * 7 *
7 * FFmpeg is free software; you can redistribute it and/or 8 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 9 * modify it under the terms of the GNU Lesser General Public
22 23
23 /** 24 /**
24 * @file fraps.c 25 * @file fraps.c
25 * Lossless Fraps 'FPS1' decoder 26 * Lossless Fraps 'FPS1' decoder
26 * @author Roine Gustafsson <roine at users sf net> 27 * @author Roine Gustafsson <roine at users sf net>
28 * @author Konstantin Shishkov
27 * 29 *
28 * Only decodes version 0 and 1 files. 30 * Only decodes version 0 and 1 files.
29 * Codec algorithm for version 0 is taken from Transcode <www.transcoding.org> 31 * Codec algorithm for version 0 is taken from Transcode <www.transcoding.org>
30 * 32 *
31 * Version 2 files, which are the most commonly found Fraps files, cannot be 33 * Version 2 files support by Konstantin Shishkov
32 * decoded yet.
33 */ 34 */
34 35
35 #include "avcodec.h" 36 #include "avcodec.h"
37 #include "bitstream.h"
38 #include "dsputil.h"
36 39
37 #define FPS_TAG MKTAG('F', 'P', 'S', 'x') 40 #define FPS_TAG MKTAG('F', 'P', 'S', 'x')
41
42 /* symbol for Huffman tree node */
43 #define HNODE -1
44
45 /**
46 * Huffman node
47 * FIXME one day this should belong to one general framework
48 */
49 typedef struct Node{
50 int16_t sym;
51 int16_t n0;
52 int count;
53 }Node;
38 54
39 /** 55 /**
40 * local variable storage 56 * local variable storage
41 */ 57 */
42 typedef struct FrapsContext{ 58 typedef struct FrapsContext{
43 AVCodecContext *avctx; 59 AVCodecContext *avctx;
44 AVFrame frame; 60 AVFrame frame;
61 Node nodes[512];
62 uint8_t *tmpbuf;
63 DSPContext dsp;
45 } FrapsContext; 64 } FrapsContext;
46 65
47 66
48 /** 67 /**
49 * initializes decoder 68 * initializes decoder
58 avctx->has_b_frames = 0; 77 avctx->has_b_frames = 0;
59 avctx->pix_fmt= PIX_FMT_NONE; /* set in decode_frame */ 78 avctx->pix_fmt= PIX_FMT_NONE; /* set in decode_frame */
60 79
61 s->avctx = avctx; 80 s->avctx = avctx;
62 s->frame.data[0] = NULL; 81 s->frame.data[0] = NULL;
82 s->tmpbuf = NULL;
83
84 dsputil_init(&s->dsp, avctx);
63 85
64 return 0; 86 return 0;
65 } 87 }
66 88
89 /**
90 * Comparator - our nodes should ascend by count
91 * but with preserved symbol order
92 */
93 static int huff_cmp(const Node *a, const Node *b){
94 return (a->count - b->count)*256 + a->sym - b->sym;
95 }
96
97 static void get_tree_codes(uint32_t *bits, int16_t *lens, Node *nodes, int node, uint32_t pfx, int pl)
98 {
99 int s;
100
101 s = nodes[node].sym;
102 if(s != HNODE){
103 bits[s] = pfx;
104 lens[s] = pl;
105 }else{
106 pfx <<= 1;
107 pl++;
108 get_tree_codes(bits, lens, nodes, nodes[node].n0, pfx, pl);
109 pfx |= 1;
110 get_tree_codes(bits, lens, nodes, nodes[node].n0+1, pfx, pl);
111 }
112 }
113
114 static int build_huff_tree(VLC *vlc, Node *nodes)
115 {
116 uint32_t bits[256];
117 int16_t lens[256];
118
119 get_tree_codes(bits, lens, nodes, 510, 0, 0);
120 return init_vlc(vlc, 9, 256, lens, 2, 2, bits, 4, 4, 0);
121 }
122
123
124 /**
125 * decode Fraps v2 packed plane
126 */
127 static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w,
128 int h, uint8_t *src, int size, int Uoff)
129 {
130 int i, j;
131 int cur_node;
132 GetBitContext gb;
133 VLC vlc;
134 int64_t sum = 0;
135
136 for(i = 0; i < 256; i++){
137 s->nodes[i].sym = i;
138 s->nodes[i].count = LE_32(src);
139 s->nodes[i].n0 = -2;
140 src += 4;
141 sum += s->nodes[i].count;
142 }
143 size -= 1024;
144
145 if(sum >> 31) {
146 av_log(s->avctx, AV_LOG_ERROR, "Too high symbol frequencies. Tree construction is not possible\n");
147 return -1;
148 }
149 qsort(s->nodes, 256, sizeof(Node), huff_cmp);
150 cur_node = 256;
151 // FIXME how it will handle nodes with zero count?
152 for(i = 0; i < 511; i += 2){
153 s->nodes[cur_node].sym = HNODE;
154 s->nodes[cur_node].count = s->nodes[i].count + s->nodes[i+1].count;
155 s->nodes[cur_node].n0 = i;
156 for(j = cur_node; j > 0; j--){
157 if(s->nodes[j].count >= s->nodes[j - 1].count) break;
158 FFSWAP(Node, s->nodes[j], s->nodes[j - 1]);
159 }
160 cur_node++;
161 }
162 if(build_huff_tree(&vlc, s->nodes) < 0){
163 av_log(s->avctx, AV_LOG_ERROR, "Error building tree\n");
164 return -1;
165 }
166 /* we have built Huffman table and are ready to decode plane */
167
168 /* convert bits so they may be used by standard bitreader */
169 s->dsp.bswap_buf(s->tmpbuf, src, size >> 2);
170
171 init_get_bits(&gb, s->tmpbuf, size * 8);
172 for(j = 0; j < h; j++){
173 for(i = 0; i < w; i++){
174 dst[i] = get_vlc2(&gb, vlc.table, 9, 3);
175 /* lines are stored as deltas between previous lines
176 * and we need to add 0x80 to the first lines of chroma planes
177 */
178 if(j) dst[i] += dst[i - stride];
179 else if(Uoff) dst[i] += 0x80;
180 }
181 dst += stride;
182 }
183 free_vlc(&vlc);
184 return 0;
185 }
67 186
68 /** 187 /**
69 * decode a frame 188 * decode a frame
70 * @param avctx codec context 189 * @param avctx codec context
71 * @param data output AVFrame 190 * @param data output AVFrame
84 uint32_t header; 203 uint32_t header;
85 unsigned int version,header_size; 204 unsigned int version,header_size;
86 unsigned int x, y; 205 unsigned int x, y;
87 uint32_t *buf32; 206 uint32_t *buf32;
88 uint32_t *luma1,*luma2,*cb,*cr; 207 uint32_t *luma1,*luma2,*cb,*cr;
208 uint32_t offs[4];
209 int i, is_chroma, planes;
89 210
90 211
91 header = LE_32(buf); 212 header = LE_32(buf);
92 version = header & 0xff; 213 version = header & 0xff;
93 header_size = (header & (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */ 214 header_size = (header & (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */
94 215
95 if (version > 1) { 216 if (version > 2 && version != 4) {
96 av_log(avctx, AV_LOG_ERROR, 217 av_log(avctx, AV_LOG_ERROR,
97 "This file is encoded with Fraps version %d. " \ 218 "This file is encoded with Fraps version %d. " \
98 "This codec can only decode version 0 and 1.\n", version); 219 "This codec can only decode version 0, 1, 2 and 4.\n", version);
99 return -1; 220 return -1;
100 } 221 }
101 222
102 buf+=4; 223 buf+=4;
103 if (header_size == 8) 224 if (header_size == 8)
185 f->linesize[0]); 306 f->linesize[0]);
186 } 307 }
187 break; 308 break;
188 309
189 case 2: 310 case 2:
311 case 4:
190 /** 312 /**
191 * Fraps v2 sub-header description. All numbers are little-endian: 313 * Fraps v2 is Huffman-coded YUV420 planes
192 * (this is all guesswork) 314 * Fraps v4 is the same except it works in grayscale
193 *
194 * 0: DWORD 'FPSx'
195 * 4: DWORD 0x00000010 unknown, perhaps flags
196 * 8: DWORD off_2 offset to plane 2
197 * 12: DWORD off_3 offset to plane 3
198 * 16: 256xDWORD freqtbl_1 frequency table for plane 1
199 * 1040: plane_1
200 * ...
201 * off_2: 256xDWORD freqtbl_2 frequency table for plane 2
202 * plane_2
203 * ...
204 * off_3: 256xDWORD freqtbl_3 frequency table for plane 3
205 * plane_3
206 */ 315 */
207 if ((BE_32(buf) != FPS_TAG)||(buf_size < (3*1024 + 8))) { 316 avctx->pix_fmt = (version == 2) ? PIX_FMT_YUV420P : PIX_FMT_GRAY8;
317 planes = (version == 2) ? 3 : 1;
318 f->reference = 1;
319 f->buffer_hints = FF_BUFFER_HINTS_VALID |
320 FF_BUFFER_HINTS_PRESERVE |
321 FF_BUFFER_HINTS_REUSABLE;
322 if (avctx->reget_buffer(avctx, f)) {
323 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
324 return -1;
325 }
326 /* skip frame */
327 if(buf_size == 8) {
328 f->pict_type = FF_P_TYPE;
329 f->key_frame = 0;
330 break;
331 }
332 f->pict_type = FF_I_TYPE;
333 f->key_frame = 1;
334 if ((LE_32(buf) != FPS_TAG)||(buf_size < (planes*1024 + 24))) {
208 av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n"); 335 av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n");
209 return -1; 336 return -1;
210 } 337 }
211 338 for(i = 0; i < planes; i++) {
212 /* NOT FINISHED */ 339 offs[i] = LE_32(buf + 4 + i * 4);
213 340 if(offs[i] >= buf_size || (i && offs[i] <= offs[i - 1] + 1024)) {
341 av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i);
342 return -1;
343 }
344 }
345 offs[planes] = buf_size;
346 for(i = 0; i < planes; i++){
347 is_chroma = !!i;
348 s->tmpbuf = av_realloc(s->tmpbuf, offs[i + 1] - offs[i] - 1024);
349 if(fraps2_decode_plane(s, f->data[i], f->linesize[i], avctx->width >> is_chroma,
350 avctx->height >> is_chroma, buf + offs[i], offs[i + 1] - offs[i], is_chroma) < 0) {
351 av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i);
352 return -1;
353 }
354 }
214 break; 355 break;
215 } 356 }
216 357
217 *frame = *f; 358 *frame = *f;
218 *data_size = sizeof(AVFrame); 359 *data_size = sizeof(AVFrame);
231 FrapsContext *s = (FrapsContext*)avctx->priv_data; 372 FrapsContext *s = (FrapsContext*)avctx->priv_data;
232 373
233 if (s->frame.data[0]) 374 if (s->frame.data[0])
234 avctx->release_buffer(avctx, &s->frame); 375 avctx->release_buffer(avctx, &s->frame);
235 376
377 av_freep(&s->tmpbuf);
236 return 0; 378 return 0;
237 } 379 }
238 380
239 381
240 AVCodec fraps_decoder = { 382 AVCodec fraps_decoder = {