Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * LCL (LossLess Codec Library) Codec | |
3 | * Copyright (c) 2002-2004 Roberto Togni | |
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 | ||
22 | /** | |
23 | * @file | |
24 | * LCL (LossLess Codec Library) Video Codec | |
25 | * Decoder for MSZH and ZLIB codecs | |
26 | * Experimental encoder for ZLIB RGB24 | |
27 | * | |
28 | * Fourcc: MSZH, ZLIB | |
29 | * | |
30 | * Original Win32 dll: | |
31 | * Ver2.23 By Kenji Oshima 2000.09.20 | |
32 | * avimszh.dll, avizlib.dll | |
33 | * | |
34 | * A description of the decoding algorithm can be found here: | |
35 | * http://www.pcisys.net/~melanson/codecs | |
36 | * | |
37 | * Supports: BGR24 (RGB 24bpp) | |
38 | * | |
39 | */ | |
40 | ||
41 | #include <stdio.h> | |
42 | #include <stdlib.h> | |
43 | ||
44 | #include "libavutil/mem.h" | |
45 | #include "libavutil/pixdesc.h" | |
46 | #include "avcodec.h" | |
47 | #include "bytestream.h" | |
48 | #include "internal.h" | |
49 | #include "lcl.h" | |
50 | ||
51 | #if CONFIG_ZLIB_DECODER | |
52 | #include <zlib.h> | |
53 | #endif | |
54 | ||
55 | /* | |
56 | * Decoder context | |
57 | */ | |
58 | typedef struct LclDecContext { | |
59 | // Image type | |
60 | int imgtype; | |
61 | // Compression type | |
62 | int compression; | |
63 | // Flags | |
64 | int flags; | |
65 | // Decompressed data size | |
66 | unsigned int decomp_size; | |
67 | // Decompression buffer | |
68 | unsigned char* decomp_buf; | |
69 | #if CONFIG_ZLIB_DECODER | |
70 | z_stream zstream; | |
71 | #endif | |
72 | } LclDecContext; | |
73 | ||
74 | ||
75 | /** | |
76 | * @param srcptr compressed source buffer, must be padded with at least 5 extra bytes | |
77 | * @param destptr must be padded sufficiently for av_memcpy_backptr | |
78 | */ | |
79 | static unsigned int mszh_decomp(const unsigned char * srcptr, int srclen, unsigned char * destptr, unsigned int destsize) | |
80 | { | |
81 | unsigned char *destptr_bak = destptr; | |
82 | unsigned char *destptr_end = destptr + destsize; | |
83 | const unsigned char *srcptr_end = srcptr + srclen; | |
84 | unsigned mask = *srcptr++; | |
85 | unsigned maskbit = 0x80; | |
86 | ||
87 | while (srcptr < srcptr_end && destptr < destptr_end) { | |
88 | if (!(mask & maskbit)) { | |
89 | memcpy(destptr, srcptr, 4); | |
90 | destptr += 4; | |
91 | srcptr += 4; | |
92 | } else { | |
93 | unsigned ofs = bytestream_get_le16(&srcptr); | |
94 | unsigned cnt = (ofs >> 11) + 1; | |
95 | ofs &= 0x7ff; | |
96 | ofs = FFMIN(ofs, destptr - destptr_bak); | |
97 | cnt *= 4; | |
98 | cnt = FFMIN(cnt, destptr_end - destptr); | |
99 | if (ofs) { | |
100 | av_memcpy_backptr(destptr, ofs, cnt); | |
101 | } else { | |
102 | // Not known what the correct behaviour is, but | |
103 | // this at least avoids uninitialized data. | |
104 | memset(destptr, 0, cnt); | |
105 | } | |
106 | destptr += cnt; | |
107 | } | |
108 | maskbit >>= 1; | |
109 | if (!maskbit) { | |
110 | mask = *srcptr++; | |
111 | while (!mask) { | |
112 | if (destptr_end - destptr < 32 || srcptr_end - srcptr < 32) break; | |
113 | memcpy(destptr, srcptr, 32); | |
114 | destptr += 32; | |
115 | srcptr += 32; | |
116 | mask = *srcptr++; | |
117 | } | |
118 | maskbit = 0x80; | |
119 | } | |
120 | } | |
121 | ||
122 | return destptr - destptr_bak; | |
123 | } | |
124 | ||
125 | ||
126 | #if CONFIG_ZLIB_DECODER | |
127 | /** | |
128 | * @brief decompress a zlib-compressed data block into decomp_buf | |
129 | * @param src compressed input buffer | |
130 | * @param src_len data length in input buffer | |
131 | * @param offset offset in decomp_buf | |
132 | * @param expected expected decompressed length | |
133 | */ | |
134 | static int zlib_decomp(AVCodecContext *avctx, const uint8_t *src, int src_len, int offset, int expected) | |
135 | { | |
136 | LclDecContext *c = avctx->priv_data; | |
137 | int zret = inflateReset(&c->zstream); | |
138 | if (zret != Z_OK) { | |
139 | av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); | |
140 | return AVERROR_UNKNOWN; | |
141 | } | |
142 | c->zstream.next_in = (uint8_t *)src; | |
143 | c->zstream.avail_in = src_len; | |
144 | c->zstream.next_out = c->decomp_buf + offset; | |
145 | c->zstream.avail_out = c->decomp_size - offset; | |
146 | zret = inflate(&c->zstream, Z_FINISH); | |
147 | if (zret != Z_OK && zret != Z_STREAM_END) { | |
148 | av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", zret); | |
149 | return AVERROR_UNKNOWN; | |
150 | } | |
151 | if (expected != (unsigned int)c->zstream.total_out) { | |
152 | av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %lu)\n", | |
153 | expected, c->zstream.total_out); | |
154 | return AVERROR_UNKNOWN; | |
155 | } | |
156 | return c->zstream.total_out; | |
157 | } | |
158 | #endif | |
159 | ||
160 | ||
161 | /* | |
162 | * | |
163 | * Decode a frame | |
164 | * | |
165 | */ | |
166 | static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) | |
167 | { | |
168 | AVFrame *frame = data; | |
169 | const uint8_t *buf = avpkt->data; | |
170 | int buf_size = avpkt->size; | |
171 | LclDecContext * const c = avctx->priv_data; | |
172 | unsigned int pixel_ptr; | |
173 | int row, col; | |
174 | unsigned char *encoded = avpkt->data, *outptr; | |
175 | uint8_t *y_out, *u_out, *v_out; | |
176 | unsigned int width = avctx->width; // Real image width | |
177 | unsigned int height = avctx->height; // Real image height | |
178 | unsigned int mszh_dlen; | |
179 | unsigned char yq, y1q, uq, vq; | |
180 | int uqvq, ret; | |
181 | unsigned int mthread_inlen, mthread_outlen; | |
182 | unsigned int len = buf_size; | |
f6fa7814 | 183 | int linesize; |
2ba45a60 DM |
184 | |
185 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) | |
186 | return ret; | |
187 | ||
188 | outptr = frame->data[0]; // Output image pointer | |
189 | ||
190 | /* Decompress frame */ | |
191 | switch (avctx->codec_id) { | |
192 | case AV_CODEC_ID_MSZH: | |
193 | switch (c->compression) { | |
194 | case COMP_MSZH: | |
f6fa7814 | 195 | if (c->imgtype == IMGTYPE_RGB24 && len == FFALIGN(width * 3, 4) * height || |
2ba45a60 DM |
196 | c->imgtype == IMGTYPE_YUV111 && len == width * height * 3) { |
197 | ; | |
198 | } else if (c->flags & FLAG_MULTITHREAD) { | |
199 | mthread_inlen = AV_RL32(buf); | |
200 | if (len < 8) { | |
201 | av_log(avctx, AV_LOG_ERROR, "len %d is too small\n", len); | |
202 | return AVERROR_INVALIDDATA; | |
203 | } | |
204 | mthread_inlen = FFMIN(mthread_inlen, len - 8); | |
205 | mthread_outlen = AV_RL32(buf + 4); | |
206 | mthread_outlen = FFMIN(mthread_outlen, c->decomp_size); | |
207 | mszh_dlen = mszh_decomp(buf + 8, mthread_inlen, c->decomp_buf, c->decomp_size); | |
208 | if (mthread_outlen != mszh_dlen) { | |
209 | av_log(avctx, AV_LOG_ERROR, "Mthread1 decoded size differs (%d != %d)\n", | |
210 | mthread_outlen, mszh_dlen); | |
211 | return AVERROR_INVALIDDATA; | |
212 | } | |
213 | mszh_dlen = mszh_decomp(buf + 8 + mthread_inlen, len - 8 - mthread_inlen, | |
214 | c->decomp_buf + mthread_outlen, c->decomp_size - mthread_outlen); | |
215 | if (mthread_outlen != mszh_dlen) { | |
216 | av_log(avctx, AV_LOG_ERROR, "Mthread2 decoded size differs (%d != %d)\n", | |
217 | mthread_outlen, mszh_dlen); | |
218 | return AVERROR_INVALIDDATA; | |
219 | } | |
220 | encoded = c->decomp_buf; | |
221 | len = c->decomp_size; | |
222 | } else { | |
223 | mszh_dlen = mszh_decomp(buf, len, c->decomp_buf, c->decomp_size); | |
224 | if (c->decomp_size != mszh_dlen) { | |
225 | av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %d)\n", | |
226 | c->decomp_size, mszh_dlen); | |
227 | return AVERROR_INVALIDDATA; | |
228 | } | |
229 | encoded = c->decomp_buf; | |
230 | len = mszh_dlen; | |
231 | } | |
232 | break; | |
233 | case COMP_MSZH_NOCOMP: { | |
234 | int bppx2; | |
235 | switch (c->imgtype) { | |
236 | case IMGTYPE_YUV111: | |
237 | case IMGTYPE_RGB24: | |
238 | bppx2 = 6; | |
239 | break; | |
240 | case IMGTYPE_YUV422: | |
241 | case IMGTYPE_YUV211: | |
242 | bppx2 = 4; | |
243 | break; | |
244 | case IMGTYPE_YUV411: | |
245 | case IMGTYPE_YUV420: | |
246 | bppx2 = 3; | |
247 | break; | |
248 | default: | |
249 | bppx2 = 0; // will error out below | |
250 | break; | |
251 | } | |
252 | if (len < ((width * height * bppx2) >> 1)) | |
253 | return AVERROR_INVALIDDATA; | |
254 | break; | |
255 | } | |
256 | default: | |
257 | av_log(avctx, AV_LOG_ERROR, "BUG! Unknown MSZH compression in frame decoder.\n"); | |
258 | return AVERROR_INVALIDDATA; | |
259 | } | |
260 | break; | |
261 | #if CONFIG_ZLIB_DECODER | |
262 | case AV_CODEC_ID_ZLIB: | |
263 | /* Using the original dll with normal compression (-1) and RGB format | |
264 | * gives a file with ZLIB fourcc, but frame is really uncompressed. | |
265 | * To be sure that's true check also frame size */ | |
266 | if (c->compression == COMP_ZLIB_NORMAL && c->imgtype == IMGTYPE_RGB24 && | |
267 | len == width * height * 3) { | |
268 | if (c->flags & FLAG_PNGFILTER) { | |
269 | memcpy(c->decomp_buf, buf, len); | |
270 | encoded = c->decomp_buf; | |
271 | } else { | |
272 | break; | |
273 | } | |
274 | } else if (c->flags & FLAG_MULTITHREAD) { | |
275 | mthread_inlen = AV_RL32(buf); | |
276 | mthread_inlen = FFMIN(mthread_inlen, len - 8); | |
277 | mthread_outlen = AV_RL32(buf + 4); | |
278 | mthread_outlen = FFMIN(mthread_outlen, c->decomp_size); | |
279 | ret = zlib_decomp(avctx, buf + 8, mthread_inlen, 0, mthread_outlen); | |
280 | if (ret < 0) return ret; | |
281 | ret = zlib_decomp(avctx, buf + 8 + mthread_inlen, len - 8 - mthread_inlen, | |
282 | mthread_outlen, mthread_outlen); | |
283 | if (ret < 0) return ret; | |
284 | } else { | |
285 | int ret = zlib_decomp(avctx, buf, len, 0, c->decomp_size); | |
286 | if (ret < 0) return ret; | |
287 | } | |
288 | encoded = c->decomp_buf; | |
289 | len = c->decomp_size; | |
290 | break; | |
291 | #endif | |
292 | default: | |
293 | av_log(avctx, AV_LOG_ERROR, "BUG! Unknown codec in frame decoder compression switch.\n"); | |
294 | return AVERROR_INVALIDDATA; | |
295 | } | |
296 | ||
297 | ||
298 | /* Apply PNG filter */ | |
299 | if (avctx->codec_id == AV_CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER)) { | |
300 | switch (c->imgtype) { | |
301 | case IMGTYPE_YUV111: | |
302 | case IMGTYPE_RGB24: | |
303 | for (row = 0; row < height; row++) { | |
304 | pixel_ptr = row * width * 3; | |
305 | yq = encoded[pixel_ptr++]; | |
306 | uqvq = AV_RL16(encoded+pixel_ptr); | |
307 | pixel_ptr += 2; | |
308 | for (col = 1; col < width; col++) { | |
309 | encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
310 | uqvq -= AV_RL16(encoded+pixel_ptr+1); | |
311 | AV_WL16(encoded+pixel_ptr+1, uqvq); | |
312 | pixel_ptr += 3; | |
313 | } | |
314 | } | |
315 | break; | |
316 | case IMGTYPE_YUV422: | |
317 | for (row = 0; row < height; row++) { | |
318 | pixel_ptr = row * width * 2; | |
319 | yq = uq = vq =0; | |
320 | for (col = 0; col < width/4; col++) { | |
321 | encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
322 | encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; | |
323 | encoded[pixel_ptr+2] = yq -= encoded[pixel_ptr+2]; | |
324 | encoded[pixel_ptr+3] = yq -= encoded[pixel_ptr+3]; | |
325 | encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4]; | |
326 | encoded[pixel_ptr+5] = uq -= encoded[pixel_ptr+5]; | |
327 | encoded[pixel_ptr+6] = vq -= encoded[pixel_ptr+6]; | |
328 | encoded[pixel_ptr+7] = vq -= encoded[pixel_ptr+7]; | |
329 | pixel_ptr += 8; | |
330 | } | |
331 | } | |
332 | break; | |
333 | case IMGTYPE_YUV411: | |
334 | for (row = 0; row < height; row++) { | |
335 | pixel_ptr = row * width / 2 * 3; | |
336 | yq = uq = vq =0; | |
337 | for (col = 0; col < width/4; col++) { | |
338 | encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
339 | encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; | |
340 | encoded[pixel_ptr+2] = yq -= encoded[pixel_ptr+2]; | |
341 | encoded[pixel_ptr+3] = yq -= encoded[pixel_ptr+3]; | |
342 | encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4]; | |
343 | encoded[pixel_ptr+5] = vq -= encoded[pixel_ptr+5]; | |
344 | pixel_ptr += 6; | |
345 | } | |
346 | } | |
347 | break; | |
348 | case IMGTYPE_YUV211: | |
349 | for (row = 0; row < height; row++) { | |
350 | pixel_ptr = row * width * 2; | |
351 | yq = uq = vq =0; | |
352 | for (col = 0; col < width/2; col++) { | |
353 | encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
354 | encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; | |
355 | encoded[pixel_ptr+2] = uq -= encoded[pixel_ptr+2]; | |
356 | encoded[pixel_ptr+3] = vq -= encoded[pixel_ptr+3]; | |
357 | pixel_ptr += 4; | |
358 | } | |
359 | } | |
360 | break; | |
361 | case IMGTYPE_YUV420: | |
362 | for (row = 0; row < height/2; row++) { | |
363 | pixel_ptr = row * width * 3; | |
364 | yq = y1q = uq = vq =0; | |
365 | for (col = 0; col < width/2; col++) { | |
366 | encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
367 | encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; | |
368 | encoded[pixel_ptr+2] = y1q -= encoded[pixel_ptr+2]; | |
369 | encoded[pixel_ptr+3] = y1q -= encoded[pixel_ptr+3]; | |
370 | encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4]; | |
371 | encoded[pixel_ptr+5] = vq -= encoded[pixel_ptr+5]; | |
372 | pixel_ptr += 6; | |
373 | } | |
374 | } | |
375 | break; | |
376 | default: | |
377 | av_log(avctx, AV_LOG_ERROR, "BUG! Unknown imagetype in pngfilter switch.\n"); | |
378 | return AVERROR_INVALIDDATA; | |
379 | } | |
380 | } | |
381 | ||
382 | /* Convert colorspace */ | |
383 | y_out = frame->data[0] + (height - 1) * frame->linesize[0]; | |
384 | u_out = frame->data[1] + (height - 1) * frame->linesize[1]; | |
385 | v_out = frame->data[2] + (height - 1) * frame->linesize[2]; | |
386 | switch (c->imgtype) { | |
387 | case IMGTYPE_YUV111: | |
388 | for (row = 0; row < height; row++) { | |
389 | for (col = 0; col < width; col++) { | |
390 | y_out[col] = *encoded++; | |
391 | u_out[col] = *encoded++ + 128; | |
392 | v_out[col] = *encoded++ + 128; | |
393 | } | |
394 | y_out -= frame->linesize[0]; | |
395 | u_out -= frame->linesize[1]; | |
396 | v_out -= frame->linesize[2]; | |
397 | } | |
398 | break; | |
399 | case IMGTYPE_YUV422: | |
400 | for (row = 0; row < height; row++) { | |
401 | for (col = 0; col < width - 3; col += 4) { | |
402 | memcpy(y_out + col, encoded, 4); | |
403 | encoded += 4; | |
404 | u_out[ col >> 1 ] = *encoded++ + 128; | |
405 | u_out[(col >> 1) + 1] = *encoded++ + 128; | |
406 | v_out[ col >> 1 ] = *encoded++ + 128; | |
407 | v_out[(col >> 1) + 1] = *encoded++ + 128; | |
408 | } | |
409 | y_out -= frame->linesize[0]; | |
410 | u_out -= frame->linesize[1]; | |
411 | v_out -= frame->linesize[2]; | |
412 | } | |
413 | break; | |
414 | case IMGTYPE_RGB24: | |
f6fa7814 | 415 | linesize = len < FFALIGN(3 * width, 4) * height ? 3 * width : FFALIGN(3 * width, 4); |
2ba45a60 DM |
416 | for (row = height - 1; row >= 0; row--) { |
417 | pixel_ptr = row * frame->linesize[0]; | |
418 | memcpy(outptr + pixel_ptr, encoded, 3 * width); | |
f6fa7814 | 419 | encoded += linesize; |
2ba45a60 DM |
420 | } |
421 | break; | |
422 | case IMGTYPE_YUV411: | |
423 | for (row = 0; row < height; row++) { | |
424 | for (col = 0; col < width - 3; col += 4) { | |
425 | memcpy(y_out + col, encoded, 4); | |
426 | encoded += 4; | |
427 | u_out[col >> 2] = *encoded++ + 128; | |
428 | v_out[col >> 2] = *encoded++ + 128; | |
429 | } | |
430 | y_out -= frame->linesize[0]; | |
431 | u_out -= frame->linesize[1]; | |
432 | v_out -= frame->linesize[2]; | |
433 | } | |
434 | break; | |
435 | case IMGTYPE_YUV211: | |
436 | for (row = 0; row < height; row++) { | |
437 | for (col = 0; col < width - 1; col += 2) { | |
438 | memcpy(y_out + col, encoded, 2); | |
439 | encoded += 2; | |
440 | u_out[col >> 1] = *encoded++ + 128; | |
441 | v_out[col >> 1] = *encoded++ + 128; | |
442 | } | |
443 | y_out -= frame->linesize[0]; | |
444 | u_out -= frame->linesize[1]; | |
445 | v_out -= frame->linesize[2]; | |
446 | } | |
447 | break; | |
448 | case IMGTYPE_YUV420: | |
449 | u_out = frame->data[1] + ((height >> 1) - 1) * frame->linesize[1]; | |
450 | v_out = frame->data[2] + ((height >> 1) - 1) * frame->linesize[2]; | |
451 | for (row = 0; row < height - 1; row += 2) { | |
452 | for (col = 0; col < width - 1; col += 2) { | |
453 | memcpy(y_out + col, encoded, 2); | |
454 | encoded += 2; | |
455 | memcpy(y_out + col - frame->linesize[0], encoded, 2); | |
456 | encoded += 2; | |
457 | u_out[col >> 1] = *encoded++ + 128; | |
458 | v_out[col >> 1] = *encoded++ + 128; | |
459 | } | |
460 | y_out -= frame->linesize[0] << 1; | |
461 | u_out -= frame->linesize[1]; | |
462 | v_out -= frame->linesize[2]; | |
463 | } | |
464 | break; | |
465 | default: | |
466 | av_log(avctx, AV_LOG_ERROR, "BUG! Unknown imagetype in image decoder.\n"); | |
467 | return AVERROR_INVALIDDATA; | |
468 | } | |
469 | ||
470 | *got_frame = 1; | |
471 | ||
472 | /* always report that the buffer was completely consumed */ | |
473 | return buf_size; | |
474 | } | |
475 | ||
476 | /* | |
477 | * | |
478 | * Init lcl decoder | |
479 | * | |
480 | */ | |
481 | static av_cold int decode_init(AVCodecContext *avctx) | |
482 | { | |
483 | LclDecContext * const c = avctx->priv_data; | |
484 | unsigned int basesize = avctx->width * avctx->height; | |
485 | unsigned int max_basesize = FFALIGN(avctx->width, 4) * | |
486 | FFALIGN(avctx->height, 4); | |
487 | unsigned int max_decomp_size; | |
488 | int subsample_h, subsample_v; | |
489 | ||
490 | if (avctx->extradata_size < 8) { | |
491 | av_log(avctx, AV_LOG_ERROR, "Extradata size too small.\n"); | |
492 | return AVERROR_INVALIDDATA; | |
493 | } | |
494 | ||
495 | /* Check codec type */ | |
496 | if ((avctx->codec_id == AV_CODEC_ID_MSZH && avctx->extradata[7] != CODEC_MSZH) || | |
497 | (avctx->codec_id == AV_CODEC_ID_ZLIB && avctx->extradata[7] != CODEC_ZLIB)) { | |
498 | av_log(avctx, AV_LOG_ERROR, "Codec id and codec type mismatch. This should not happen.\n"); | |
499 | } | |
500 | ||
501 | /* Detect image type */ | |
502 | switch (c->imgtype = avctx->extradata[4]) { | |
503 | case IMGTYPE_YUV111: | |
504 | c->decomp_size = basesize * 3; | |
505 | max_decomp_size = max_basesize * 3; | |
506 | avctx->pix_fmt = AV_PIX_FMT_YUV444P; | |
507 | av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 1:1:1.\n"); | |
508 | break; | |
509 | case IMGTYPE_YUV422: | |
510 | c->decomp_size = basesize * 2; | |
511 | max_decomp_size = max_basesize * 2; | |
512 | avctx->pix_fmt = AV_PIX_FMT_YUV422P; | |
513 | av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:2:2.\n"); | |
514 | if (avctx->width % 4) { | |
515 | avpriv_request_sample(avctx, "Unsupported dimensions\n"); | |
516 | return AVERROR_INVALIDDATA; | |
517 | } | |
518 | break; | |
519 | case IMGTYPE_RGB24: | |
520 | c->decomp_size = basesize * 3; | |
521 | max_decomp_size = max_basesize * 3; | |
522 | avctx->pix_fmt = AV_PIX_FMT_BGR24; | |
523 | av_log(avctx, AV_LOG_DEBUG, "Image type is RGB 24.\n"); | |
524 | break; | |
525 | case IMGTYPE_YUV411: | |
526 | c->decomp_size = basesize / 2 * 3; | |
527 | max_decomp_size = max_basesize / 2 * 3; | |
528 | avctx->pix_fmt = AV_PIX_FMT_YUV411P; | |
529 | av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:1:1.\n"); | |
530 | break; | |
531 | case IMGTYPE_YUV211: | |
532 | c->decomp_size = basesize * 2; | |
533 | max_decomp_size = max_basesize * 2; | |
534 | avctx->pix_fmt = AV_PIX_FMT_YUV422P; | |
535 | av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 2:1:1.\n"); | |
536 | break; | |
537 | case IMGTYPE_YUV420: | |
538 | c->decomp_size = basesize / 2 * 3; | |
539 | max_decomp_size = max_basesize / 2 * 3; | |
540 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | |
541 | av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:2:0.\n"); | |
542 | break; | |
543 | default: | |
544 | av_log(avctx, AV_LOG_ERROR, "Unsupported image format %d.\n", c->imgtype); | |
545 | return AVERROR_INVALIDDATA; | |
546 | } | |
547 | ||
548 | av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &subsample_h, &subsample_v); | |
549 | if (avctx->width % (1<<subsample_h) || avctx->height % (1<<subsample_v)) { | |
550 | avpriv_request_sample(avctx, "Unsupported dimensions\n"); | |
551 | return AVERROR_INVALIDDATA; | |
552 | } | |
553 | ||
554 | /* Detect compression method */ | |
555 | c->compression = (int8_t)avctx->extradata[5]; | |
556 | switch (avctx->codec_id) { | |
557 | case AV_CODEC_ID_MSZH: | |
558 | switch (c->compression) { | |
559 | case COMP_MSZH: | |
560 | av_log(avctx, AV_LOG_DEBUG, "Compression enabled.\n"); | |
561 | break; | |
562 | case COMP_MSZH_NOCOMP: | |
563 | c->decomp_size = 0; | |
564 | av_log(avctx, AV_LOG_DEBUG, "No compression.\n"); | |
565 | break; | |
566 | default: | |
567 | av_log(avctx, AV_LOG_ERROR, "Unsupported compression format for MSZH (%d).\n", c->compression); | |
568 | return AVERROR_INVALIDDATA; | |
569 | } | |
570 | break; | |
571 | #if CONFIG_ZLIB_DECODER | |
572 | case AV_CODEC_ID_ZLIB: | |
573 | switch (c->compression) { | |
574 | case COMP_ZLIB_HISPEED: | |
575 | av_log(avctx, AV_LOG_DEBUG, "High speed compression.\n"); | |
576 | break; | |
577 | case COMP_ZLIB_HICOMP: | |
578 | av_log(avctx, AV_LOG_DEBUG, "High compression.\n"); | |
579 | break; | |
580 | case COMP_ZLIB_NORMAL: | |
581 | av_log(avctx, AV_LOG_DEBUG, "Normal compression.\n"); | |
582 | break; | |
583 | default: | |
584 | if (c->compression < Z_NO_COMPRESSION || c->compression > Z_BEST_COMPRESSION) { | |
585 | av_log(avctx, AV_LOG_ERROR, "Unsupported compression level for ZLIB: (%d).\n", c->compression); | |
586 | return AVERROR_INVALIDDATA; | |
587 | } | |
588 | av_log(avctx, AV_LOG_DEBUG, "Compression level for ZLIB: (%d).\n", c->compression); | |
589 | } | |
590 | break; | |
591 | #endif | |
592 | default: | |
593 | av_log(avctx, AV_LOG_ERROR, "BUG! Unknown codec in compression switch.\n"); | |
594 | return AVERROR_INVALIDDATA; | |
595 | } | |
596 | ||
597 | /* Allocate decompression buffer */ | |
598 | if (c->decomp_size) { | |
599 | if (!(c->decomp_buf = av_malloc(max_decomp_size))) { | |
600 | av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); | |
601 | return AVERROR(ENOMEM); | |
602 | } | |
603 | } | |
604 | ||
605 | /* Detect flags */ | |
606 | c->flags = avctx->extradata[6]; | |
607 | if (c->flags & FLAG_MULTITHREAD) | |
608 | av_log(avctx, AV_LOG_DEBUG, "Multithread encoder flag set.\n"); | |
609 | if (c->flags & FLAG_NULLFRAME) | |
610 | av_log(avctx, AV_LOG_DEBUG, "Nullframe insertion flag set.\n"); | |
611 | if (avctx->codec_id == AV_CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER)) | |
612 | av_log(avctx, AV_LOG_DEBUG, "PNG filter flag set.\n"); | |
613 | if (c->flags & FLAGMASK_UNUSED) | |
614 | av_log(avctx, AV_LOG_ERROR, "Unknown flag set (%d).\n", c->flags); | |
615 | ||
616 | /* If needed init zlib */ | |
617 | #if CONFIG_ZLIB_DECODER | |
618 | if (avctx->codec_id == AV_CODEC_ID_ZLIB) { | |
619 | int zret; | |
620 | c->zstream.zalloc = Z_NULL; | |
621 | c->zstream.zfree = Z_NULL; | |
622 | c->zstream.opaque = Z_NULL; | |
623 | zret = inflateInit(&c->zstream); | |
624 | if (zret != Z_OK) { | |
625 | av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); | |
626 | av_freep(&c->decomp_buf); | |
627 | return AVERROR_UNKNOWN; | |
628 | } | |
629 | } | |
630 | #endif | |
631 | ||
632 | return 0; | |
633 | } | |
634 | ||
635 | /* | |
636 | * | |
637 | * Uninit lcl decoder | |
638 | * | |
639 | */ | |
640 | static av_cold int decode_end(AVCodecContext *avctx) | |
641 | { | |
642 | LclDecContext * const c = avctx->priv_data; | |
643 | ||
644 | av_freep(&c->decomp_buf); | |
645 | #if CONFIG_ZLIB_DECODER | |
646 | if (avctx->codec_id == AV_CODEC_ID_ZLIB) | |
647 | inflateEnd(&c->zstream); | |
648 | #endif | |
649 | ||
650 | return 0; | |
651 | } | |
652 | ||
653 | #if CONFIG_MSZH_DECODER | |
654 | AVCodec ff_mszh_decoder = { | |
655 | .name = "mszh", | |
656 | .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) MSZH"), | |
657 | .type = AVMEDIA_TYPE_VIDEO, | |
658 | .id = AV_CODEC_ID_MSZH, | |
659 | .priv_data_size = sizeof(LclDecContext), | |
660 | .init = decode_init, | |
661 | .close = decode_end, | |
662 | .decode = decode_frame, | |
663 | .capabilities = CODEC_CAP_DR1, | |
664 | }; | |
665 | #endif | |
666 | ||
667 | #if CONFIG_ZLIB_DECODER | |
668 | AVCodec ff_zlib_decoder = { | |
669 | .name = "zlib", | |
670 | .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), | |
671 | .type = AVMEDIA_TYPE_VIDEO, | |
672 | .id = AV_CODEC_ID_ZLIB, | |
673 | .priv_data_size = sizeof(LclDecContext), | |
674 | .init = decode_init, | |
675 | .close = decode_end, | |
676 | .decode = decode_frame, | |
677 | .capabilities = CODEC_CAP_DR1, | |
678 | }; | |
679 | #endif |