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