2 * Zip Motion Blocks Video (ZMBV) decoder
3 * Copyright (c) 2006 Konstantin Shishkov
5 * This file is part of Libav.
7 * Libav 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.
12 * Libav 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * Zip Motion Blocks Video decoder
30 #include "libavutil/common.h"
31 #include "libavutil/intreadwrite.h"
37 #define ZMBV_KEYFRAME 1
38 #define ZMBV_DELTAPAL 2
55 typedef struct ZmbvContext
{
56 AVCodecContext
*avctx
;
59 unsigned int decomp_size
;
70 int (*decode_intra
)(struct ZmbvContext
*c
);
71 int (*decode_xor
)(struct ZmbvContext
*c
);
75 * Decode XOR'ed frame - 8bpp version
78 static int zmbv_decode_xor_8(ZmbvContext
*c
)
80 uint8_t *src
= c
->decomp_buf
;
81 uint8_t *output
, *prev
;
84 int d
, dx
, dy
, bw2
, bh2
;
92 if (c
->flags
& ZMBV_DELTAPAL
) {
93 for (i
= 0; i
< 768; i
++)
98 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
101 for (y
= 0; y
< c
->height
; y
+= c
->bh
) {
102 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
103 for (x
= 0; x
< c
->width
; x
+= c
->bw
) {
104 uint8_t *out
, *tprev
;
107 dx
= mvec
[block
] >> 1;
108 dy
= mvec
[block
+ 1] >> 1;
111 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
113 /* copy block - motion vectors out of bounds are used to zero blocks */
115 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
118 for (j
= 0; j
< bh2
; j
++) {
119 if (my
+ j
< 0 || my
+ j
>= c
->height
) {
122 for (i
= 0; i
< bw2
; i
++) {
123 if (mx
+ i
< 0 || mx
+ i
>= c
->width
)
133 if (d
) { /* apply XOR'ed difference */
135 for (j
= 0; j
< bh2
; j
++) {
136 for (i
= 0; i
< bw2
; i
++)
142 output
+= c
->width
* c
->bh
;
143 prev
+= c
->width
* c
->bh
;
145 if (src
- c
->decomp_buf
!= c
->decomp_len
)
146 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %ti of %i bytes\n",
147 src
-c
->decomp_buf
, c
->decomp_len
);
152 * Decode XOR'ed frame - 15bpp and 16bpp version
155 static int zmbv_decode_xor_16(ZmbvContext
*c
)
157 uint8_t *src
= c
->decomp_buf
;
158 uint16_t *output
, *prev
;
161 int d
, dx
, dy
, bw2
, bh2
;
166 output
= (uint16_t*)c
->cur
;
167 prev
= (uint16_t*)c
->prev
;
170 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
173 for (y
= 0; y
< c
->height
; y
+= c
->bh
) {
174 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
175 for (x
= 0; x
< c
->width
; x
+= c
->bw
) {
176 uint16_t *out
, *tprev
;
179 dx
= mvec
[block
] >> 1;
180 dy
= mvec
[block
+ 1] >> 1;
183 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
185 /* copy block - motion vectors out of bounds are used to zero blocks */
187 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
190 for (j
= 0; j
< bh2
; j
++) {
191 if (my
+ j
< 0 || my
+ j
>= c
->height
) {
192 memset(out
, 0, bw2
* 2);
194 for (i
= 0; i
< bw2
; i
++) {
195 if (mx
+ i
< 0 || mx
+ i
>= c
->width
)
205 if (d
) { /* apply XOR'ed difference */
207 for (j
= 0; j
< bh2
; j
++){
208 for (i
= 0; i
< bw2
; i
++) {
209 out
[i
] ^= *((uint16_t*)src
);
216 output
+= c
->width
* c
->bh
;
217 prev
+= c
->width
* c
->bh
;
219 if (src
- c
->decomp_buf
!= c
->decomp_len
)
220 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %ti of %i bytes\n",
221 src
-c
->decomp_buf
, c
->decomp_len
);
225 #ifdef ZMBV_ENABLE_24BPP
227 * Decode XOR'ed frame - 24bpp version
230 static int zmbv_decode_xor_24(ZmbvContext
*c
)
232 uint8_t *src
= c
->decomp_buf
;
233 uint8_t *output
, *prev
;
236 int d
, dx
, dy
, bw2
, bh2
;
245 stride
= c
->width
* 3;
247 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
250 for (y
= 0; y
< c
->height
; y
+= c
->bh
) {
251 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
252 for (x
= 0; x
< c
->width
; x
+= c
->bw
) {
253 uint8_t *out
, *tprev
;
256 dx
= mvec
[block
] >> 1;
257 dy
= mvec
[block
+ 1] >> 1;
260 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
262 /* copy block - motion vectors out of bounds are used to zero blocks */
263 out
= output
+ x
* 3;
264 tprev
= prev
+ (x
+ dx
) * 3 + dy
* stride
;
267 for (j
= 0; j
< bh2
; j
++) {
268 if (my
+ j
< 0 || my
+ j
>= c
->height
) {
269 memset(out
, 0, bw2
* 3);
271 for (i
= 0; i
< bw2
; i
++){
272 if (mx
+ i
< 0 || mx
+ i
>= c
->width
) {
277 out
[i
* 3 + 0] = tprev
[i
* 3 + 0];
278 out
[i
* 3 + 1] = tprev
[i
* 3 + 1];
279 out
[i
* 3 + 2] = tprev
[i
* 3 + 2];
287 if (d
) { /* apply XOR'ed difference */
288 out
= output
+ x
* 3;
289 for (j
= 0; j
< bh2
; j
++) {
290 for (i
= 0; i
< bw2
; i
++) {
291 out
[i
* 3 + 0] ^= *src
++;
292 out
[i
* 3 + 1] ^= *src
++;
293 out
[i
* 3 + 2] ^= *src
++;
299 output
+= stride
* c
->bh
;
300 prev
+= stride
* c
->bh
;
302 if (src
- c
->decomp_buf
!= c
->decomp_len
)
303 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %i of %i bytes\n",
304 src
-c
->decomp_buf
, c
->decomp_len
);
307 #endif //ZMBV_ENABLE_24BPP
310 * Decode XOR'ed frame - 32bpp version
313 static int zmbv_decode_xor_32(ZmbvContext
*c
)
315 uint8_t *src
= c
->decomp_buf
;
316 uint32_t *output
, *prev
;
319 int d
, dx
, dy
, bw2
, bh2
;
324 output
= (uint32_t*)c
->cur
;
325 prev
= (uint32_t*)c
->prev
;
328 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
331 for (y
= 0; y
< c
->height
; y
+= c
->bh
) {
332 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
333 for (x
= 0; x
< c
->width
; x
+= c
->bw
) {
334 uint32_t *out
, *tprev
;
337 dx
= mvec
[block
] >> 1;
338 dy
= mvec
[block
+ 1] >> 1;
341 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
343 /* copy block - motion vectors out of bounds are used to zero blocks */
345 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
348 for (j
= 0; j
< bh2
; j
++) {
349 if (my
+ j
< 0 || my
+ j
>= c
->height
) {
350 memset(out
, 0, bw2
* 4);
352 for (i
= 0; i
< bw2
; i
++){
353 if (mx
+ i
< 0 || mx
+ i
>= c
->width
)
363 if (d
) { /* apply XOR'ed difference */
365 for (j
= 0; j
< bh2
; j
++){
366 for (i
= 0; i
< bw2
; i
++) {
367 out
[i
] ^= *((uint32_t *) src
);
374 output
+= c
->width
* c
->bh
;
375 prev
+= c
->width
* c
->bh
;
377 if (src
- c
->decomp_buf
!= c
->decomp_len
)
378 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %ti of %i bytes\n",
379 src
-c
->decomp_buf
, c
->decomp_len
);
386 static int zmbv_decode_intra(ZmbvContext
*c
)
388 uint8_t *src
= c
->decomp_buf
;
390 /* make the palette available on the way out */
391 if (c
->fmt
== ZMBV_FMT_8BPP
) {
392 memcpy(c
->pal
, src
, 768);
396 memcpy(c
->cur
, src
, c
->width
* c
->height
* (c
->bpp
/ 8));
400 static int decode_frame(AVCodecContext
*avctx
, void *data
, int *got_frame
, AVPacket
*avpkt
)
402 AVFrame
*frame
= data
;
403 const uint8_t *buf
= avpkt
->data
;
404 int buf_size
= avpkt
->size
;
405 ZmbvContext
* const c
= avctx
->priv_data
;
406 int zret
= Z_OK
; // Zlib return code
408 int hi_ver
, lo_ver
, ret
;
411 if ((ret
= ff_get_buffer(avctx
, frame
, 0)) < 0) {
412 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
419 if (c
->flags
& ZMBV_KEYFRAME
) {
426 c
->decode_intra
= NULL
;
427 c
->decode_xor
= NULL
;
431 av_log(avctx
, AV_LOG_DEBUG
,
432 "Flags=%X ver=%i.%i comp=%i fmt=%i blk=%ix%i\n",
433 c
->flags
,hi_ver
,lo_ver
,c
->comp
,c
->fmt
,c
->bw
,c
->bh
);
434 if (hi_ver
!= 0 || lo_ver
!= 1) {
435 av_log_ask_for_sample(avctx
, "Unsupported version %i.%i\n",
437 return AVERROR_PATCHWELCOME
;
439 if (c
->bw
== 0 || c
->bh
== 0) {
440 av_log_ask_for_sample(avctx
, "Unsupported block size %ix%i\n",
442 return AVERROR_PATCHWELCOME
;
444 if (c
->comp
!= 0 && c
->comp
!= 1) {
445 av_log_ask_for_sample(avctx
, "Unsupported compression type %i\n",
447 return AVERROR_PATCHWELCOME
;
453 c
->decode_intra
= zmbv_decode_intra
;
454 c
->decode_xor
= zmbv_decode_xor_8
;
459 c
->decode_intra
= zmbv_decode_intra
;
460 c
->decode_xor
= zmbv_decode_xor_16
;
462 #ifdef ZMBV_ENABLE_24BPP
465 c
->decode_intra
= zmbv_decode_intra
;
466 c
->decode_xor
= zmbv_decode_xor_24
;
468 #endif //ZMBV_ENABLE_24BPP
471 c
->decode_intra
= zmbv_decode_intra
;
472 c
->decode_xor
= zmbv_decode_xor_32
;
475 c
->decode_intra
= NULL
;
476 c
->decode_xor
= NULL
;
477 av_log_ask_for_sample(avctx
, "Unsupported (for now) format %i\n",
479 return AVERROR_PATCHWELCOME
;
482 zret
= inflateReset(&c
->zstream
);
484 av_log(avctx
, AV_LOG_ERROR
, "Inflate reset error: %d\n", zret
);
485 return AVERROR_UNKNOWN
;
488 tmp
= av_realloc(c
->cur
, avctx
->width
* avctx
->height
* (c
->bpp
/ 8));
490 return AVERROR(ENOMEM
);
492 tmp
= av_realloc(c
->prev
, avctx
->width
* avctx
->height
* (c
->bpp
/ 8));
494 return AVERROR(ENOMEM
);
496 c
->bx
= (c
->width
+ c
->bw
- 1) / c
->bw
;
497 c
->by
= (c
->height
+ c
->bh
- 1) / c
->bh
;
500 if (c
->decode_intra
== NULL
) {
501 av_log(avctx
, AV_LOG_ERROR
, "Error! Got no format or no keyframe!\n");
502 return AVERROR_INVALIDDATA
;
505 if (c
->comp
== 0) { //Uncompressed data
506 memcpy(c
->decomp_buf
, buf
, len
);
508 } else { // ZLIB-compressed data
509 c
->zstream
.total_in
= c
->zstream
.total_out
= 0;
510 c
->zstream
.next_in
= buf
;
511 c
->zstream
.avail_in
= len
;
512 c
->zstream
.next_out
= c
->decomp_buf
;
513 c
->zstream
.avail_out
= c
->decomp_size
;
514 zret
= inflate(&c
->zstream
, Z_SYNC_FLUSH
);
515 if (zret
!= Z_OK
&& zret
!= Z_STREAM_END
) {
516 av_log(avctx
, AV_LOG_ERROR
, "inflate error %d\n", zret
);
517 return AVERROR_INVALIDDATA
;
519 c
->decomp_len
= c
->zstream
.total_out
;
521 if (c
->flags
& ZMBV_KEYFRAME
) {
522 frame
->key_frame
= 1;
523 frame
->pict_type
= AV_PICTURE_TYPE_I
;
526 frame
->key_frame
= 0;
527 frame
->pict_type
= AV_PICTURE_TYPE_P
;
537 out
= frame
->data
[0];
541 for (j
= 0; j
< c
->height
; j
++) {
542 for (i
= 0; i
< c
->width
; i
++) {
543 out
[i
* 3 + 0] = c
->pal
[(*src
) * 3 + 0];
544 out
[i
* 3 + 1] = c
->pal
[(*src
) * 3 + 1];
545 out
[i
* 3 + 2] = c
->pal
[(*src
) * 3 + 2];
548 out
+= frame
->linesize
[0];
552 for (j
= 0; j
< c
->height
; j
++) {
553 for (i
= 0; i
< c
->width
; i
++) {
554 uint16_t tmp
= AV_RL16(src
);
556 out
[i
* 3 + 0] = (tmp
& 0x7C00) >> 7;
557 out
[i
* 3 + 1] = (tmp
& 0x03E0) >> 2;
558 out
[i
* 3 + 2] = (tmp
& 0x001F) << 3;
560 out
+= frame
->linesize
[0];
564 for (j
= 0; j
< c
->height
; j
++) {
565 for (i
= 0; i
< c
->width
; i
++) {
566 uint16_t tmp
= AV_RL16(src
);
568 out
[i
* 3 + 0] = (tmp
& 0xF800) >> 8;
569 out
[i
* 3 + 1] = (tmp
& 0x07E0) >> 3;
570 out
[i
* 3 + 2] = (tmp
& 0x001F) << 3;
572 out
+= frame
->linesize
[0];
575 #ifdef ZMBV_ENABLE_24BPP
577 for (j
= 0; j
< c
->height
; j
++) {
578 memcpy(out
, src
, c
->width
* 3);
580 out
+= frame
->linesize
[0];
583 #endif //ZMBV_ENABLE_24BPP
585 for (j
= 0; j
< c
->height
; j
++) {
586 for (i
= 0; i
< c
->width
; i
++) {
587 uint32_t tmp
= AV_RL32(src
);
589 AV_WB24(out
+(i
*3), tmp
);
591 out
+= frame
->linesize
[0];
595 av_log(avctx
, AV_LOG_ERROR
, "Cannot handle format %i\n", c
->fmt
);
597 FFSWAP(uint8_t *, c
->cur
, c
->prev
);
601 /* always report that the buffer was completely consumed */
605 static av_cold
int decode_init(AVCodecContext
*avctx
)
607 ZmbvContext
* const c
= avctx
->priv_data
;
608 int zret
; // Zlib return code
612 c
->width
= avctx
->width
;
613 c
->height
= avctx
->height
;
615 c
->bpp
= avctx
->bits_per_coded_sample
;
617 // Needed if zlib unused or init aborted before inflateInit
618 memset(&c
->zstream
, 0, sizeof(z_stream
));
620 avctx
->pix_fmt
= AV_PIX_FMT_RGB24
;
621 c
->decomp_size
= (avctx
->width
+ 255) * 4 * (avctx
->height
+ 64);
623 /* Allocate decompression buffer */
624 if (c
->decomp_size
) {
625 if ((c
->decomp_buf
= av_malloc(c
->decomp_size
)) == NULL
) {
626 av_log(avctx
, AV_LOG_ERROR
,
627 "Can't allocate decompression buffer.\n");
628 return AVERROR(ENOMEM
);
632 c
->zstream
.zalloc
= Z_NULL
;
633 c
->zstream
.zfree
= Z_NULL
;
634 c
->zstream
.opaque
= Z_NULL
;
635 zret
= inflateInit(&c
->zstream
);
637 av_log(avctx
, AV_LOG_ERROR
, "Inflate init error: %d\n", zret
);
638 return AVERROR_UNKNOWN
;
644 static av_cold
int decode_end(AVCodecContext
*avctx
)
646 ZmbvContext
* const c
= avctx
->priv_data
;
648 av_freep(&c
->decomp_buf
);
650 inflateEnd(&c
->zstream
);
657 AVCodec ff_zmbv_decoder
= {
659 .type
= AVMEDIA_TYPE_VIDEO
,
660 .id
= AV_CODEC_ID_ZMBV
,
661 .priv_data_size
= sizeof(ZmbvContext
),
664 .decode
= decode_frame
,
665 .capabilities
= CODEC_CAP_DR1
,
666 .long_name
= NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),