fraps.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:7k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*
  2.  * Fraps FPS1 decoder
  3.  * Copyright (c) 2005 Roine Gustafsson
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  */
  20.  
  21. /**
  22.  * @file fraps.c
  23.  * Lossless Fraps 'FPS1' decoder
  24.  * @author Roine Gustafsson <roine at users sf net>
  25.  * 
  26.  * Only decodes version 0 and 1 files.
  27.  * Codec algorithm for version 0 is taken from Transcode <www.transcoding.org>
  28.  *
  29.  * Version 2 files, which are the most commonly found Fraps files, cannot be
  30.  * decoded yet.
  31.  */
  32.  
  33. #include "avcodec.h"
  34. #define FPS_TAG MKTAG('F', 'P', 'S', 'x')
  35. /**
  36.  * local variable storage
  37.  */
  38. typedef struct FrapsContext{
  39.     AVCodecContext *avctx;
  40.     AVFrame frame;
  41. } FrapsContext;
  42. /**
  43.  * initializes decoder
  44.  * @param avctx codec context
  45.  * @return 0 on success or negative if fails
  46.  */
  47. static int decode_init(AVCodecContext *avctx)
  48. {
  49.     FrapsContext * const s = avctx->priv_data;
  50.     avctx->coded_frame = (AVFrame*)&s->frame;
  51.     avctx->has_b_frames = 0;
  52.     avctx->pix_fmt= PIX_FMT_NONE; /* set in decode_frame */
  53.     s->avctx = avctx;
  54.     s->frame.data[0] = NULL;    
  55.     return 0;
  56. }
  57. /**
  58.  * decode a frame
  59.  * @param avctx codec context
  60.  * @param data output AVFrame
  61.  * @param data_size size of output data or 0 if no picture is returned
  62.  * @param buf input data frame
  63.  * @param buf_size size of input data frame
  64.  * @return number of consumed bytes on success or negative if decode fails
  65.  */
  66. static int decode_frame(AVCodecContext *avctx, 
  67.                         void *data, int *data_size,
  68.                         uint8_t *buf, int buf_size)
  69. {
  70.     FrapsContext * const s = avctx->priv_data;
  71.     AVFrame *frame = data;
  72.     AVFrame * const f = (AVFrame*)&s->frame;
  73.     uint32_t header;
  74.     unsigned int version,header_size;
  75.     unsigned int x, y;
  76.     uint32_t *buf32;
  77.     uint32_t *luma1,*luma2,*cb,*cr;
  78.     header = LE_32(buf);
  79.     version = header & 0xff;
  80.     header_size = (header & (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */
  81.     if (version > 1) {
  82.         av_log(avctx, AV_LOG_ERROR, 
  83.                "This file is encoded with Fraps version %d. " 
  84.                "This codec can only decode version 0 and 1.n", version);
  85.         return -1;
  86.     }
  87.     buf+=4;
  88.     if (header_size == 8)
  89.         buf+=4;
  90.         
  91.     switch(version) {
  92.     case 0:
  93.     default:
  94.         /* Fraps v0 is a reordered YUV420 */
  95.         avctx->pix_fmt = PIX_FMT_YUV420P;
  96.         if ( (buf_size != avctx->width*avctx->height*3/2+header_size) && 
  97.              (buf_size != header_size) ) {
  98.             av_log(avctx, AV_LOG_ERROR,
  99.                    "Invalid frame length %d (should be %d)n", 
  100.                    buf_size, avctx->width*avctx->height*3/2+header_size);
  101.             return -1;
  102.         }
  103.         
  104.         if (( (avctx->width % 8) != 0) || ( (avctx->height % 2) != 0 )) {
  105.             av_log(avctx, AV_LOG_ERROR, "Invalid frame size %dx%dn", 
  106.                    avctx->width, avctx->height);
  107.             return -1;
  108.         }
  109.         f->reference = 1; 
  110.         f->buffer_hints = FF_BUFFER_HINTS_VALID | 
  111.                           FF_BUFFER_HINTS_PRESERVE | 
  112.                           FF_BUFFER_HINTS_REUSABLE;
  113.         if (avctx->reget_buffer(avctx, f)) {
  114.             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failedn");
  115.             return -1;
  116.         }        
  117.         /* bit 31 means same as previous pic */
  118.         f->pict_type = (header & (1<<31))? FF_P_TYPE : FF_I_TYPE; 
  119.         f->key_frame = f->pict_type == FF_I_TYPE;
  120.         if (f->pict_type == FF_I_TYPE) { 
  121.             buf32=(uint32_t*)buf;
  122.             for(y=0; y<avctx->height/2; y++){
  123.                 luma1=(uint32_t*)&f->data[0][ y*2*f->linesize[0] ];
  124.                 luma2=(uint32_t*)&f->data[0][ (y*2+1)*f->linesize[0] ];
  125.                 cr=(uint32_t*)&f->data[1][ y*f->linesize[1] ];
  126.                 cb=(uint32_t*)&f->data[2][ y*f->linesize[2] ];
  127.                 for(x=0; x<avctx->width; x+=8){
  128.                     *(luma1++) = *(buf32++);
  129.                     *(luma1++) = *(buf32++);
  130.                     *(luma2++) = *(buf32++);
  131.                     *(luma2++) = *(buf32++);
  132.                     *(cr++) = *(buf32++);
  133.                     *(cb++) = *(buf32++);
  134.                 }
  135.             }
  136.         }
  137.         break;
  138.     case 1:
  139.         /* Fraps v1 is an upside-down BGR24 */
  140.         avctx->pix_fmt = PIX_FMT_BGR24;
  141.         if ( (buf_size != avctx->width*avctx->height*3+header_size) && 
  142.              (buf_size != header_size) ) {
  143.             av_log(avctx, AV_LOG_ERROR, 
  144.                    "Invalid frame length %d (should be %d)n",
  145.                    buf_size, avctx->width*avctx->height*3+header_size);
  146.             return -1;
  147.         }
  148.         f->reference = 1;
  149.         f->buffer_hints = FF_BUFFER_HINTS_VALID |
  150.                           FF_BUFFER_HINTS_PRESERVE |
  151.                           FF_BUFFER_HINTS_REUSABLE;
  152.         if (avctx->reget_buffer(avctx, f)) {
  153.             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failedn");
  154.             return -1;
  155.         }
  156.         /* bit 31 means same as previous pic */
  157.         f->pict_type = (header & (1<<31))? FF_P_TYPE : FF_I_TYPE;
  158.         f->key_frame = f->pict_type == FF_I_TYPE;
  159.         if (f->pict_type == FF_I_TYPE) {
  160.             for(y=0; y<avctx->height; y++)
  161.                 memcpy(&f->data[0][ (avctx->height-y)*f->linesize[0] ],
  162.                        &buf[y*avctx->width*3],
  163.                        f->linesize[0]);
  164.         }
  165.         break;
  166.     case 2:
  167.         /**
  168.          * Fraps v2 sub-header description. All numbers are little-endian:
  169.          * (this is all guesswork)
  170.          *
  171.          *       0:     DWORD 'FPSx'
  172.          *       4:     DWORD 0x00000010   unknown, perhaps flags
  173.          *       8:     DWORD off_2        offset to plane 2
  174.          *      12:     DWORD off_3        offset to plane 3
  175.          *      16: 256xDWORD freqtbl_1    frequency table for plane 1
  176.          *    1040:           plane_1
  177.          *     ...
  178.          *   off_2: 256xDWORD freqtbl_2    frequency table for plane 2
  179.          *                    plane_2
  180.          *    ...
  181.          *   off_3: 256xDWORD freqtbl_3    frequency table for plane 3
  182.          *                    plane_3
  183.          */
  184.         if ((BE_32(buf) != FPS_TAG)||(buf_size < (3*1024 + 8))) {
  185.             av_log(avctx, AV_LOG_ERROR, "Fraps: error in data streamn");
  186.             return -1;
  187.         }
  188.         /* NOT FINISHED */
  189.         break;
  190.     }
  191.     *frame = *f;
  192.     *data_size = sizeof(AVFrame);
  193.     return buf_size;
  194. }
  195. /**
  196.  * closes decoder
  197.  * @param avctx codec context
  198.  * @return 0 on success or negative if fails
  199.  */
  200. static int decode_end(AVCodecContext *avctx)
  201. {
  202.     FrapsContext *s = (FrapsContext*)avctx->priv_data;
  203.     if (s->frame.data[0])
  204.         avctx->release_buffer(avctx, &s->frame);
  205.     return 0;
  206. }
  207. AVCodec fraps_decoder = {
  208.     "fraps",
  209.     CODEC_TYPE_VIDEO,
  210.     CODEC_ID_FRAPS,
  211.     sizeof(FrapsContext),
  212.     decode_init,
  213.     NULL,
  214.     decode_end,
  215.     decode_frame,
  216.     CODEC_CAP_DR1,
  217. };