1/* 2 * Fraps FPS1 decoder 3 * Copyright (c) 2005 Roine Gustafsson 4 * Copyright (c) 2006 Konstantin Shishkov 5 * 6 * This file is part of FFmpeg. 7 * 8 * FFmpeg 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. 12 * 13 * FFmpeg 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. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with FFmpeg; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23/** 24 * @file 25 * Lossless Fraps 'FPS1' decoder 26 * @author Roine Gustafsson (roine at users sf net) 27 * @author Konstantin Shishkov 28 * 29 * Codec algorithm for version 0 is taken from Transcode <www.transcoding.org> 30 * 31 * Version 2 files support by Konstantin Shishkov 32 */ 33 34#include "config.h" 35 36#define CACHED_BITSTREAM_READER HAVE_FAST_64BIT 37#define UNCHECKED_BITSTREAM_READER 1 38#include "avcodec.h" 39#include "get_bits.h" 40#include "huffman.h" 41#include "bytestream.h" 42#include "bswapdsp.h" 43#include "codec_internal.h" 44#include "thread.h" 45 46#define FPS_TAG MKTAG('F', 'P', 'S', 'x') 47#define VLC_BITS 11 48 49/** 50 * local variable storage 51 */ 52typedef struct FrapsContext { 53 AVCodecContext *avctx; 54 BswapDSPContext bdsp; 55 uint8_t *tmpbuf; 56 int tmpbuf_size; 57} FrapsContext; 58 59 60/** 61 * initializes decoder 62 * @param avctx codec context 63 * @return 0 on success or negative if fails 64 */ 65static av_cold int decode_init(AVCodecContext *avctx) 66{ 67 FrapsContext * const s = avctx->priv_data; 68 69 s->avctx = avctx; 70 s->tmpbuf = NULL; 71 72 ff_bswapdsp_init(&s->bdsp); 73 74 return 0; 75} 76 77/** 78 * Comparator - our nodes should ascend by count 79 * but with preserved symbol order 80 */ 81static int huff_cmp(const void *va, const void *vb) 82{ 83 const Node *a = va, *b = vb; 84 return (a->count - b->count)*256 + a->sym - b->sym; 85} 86 87/** 88 * decode Fraps v2 packed plane 89 */ 90static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, 91 int h, const uint8_t *src, int size, int Uoff, 92 const int step) 93{ 94 int i, j, ret; 95 GetBitContext gb; 96 VLC vlc; 97 Node nodes[512]; 98 99 for (i = 0; i < 256; i++) 100 nodes[i].count = bytestream_get_le32(&src); 101 size -= 1024; 102 if ((ret = ff_huff_build_tree(s->avctx, &vlc, 256, VLC_BITS, 103 nodes, huff_cmp, 104 FF_HUFFMAN_FLAG_ZERO_COUNT)) < 0) 105 return ret; 106 /* we have built Huffman table and are ready to decode plane */ 107 108 /* convert bits so they may be used by standard bitreader */ 109 s->bdsp.bswap_buf((uint32_t *) s->tmpbuf, 110 (const uint32_t *) src, size >> 2); 111 112 if ((ret = init_get_bits8(&gb, s->tmpbuf, size)) < 0) 113 return ret; 114 115 for (j = 0; j < h; j++) { 116 for (i = 0; i < w*step; i += step) { 117 dst[i] = get_vlc2(&gb, 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 120 */ 121 if (j) 122 dst[i] += dst[i - stride]; 123 else if (Uoff) 124 dst[i] += 0x80; 125 if (get_bits_left(&gb) < 0) { 126 ff_free_vlc(&vlc); 127 return AVERROR_INVALIDDATA; 128 } 129 } 130 dst += stride; 131 } 132 ff_free_vlc(&vlc); 133 return 0; 134} 135 136static int decode_frame(AVCodecContext *avctx, AVFrame *f, 137 int *got_frame, AVPacket *avpkt) 138{ 139 FrapsContext * const s = avctx->priv_data; 140 const uint8_t *buf = avpkt->data; 141 int buf_size = avpkt->size; 142 uint32_t header; 143 unsigned int version,header_size; 144 unsigned int x, y; 145 const uint32_t *buf32; 146 uint32_t *luma1,*luma2,*cb,*cr; 147 uint32_t offs[4]; 148 int i, j, ret, is_chroma; 149 const int planes = 3; 150 int is_pal; 151 uint8_t *out; 152 153 if (buf_size < 4) { 154 av_log(avctx, AV_LOG_ERROR, "Packet is too short\n"); 155 return AVERROR_INVALIDDATA; 156 } 157 158 header = AV_RL32(buf); 159 version = header & 0xff; 160 is_pal = buf[1] == 2 && version == 1; 161 header_size = (header & (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */ 162 163 if (version > 5) { 164 avpriv_report_missing_feature(avctx, "Fraps version %u", version); 165 return AVERROR_PATCHWELCOME; 166 } 167 168 buf += header_size; 169 170 if (is_pal) { 171 unsigned needed_size = avctx->width * avctx->height + 1024; 172 needed_size += header_size; 173 if (buf_size != needed_size) { 174 av_log(avctx, AV_LOG_ERROR, 175 "Invalid frame length %d (should be %d)\n", 176 buf_size, needed_size); 177 return AVERROR_INVALIDDATA; 178 } 179 } else if (version < 2) { 180 unsigned needed_size = avctx->width * avctx->height * 3; 181 if (version == 0) needed_size /= 2; 182 needed_size += header_size; 183 /* bit 31 means same as previous pic */ 184 if (header & (1U<<31)) { 185 *got_frame = 0; 186 return buf_size; 187 } 188 if (buf_size != needed_size) { 189 av_log(avctx, AV_LOG_ERROR, 190 "Invalid frame length %d (should be %d)\n", 191 buf_size, needed_size); 192 return AVERROR_INVALIDDATA; 193 } 194 } else { 195 /* skip frame */ 196 if (buf_size == 8) { 197 *got_frame = 0; 198 return buf_size; 199 } 200 if (AV_RL32(buf) != FPS_TAG || buf_size < planes*1024 + 24) { 201 av_log(avctx, AV_LOG_ERROR, "error in data stream\n"); 202 return AVERROR_INVALIDDATA; 203 } 204 for (i = 0; i < planes; i++) { 205 offs[i] = AV_RL32(buf + 4 + i * 4); 206 if (offs[i] >= buf_size - header_size || (i && offs[i] <= offs[i - 1] + 1024)) { 207 av_log(avctx, AV_LOG_ERROR, "plane %i offset is out of bounds\n", i); 208 return AVERROR_INVALIDDATA; 209 } 210 } 211 offs[planes] = buf_size - header_size; 212 for (i = 0; i < planes; i++) { 213 av_fast_padded_malloc(&s->tmpbuf, &s->tmpbuf_size, offs[i + 1] - offs[i] - 1024); 214 if (!s->tmpbuf) 215 return AVERROR(ENOMEM); 216 } 217 } 218 219 f->pict_type = AV_PICTURE_TYPE_I; 220 f->key_frame = 1; 221 222 avctx->pix_fmt = version & 1 ? is_pal ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_BGR24 : AV_PIX_FMT_YUVJ420P; 223 avctx->color_range = version & 1 ? AVCOL_RANGE_UNSPECIFIED 224 : AVCOL_RANGE_JPEG; 225 avctx->colorspace = version & 1 ? AVCOL_SPC_UNSPECIFIED : AVCOL_SPC_BT709; 226 227 if ((ret = ff_thread_get_buffer(avctx, f, 0)) < 0) 228 return ret; 229 230 switch (version) { 231 case 0: 232 default: 233 /* Fraps v0 is a reordered YUV420 */ 234 if (((avctx->width % 8) != 0) || ((avctx->height % 2) != 0)) { 235 av_log(avctx, AV_LOG_ERROR, "Invalid frame size %dx%d\n", 236 avctx->width, avctx->height); 237 return AVERROR_INVALIDDATA; 238 } 239 240 buf32 = (const uint32_t*)buf; 241 for (y = 0; y < avctx->height / 2; y++) { 242 luma1 = (uint32_t*)&f->data[0][ y * 2 * f->linesize[0] ]; 243 luma2 = (uint32_t*)&f->data[0][ (y * 2 + 1) * f->linesize[0] ]; 244 cr = (uint32_t*)&f->data[1][ y * f->linesize[1] ]; 245 cb = (uint32_t*)&f->data[2][ y * f->linesize[2] ]; 246 for (x = 0; x < avctx->width; x += 8) { 247 *luma1++ = *buf32++; 248 *luma1++ = *buf32++; 249 *luma2++ = *buf32++; 250 *luma2++ = *buf32++; 251 *cr++ = *buf32++; 252 *cb++ = *buf32++; 253 } 254 } 255 break; 256 257 case 1: 258 if (is_pal) { 259 uint32_t *pal = (uint32_t *)f->data[1]; 260 261 for (y = 0; y < 256; y++) { 262 pal[y] = AV_RL32(buf) | 0xFF000000; 263 buf += 4; 264 } 265 266 for (y = 0; y <avctx->height; y++) 267 memcpy(&f->data[0][y * f->linesize[0]], 268 &buf[y * avctx->width], 269 avctx->width); 270 } else { 271 /* Fraps v1 is an upside-down BGR24 */ 272 for (y = 0; y<avctx->height; y++) 273 memcpy(&f->data[0][(avctx->height - y - 1) * f->linesize[0]], 274 &buf[y * avctx->width * 3], 275 3 * avctx->width); 276 } 277 break; 278 279 case 2: 280 case 4: 281 /** 282 * Fraps v2 is Huffman-coded YUV420 planes 283 * Fraps v4 is virtually the same 284 */ 285 for (i = 0; i < planes; i++) { 286 is_chroma = !!i; 287 if ((ret = fraps2_decode_plane(s, f->data[i], f->linesize[i], 288 avctx->width >> is_chroma, 289 avctx->height >> is_chroma, 290 buf + offs[i], offs[i + 1] - offs[i], 291 is_chroma, 1)) < 0) { 292 av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i); 293 return ret; 294 } 295 } 296 break; 297 case 3: 298 case 5: 299 /* Virtually the same as version 4, but is for RGB24 */ 300 for (i = 0; i < planes; i++) { 301 if ((ret = fraps2_decode_plane(s, f->data[0] + i + (f->linesize[0] * (avctx->height - 1)), 302 -f->linesize[0], avctx->width, avctx->height, 303 buf + offs[i], offs[i + 1] - offs[i], 0, 3)) < 0) { 304 av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i); 305 return ret; 306 } 307 } 308 out = f->data[0]; 309 // convert pseudo-YUV into real RGB 310 for (j = 0; j < avctx->height; j++) { 311 uint8_t *line_end = out + 3*avctx->width; 312 while (out < line_end) { 313 out[0] += out[1]; 314 out[2] += out[1]; 315 out += 3; 316 } 317 out += f->linesize[0] - 3*avctx->width; 318 } 319 break; 320 } 321 322 *got_frame = 1; 323 324 return buf_size; 325} 326 327 328/** 329 * closes decoder 330 * @param avctx codec context 331 * @return 0 on success or negative if fails 332 */ 333static av_cold int decode_end(AVCodecContext *avctx) 334{ 335 FrapsContext *s = (FrapsContext*)avctx->priv_data; 336 337 av_freep(&s->tmpbuf); 338 return 0; 339} 340 341 342const FFCodec ff_fraps_decoder = { 343 .p.name = "fraps", 344 .p.long_name = NULL_IF_CONFIG_SMALL("Fraps"), 345 .p.type = AVMEDIA_TYPE_VIDEO, 346 .p.id = AV_CODEC_ID_FRAPS, 347 .priv_data_size = sizeof(FrapsContext), 348 .init = decode_init, 349 .close = decode_end, 350 FF_CODEC_DECODE_CB(decode_frame), 351 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, 352 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 353}; 354