3 * Copyright (c) 2005 Roine Gustafsson
4 * Copyright (c) 2006 Konstantin Shishkov
6 * This file is part of Libav.
8 * Libav is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * Libav is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with Libav; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * Lossless Fraps 'FPS1' decoder
26 * @author Roine Gustafsson (roine at users sf net)
27 * @author Konstantin Shishkov
29 * Codec algorithm for version 0 is taken from Transcode <www.transcoding.org>
31 * Version 2 files support by Konstantin Shishkov
35 #include "bitstream.h"
37 #include "bytestream.h"
41 #define FPS_TAG MKTAG('F', 'P', 'S', 'x')
45 * local variable storage
47 typedef struct FrapsContext
{
48 AVCodecContext
*avctx
;
58 * @param avctx codec context
59 * @return 0 on success or negative if fails
61 static av_cold
int decode_init(AVCodecContext
*avctx
)
63 FrapsContext
* const s
= avctx
->priv_data
;
65 avctx
->pix_fmt
= AV_PIX_FMT_NONE
; /* set in decode_frame */
70 s
->frame
= av_frame_alloc();
72 return AVERROR(ENOMEM
);
74 ff_bswapdsp_init(&s
->bdsp
);
80 * Comparator - our nodes should ascend by count
81 * but with preserved symbol order
83 static int huff_cmp(const void *va
, const void *vb
)
85 const Node
*a
= va
, *b
= vb
;
86 return (a
->count
- b
->count
)*256 + a
->sym
- b
->sym
;
90 * decode Fraps v2 packed plane
92 static int fraps2_decode_plane(FrapsContext
*s
, uint8_t *dst
, int stride
, int w
,
93 int h
, const uint8_t *src
, int size
, int Uoff
,
101 for (i
= 0; i
< 256; i
++)
102 nodes
[i
].count
= bytestream_get_le32(&src
);
104 if ((ret
= ff_huff_build_tree(s
->avctx
, &vlc
, 256, VLC_BITS
,
106 FF_HUFFMAN_FLAG_ZERO_COUNT
)) < 0)
108 /* we have built Huffman table and are ready to decode plane */
110 /* convert bits so they may be used by standard bitreader */
111 s
->bdsp
.bswap_buf((uint32_t *) s
->tmpbuf
,
112 (const uint32_t *) src
, size
>> 2);
114 bitstream_init8(&bc
, s
->tmpbuf
, size
);
115 for (j
= 0; j
< h
; j
++) {
116 for (i
= 0; i
< w
*step
; i
+= step
) {
117 dst
[i
] = bitstream_read_vlc(&bc
, vlc
.table
, VLC_BITS
, 3);
118 /* lines are stored as deltas between previous lines
119 * and we need to add 0x80 to the first lines of chroma planes
122 dst
[i
] += dst
[i
- stride
];
125 if (bitstream_bits_left(&bc
) < 0) {
127 return AVERROR_INVALIDDATA
;
136 static int decode_frame(AVCodecContext
*avctx
,
137 void *data
, int *got_frame
,
140 FrapsContext
* const s
= avctx
->priv_data
;
141 const uint8_t *buf
= avpkt
->data
;
142 int buf_size
= avpkt
->size
;
143 AVFrame
*frame
= data
;
144 AVFrame
* const f
= s
->frame
;
146 unsigned int version
,header_size
;
148 const uint32_t *buf32
;
149 uint32_t *luma1
,*luma2
,*cb
,*cr
;
151 int i
, j
, ret
, is_chroma
, planes
;
152 enum AVPixelFormat pix_fmt
;
153 int prev_pic_bit
, expected_size
;
156 av_log(avctx
, AV_LOG_ERROR
, "Packet is too short\n");
157 return AVERROR_INVALIDDATA
;
160 header
= AV_RL32(buf
);
161 version
= header
& 0xff;
162 header_size
= (header
& (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */
163 prev_pic_bit
= header
& (1U << 31); /* bit 31 means same as previous pic */
166 avpriv_report_missing_feature(avctx
, "Fraps version %u", version
);
167 return AVERROR_PATCHWELCOME
;
171 if (header_size
== 8)
174 pix_fmt
= version
& 1 ? AV_PIX_FMT_BGR24
: AV_PIX_FMT_YUVJ420P
;
175 if (avctx
->pix_fmt
!= pix_fmt
&& f
->data
[0]) {
178 avctx
->pix_fmt
= pix_fmt
;
179 avctx
->color_range
= version
& 1 ? AVCOL_RANGE_UNSPECIFIED
182 expected_size
= header_size
;
187 /* Fraps v0 is a reordered YUV420 */
189 expected_size
+= avctx
->width
* avctx
->height
* 3 / 2;
190 if (buf_size
!= expected_size
) {
191 av_log(avctx
, AV_LOG_ERROR
,
192 "Invalid frame length %d (should be %d)\n",
193 buf_size
, expected_size
);
194 return AVERROR_INVALIDDATA
;
197 if (((avctx
->width
% 8) != 0) || ((avctx
->height
% 2) != 0)) {
198 av_log(avctx
, AV_LOG_ERROR
, "Invalid frame size %dx%d\n",
199 avctx
->width
, avctx
->height
);
200 return AVERROR_INVALIDDATA
;
203 if ((ret
= ff_reget_buffer(avctx
, f
)) < 0) {
204 av_log(avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
207 f
->pict_type
= prev_pic_bit
? AV_PICTURE_TYPE_P
: AV_PICTURE_TYPE_I
;
208 f
->key_frame
= f
->pict_type
== AV_PICTURE_TYPE_I
;
210 if (f
->pict_type
== AV_PICTURE_TYPE_I
) {
211 buf32
= (const uint32_t*)buf
;
212 for (y
= 0; y
< avctx
->height
/ 2; y
++) {
213 luma1
= (uint32_t*)&f
->data
[0][ y
* 2 * f
->linesize
[0]];
214 luma2
= (uint32_t*)&f
->data
[0][(y
* 2 + 1) * f
->linesize
[0]];
215 cr
= (uint32_t*)&f
->data
[1][ y
* f
->linesize
[1]];
216 cb
= (uint32_t*)&f
->data
[2][ y
* f
->linesize
[2]];
217 for (x
= 0; x
< avctx
->width
; x
+= 8) {
218 *(luma1
++) = *(buf32
++);
219 *(luma1
++) = *(buf32
++);
220 *(luma2
++) = *(buf32
++);
221 *(luma2
++) = *(buf32
++);
222 *(cr
++) = *(buf32
++);
223 *(cb
++) = *(buf32
++);
230 /* Fraps v1 is an upside-down BGR24 */
232 expected_size
+= avctx
->width
* avctx
->height
* 3;
233 if (buf_size
!= expected_size
) {
234 av_log(avctx
, AV_LOG_ERROR
,
235 "Invalid frame length %d (should be %d)\n",
236 buf_size
, expected_size
);
237 return AVERROR_INVALIDDATA
;
240 if ((ret
= ff_reget_buffer(avctx
, f
)) < 0) {
241 av_log(avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
244 f
->pict_type
= prev_pic_bit
? AV_PICTURE_TYPE_P
: AV_PICTURE_TYPE_I
;
245 f
->key_frame
= f
->pict_type
== AV_PICTURE_TYPE_I
;
247 if (f
->pict_type
== AV_PICTURE_TYPE_I
) {
248 for (y
= 0; y
<avctx
->height
; y
++)
249 memcpy(&f
->data
[0][(avctx
->height
- y
- 1) * f
->linesize
[0]],
250 &buf
[y
* avctx
->width
* 3],
258 * Fraps v2 is Huffman-coded YUV420 planes
259 * Fraps v4 is virtually the same
262 if ((ret
= ff_reget_buffer(avctx
, f
)) < 0) {
263 av_log(avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
268 f
->pict_type
= AV_PICTURE_TYPE_P
;
272 f
->pict_type
= AV_PICTURE_TYPE_I
;
274 if ((AV_RL32(buf
) != FPS_TAG
) || (buf_size
< (planes
* 1024 + 24))) {
275 av_log(avctx
, AV_LOG_ERROR
, "Fraps: error in data stream\n");
276 return AVERROR_INVALIDDATA
;
278 for (i
= 0; i
< planes
; i
++) {
279 offs
[i
] = AV_RL32(buf
+ 4 + i
* 4);
280 if (offs
[i
] >= buf_size
|| (i
&& offs
[i
] <= offs
[i
- 1] + 1024)) {
281 av_log(avctx
, AV_LOG_ERROR
, "Fraps: plane %i offset is out of bounds\n", i
);
282 return AVERROR_INVALIDDATA
;
285 offs
[planes
] = buf_size
;
286 for (i
= 0; i
< planes
; i
++) {
288 av_fast_padded_malloc(&s
->tmpbuf
, &s
->tmpbuf_size
,
289 offs
[i
+ 1] - offs
[i
] - 1024);
291 return AVERROR(ENOMEM
);
292 if ((ret
= fraps2_decode_plane(s
, f
->data
[i
], f
->linesize
[i
],
293 avctx
->width
>> is_chroma
,
294 avctx
->height
>> is_chroma
,
295 buf
+ offs
[i
], offs
[i
+ 1] - offs
[i
],
296 is_chroma
, 1)) < 0) {
297 av_log(avctx
, AV_LOG_ERROR
, "Error decoding plane %i\n", i
);
304 /* Virtually the same as version 4, but is for RGB24 */
306 if ((ret
= ff_reget_buffer(avctx
, f
)) < 0) {
307 av_log(avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
312 f
->pict_type
= AV_PICTURE_TYPE_P
;
316 f
->pict_type
= AV_PICTURE_TYPE_I
;
318 if ((AV_RL32(buf
) != FPS_TAG
)||(buf_size
< (planes
*1024 + 24))) {
319 av_log(avctx
, AV_LOG_ERROR
, "Fraps: error in data stream\n");
320 return AVERROR_INVALIDDATA
;
322 for (i
= 0; i
< planes
; i
++) {
323 offs
[i
] = AV_RL32(buf
+ 4 + i
* 4);
324 if (offs
[i
] >= buf_size
|| (i
&& offs
[i
] <= offs
[i
- 1] + 1024)) {
325 av_log(avctx
, AV_LOG_ERROR
, "Fraps: plane %i offset is out of bounds\n", i
);
326 return AVERROR_INVALIDDATA
;
329 offs
[planes
] = buf_size
;
330 for (i
= 0; i
< planes
; i
++) {
331 av_fast_padded_malloc(&s
->tmpbuf
, &s
->tmpbuf_size
,
332 offs
[i
+ 1] - offs
[i
] - 1024);
334 return AVERROR(ENOMEM
);
335 if ((ret
= fraps2_decode_plane(s
, f
->data
[0] + i
+ (f
->linesize
[0] * (avctx
->height
- 1)),
336 -f
->linesize
[0], avctx
->width
, avctx
->height
,
337 buf
+ offs
[i
], offs
[i
+ 1] - offs
[i
], 0, 3)) < 0) {
338 av_log(avctx
, AV_LOG_ERROR
, "Error decoding plane %i\n", i
);
342 // convert pseudo-YUV into real RGB
343 for (j
= 0; j
< avctx
->height
; j
++) {
344 for (i
= 0; i
< avctx
->width
; i
++) {
345 f
->data
[0][0 + i
*3 + j
*f
->linesize
[0]] += f
->data
[0][1 + i
*3 + j
*f
->linesize
[0]];
346 f
->data
[0][2 + i
*3 + j
*f
->linesize
[0]] += f
->data
[0][1 + i
*3 + j
*f
->linesize
[0]];
352 if ((ret
= av_frame_ref(frame
, f
)) < 0)
362 * @param avctx codec context
363 * @return 0 on success or negative if fails
365 static av_cold
int decode_end(AVCodecContext
*avctx
)
367 FrapsContext
*s
= (FrapsContext
*)avctx
->priv_data
;
369 av_frame_free(&s
->frame
);
371 av_freep(&s
->tmpbuf
);
376 AVCodec ff_fraps_decoder
= {
378 .long_name
= NULL_IF_CONFIG_SMALL("Fraps"),
379 .type
= AVMEDIA_TYPE_VIDEO
,
380 .id
= AV_CODEC_ID_FRAPS
,
381 .priv_data_size
= sizeof(FrapsContext
),
384 .decode
= decode_frame
,
385 .capabilities
= AV_CODEC_CAP_DR1
,
386 .caps_internal
= FF_CODEC_CAP_INIT_THREADSAFE
,