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