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