Mercurial > libavcodec.hg
annotate cscd.c @ 8204:507854688c43 libavcodec
Some BMP files have file size declared in the header equal to headers size
without image data, so try to correct that value before conducting checks on
declared file size.
author | kostya |
---|---|
date | Mon, 24 Nov 2008 11:24:02 +0000 |
parents | 4525dcd81357 |
children | 7a463923ecd1 |
rev | line source |
---|---|
3030 | 1 /* |
2 * CamStudio decoder | |
3 * Copyright (c) 2006 Reimar Doeffinger | |
4 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3060
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3060
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3060
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
3030 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3060
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
3030 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3060
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
3030 | 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 | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3060
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
3034
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
3030 | 20 */ |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
23 | |
24 #include "avcodec.h" | |
25 | |
26 #ifdef CONFIG_ZLIB | |
27 #include <zlib.h> | |
28 #endif | |
6763 | 29 #include "libavutil/lzo.h" |
3030 | 30 |
31 typedef struct { | |
32 AVFrame pic; | |
33 int linelen, height, bpp; | |
34 unsigned int decomp_size; | |
35 unsigned char* decomp_buf; | |
36 } CamStudioContext; | |
37 | |
6312 | 38 static void copy_frame_default(AVFrame *f, const uint8_t *src, |
3030 | 39 int linelen, int height) { |
40 int i; | |
41 uint8_t *dst = f->data[0]; | |
42 dst += (height - 1) * f->linesize[0]; | |
43 for (i = height; i; i--) { | |
44 memcpy(dst, src, linelen); | |
45 src += linelen; | |
46 dst -= f->linesize[0]; | |
47 } | |
48 } | |
49 | |
6312 | 50 static void add_frame_default(AVFrame *f, const uint8_t *src, |
3030 | 51 int linelen, int height) { |
52 int i, j; | |
53 uint8_t *dst = f->data[0]; | |
54 dst += (height - 1) * f->linesize[0]; | |
55 for (i = height; i; i--) { | |
56 for (j = linelen; j; j--) | |
57 *dst++ += *src++; | |
58 dst -= f->linesize[0] + linelen; | |
59 } | |
60 } | |
61 | |
62 #ifndef WORDS_BIGENDIAN | |
63 #define copy_frame_16 copy_frame_default | |
64 #define copy_frame_32 copy_frame_default | |
65 #define add_frame_16 add_frame_default | |
66 #define add_frame_32 add_frame_default | |
67 #else | |
6312 | 68 static void copy_frame_16(AVFrame *f, const uint8_t *src, |
3030 | 69 int linelen, int height) { |
70 int i, j; | |
71 uint8_t *dst = f->data[0]; | |
72 dst += (height - 1) * f->linesize[0]; | |
73 for (i = height; i; i--) { | |
74 for (j = linelen / 2; j; j--) { | |
75 dst[0] = src[1]; | |
76 dst[1] = src[0]; | |
77 src += 2; | |
78 dst += 2; | |
79 } | |
80 dst -= f->linesize[0] + linelen; | |
81 } | |
82 } | |
83 | |
6312 | 84 static void copy_frame_32(AVFrame *f, const uint8_t *src, |
3030 | 85 int linelen, int height) { |
86 int i, j; | |
87 uint8_t *dst = f->data[0]; | |
88 dst += (height - 1) * f->linesize[0]; | |
89 for (i = height; i; i--) { | |
90 for (j = linelen / 4; j; j--) { | |
91 dst[0] = src[3]; | |
92 dst[1] = src[2]; | |
93 dst[2] = src[1]; | |
94 dst[3] = src[0]; | |
95 src += 4; | |
96 dst += 4; | |
97 } | |
98 dst -= f->linesize[0] + linelen; | |
99 } | |
100 } | |
101 | |
6312 | 102 static void add_frame_16(AVFrame *f, const uint8_t *src, |
3030 | 103 int linelen, int height) { |
104 int i, j; | |
105 uint8_t *dst = f->data[0]; | |
106 dst += (height - 1) * f->linesize[0]; | |
107 for (i = height; i; i--) { | |
108 for (j = linelen / 2; j; j--) { | |
109 dst[0] += src[1]; | |
110 dst[1] += src[0]; | |
111 src += 2; | |
112 dst += 2; | |
113 } | |
114 dst -= f->linesize[0] + linelen; | |
115 } | |
116 } | |
117 | |
6312 | 118 static void add_frame_32(AVFrame *f, const uint8_t *src, |
3030 | 119 int linelen, int height) { |
120 int i, j; | |
121 uint8_t *dst = f->data[0]; | |
122 dst += (height - 1) * f->linesize[0]; | |
123 for (i = height; i; i--) { | |
124 for (j = linelen / 4; j; j--) { | |
125 dst[0] += src[3]; | |
126 dst[1] += src[2]; | |
127 dst[2] += src[1]; | |
128 dst[3] += src[0]; | |
129 src += 4; | |
130 dst += 4; | |
131 } | |
132 dst -= f->linesize[0] + linelen; | |
133 } | |
134 } | |
135 #endif | |
136 | |
137 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |
6262 | 138 const uint8_t *buf, int buf_size) { |
4827 | 139 CamStudioContext *c = avctx->priv_data; |
3030 | 140 AVFrame *picture = data; |
141 | |
142 if (buf_size < 2) { | |
143 av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); | |
144 return -1; | |
145 } | |
146 | |
147 if (c->pic.data[0]) | |
148 avctx->release_buffer(avctx, &c->pic); | |
149 c->pic.reference = 1; | |
150 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE | | |
151 FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | |
152 if (avctx->get_buffer(avctx, &c->pic) < 0) { | |
153 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
154 return -1; | |
155 } | |
156 | |
157 // decompress data | |
158 switch ((buf[0] >> 1) & 7) { | |
159 case 0: { // lzo compression | |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
3030
diff
changeset
|
160 int outlen = c->decomp_size, inlen = buf_size - 2; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
3030
diff
changeset
|
161 if (lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen)) |
3030 | 162 av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); |
163 break; | |
164 } | |
165 case 1: { // zlib compression | |
166 #ifdef CONFIG_ZLIB | |
167 unsigned long dlen = c->decomp_size; | |
168 if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK) | |
169 av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n"); | |
170 break; | |
171 #else | |
172 av_log(avctx, AV_LOG_ERROR, "compiled without zlib support\n"); | |
173 return -1; | |
174 #endif | |
175 } | |
176 default: | |
177 av_log(avctx, AV_LOG_ERROR, "unknown compression\n"); | |
178 return -1; | |
179 } | |
180 | |
181 // flip upside down, add difference frame | |
182 if (buf[0] & 1) { // keyframe | |
183 c->pic.pict_type = FF_I_TYPE; | |
184 c->pic.key_frame = 1; | |
185 switch (c->bpp) { | |
186 case 16: | |
187 copy_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height); | |
188 break; | |
189 case 32: | |
190 copy_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height); | |
191 break; | |
192 default: | |
193 copy_frame_default(&c->pic, c->decomp_buf, c->linelen, c->height); | |
194 } | |
195 } else { | |
196 c->pic.pict_type = FF_P_TYPE; | |
197 c->pic.key_frame = 0; | |
198 switch (c->bpp) { | |
199 case 16: | |
200 add_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height); | |
201 break; | |
202 case 32: | |
203 add_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height); | |
204 break; | |
205 default: | |
206 add_frame_default(&c->pic, c->decomp_buf, c->linelen, c->height); | |
207 } | |
208 } | |
209 | |
210 *picture = c->pic; | |
211 *data_size = sizeof(AVFrame); | |
212 return buf_size; | |
213 } | |
214 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6312
diff
changeset
|
215 static av_cold int decode_init(AVCodecContext *avctx) { |
4827 | 216 CamStudioContext *c = avctx->priv_data; |
3030 | 217 if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) { |
218 return 1; | |
219 } | |
7823
4525dcd81357
Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents:
7040
diff
changeset
|
220 switch (avctx->bits_per_coded_sample) { |
4290
e7dfc2743e26
Fix 16 bit cscd samples, 16 bit raw means RGB555 on Windows, and the original
reimar
parents:
4289
diff
changeset
|
221 case 16: avctx->pix_fmt = PIX_FMT_RGB555; break; |
3030 | 222 case 24: avctx->pix_fmt = PIX_FMT_BGR24; break; |
4494
ce643a22f049
Replace deprecated PIX_FMT names by the newer variants.
diego
parents:
4290
diff
changeset
|
223 case 32: avctx->pix_fmt = PIX_FMT_RGB32; break; |
3030 | 224 default: |
225 av_log(avctx, AV_LOG_ERROR, | |
4289 | 226 "CamStudio codec error: invalid depth %i bpp\n", |
7823
4525dcd81357
Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents:
7040
diff
changeset
|
227 avctx->bits_per_coded_sample); |
3030 | 228 return 1; |
229 } | |
7823
4525dcd81357
Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents:
7040
diff
changeset
|
230 c->bpp = avctx->bits_per_coded_sample; |
3030 | 231 c->pic.data[0] = NULL; |
7823
4525dcd81357
Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents:
7040
diff
changeset
|
232 c->linelen = avctx->width * avctx->bits_per_coded_sample / 8; |
3030 | 233 c->height = avctx->height; |
234 c->decomp_size = c->height * c->linelen; | |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3036
diff
changeset
|
235 c->decomp_buf = av_malloc(c->decomp_size + LZO_OUTPUT_PADDING); |
3030 | 236 if (!c->decomp_buf) { |
237 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); | |
238 return 1; | |
239 } | |
240 return 0; | |
241 } | |
242 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6312
diff
changeset
|
243 static av_cold int decode_end(AVCodecContext *avctx) { |
4827 | 244 CamStudioContext *c = avctx->priv_data; |
3030 | 245 av_freep(&c->decomp_buf); |
246 if (c->pic.data[0]) | |
247 avctx->release_buffer(avctx, &c->pic); | |
248 return 0; | |
249 } | |
250 | |
251 AVCodec cscd_decoder = { | |
252 "camstudio", | |
253 CODEC_TYPE_VIDEO, | |
254 CODEC_ID_CSCD, | |
255 sizeof(CamStudioContext), | |
256 decode_init, | |
257 NULL, | |
258 decode_end, | |
259 decode_frame, | |
260 CODEC_CAP_DR1, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6763
diff
changeset
|
261 .long_name = NULL_IF_CONFIG_SMALL("CamStudio"), |
3030 | 262 }; |
263 |