Mercurial > libavcodec.hg
annotate cscd.c @ 3990:746a60ba3177 libavcodec
enable CMOV_IS_FAST as its faster or equal speed on every cpu (duron, athlon, PM, P3) from which ive seen benchmarks, it might be slower on P4 but noone has posted benchmarks ...
author | michael |
---|---|
date | Wed, 11 Oct 2006 12:23:40 +0000 |
parents | c8c591fe26f8 |
children | b2a291ea653f |
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 "common.h" | |
25 #include "avcodec.h" | |
26 | |
27 #ifdef CONFIG_ZLIB | |
28 #include <zlib.h> | |
29 #endif | |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
3030
diff
changeset
|
30 #include "lzo.h" |
3030 | 31 |
32 typedef struct { | |
33 AVFrame pic; | |
34 int linelen, height, bpp; | |
35 unsigned int decomp_size; | |
36 unsigned char* decomp_buf; | |
37 } CamStudioContext; | |
38 | |
39 static void copy_frame_default(AVFrame *f, uint8_t *src, | |
40 int linelen, int height) { | |
41 int i; | |
42 uint8_t *dst = f->data[0]; | |
43 dst += (height - 1) * f->linesize[0]; | |
44 for (i = height; i; i--) { | |
45 memcpy(dst, src, linelen); | |
46 src += linelen; | |
47 dst -= f->linesize[0]; | |
48 } | |
49 } | |
50 | |
51 static void add_frame_default(AVFrame *f, uint8_t *src, | |
52 int linelen, int height) { | |
53 int i, j; | |
54 uint8_t *dst = f->data[0]; | |
55 dst += (height - 1) * f->linesize[0]; | |
56 for (i = height; i; i--) { | |
57 for (j = linelen; j; j--) | |
58 *dst++ += *src++; | |
59 dst -= f->linesize[0] + linelen; | |
60 } | |
61 } | |
62 | |
63 #ifndef WORDS_BIGENDIAN | |
64 #define copy_frame_16 copy_frame_default | |
65 #define copy_frame_32 copy_frame_default | |
66 #define add_frame_16 add_frame_default | |
67 #define add_frame_32 add_frame_default | |
68 #else | |
69 static void copy_frame_16(AVFrame *f, uint8_t *src, | |
70 int linelen, int height) { | |
71 int i, j; | |
72 uint8_t *dst = f->data[0]; | |
73 dst += (height - 1) * f->linesize[0]; | |
74 for (i = height; i; i--) { | |
75 for (j = linelen / 2; j; j--) { | |
76 dst[0] = src[1]; | |
77 dst[1] = src[0]; | |
78 src += 2; | |
79 dst += 2; | |
80 } | |
81 dst -= f->linesize[0] + linelen; | |
82 } | |
83 } | |
84 | |
85 static void copy_frame_32(AVFrame *f, uint8_t *src, | |
86 int linelen, int height) { | |
87 int i, j; | |
88 uint8_t *dst = f->data[0]; | |
89 dst += (height - 1) * f->linesize[0]; | |
90 for (i = height; i; i--) { | |
91 for (j = linelen / 4; j; j--) { | |
92 dst[0] = src[3]; | |
93 dst[1] = src[2]; | |
94 dst[2] = src[1]; | |
95 dst[3] = src[0]; | |
96 src += 4; | |
97 dst += 4; | |
98 } | |
99 dst -= f->linesize[0] + linelen; | |
100 } | |
101 } | |
102 | |
103 static void add_frame_16(AVFrame *f, uint8_t *src, | |
104 int linelen, int height) { | |
105 int i, j; | |
106 uint8_t *dst = f->data[0]; | |
107 dst += (height - 1) * f->linesize[0]; | |
108 for (i = height; i; i--) { | |
109 for (j = linelen / 2; j; j--) { | |
110 dst[0] += src[1]; | |
111 dst[1] += src[0]; | |
112 src += 2; | |
113 dst += 2; | |
114 } | |
115 dst -= f->linesize[0] + linelen; | |
116 } | |
117 } | |
118 | |
119 static void add_frame_32(AVFrame *f, uint8_t *src, | |
120 int linelen, int height) { | |
121 int i, j; | |
122 uint8_t *dst = f->data[0]; | |
123 dst += (height - 1) * f->linesize[0]; | |
124 for (i = height; i; i--) { | |
125 for (j = linelen / 4; j; j--) { | |
126 dst[0] += src[3]; | |
127 dst[1] += src[2]; | |
128 dst[2] += src[1]; | |
129 dst[3] += src[0]; | |
130 src += 4; | |
131 dst += 4; | |
132 } | |
133 dst -= f->linesize[0] + linelen; | |
134 } | |
135 } | |
136 #endif | |
137 | |
138 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |
139 uint8_t *buf, int buf_size) { | |
140 CamStudioContext *c = (CamStudioContext *)avctx->priv_data; | |
141 AVFrame *picture = data; | |
142 | |
143 if (buf_size < 2) { | |
144 av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); | |
145 return -1; | |
146 } | |
147 | |
148 if (c->pic.data[0]) | |
149 avctx->release_buffer(avctx, &c->pic); | |
150 c->pic.reference = 1; | |
151 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE | | |
152 FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | |
153 if (avctx->get_buffer(avctx, &c->pic) < 0) { | |
154 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
155 return -1; | |
156 } | |
157 | |
158 // decompress data | |
159 switch ((buf[0] >> 1) & 7) { | |
160 case 0: { // lzo compression | |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
3030
diff
changeset
|
161 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
|
162 if (lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen)) |
3030 | 163 av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); |
164 break; | |
165 } | |
166 case 1: { // zlib compression | |
167 #ifdef CONFIG_ZLIB | |
168 unsigned long dlen = c->decomp_size; | |
169 if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK) | |
170 av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n"); | |
171 break; | |
172 #else | |
173 av_log(avctx, AV_LOG_ERROR, "compiled without zlib support\n"); | |
174 return -1; | |
175 #endif | |
176 } | |
177 default: | |
178 av_log(avctx, AV_LOG_ERROR, "unknown compression\n"); | |
179 return -1; | |
180 } | |
181 | |
182 // flip upside down, add difference frame | |
183 if (buf[0] & 1) { // keyframe | |
184 c->pic.pict_type = FF_I_TYPE; | |
185 c->pic.key_frame = 1; | |
186 switch (c->bpp) { | |
187 case 16: | |
188 copy_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height); | |
189 break; | |
190 case 32: | |
191 copy_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height); | |
192 break; | |
193 default: | |
194 copy_frame_default(&c->pic, c->decomp_buf, c->linelen, c->height); | |
195 } | |
196 } else { | |
197 c->pic.pict_type = FF_P_TYPE; | |
198 c->pic.key_frame = 0; | |
199 switch (c->bpp) { | |
200 case 16: | |
201 add_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height); | |
202 break; | |
203 case 32: | |
204 add_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height); | |
205 break; | |
206 default: | |
207 add_frame_default(&c->pic, c->decomp_buf, c->linelen, c->height); | |
208 } | |
209 } | |
210 | |
211 *picture = c->pic; | |
212 *data_size = sizeof(AVFrame); | |
213 return buf_size; | |
214 } | |
215 | |
216 static int decode_init(AVCodecContext *avctx) { | |
217 CamStudioContext *c = (CamStudioContext *)avctx->priv_data; | |
218 if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) { | |
219 return 1; | |
220 } | |
221 avctx->has_b_frames = 0; | |
222 switch (avctx->bits_per_sample) { | |
223 case 16: avctx->pix_fmt = PIX_FMT_RGB565; break; | |
224 case 24: avctx->pix_fmt = PIX_FMT_BGR24; break; | |
225 case 32: avctx->pix_fmt = PIX_FMT_RGBA32; break; | |
226 default: | |
227 av_log(avctx, AV_LOG_ERROR, | |
228 "CamStudio codec error: unvalid depth %i bpp\n", | |
229 avctx->bits_per_sample); | |
230 return 1; | |
231 } | |
232 c->bpp = avctx->bits_per_sample; | |
233 c->pic.data[0] = NULL; | |
234 c->linelen = avctx->width * avctx->bits_per_sample / 8; | |
235 c->height = avctx->height; | |
236 c->decomp_size = c->height * c->linelen; | |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3036
diff
changeset
|
237 c->decomp_buf = av_malloc(c->decomp_size + LZO_OUTPUT_PADDING); |
3030 | 238 if (!c->decomp_buf) { |
239 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); | |
240 return 1; | |
241 } | |
242 return 0; | |
243 } | |
244 | |
245 static int decode_end(AVCodecContext *avctx) { | |
246 CamStudioContext *c = (CamStudioContext *)avctx->priv_data; | |
247 av_freep(&c->decomp_buf); | |
248 if (c->pic.data[0]) | |
249 avctx->release_buffer(avctx, &c->pic); | |
250 return 0; | |
251 } | |
252 | |
253 AVCodec cscd_decoder = { | |
254 "camstudio", | |
255 CODEC_TYPE_VIDEO, | |
256 CODEC_ID_CSCD, | |
257 sizeof(CamStudioContext), | |
258 decode_init, | |
259 NULL, | |
260 decode_end, | |
261 decode_frame, | |
262 CODEC_CAP_DR1, | |
263 }; | |
264 |