libavcodec/fraps.c
Go to the documentation of this file.
00001 /*
00002  * Fraps FPS1 decoder
00003  * Copyright (c) 2005 Roine Gustafsson
00004  * Copyright (c) 2006 Konstantin Shishkov
00005  *
00006  * This file is part of Libav.
00007  *
00008  * Libav is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * Libav is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with Libav; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00034 #include "avcodec.h"
00035 #include "get_bits.h"
00036 #include "huffman.h"
00037 #include "bytestream.h"
00038 #include "dsputil.h"
00039 
00040 #define FPS_TAG MKTAG('F', 'P', 'S', 'x')
00041 
00045 typedef struct FrapsContext{
00046     AVCodecContext *avctx;
00047     AVFrame frame;
00048     uint8_t *tmpbuf;
00049     DSPContext dsp;
00050 } FrapsContext;
00051 
00052 
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; /* set in decode_frame */
00064 
00065     s->avctx = avctx;
00066     s->tmpbuf = NULL;
00067 
00068     dsputil_init(&s->dsp, avctx);
00069 
00070     return 0;
00071 }
00072 
00077 static int huff_cmp(const void *va, const void *vb){
00078     const Node *a = va, *b = vb;
00079     return (a->count - b->count)*256 + a->sym - b->sym;
00080 }
00081 
00085 static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w,
00086                                int h, const uint8_t *src, int size, int Uoff,
00087                                const int step)
00088 {
00089     int i, j;
00090     GetBitContext gb;
00091     VLC vlc;
00092     Node nodes[512];
00093 
00094     for(i = 0; i < 256; i++)
00095         nodes[i].count = bytestream_get_le32(&src);
00096     size -= 1024;
00097     if (ff_huff_build_tree(s->avctx, &vlc, 256, nodes, huff_cmp,
00098                            FF_HUFFMAN_FLAG_ZERO_COUNT) < 0)
00099         return -1;
00100     /* we have built Huffman table and are ready to decode plane */
00101 
00102     /* convert bits so they may be used by standard bitreader */
00103     s->dsp.bswap_buf((uint32_t *)s->tmpbuf, (const uint32_t *)src, size >> 2);
00104 
00105     init_get_bits(&gb, s->tmpbuf, size * 8);
00106     for(j = 0; j < h; j++){
00107         for(i = 0; i < w*step; i += step){
00108             dst[i] = get_vlc2(&gb, vlc.table, 9, 3);
00109             /* lines are stored as deltas between previous lines
00110              * and we need to add 0x80 to the first lines of chroma planes
00111              */
00112             if(j) dst[i] += dst[i - stride];
00113             else if(Uoff) dst[i] += 0x80;
00114             if (get_bits_left(&gb) < 0) {
00115                 ff_free_vlc(&vlc);
00116                 return AVERROR_INVALIDDATA;
00117             }
00118         }
00119         dst += stride;
00120     }
00121     ff_free_vlc(&vlc);
00122     return 0;
00123 }
00124 
00125 static int decode_frame(AVCodecContext *avctx,
00126                         void *data, int *data_size,
00127                         AVPacket *avpkt)
00128 {
00129     const uint8_t *buf = avpkt->data;
00130     int buf_size = avpkt->size;
00131     FrapsContext * const s = avctx->priv_data;
00132     AVFrame *frame = data;
00133     AVFrame * const f = (AVFrame*)&s->frame;
00134     uint32_t header;
00135     unsigned int version,header_size;
00136     unsigned int x, y;
00137     const uint32_t *buf32;
00138     uint32_t *luma1,*luma2,*cb,*cr;
00139     uint32_t offs[4];
00140     int i, j, is_chroma, planes;
00141     enum PixelFormat pix_fmt;
00142     int prev_pic_bit, expected_size;
00143 
00144     if (buf_size < 4) {
00145         av_log(avctx, AV_LOG_ERROR, "Packet is too short\n");
00146         return AVERROR_INVALIDDATA;
00147     }
00148 
00149     header = AV_RL32(buf);
00150     version = header & 0xff;
00151     header_size = (header & (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */
00152     prev_pic_bit = header & (1U << 31); /* bit 31 means same as previous pic */
00153 
00154     if (version > 5) {
00155         av_log(avctx, AV_LOG_ERROR,
00156                "This file is encoded with Fraps version %d. " \
00157                "This codec can only decode versions <= 5.\n", version);
00158         return -1;
00159     }
00160 
00161     buf+=4;
00162     if (header_size == 8)
00163         buf+=4;
00164 
00165     pix_fmt = version & 1 ? PIX_FMT_BGR24 : PIX_FMT_YUVJ420P;
00166     if (avctx->pix_fmt != pix_fmt && f->data[0]) {
00167         avctx->release_buffer(avctx, f);
00168     }
00169     avctx->pix_fmt = pix_fmt;
00170 
00171     expected_size = header_size;
00172 
00173     switch (version) {
00174     case 0:
00175     default:
00176         /* Fraps v0 is a reordered YUV420 */
00177         if (!prev_pic_bit)
00178             expected_size += avctx->width * avctx->height * 3 / 2;
00179         if (buf_size != expected_size) {
00180             av_log(avctx, AV_LOG_ERROR,
00181                    "Invalid frame length %d (should be %d)\n",
00182                    buf_size, expected_size);
00183             return AVERROR_INVALIDDATA;
00184         }
00185 
00186         if (( (avctx->width % 8) != 0) || ( (avctx->height % 2) != 0 )) {
00187             av_log(avctx, AV_LOG_ERROR, "Invalid frame size %dx%d\n",
00188                    avctx->width, avctx->height);
00189             return -1;
00190         }
00191 
00192         f->reference = 1;
00193         f->buffer_hints = FF_BUFFER_HINTS_VALID |
00194                           FF_BUFFER_HINTS_PRESERVE |
00195                           FF_BUFFER_HINTS_REUSABLE;
00196         if (avctx->reget_buffer(avctx, f)) {
00197             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00198             return -1;
00199         }
00200         f->pict_type = prev_pic_bit ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
00201         f->key_frame = f->pict_type == AV_PICTURE_TYPE_I;
00202 
00203         if (f->pict_type == AV_PICTURE_TYPE_I) {
00204             buf32=(const uint32_t*)buf;
00205             for(y=0; y<avctx->height/2; y++){
00206                 luma1=(uint32_t*)&f->data[0][ y*2*f->linesize[0] ];
00207                 luma2=(uint32_t*)&f->data[0][ (y*2+1)*f->linesize[0] ];
00208                 cr=(uint32_t*)&f->data[1][ y*f->linesize[1] ];
00209                 cb=(uint32_t*)&f->data[2][ y*f->linesize[2] ];
00210                 for(x=0; x<avctx->width; x+=8){
00211                     *(luma1++) = *(buf32++);
00212                     *(luma1++) = *(buf32++);
00213                     *(luma2++) = *(buf32++);
00214                     *(luma2++) = *(buf32++);
00215                     *(cr++) = *(buf32++);
00216                     *(cb++) = *(buf32++);
00217                 }
00218             }
00219         }
00220         break;
00221 
00222     case 1:
00223         /* Fraps v1 is an upside-down BGR24 */
00224         if (!prev_pic_bit)
00225             expected_size += avctx->width * avctx->height * 3;
00226         if (buf_size != expected_size) {
00227             av_log(avctx, AV_LOG_ERROR,
00228                    "Invalid frame length %d (should be %d)\n",
00229                    buf_size, expected_size);
00230             return AVERROR_INVALIDDATA;
00231         }
00232 
00233         f->reference = 1;
00234         f->buffer_hints = FF_BUFFER_HINTS_VALID |
00235                           FF_BUFFER_HINTS_PRESERVE |
00236                           FF_BUFFER_HINTS_REUSABLE;
00237         if (avctx->reget_buffer(avctx, f)) {
00238             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00239             return -1;
00240         }
00241         f->pict_type = prev_pic_bit ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
00242         f->key_frame = f->pict_type == AV_PICTURE_TYPE_I;
00243 
00244         if (f->pict_type == AV_PICTURE_TYPE_I) {
00245             for(y=0; y<avctx->height; y++)
00246                 memcpy(&f->data[0][ (avctx->height-y)*f->linesize[0] ],
00247                        &buf[y*avctx->width*3],
00248                        3*avctx->width);
00249         }
00250         break;
00251 
00252     case 2:
00253     case 4:
00258         planes = 3;
00259         f->reference = 1;
00260         f->buffer_hints = FF_BUFFER_HINTS_VALID |
00261                           FF_BUFFER_HINTS_PRESERVE |
00262                           FF_BUFFER_HINTS_REUSABLE;
00263         if (avctx->reget_buffer(avctx, f)) {
00264             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00265             return -1;
00266         }
00267         /* skip frame */
00268         if(buf_size == 8) {
00269             f->pict_type = AV_PICTURE_TYPE_P;
00270             f->key_frame = 0;
00271             break;
00272         }
00273         f->pict_type = AV_PICTURE_TYPE_I;
00274         f->key_frame = 1;
00275         if ((AV_RL32(buf) != FPS_TAG)||(buf_size < (planes*1024 + 24))) {
00276             av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n");
00277             return -1;
00278         }
00279         for(i = 0; i < planes; i++) {
00280             offs[i] = AV_RL32(buf + 4 + i * 4);
00281             if(offs[i] >= buf_size || (i && offs[i] <= offs[i - 1] + 1024)) {
00282                 av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i);
00283                 return -1;
00284             }
00285         }
00286         offs[planes] = buf_size;
00287         for(i = 0; i < planes; i++){
00288             is_chroma = !!i;
00289             s->tmpbuf = av_realloc(s->tmpbuf, offs[i + 1] - offs[i] - 1024 + FF_INPUT_BUFFER_PADDING_SIZE);
00290             if(fraps2_decode_plane(s, f->data[i], f->linesize[i], avctx->width >> is_chroma,
00291                     avctx->height >> is_chroma, buf + offs[i], offs[i + 1] - offs[i], is_chroma, 1) < 0) {
00292                 av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i);
00293                 return -1;
00294             }
00295         }
00296         break;
00297     case 3:
00298     case 5:
00299         /* Virtually the same as version 4, but is for RGB24 */
00300         planes = 3;
00301         f->reference = 1;
00302         f->buffer_hints = FF_BUFFER_HINTS_VALID |
00303                           FF_BUFFER_HINTS_PRESERVE |
00304                           FF_BUFFER_HINTS_REUSABLE;
00305         if (avctx->reget_buffer(avctx, f)) {
00306             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00307             return -1;
00308         }
00309         /* skip frame */
00310         if(buf_size == 8) {
00311             f->pict_type = AV_PICTURE_TYPE_P;
00312             f->key_frame = 0;
00313             break;
00314         }
00315         f->pict_type = AV_PICTURE_TYPE_I;
00316         f->key_frame = 1;
00317         if ((AV_RL32(buf) != FPS_TAG)||(buf_size < (planes*1024 + 24))) {
00318             av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n");
00319             return -1;
00320         }
00321         for(i = 0; i < planes; i++) {
00322             offs[i] = AV_RL32(buf + 4 + i * 4);
00323             if(offs[i] >= buf_size || (i && offs[i] <= offs[i - 1] + 1024)) {
00324                 av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i);
00325                 return -1;
00326             }
00327         }
00328         offs[planes] = buf_size;
00329         for(i = 0; i < planes; i++){
00330             s->tmpbuf = av_realloc(s->tmpbuf, offs[i + 1] - offs[i] - 1024 + FF_INPUT_BUFFER_PADDING_SIZE);
00331             if(fraps2_decode_plane(s, f->data[0] + i + (f->linesize[0] * (avctx->height - 1)), -f->linesize[0],
00332                     avctx->width, avctx->height, buf + offs[i], offs[i + 1] - offs[i], 0, 3) < 0) {
00333                 av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i);
00334                 return -1;
00335             }
00336         }
00337         // convert pseudo-YUV into real RGB
00338         for(j = 0; j < avctx->height; j++){
00339             for(i = 0; i < avctx->width; i++){
00340                 f->data[0][0 + i*3 + j*f->linesize[0]] += f->data[0][1 + i*3 + j*f->linesize[0]];
00341                 f->data[0][2 + i*3 + j*f->linesize[0]] += f->data[0][1 + i*3 + j*f->linesize[0]];
00342             }
00343         }
00344         break;
00345     }
00346 
00347     *frame = *f;
00348     *data_size = sizeof(AVFrame);
00349 
00350     return buf_size;
00351 }
00352 
00353 
00359 static av_cold int decode_end(AVCodecContext *avctx)
00360 {
00361     FrapsContext *s = (FrapsContext*)avctx->priv_data;
00362 
00363     if (s->frame.data[0])
00364         avctx->release_buffer(avctx, &s->frame);
00365 
00366     av_freep(&s->tmpbuf);
00367     return 0;
00368 }
00369 
00370 
00371 AVCodec ff_fraps_decoder = {
00372     .name           = "fraps",
00373     .type           = AVMEDIA_TYPE_VIDEO,
00374     .id             = CODEC_ID_FRAPS,
00375     .priv_data_size = sizeof(FrapsContext),
00376     .init           = decode_init,
00377     .close          = decode_end,
00378     .decode         = decode_frame,
00379     .capabilities   = CODEC_CAP_DR1,
00380     .long_name = NULL_IF_CONFIG_SMALL("Fraps"),
00381 };