Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Zip Motion Blocks Video (ZMBV) decoder | ||
3 | * Copyright (c) 2006 Konstantin Shishkov | ||
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 | * Zip Motion Blocks Video decoder | ||
25 | */ | ||
26 | |||
27 | #include <stddef.h> | ||
28 | |||
29 | #include "libavutil/common.h" | ||
30 | #include "libavutil/imgutils.h" | ||
31 | #include "libavutil/intreadwrite.h" | ||
32 | #include "libavutil/mem.h" | ||
33 | #include "avcodec.h" | ||
34 | #include "codec_internal.h" | ||
35 | #include "decode.h" | ||
36 | #include "zlib_wrapper.h" | ||
37 | |||
38 | #include <zlib.h> | ||
39 | |||
40 | #define ZMBV_KEYFRAME 1 | ||
41 | #define ZMBV_DELTAPAL 2 | ||
42 | |||
43 | enum ZmbvFormat { | ||
44 | ZMBV_FMT_NONE = 0, | ||
45 | ZMBV_FMT_1BPP = 1, | ||
46 | ZMBV_FMT_2BPP = 2, | ||
47 | ZMBV_FMT_4BPP = 3, | ||
48 | ZMBV_FMT_8BPP = 4, | ||
49 | ZMBV_FMT_15BPP = 5, | ||
50 | ZMBV_FMT_16BPP = 6, | ||
51 | ZMBV_FMT_24BPP = 7, | ||
52 | ZMBV_FMT_32BPP = 8 | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * Decoder context | ||
57 | */ | ||
58 | typedef struct ZmbvContext { | ||
59 | AVCodecContext *avctx; | ||
60 | |||
61 | int bpp; | ||
62 | int alloc_bpp; | ||
63 | unsigned int decomp_size; | ||
64 | uint8_t* decomp_buf; | ||
65 | uint8_t pal[768]; | ||
66 | uint8_t *prev, *cur; | ||
67 | int width, height; | ||
68 | int fmt; | ||
69 | int comp; | ||
70 | int flags; | ||
71 | int stride; | ||
72 | int bw, bh, bx, by; | ||
73 | int decomp_len; | ||
74 | int got_keyframe; | ||
75 | FFZStream zstream; | ||
76 | int (*decode_xor)(struct ZmbvContext *c); | ||
77 | } ZmbvContext; | ||
78 | |||
79 | /** | ||
80 | * Decode XOR'ed frame - 8bpp version | ||
81 | */ | ||
82 | |||
83 | 275 | static int zmbv_decode_xor_8(ZmbvContext *c) | |
84 | { | ||
85 | 275 | uint8_t *src = c->decomp_buf; | |
86 | uint8_t *output, *prev; | ||
87 | int8_t *mvec; | ||
88 | int x, y; | ||
89 | int d, dx, dy, bw2, bh2; | ||
90 | int block; | ||
91 | int i, j; | ||
92 | int mx, my; | ||
93 | |||
94 | 275 | output = c->cur; | |
95 | 275 | prev = c->prev; | |
96 | |||
97 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
|
275 | if (c->flags & ZMBV_DELTAPAL) { |
98 | ✗ | for (i = 0; i < 768; i++) | |
99 | ✗ | c->pal[i] ^= *src++; | |
100 | } | ||
101 | |||
102 | 275 | mvec = (int8_t*)src; | |
103 | 275 | src += ((c->bx * c->by * 2 + 3) & ~3); | |
104 | |||
105 | 275 | block = 0; | |
106 |
2/2✓ Branch 0 taken 3575 times.
✓ Branch 1 taken 275 times.
|
3850 | for (y = 0; y < c->height; y += c->bh) { |
107 | 3575 | bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); | |
108 |
2/2✓ Branch 0 taken 71500 times.
✓ Branch 1 taken 3575 times.
|
75075 | for (x = 0; x < c->width; x += c->bw) { |
109 | uint8_t *out, *tprev; | ||
110 | |||
111 | 71500 | d = mvec[block] & 1; | |
112 | 71500 | dx = mvec[block] >> 1; | |
113 | 71500 | dy = mvec[block + 1] >> 1; | |
114 | 71500 | block += 2; | |
115 | |||
116 | 71500 | bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); | |
117 | |||
118 | /* copy block - motion vectors out of bounds are used to zero blocks */ | ||
119 | 71500 | out = output + x; | |
120 | 71500 | tprev = prev + x + dx + dy * c->width; | |
121 | 71500 | mx = x + dx; | |
122 | 71500 | my = y + dy; | |
123 |
2/2✓ Branch 0 taken 1100000 times.
✓ Branch 1 taken 71500 times.
|
1171500 | for (j = 0; j < bh2; j++) { |
124 |
2/4✓ Branch 0 taken 1100000 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1100000 times.
|
1100000 | if (my + j < 0 || my + j >= c->height) { |
125 | ✗ | memset(out, 0, bw2); | |
126 |
2/4✓ Branch 0 taken 1100000 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1100000 times.
✗ Branch 3 not taken.
|
1100000 | } else if (mx >= 0 && mx + bw2 <= c->width){ |
127 | 1100000 | memcpy(out, tprev, sizeof(*out) * bw2); | |
128 | } else { | ||
129 | ✗ | for (i = 0; i < bw2; i++) { | |
130 | ✗ | if (mx + i < 0 || mx + i >= c->width) | |
131 | ✗ | out[i] = 0; | |
132 | else | ||
133 | ✗ | out[i] = tprev[i]; | |
134 | } | ||
135 | } | ||
136 | 1100000 | out += c->width; | |
137 | 1100000 | tprev += c->width; | |
138 | } | ||
139 | |||
140 |
2/2✓ Branch 0 taken 1486 times.
✓ Branch 1 taken 70014 times.
|
71500 | if (d) { /* apply XOR'ed difference */ |
141 | 1486 | out = output + x; | |
142 |
2/2✓ Branch 0 taken 23776 times.
✓ Branch 1 taken 1486 times.
|
25262 | for (j = 0; j < bh2; j++) { |
143 |
2/2✓ Branch 0 taken 380416 times.
✓ Branch 1 taken 23776 times.
|
404192 | for (i = 0; i < bw2; i++) |
144 | 380416 | out[i] ^= *src++; | |
145 | 23776 | out += c->width; | |
146 | } | ||
147 | } | ||
148 | } | ||
149 | 3575 | output += c->width * c->bh; | |
150 | 3575 | prev += c->width * c->bh; | |
151 | } | ||
152 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 274 times.
|
275 | if (src - c->decomp_buf != c->decomp_len) |
153 | 1 | av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", | |
154 | 1 | src-c->decomp_buf, c->decomp_len); | |
155 | 275 | return 0; | |
156 | } | ||
157 | |||
158 | /** | ||
159 | * Decode XOR'ed frame - 15bpp and 16bpp version | ||
160 | */ | ||
161 | |||
162 | 336 | static int zmbv_decode_xor_16(ZmbvContext *c) | |
163 | { | ||
164 | 336 | uint8_t *src = c->decomp_buf; | |
165 | uint16_t *output, *prev; | ||
166 | int8_t *mvec; | ||
167 | int x, y; | ||
168 | int d, dx, dy, bw2, bh2; | ||
169 | int block; | ||
170 | int i, j; | ||
171 | int mx, my; | ||
172 | |||
173 | 336 | output = (uint16_t*)c->cur; | |
174 | 336 | prev = (uint16_t*)c->prev; | |
175 | |||
176 | 336 | mvec = (int8_t*)src; | |
177 | 336 | src += ((c->bx * c->by * 2 + 3) & ~3); | |
178 | |||
179 | 336 | block = 0; | |
180 |
2/2✓ Branch 0 taken 4368 times.
✓ Branch 1 taken 336 times.
|
4704 | for (y = 0; y < c->height; y += c->bh) { |
181 | 4368 | bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); | |
182 |
2/2✓ Branch 0 taken 87360 times.
✓ Branch 1 taken 4368 times.
|
91728 | for (x = 0; x < c->width; x += c->bw) { |
183 | uint16_t *out, *tprev; | ||
184 | |||
185 | 87360 | d = mvec[block] & 1; | |
186 | 87360 | dx = mvec[block] >> 1; | |
187 | 87360 | dy = mvec[block + 1] >> 1; | |
188 | 87360 | block += 2; | |
189 | |||
190 | 87360 | bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); | |
191 | |||
192 | /* copy block - motion vectors out of bounds are used to zero blocks */ | ||
193 | 87360 | out = output + x; | |
194 | 87360 | tprev = prev + x + dx + dy * c->width; | |
195 | 87360 | mx = x + dx; | |
196 | 87360 | my = y + dy; | |
197 |
2/2✓ Branch 0 taken 1344000 times.
✓ Branch 1 taken 87360 times.
|
1431360 | for (j = 0; j < bh2; j++) { |
198 |
4/4✓ Branch 0 taken 1343985 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 320 times.
✓ Branch 3 taken 1343665 times.
|
1344000 | if (my + j < 0 || my + j >= c->height) { |
199 | 335 | memset(out, 0, bw2 * 2); | |
200 |
4/4✓ Branch 0 taken 1343633 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 1343577 times.
✓ Branch 3 taken 56 times.
|
1343665 | } else if (mx >= 0 && mx + bw2 <= c->width){ |
201 | 1343577 | memcpy(out, tprev, sizeof(*out) * bw2); | |
202 | } else { | ||
203 |
2/2✓ Branch 0 taken 1408 times.
✓ Branch 1 taken 88 times.
|
1496 | for (i = 0; i < bw2; i++) { |
204 |
4/4✓ Branch 0 taken 1264 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 1104 times.
|
1408 | if (mx + i < 0 || mx + i >= c->width) |
205 | 304 | out[i] = 0; | |
206 | else | ||
207 | 1104 | out[i] = tprev[i]; | |
208 | } | ||
209 | } | ||
210 | 1344000 | out += c->width; | |
211 | 1344000 | tprev += c->width; | |
212 | } | ||
213 | |||
214 |
2/2✓ Branch 0 taken 8260 times.
✓ Branch 1 taken 79100 times.
|
87360 | if (d) { /* apply XOR'ed difference */ |
215 | 8260 | out = output + x; | |
216 |
2/2✓ Branch 0 taken 128448 times.
✓ Branch 1 taken 8260 times.
|
136708 | for (j = 0; j < bh2; j++){ |
217 |
2/2✓ Branch 0 taken 2055168 times.
✓ Branch 1 taken 128448 times.
|
2183616 | for (i = 0; i < bw2; i++) { |
218 | 2055168 | out[i] ^= *((uint16_t*)src); | |
219 | 2055168 | src += 2; | |
220 | } | ||
221 | 128448 | out += c->width; | |
222 | } | ||
223 | } | ||
224 | } | ||
225 | 4368 | output += c->width * c->bh; | |
226 | 4368 | prev += c->width * c->bh; | |
227 | } | ||
228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
|
336 | if (src - c->decomp_buf != c->decomp_len) |
229 | ✗ | av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", | |
230 | ✗ | src-c->decomp_buf, c->decomp_len); | |
231 | 336 | return 0; | |
232 | } | ||
233 | |||
234 | #ifdef ZMBV_ENABLE_24BPP | ||
235 | /** | ||
236 | * Decode XOR'ed frame - 24bpp version | ||
237 | */ | ||
238 | |||
239 | static int zmbv_decode_xor_24(ZmbvContext *c) | ||
240 | { | ||
241 | uint8_t *src = c->decomp_buf; | ||
242 | uint8_t *output, *prev; | ||
243 | int8_t *mvec; | ||
244 | int x, y; | ||
245 | int d, dx, dy, bw2, bh2; | ||
246 | int block; | ||
247 | int i, j; | ||
248 | int mx, my; | ||
249 | int stride; | ||
250 | |||
251 | output = c->cur; | ||
252 | prev = c->prev; | ||
253 | |||
254 | stride = c->width * 3; | ||
255 | mvec = (int8_t*)src; | ||
256 | src += ((c->bx * c->by * 2 + 3) & ~3); | ||
257 | |||
258 | block = 0; | ||
259 | for (y = 0; y < c->height; y += c->bh) { | ||
260 | bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); | ||
261 | for (x = 0; x < c->width; x += c->bw) { | ||
262 | uint8_t *out, *tprev; | ||
263 | |||
264 | d = mvec[block] & 1; | ||
265 | dx = mvec[block] >> 1; | ||
266 | dy = mvec[block + 1] >> 1; | ||
267 | block += 2; | ||
268 | |||
269 | bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); | ||
270 | |||
271 | /* copy block - motion vectors out of bounds are used to zero blocks */ | ||
272 | out = output + x * 3; | ||
273 | tprev = prev + (x + dx) * 3 + dy * stride; | ||
274 | mx = x + dx; | ||
275 | my = y + dy; | ||
276 | for (j = 0; j < bh2; j++) { | ||
277 | if (my + j < 0 || my + j >= c->height) { | ||
278 | memset(out, 0, bw2 * 3); | ||
279 | } else if (mx >= 0 && mx + bw2 <= c->width){ | ||
280 | memcpy(out, tprev, 3 * bw2); | ||
281 | } else { | ||
282 | for (i = 0; i < bw2; i++){ | ||
283 | if (mx + i < 0 || mx + i >= c->width) { | ||
284 | out[i * 3 + 0] = 0; | ||
285 | out[i * 3 + 1] = 0; | ||
286 | out[i * 3 + 2] = 0; | ||
287 | } else { | ||
288 | out[i * 3 + 0] = tprev[i * 3 + 0]; | ||
289 | out[i * 3 + 1] = tprev[i * 3 + 1]; | ||
290 | out[i * 3 + 2] = tprev[i * 3 + 2]; | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | out += stride; | ||
295 | tprev += stride; | ||
296 | } | ||
297 | |||
298 | if (d) { /* apply XOR'ed difference */ | ||
299 | out = output + x * 3; | ||
300 | for (j = 0; j < bh2; j++) { | ||
301 | for (i = 0; i < bw2; i++) { | ||
302 | out[i * 3 + 0] ^= *src++; | ||
303 | out[i * 3 + 1] ^= *src++; | ||
304 | out[i * 3 + 2] ^= *src++; | ||
305 | } | ||
306 | out += stride; | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | output += stride * c->bh; | ||
311 | prev += stride * c->bh; | ||
312 | } | ||
313 | if (src - c->decomp_buf != c->decomp_len) | ||
314 | av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", | ||
315 | src-c->decomp_buf, c->decomp_len); | ||
316 | return 0; | ||
317 | } | ||
318 | #endif //ZMBV_ENABLE_24BPP | ||
319 | |||
320 | /** | ||
321 | * Decode XOR'ed frame - 32bpp version | ||
322 | */ | ||
323 | |||
324 | 168 | static int zmbv_decode_xor_32(ZmbvContext *c) | |
325 | { | ||
326 | 168 | uint8_t *src = c->decomp_buf; | |
327 | uint32_t *output, *prev; | ||
328 | int8_t *mvec; | ||
329 | int x, y; | ||
330 | int d, dx, dy, bw2, bh2; | ||
331 | int block; | ||
332 | int i, j; | ||
333 | int mx, my; | ||
334 | |||
335 | 168 | output = (uint32_t*)c->cur; | |
336 | 168 | prev = (uint32_t*)c->prev; | |
337 | |||
338 | 168 | mvec = (int8_t*)src; | |
339 | 168 | src += ((c->bx * c->by * 2 + 3) & ~3); | |
340 | |||
341 | 168 | block = 0; | |
342 |
2/2✓ Branch 0 taken 2184 times.
✓ Branch 1 taken 168 times.
|
2352 | for (y = 0; y < c->height; y += c->bh) { |
343 | 2184 | bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); | |
344 |
2/2✓ Branch 0 taken 43680 times.
✓ Branch 1 taken 2184 times.
|
45864 | for (x = 0; x < c->width; x += c->bw) { |
345 | uint32_t *out, *tprev; | ||
346 | |||
347 | 43680 | d = mvec[block] & 1; | |
348 | 43680 | dx = mvec[block] >> 1; | |
349 | 43680 | dy = mvec[block + 1] >> 1; | |
350 | 43680 | block += 2; | |
351 | |||
352 | 43680 | bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); | |
353 | |||
354 | /* copy block - motion vectors out of bounds are used to zero blocks */ | ||
355 | 43680 | out = output + x; | |
356 | 43680 | tprev = prev + x + dx + dy * c->width; | |
357 | 43680 | mx = x + dx; | |
358 | 43680 | my = y + dy; | |
359 |
2/2✓ Branch 0 taken 672000 times.
✓ Branch 1 taken 43680 times.
|
715680 | for (j = 0; j < bh2; j++) { |
360 |
4/4✓ Branch 0 taken 671984 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 671824 times.
|
672000 | if (my + j < 0 || my + j >= c->height) { |
361 | 176 | memset(out, 0, bw2 * 4); | |
362 |
4/4✓ Branch 0 taken 671792 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 671760 times.
✓ Branch 3 taken 32 times.
|
671824 | } else if (mx >= 0 && mx + bw2 <= c->width){ |
363 | 671760 | memcpy(out, tprev, sizeof(*out) * bw2); | |
364 | } else { | ||
365 |
2/2✓ Branch 0 taken 1024 times.
✓ Branch 1 taken 64 times.
|
1088 | for (i = 0; i < bw2; i++){ |
366 |
4/4✓ Branch 0 taken 880 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 768 times.
|
1024 | if (mx + i < 0 || mx + i >= c->width) |
367 | 256 | out[i] = 0; | |
368 | else | ||
369 | 768 | out[i] = tprev[i]; | |
370 | } | ||
371 | } | ||
372 | 672000 | out += c->width; | |
373 | 672000 | tprev += c->width; | |
374 | } | ||
375 | |||
376 |
2/2✓ Branch 0 taken 4451 times.
✓ Branch 1 taken 39229 times.
|
43680 | if (d) { /* apply XOR'ed difference */ |
377 | 4451 | out = output + x; | |
378 |
2/2✓ Branch 0 taken 69136 times.
✓ Branch 1 taken 4451 times.
|
73587 | for (j = 0; j < bh2; j++){ |
379 |
2/2✓ Branch 0 taken 1106176 times.
✓ Branch 1 taken 69136 times.
|
1175312 | for (i = 0; i < bw2; i++) { |
380 | 1106176 | out[i] ^= *((uint32_t *) src); | |
381 | 1106176 | src += 4; | |
382 | } | ||
383 | 69136 | out += c->width; | |
384 | } | ||
385 | } | ||
386 | } | ||
387 | 2184 | output += c->width * c->bh; | |
388 | 2184 | prev += c->width * c->bh; | |
389 | } | ||
390 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
|
168 | if (src - c->decomp_buf != c->decomp_len) |
391 | ✗ | av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", | |
392 | ✗ | src-c->decomp_buf, c->decomp_len); | |
393 | 168 | return 0; | |
394 | } | ||
395 | |||
396 | /** | ||
397 | * Decode intraframe | ||
398 | */ | ||
399 | 8 | static int zmbv_decode_intra(ZmbvContext *c) | |
400 | { | ||
401 | 8 | uint8_t *src = c->decomp_buf; | |
402 | |||
403 | /* make the palette available on the way out */ | ||
404 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
|
8 | if (c->fmt == ZMBV_FMT_8BPP) { |
405 | 2 | memcpy(c->pal, src, 768); | |
406 | 2 | src += 768; | |
407 | } | ||
408 | |||
409 | 8 | memcpy(c->cur, src, c->width * c->height * (c->bpp / 8)); | |
410 | 8 | return 0; | |
411 | } | ||
412 | |||
413 | 787 | static int decode_frame(AVCodecContext *avctx, AVFrame *frame, | |
414 | int *got_frame, AVPacket *avpkt) | ||
415 | { | ||
416 | 787 | const uint8_t *buf = avpkt->data; | |
417 | 787 | int buf_size = avpkt->size; | |
418 | 787 | ZmbvContext * const c = avctx->priv_data; | |
419 | 787 | int zret = Z_OK; // Zlib return code | |
420 | 787 | int len = buf_size; | |
421 | int hi_ver, lo_ver, ret; | ||
422 | int expected_size; | ||
423 | |||
424 | /* parse header */ | ||
425 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 787 times.
|
787 | if (len < 1) |
426 | ✗ | return AVERROR_INVALIDDATA; | |
427 | 787 | c->flags = buf[0]; | |
428 | 787 | buf++; len--; | |
429 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 779 times.
|
787 | if (c->flags & ZMBV_KEYFRAME) { |
430 | 8 | c->got_keyframe = 0; | |
431 | |||
432 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (len < 6) |
433 | ✗ | return AVERROR_INVALIDDATA; | |
434 | 8 | hi_ver = buf[0]; | |
435 | 8 | lo_ver = buf[1]; | |
436 | 8 | c->comp = buf[2]; | |
437 | 8 | c->fmt = buf[3]; | |
438 | 8 | c->bw = buf[4]; | |
439 | 8 | c->bh = buf[5]; | |
440 | 8 | c->decode_xor = NULL; | |
441 | |||
442 | 8 | buf += 6; | |
443 | 8 | len -= 6; | |
444 | 8 | av_log(avctx, AV_LOG_DEBUG, | |
445 | "Flags=%X ver=%i.%i comp=%i fmt=%i blk=%ix%i\n", | ||
446 | c->flags,hi_ver,lo_ver,c->comp,c->fmt,c->bw,c->bh); | ||
447 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (hi_ver != 0 || lo_ver != 1) { |
448 | ✗ | avpriv_request_sample(avctx, "Version %i.%i", hi_ver, lo_ver); | |
449 | ✗ | return AVERROR_PATCHWELCOME; | |
450 | } | ||
451 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (c->bw == 0 || c->bh == 0) { |
452 | ✗ | avpriv_request_sample(avctx, "Block size %ix%i", c->bw, c->bh); | |
453 | ✗ | return AVERROR_PATCHWELCOME; | |
454 | } | ||
455 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (c->comp != 0 && c->comp != 1) { |
456 | ✗ | avpriv_request_sample(avctx, "Compression type %i", c->comp); | |
457 | ✗ | return AVERROR_PATCHWELCOME; | |
458 | } | ||
459 | |||
460 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
8 | switch (c->fmt) { |
461 | 2 | case ZMBV_FMT_8BPP: | |
462 | 2 | c->bpp = 8; | |
463 | 2 | c->decode_xor = zmbv_decode_xor_8; | |
464 | 2 | avctx->pix_fmt = AV_PIX_FMT_PAL8; | |
465 | 2 | c->stride = c->width; | |
466 | 2 | break; | |
467 | 4 | case ZMBV_FMT_15BPP: | |
468 | case ZMBV_FMT_16BPP: | ||
469 | 4 | c->bpp = 16; | |
470 | 4 | c->decode_xor = zmbv_decode_xor_16; | |
471 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | if (c->fmt == ZMBV_FMT_15BPP) |
472 | 2 | avctx->pix_fmt = AV_PIX_FMT_RGB555LE; | |
473 | else | ||
474 | 2 | avctx->pix_fmt = AV_PIX_FMT_RGB565LE; | |
475 | 4 | c->stride = c->width * 2; | |
476 | 4 | break; | |
477 | #ifdef ZMBV_ENABLE_24BPP | ||
478 | case ZMBV_FMT_24BPP: | ||
479 | c->bpp = 24; | ||
480 | c->decode_xor = zmbv_decode_xor_24; | ||
481 | avctx->pix_fmt = AV_PIX_FMT_BGR24; | ||
482 | c->stride = c->width * 3; | ||
483 | break; | ||
484 | #endif //ZMBV_ENABLE_24BPP | ||
485 | 2 | case ZMBV_FMT_32BPP: | |
486 | 2 | c->bpp = 32; | |
487 | 2 | c->decode_xor = zmbv_decode_xor_32; | |
488 | 2 | avctx->pix_fmt = AV_PIX_FMT_BGR0; | |
489 | 2 | c->stride = c->width * 4; | |
490 | 2 | break; | |
491 | ✗ | default: | |
492 | ✗ | c->decode_xor = NULL; | |
493 | ✗ | avpriv_request_sample(avctx, "Format %i", c->fmt); | |
494 | ✗ | return AVERROR_PATCHWELCOME; | |
495 | } | ||
496 | |||
497 | 8 | zret = inflateReset(&c->zstream.zstream); | |
498 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (zret != Z_OK) { |
499 | ✗ | av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); | |
500 | ✗ | return AVERROR_UNKNOWN; | |
501 | } | ||
502 | |||
503 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (c->alloc_bpp < c->bpp) { |
504 | 8 | c->cur = av_realloc_f(c->cur, avctx->width * avctx->height, (c->bpp / 8)); | |
505 | 8 | c->prev = av_realloc_f(c->prev, avctx->width * avctx->height, (c->bpp / 8)); | |
506 | 8 | c->alloc_bpp = c->bpp; | |
507 | } | ||
508 | 8 | c->bx = (c->width + c->bw - 1) / c->bw; | |
509 | 8 | c->by = (c->height+ c->bh - 1) / c->bh; | |
510 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (!c->cur || !c->prev) { |
511 | ✗ | c->alloc_bpp = 0; | |
512 | ✗ | return AVERROR(ENOMEM); | |
513 | } | ||
514 | 8 | memset(c->cur, 0, avctx->width * avctx->height * (c->bpp / 8)); | |
515 | 8 | memset(c->prev, 0, avctx->width * avctx->height * (c->bpp / 8)); | |
516 | 8 | c->got_keyframe = 1; | |
517 | } | ||
518 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 779 times.
|
787 | if (c->flags & ZMBV_KEYFRAME) { |
519 | 8 | expected_size = avctx->width * avctx->height * (c->bpp / 8); | |
520 | } else { | ||
521 | 779 | expected_size = (c->bx * c->by * 2 + 3) & ~3; | |
522 | } | ||
523 |
2/2✓ Branch 0 taken 277 times.
✓ Branch 1 taken 510 times.
|
787 | if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && |
524 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 275 times.
|
277 | (c->flags & (ZMBV_DELTAPAL | ZMBV_KEYFRAME))) |
525 | 2 | expected_size += 768; | |
526 | |||
527 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 787 times.
|
787 | if (!c->got_keyframe) { |
528 | ✗ | av_log(avctx, AV_LOG_ERROR, "Error! Got no format or no keyframe!\n"); | |
529 | ✗ | return AVERROR_INVALIDDATA; | |
530 | } | ||
531 | |||
532 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 787 times.
|
787 | if (c->comp == 0) { // uncompressed data |
533 | ✗ | if (c->decomp_size < len) { | |
534 | ✗ | av_log(avctx, AV_LOG_ERROR, "Buffer too small\n"); | |
535 | ✗ | return AVERROR_INVALIDDATA; | |
536 | } | ||
537 | ✗ | memcpy(c->decomp_buf, buf, len); | |
538 | ✗ | c->decomp_len = len; | |
539 | } else { // ZLIB-compressed data | ||
540 | 787 | z_stream *const zstream = &c->zstream.zstream; | |
541 | |||
542 | 787 | zstream->total_in = zstream->total_out = 0; | |
543 | 787 | zstream->next_in = buf; | |
544 | 787 | zstream->avail_in = len; | |
545 | 787 | zstream->next_out = c->decomp_buf; | |
546 | 787 | zstream->avail_out = c->decomp_size; | |
547 | 787 | zret = inflate(zstream, Z_SYNC_FLUSH); | |
548 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 787 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
787 | if (zret != Z_OK && zret != Z_STREAM_END) { |
549 | ✗ | av_log(avctx, AV_LOG_ERROR, "inflate error %d\n", zret); | |
550 | ✗ | return AVERROR_INVALIDDATA; | |
551 | } | ||
552 | 787 | c->decomp_len = zstream->total_out; | |
553 | } | ||
554 |
1/2✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
|
787 | if (expected_size > c->decomp_len || |
555 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 779 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
787 | (c->flags & ZMBV_KEYFRAME) && expected_size < c->decomp_len) { |
556 | ✗ | av_log(avctx, AV_LOG_ERROR, "decompressed size %d is incorrect, expected %d\n", c->decomp_len, expected_size); | |
557 | ✗ | return AVERROR_INVALIDDATA; | |
558 | } | ||
559 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 787 times.
|
787 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
560 | ✗ | return ret; | |
561 | |||
562 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 779 times.
|
787 | if (c->flags & ZMBV_KEYFRAME) { |
563 | 8 | frame->flags |= AV_FRAME_FLAG_KEY; | |
564 | 8 | frame->pict_type = AV_PICTURE_TYPE_I; | |
565 | 8 | zmbv_decode_intra(c); | |
566 | } else { | ||
567 | 779 | frame->flags &= ~AV_FRAME_FLAG_KEY; | |
568 | 779 | frame->pict_type = AV_PICTURE_TYPE_P; | |
569 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 779 times.
|
779 | if (c->decomp_len < 2LL * ((c->width + c->bw - 1) / c->bw) * ((c->height + c->bh - 1) / c->bh)) |
570 | ✗ | return AVERROR_INVALIDDATA; | |
571 |
1/2✓ Branch 0 taken 779 times.
✗ Branch 1 not taken.
|
779 | if (c->decomp_len) |
572 | 779 | c->decode_xor(c); | |
573 | } | ||
574 | |||
575 | /* update frames */ | ||
576 | { | ||
577 | uint8_t *out, *src; | ||
578 | int j; | ||
579 | |||
580 | 787 | out = frame->data[0]; | |
581 | 787 | src = c->cur; | |
582 |
2/3✓ Branch 0 taken 277 times.
✓ Branch 1 taken 510 times.
✗ Branch 2 not taken.
|
787 | switch (c->fmt) { |
583 | 277 | case ZMBV_FMT_8BPP: | |
584 |
2/2✓ Branch 0 taken 70912 times.
✓ Branch 1 taken 277 times.
|
71189 | for (j = 0; j < 256; j++) |
585 | 70912 | AV_WN32(&frame->data[1][j * 4], 0xFFU << 24 | AV_RB24(&c->pal[j * 3])); | |
586 | case ZMBV_FMT_15BPP: | ||
587 | case ZMBV_FMT_16BPP: | ||
588 | #ifdef ZMBV_ENABLE_24BPP | ||
589 | case ZMBV_FMT_24BPP: | ||
590 | #endif | ||
591 | case ZMBV_FMT_32BPP: | ||
592 | 787 | av_image_copy_plane(out, frame->linesize[0], src, c->stride, | |
593 | c->stride, c->height); | ||
594 | 787 | break; | |
595 | ✗ | default: | |
596 | ✗ | av_log(avctx, AV_LOG_ERROR, "Cannot handle format %i\n", c->fmt); | |
597 | } | ||
598 | 787 | FFSWAP(uint8_t *, c->cur, c->prev); | |
599 | } | ||
600 | 787 | *got_frame = 1; | |
601 | |||
602 | /* always report that the buffer was completely consumed */ | ||
603 | 787 | return buf_size; | |
604 | } | ||
605 | |||
606 | 8 | static av_cold int decode_init(AVCodecContext *avctx) | |
607 | { | ||
608 | 8 | ZmbvContext * const c = avctx->priv_data; | |
609 | |||
610 | 8 | c->avctx = avctx; | |
611 | |||
612 | 8 | c->width = avctx->width; | |
613 | 8 | c->height = avctx->height; | |
614 | |||
615 | 8 | c->bpp = avctx->bits_per_coded_sample; | |
616 | |||
617 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if ((avctx->width + 255ULL) * (avctx->height + 64ULL) > FFMIN(avctx->max_pixels, INT_MAX / 4) ) { |
618 | ✗ | av_log(avctx, AV_LOG_ERROR, "Internal buffer (decomp_size) larger than max_pixels or too large\n"); | |
619 | ✗ | return AVERROR_INVALIDDATA; | |
620 | } | ||
621 | |||
622 | 8 | c->decomp_size = (avctx->width + 255) * 4 * (avctx->height + 64); | |
623 | |||
624 | /* Allocate decompression buffer */ | ||
625 | 8 | c->decomp_buf = av_mallocz(c->decomp_size); | |
626 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!c->decomp_buf) { |
627 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
628 | "Can't allocate decompression buffer.\n"); | ||
629 | ✗ | return AVERROR(ENOMEM); | |
630 | } | ||
631 | |||
632 | 8 | return ff_inflate_init(&c->zstream, avctx); | |
633 | } | ||
634 | |||
635 | 8 | static av_cold int decode_end(AVCodecContext *avctx) | |
636 | { | ||
637 | 8 | ZmbvContext * const c = avctx->priv_data; | |
638 | |||
639 | 8 | av_freep(&c->decomp_buf); | |
640 | |||
641 | 8 | av_freep(&c->cur); | |
642 | 8 | av_freep(&c->prev); | |
643 | 8 | ff_inflate_end(&c->zstream); | |
644 | |||
645 | 8 | return 0; | |
646 | } | ||
647 | |||
648 | const FFCodec ff_zmbv_decoder = { | ||
649 | .p.name = "zmbv", | ||
650 | CODEC_LONG_NAME("Zip Motion Blocks Video"), | ||
651 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
652 | .p.id = AV_CODEC_ID_ZMBV, | ||
653 | .priv_data_size = sizeof(ZmbvContext), | ||
654 | .init = decode_init, | ||
655 | .close = decode_end, | ||
656 | FF_CODEC_DECODE_CB(decode_frame), | ||
657 | .p.capabilities = AV_CODEC_CAP_DR1, | ||
658 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | ||
659 | }; | ||
660 |