00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "avcodec.h"
00035 #include "bitstream.h"
00036 #include "huffman.h"
00037 #include "bytestream.h"
00038 #include "dsputil.h"
00039
00040 #define FPS_TAG MKTAG('F', 'P', 'S', 'x')
00041
00042
00043
00044
00045 typedef struct FrapsContext{
00046 AVCodecContext *avctx;
00047 AVFrame frame;
00048 uint8_t *tmpbuf;
00049 DSPContext dsp;
00050 } FrapsContext;
00051
00052
00053
00054
00055
00056
00057
00058 static av_cold int decode_init(AVCodecContext *avctx)
00059 {
00060 FrapsContext * const s = avctx->priv_data;
00061
00062 avctx->coded_frame = (AVFrame*)&s->frame;
00063 avctx->pix_fmt= PIX_FMT_NONE;
00064
00065 s->avctx = avctx;
00066 s->frame.data[0] = NULL;
00067 s->tmpbuf = NULL;
00068
00069 dsputil_init(&s->dsp, avctx);
00070
00071 return 0;
00072 }
00073
00074
00075
00076
00077
00078 static int huff_cmp(const void *va, const void *vb){
00079 const Node *a = va, *b = vb;
00080 return (a->count - b->count)*256 + a->sym - b->sym;
00081 }
00082
00083
00084
00085
00086 static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w,
00087 int h, const uint8_t *src, int size, int Uoff,
00088 const int step)
00089 {
00090 int i, j;
00091 GetBitContext gb;
00092 VLC vlc;
00093 Node nodes[512];
00094
00095 for(i = 0; i < 256; i++)
00096 nodes[i].count = bytestream_get_le32(&src);
00097 size -= 1024;
00098 if (ff_huff_build_tree(s->avctx, &vlc, 256, nodes, huff_cmp,
00099 FF_HUFFMAN_FLAG_ZERO_COUNT) < 0)
00100 return -1;
00101
00102
00103
00104 s->dsp.bswap_buf((uint32_t *)s->tmpbuf, (const uint32_t *)src, size >> 2);
00105
00106 init_get_bits(&gb, s->tmpbuf, size * 8);
00107 for(j = 0; j < h; j++){
00108 for(i = 0; i < w*step; i += step){
00109 dst[i] = get_vlc2(&gb, vlc.table, 9, 3);
00110
00111
00112
00113 if(j) dst[i] += dst[i - stride];
00114 else if(Uoff) dst[i] += 0x80;
00115 }
00116 dst += stride;
00117 }
00118 free_vlc(&vlc);
00119 return 0;
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 static int decode_frame(AVCodecContext *avctx,
00132 void *data, int *data_size,
00133 const uint8_t *buf, int buf_size)
00134 {
00135 FrapsContext * const s = avctx->priv_data;
00136 AVFrame *frame = data;
00137 AVFrame * const f = (AVFrame*)&s->frame;
00138 uint32_t header;
00139 unsigned int version,header_size;
00140 unsigned int x, y;
00141 const uint32_t *buf32;
00142 uint32_t *luma1,*luma2,*cb,*cr;
00143 uint32_t offs[4];
00144 int i, is_chroma, planes;
00145
00146
00147 header = AV_RL32(buf);
00148 version = header & 0xff;
00149 header_size = (header & (1<<30))? 8 : 4;
00150
00151 if (version > 2 && version != 4 && version != 5) {
00152 av_log(avctx, AV_LOG_ERROR,
00153 "This file is encoded with Fraps version %d. " \
00154 "This codec can only decode version 0, 1, 2 and 4.\n", version);
00155 return -1;
00156 }
00157
00158 buf+=4;
00159 if (header_size == 8)
00160 buf+=4;
00161
00162 switch(version) {
00163 case 0:
00164 default:
00165
00166 avctx->pix_fmt = PIX_FMT_YUV420P;
00167
00168 if ( (buf_size != avctx->width*avctx->height*3/2+header_size) &&
00169 (buf_size != header_size) ) {
00170 av_log(avctx, AV_LOG_ERROR,
00171 "Invalid frame length %d (should be %d)\n",
00172 buf_size, avctx->width*avctx->height*3/2+header_size);
00173 return -1;
00174 }
00175
00176 if (( (avctx->width % 8) != 0) || ( (avctx->height % 2) != 0 )) {
00177 av_log(avctx, AV_LOG_ERROR, "Invalid frame size %dx%d\n",
00178 avctx->width, avctx->height);
00179 return -1;
00180 }
00181
00182 f->reference = 1;
00183 f->buffer_hints = FF_BUFFER_HINTS_VALID |
00184 FF_BUFFER_HINTS_PRESERVE |
00185 FF_BUFFER_HINTS_REUSABLE;
00186 if (avctx->reget_buffer(avctx, f)) {
00187 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00188 return -1;
00189 }
00190
00191 f->pict_type = (header & (1<<31))? FF_P_TYPE : FF_I_TYPE;
00192 f->key_frame = f->pict_type == FF_I_TYPE;
00193
00194 if (f->pict_type == FF_I_TYPE) {
00195 buf32=(const uint32_t*)buf;
00196 for(y=0; y<avctx->height/2; y++){
00197 luma1=(uint32_t*)&f->data[0][ y*2*f->linesize[0] ];
00198 luma2=(uint32_t*)&f->data[0][ (y*2+1)*f->linesize[0] ];
00199 cr=(uint32_t*)&f->data[1][ y*f->linesize[1] ];
00200 cb=(uint32_t*)&f->data[2][ y*f->linesize[2] ];
00201 for(x=0; x<avctx->width; x+=8){
00202 *(luma1++) = *(buf32++);
00203 *(luma1++) = *(buf32++);
00204 *(luma2++) = *(buf32++);
00205 *(luma2++) = *(buf32++);
00206 *(cr++) = *(buf32++);
00207 *(cb++) = *(buf32++);
00208 }
00209 }
00210 }
00211 break;
00212
00213 case 1:
00214
00215 avctx->pix_fmt = PIX_FMT_BGR24;
00216
00217 if ( (buf_size != avctx->width*avctx->height*3+header_size) &&
00218 (buf_size != header_size) ) {
00219 av_log(avctx, AV_LOG_ERROR,
00220 "Invalid frame length %d (should be %d)\n",
00221 buf_size, avctx->width*avctx->height*3+header_size);
00222 return -1;
00223 }
00224
00225 f->reference = 1;
00226 f->buffer_hints = FF_BUFFER_HINTS_VALID |
00227 FF_BUFFER_HINTS_PRESERVE |
00228 FF_BUFFER_HINTS_REUSABLE;
00229 if (avctx->reget_buffer(avctx, f)) {
00230 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00231 return -1;
00232 }
00233
00234 f->pict_type = (header & (1<<31))? FF_P_TYPE : FF_I_TYPE;
00235 f->key_frame = f->pict_type == FF_I_TYPE;
00236
00237 if (f->pict_type == FF_I_TYPE) {
00238 for(y=0; y<avctx->height; y++)
00239 memcpy(&f->data[0][ (avctx->height-y)*f->linesize[0] ],
00240 &buf[y*avctx->width*3],
00241 f->linesize[0]);
00242 }
00243 break;
00244
00245 case 2:
00246 case 4:
00247
00248
00249
00250
00251 avctx->pix_fmt = PIX_FMT_YUV420P;
00252 planes = 3;
00253 f->reference = 1;
00254 f->buffer_hints = FF_BUFFER_HINTS_VALID |
00255 FF_BUFFER_HINTS_PRESERVE |
00256 FF_BUFFER_HINTS_REUSABLE;
00257 if (avctx->reget_buffer(avctx, f)) {
00258 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00259 return -1;
00260 }
00261
00262 if(buf_size == 8) {
00263 f->pict_type = FF_P_TYPE;
00264 f->key_frame = 0;
00265 break;
00266 }
00267 f->pict_type = FF_I_TYPE;
00268 f->key_frame = 1;
00269 if ((AV_RL32(buf) != FPS_TAG)||(buf_size < (planes*1024 + 24))) {
00270 av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n");
00271 return -1;
00272 }
00273 for(i = 0; i < planes; i++) {
00274 offs[i] = AV_RL32(buf + 4 + i * 4);
00275 if(offs[i] >= buf_size || (i && offs[i] <= offs[i - 1] + 1024)) {
00276 av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i);
00277 return -1;
00278 }
00279 }
00280 offs[planes] = buf_size;
00281 for(i = 0; i < planes; i++){
00282 is_chroma = !!i;
00283 s->tmpbuf = av_realloc(s->tmpbuf, offs[i + 1] - offs[i] - 1024 + FF_INPUT_BUFFER_PADDING_SIZE);
00284 if(fraps2_decode_plane(s, f->data[i], f->linesize[i], avctx->width >> is_chroma,
00285 avctx->height >> is_chroma, buf + offs[i], offs[i + 1] - offs[i], is_chroma, 1) < 0) {
00286 av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i);
00287 return -1;
00288 }
00289 }
00290 break;
00291 case 5:
00292
00293 avctx->pix_fmt = PIX_FMT_BGR24;
00294 planes = 3;
00295 f->reference = 1;
00296 f->buffer_hints = FF_BUFFER_HINTS_VALID |
00297 FF_BUFFER_HINTS_PRESERVE |
00298 FF_BUFFER_HINTS_REUSABLE;
00299 if (avctx->reget_buffer(avctx, f)) {
00300 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00301 return -1;
00302 }
00303
00304 if(buf_size == 8) {
00305 f->pict_type = FF_P_TYPE;
00306 f->key_frame = 0;
00307 break;
00308 }
00309 f->pict_type = FF_I_TYPE;
00310 f->key_frame = 1;
00311 if ((AV_RL32(buf) != FPS_TAG)||(buf_size < (planes*1024 + 24))) {
00312 av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n");
00313 return -1;
00314 }
00315 for(i = 0; i < planes; i++) {
00316 offs[i] = AV_RL32(buf + 4 + i * 4);
00317 if(offs[i] >= buf_size || (i && offs[i] <= offs[i - 1] + 1024)) {
00318 av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i);
00319 return -1;
00320 }
00321 }
00322 offs[planes] = buf_size;
00323 for(i = 0; i < planes; i++){
00324 s->tmpbuf = av_realloc(s->tmpbuf, offs[i + 1] - offs[i] - 1024 + FF_INPUT_BUFFER_PADDING_SIZE);
00325 if(fraps2_decode_plane(s, f->data[0] + i + (f->linesize[0] * (avctx->height - 1)), -f->linesize[0],
00326 avctx->width, avctx->height, buf + offs[i], offs[i + 1] - offs[i], 1, 3) < 0) {
00327 av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i);
00328 return -1;
00329 }
00330 }
00331 break;
00332 }
00333
00334 *frame = *f;
00335 *data_size = sizeof(AVFrame);
00336
00337 return buf_size;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346 static av_cold int decode_end(AVCodecContext *avctx)
00347 {
00348 FrapsContext *s = (FrapsContext*)avctx->priv_data;
00349
00350 if (s->frame.data[0])
00351 avctx->release_buffer(avctx, &s->frame);
00352
00353 av_freep(&s->tmpbuf);
00354 return 0;
00355 }
00356
00357
00358 AVCodec fraps_decoder = {
00359 "fraps",
00360 CODEC_TYPE_VIDEO,
00361 CODEC_ID_FRAPS,
00362 sizeof(FrapsContext),
00363 decode_init,
00364 NULL,
00365 decode_end,
00366 decode_frame,
00367 CODEC_CAP_DR1,
00368 .long_name = NULL_IF_CONFIG_SMALL("Fraps"),
00369 };