00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023
00024 #include "avcodec.h"
00025
00026 #if CONFIG_ZLIB
00027 #include <zlib.h>
00028 #endif
00029 #include "libavutil/lzo.h"
00030
00031 typedef struct {
00032 AVFrame pic;
00033 int linelen, height, bpp;
00034 unsigned int decomp_size;
00035 unsigned char* decomp_buf;
00036 } CamStudioContext;
00037
00038 static void copy_frame_default(AVFrame *f, const uint8_t *src, int src_stride,
00039 int linelen, int height) {
00040 int i;
00041 uint8_t *dst = f->data[0];
00042 dst += (height - 1) * f->linesize[0];
00043 for (i = height; i; i--) {
00044 memcpy(dst, src, linelen);
00045 src += src_stride;
00046 dst -= f->linesize[0];
00047 }
00048 }
00049
00050 static void add_frame_default(AVFrame *f, const uint8_t *src, int src_stride,
00051 int linelen, int height) {
00052 int i, j;
00053 uint8_t *dst = f->data[0];
00054 dst += (height - 1) * f->linesize[0];
00055 for (i = height; i; i--) {
00056 for (j = linelen; j; j--)
00057 *dst++ += *src++;
00058 src += src_stride - linelen;
00059 dst -= f->linesize[0] + linelen;
00060 }
00061 }
00062
00063 #if !HAVE_BIGENDIAN
00064 #define copy_frame_16(f, s, l, h) copy_frame_default(f, s, l, l, h)
00065 #define copy_frame_32(f, s, l, h) copy_frame_default(f, s, l, l, h)
00066 #define add_frame_16(f, s, l, h) add_frame_default(f, s, l, l, h)
00067 #define add_frame_32(f, s, l, h) add_frame_default(f, s, l, l, h)
00068 #else
00069 static void copy_frame_16(AVFrame *f, const uint8_t *src,
00070 int linelen, int height) {
00071 int i, j;
00072 uint8_t *dst = f->data[0];
00073 dst += (height - 1) * f->linesize[0];
00074 for (i = height; i; i--) {
00075 for (j = linelen / 2; j; j--) {
00076 dst[0] = src[1];
00077 dst[1] = src[0];
00078 src += 2;
00079 dst += 2;
00080 }
00081 dst -= f->linesize[0] + linelen;
00082 }
00083 }
00084
00085 static void copy_frame_32(AVFrame *f, const uint8_t *src,
00086 int linelen, int height) {
00087 int i, j;
00088 uint8_t *dst = f->data[0];
00089 dst += (height - 1) * f->linesize[0];
00090 for (i = height; i; i--) {
00091 for (j = linelen / 4; j; j--) {
00092 dst[0] = src[3];
00093 dst[1] = src[2];
00094 dst[2] = src[1];
00095 dst[3] = src[0];
00096 src += 4;
00097 dst += 4;
00098 }
00099 dst -= f->linesize[0] + linelen;
00100 }
00101 }
00102
00103 static void add_frame_16(AVFrame *f, const uint8_t *src,
00104 int linelen, int height) {
00105 int i, j;
00106 uint8_t *dst = f->data[0];
00107 dst += (height - 1) * f->linesize[0];
00108 for (i = height; i; i--) {
00109 for (j = linelen / 2; j; j--) {
00110 dst[0] += src[1];
00111 dst[1] += src[0];
00112 src += 2;
00113 dst += 2;
00114 }
00115 dst -= f->linesize[0] + linelen;
00116 }
00117 }
00118
00119 static void add_frame_32(AVFrame *f, const uint8_t *src,
00120 int linelen, int height) {
00121 int i, j;
00122 uint8_t *dst = f->data[0];
00123 dst += (height - 1) * f->linesize[0];
00124 for (i = height; i; i--) {
00125 for (j = linelen / 4; j; j--) {
00126 dst[0] += src[3];
00127 dst[1] += src[2];
00128 dst[2] += src[1];
00129 dst[3] += src[0];
00130 src += 4;
00131 dst += 4;
00132 }
00133 dst -= f->linesize[0] + linelen;
00134 }
00135 }
00136 #endif
00137
00138 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
00139 AVPacket *avpkt) {
00140 const uint8_t *buf = avpkt->data;
00141 int buf_size = avpkt->size;
00142 CamStudioContext *c = avctx->priv_data;
00143 AVFrame *picture = data;
00144
00145 if (buf_size < 2) {
00146 av_log(avctx, AV_LOG_ERROR, "coded frame too small\n");
00147 return -1;
00148 }
00149
00150 if (c->pic.data[0])
00151 avctx->release_buffer(avctx, &c->pic);
00152 c->pic.reference = 1;
00153 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE |
00154 FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00155 if (avctx->get_buffer(avctx, &c->pic) < 0) {
00156 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00157 return -1;
00158 }
00159
00160
00161 switch ((buf[0] >> 1) & 7) {
00162 case 0: {
00163 int outlen = c->decomp_size, inlen = buf_size - 2;
00164 if (av_lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen))
00165 av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n");
00166 break;
00167 }
00168 case 1: {
00169 #if CONFIG_ZLIB
00170 unsigned long dlen = c->decomp_size;
00171 if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK)
00172 av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n");
00173 break;
00174 #else
00175 av_log(avctx, AV_LOG_ERROR, "compiled without zlib support\n");
00176 return -1;
00177 #endif
00178 }
00179 default:
00180 av_log(avctx, AV_LOG_ERROR, "unknown compression\n");
00181 return -1;
00182 }
00183
00184
00185 if (buf[0] & 1) {
00186 c->pic.pict_type = AV_PICTURE_TYPE_I;
00187 c->pic.key_frame = 1;
00188 switch (c->bpp) {
00189 case 16:
00190 copy_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height);
00191 break;
00192 case 32:
00193 copy_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height);
00194 break;
00195 default:
00196 copy_frame_default(&c->pic, c->decomp_buf, FFALIGN(c->linelen, 4),
00197 c->linelen, c->height);
00198 }
00199 } else {
00200 c->pic.pict_type = AV_PICTURE_TYPE_P;
00201 c->pic.key_frame = 0;
00202 switch (c->bpp) {
00203 case 16:
00204 add_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height);
00205 break;
00206 case 32:
00207 add_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height);
00208 break;
00209 default:
00210 add_frame_default(&c->pic, c->decomp_buf, FFALIGN(c->linelen, 4),
00211 c->linelen, c->height);
00212 }
00213 }
00214
00215 *picture = c->pic;
00216 *data_size = sizeof(AVFrame);
00217 return buf_size;
00218 }
00219
00220 static av_cold int decode_init(AVCodecContext *avctx) {
00221 CamStudioContext *c = avctx->priv_data;
00222 int stride;
00223 switch (avctx->bits_per_coded_sample) {
00224 case 16: avctx->pix_fmt = PIX_FMT_RGB555; break;
00225 case 24: avctx->pix_fmt = PIX_FMT_BGR24; break;
00226 case 32: avctx->pix_fmt = PIX_FMT_RGB32; break;
00227 default:
00228 av_log(avctx, AV_LOG_ERROR,
00229 "CamStudio codec error: invalid depth %i bpp\n",
00230 avctx->bits_per_coded_sample);
00231 return AVERROR_INVALIDDATA;
00232 }
00233 c->bpp = avctx->bits_per_coded_sample;
00234 avcodec_get_frame_defaults(&c->pic);
00235 c->pic.data[0] = NULL;
00236 c->linelen = avctx->width * avctx->bits_per_coded_sample / 8;
00237 c->height = avctx->height;
00238 stride = c->linelen;
00239 if (avctx->bits_per_coded_sample == 24)
00240 stride = FFALIGN(stride, 4);
00241 c->decomp_size = c->height * stride;
00242 c->decomp_buf = av_malloc(c->decomp_size + AV_LZO_OUTPUT_PADDING);
00243 if (!c->decomp_buf) {
00244 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
00245 return AVERROR(ENOMEM);
00246 }
00247 return 0;
00248 }
00249
00250 static av_cold int decode_end(AVCodecContext *avctx) {
00251 CamStudioContext *c = avctx->priv_data;
00252 av_freep(&c->decomp_buf);
00253 if (c->pic.data[0])
00254 avctx->release_buffer(avctx, &c->pic);
00255 return 0;
00256 }
00257
00258 AVCodec ff_cscd_decoder = {
00259 "camstudio",
00260 AVMEDIA_TYPE_VIDEO,
00261 CODEC_ID_CSCD,
00262 sizeof(CamStudioContext),
00263 decode_init,
00264 NULL,
00265 decode_end,
00266 decode_frame,
00267 CODEC_CAP_DR1,
00268 .long_name = NULL_IF_CONFIG_SMALL("CamStudio"),
00269 };
00270