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