Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * CamStudio decoder
  3.  * Copyright (c) 2006 Reimar Doeffinger
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23.  
  24. #include "avcodec.h"
  25. #include "internal.h"
  26. #include "libavutil/common.h"
  27.  
  28. #if CONFIG_ZLIB
  29. #include <zlib.h>
  30. #endif
  31. #include "libavutil/lzo.h"
  32.  
  33. typedef struct {
  34.     AVFrame *pic;
  35.     int linelen, height, bpp;
  36.     unsigned int decomp_size;
  37.     unsigned char* decomp_buf;
  38. } CamStudioContext;
  39.  
  40. static void copy_frame_default(AVFrame *f, const uint8_t *src,
  41.                                int linelen, int height) {
  42.     int i, src_stride = FFALIGN(linelen, 4);
  43.     uint8_t *dst = f->data[0];
  44.     dst += (height - 1) * f->linesize[0];
  45.     for (i = height; i; i--) {
  46.         memcpy(dst, src, linelen);
  47.         src += src_stride;
  48.         dst -= f->linesize[0];
  49.     }
  50. }
  51.  
  52. static void add_frame_default(AVFrame *f, const uint8_t *src,
  53.                               int linelen, int height) {
  54.     int i, j, src_stride = FFALIGN(linelen, 4);
  55.     uint8_t *dst = f->data[0];
  56.     dst += (height - 1) * f->linesize[0];
  57.     for (i = height; i; i--) {
  58.         for (j = linelen; j; j--)
  59.             *dst++ += *src++;
  60.         src += src_stride - linelen;
  61.         dst -= f->linesize[0] + linelen;
  62.     }
  63. }
  64.  
  65. static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
  66.                         AVPacket *avpkt) {
  67.     const uint8_t *buf = avpkt->data;
  68.     int buf_size = avpkt->size;
  69.     CamStudioContext *c = avctx->priv_data;
  70.     int ret;
  71.  
  72.     if (buf_size < 2) {
  73.         av_log(avctx, AV_LOG_ERROR, "coded frame too small\n");
  74.         return AVERROR_INVALIDDATA;
  75.     }
  76.  
  77.     if ((ret = ff_reget_buffer(avctx, c->pic)) < 0)
  78.         return ret;
  79.  
  80.     // decompress data
  81.     switch ((buf[0] >> 1) & 7) {
  82.         case 0: { // lzo compression
  83.             int outlen = c->decomp_size, inlen = buf_size - 2;
  84.             if (av_lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen))
  85.                 av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n");
  86.             break;
  87.         }
  88.         case 1: { // zlib compression
  89. #if CONFIG_ZLIB
  90.             unsigned long dlen = c->decomp_size;
  91.             if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK)
  92.                 av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n");
  93.             break;
  94. #else
  95.             av_log(avctx, AV_LOG_ERROR, "compiled without zlib support\n");
  96.             return AVERROR(ENOSYS);
  97. #endif
  98.         }
  99.         default:
  100.             av_log(avctx, AV_LOG_ERROR, "unknown compression\n");
  101.             return AVERROR_INVALIDDATA;
  102.     }
  103.  
  104.     // flip upside down, add difference frame
  105.     if (buf[0] & 1) { // keyframe
  106.         c->pic->pict_type = AV_PICTURE_TYPE_I;
  107.         c->pic->key_frame = 1;
  108.               copy_frame_default(c->pic, c->decomp_buf,
  109.                                  c->linelen, c->height);
  110.     } else {
  111.         c->pic->pict_type = AV_PICTURE_TYPE_P;
  112.         c->pic->key_frame = 0;
  113.               add_frame_default(c->pic, c->decomp_buf,
  114.                                 c->linelen, c->height);
  115.     }
  116.  
  117.     *got_frame = 1;
  118.     if ((ret = av_frame_ref(data, c->pic)) < 0)
  119.         return ret;
  120.  
  121.     return buf_size;
  122. }
  123.  
  124. static av_cold int decode_init(AVCodecContext *avctx) {
  125.     CamStudioContext *c = avctx->priv_data;
  126.     int stride;
  127.     switch (avctx->bits_per_coded_sample) {
  128.         case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555LE; break;
  129.         case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
  130.         case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA; break;
  131.         default:
  132.             av_log(avctx, AV_LOG_ERROR,
  133.                    "CamStudio codec error: invalid depth %i bpp\n",
  134.                    avctx->bits_per_coded_sample);
  135.             return AVERROR_INVALIDDATA;
  136.     }
  137.     c->bpp = avctx->bits_per_coded_sample;
  138.     c->linelen = avctx->width * avctx->bits_per_coded_sample / 8;
  139.     c->height = avctx->height;
  140.     stride = FFALIGN(c->linelen, 4);
  141.     c->decomp_size = c->height * stride;
  142.     c->decomp_buf = av_malloc(c->decomp_size + AV_LZO_OUTPUT_PADDING);
  143.     if (!c->decomp_buf) {
  144.         av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
  145.         return AVERROR(ENOMEM);
  146.     }
  147.     c->pic = av_frame_alloc();
  148.     if (!c->pic)
  149.         return AVERROR(ENOMEM);
  150.     return 0;
  151. }
  152.  
  153. static av_cold int decode_end(AVCodecContext *avctx) {
  154.     CamStudioContext *c = avctx->priv_data;
  155.     av_freep(&c->decomp_buf);
  156.     av_frame_free(&c->pic);
  157.     return 0;
  158. }
  159.  
  160. AVCodec ff_cscd_decoder = {
  161.     .name           = "camstudio",
  162.     .long_name      = NULL_IF_CONFIG_SMALL("CamStudio"),
  163.     .type           = AVMEDIA_TYPE_VIDEO,
  164.     .id             = AV_CODEC_ID_CSCD,
  165.     .priv_data_size = sizeof(CamStudioContext),
  166.     .init           = decode_init,
  167.     .close          = decode_end,
  168.     .decode         = decode_frame,
  169.     .capabilities   = CODEC_CAP_DR1,
  170. };
  171.