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