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