2 * Zip Motion Blocks Video (ZMBV) decoder
3 * Copyright (c) 2006 Konstantin Shishkov
5 * This file is part of FFmpeg.
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.
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.
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
24 * Zip Motion Blocks Video decoder
30 #include "libavutil/common.h"
31 #include "libavutil/imgutils.h"
32 #include "libavutil/intreadwrite.h"
38 #define ZMBV_KEYFRAME 1
39 #define ZMBV_DELTAPAL 2
56 typedef struct ZmbvContext
{
57 AVCodecContext
*avctx
;
60 unsigned int decomp_size
;
72 int (*decode_intra
)(struct ZmbvContext
*c
);
73 int (*decode_xor
)(struct ZmbvContext
*c
);
77 * Decode XOR'ed frame - 8bpp version
80 static int zmbv_decode_xor_8(ZmbvContext
*c
)
82 uint8_t *src
= c
->decomp_buf
;
83 uint8_t *output
, *prev
;
86 int d
, dx
, dy
, bw2
, bh2
;
94 if (c
->flags
& ZMBV_DELTAPAL
) {
95 for (i
= 0; i
< 768; i
++)
100 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
103 for (y
= 0; y
< c
->height
; y
+= c
->bh
) {
104 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
105 for (x
= 0; x
< c
->width
; x
+= c
->bw
) {
106 uint8_t *out
, *tprev
;
109 dx
= mvec
[block
] >> 1;
110 dy
= mvec
[block
+ 1] >> 1;
113 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
115 /* copy block - motion vectors out of bounds are used to zero blocks */
117 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
120 for (j
= 0; j
< bh2
; j
++) {
121 if (my
+ j
< 0 || my
+ j
>= c
->height
) {
124 for (i
= 0; i
< bw2
; i
++) {
125 if (mx
+ i
< 0 || mx
+ i
>= c
->width
)
135 if (d
) { /* apply XOR'ed difference */
137 for (j
= 0; j
< bh2
; j
++) {
138 for (i
= 0; i
< bw2
; i
++)
144 output
+= c
->width
* c
->bh
;
145 prev
+= c
->width
* c
->bh
;
147 if (src
- c
->decomp_buf
!= c
->decomp_len
)
148 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %"PTRDIFF_SPECIFIER
" of %i bytes\n",
149 src
-c
->decomp_buf
, c
->decomp_len
);
154 * Decode XOR'ed frame - 15bpp and 16bpp version
157 static int zmbv_decode_xor_16(ZmbvContext
*c
)
159 uint8_t *src
= c
->decomp_buf
;
160 uint16_t *output
, *prev
;
163 int d
, dx
, dy
, bw2
, bh2
;
168 output
= (uint16_t*)c
->cur
;
169 prev
= (uint16_t*)c
->prev
;
172 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
175 for (y
= 0; y
< c
->height
; y
+= c
->bh
) {
176 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
177 for (x
= 0; x
< c
->width
; x
+= c
->bw
) {
178 uint16_t *out
, *tprev
;
181 dx
= mvec
[block
] >> 1;
182 dy
= mvec
[block
+ 1] >> 1;
185 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
187 /* copy block - motion vectors out of bounds are used to zero blocks */
189 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
192 for (j
= 0; j
< bh2
; j
++) {
193 if (my
+ j
< 0 || my
+ j
>= c
->height
) {
194 memset(out
, 0, bw2
* 2);
196 for (i
= 0; i
< bw2
; i
++) {
197 if (mx
+ i
< 0 || mx
+ i
>= c
->width
)
207 if (d
) { /* apply XOR'ed difference */
209 for (j
= 0; j
< bh2
; j
++){
210 for (i
= 0; i
< bw2
; i
++) {
211 out
[i
] ^= *((uint16_t*)src
);
218 output
+= c
->width
* c
->bh
;
219 prev
+= c
->width
* c
->bh
;
221 if (src
- c
->decomp_buf
!= c
->decomp_len
)
222 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %"PTRDIFF_SPECIFIER
" of %i bytes\n",
223 src
-c
->decomp_buf
, c
->decomp_len
);
227 #ifdef ZMBV_ENABLE_24BPP
229 * Decode XOR'ed frame - 24bpp version
232 static int zmbv_decode_xor_24(ZmbvContext
*c
)
234 uint8_t *src
= c
->decomp_buf
;
235 uint8_t *output
, *prev
;
238 int d
, dx
, dy
, bw2
, bh2
;
247 stride
= c
->width
* 3;
249 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
252 for (y
= 0; y
< c
->height
; y
+= c
->bh
) {
253 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
254 for (x
= 0; x
< c
->width
; x
+= c
->bw
) {
255 uint8_t *out
, *tprev
;
258 dx
= mvec
[block
] >> 1;
259 dy
= mvec
[block
+ 1] >> 1;
262 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
264 /* copy block - motion vectors out of bounds are used to zero blocks */
265 out
= output
+ x
* 3;
266 tprev
= prev
+ (x
+ dx
) * 3 + dy
* stride
;
269 for (j
= 0; j
< bh2
; j
++) {
270 if (my
+ j
< 0 || my
+ j
>= c
->height
) {
271 memset(out
, 0, bw2
* 3);
273 for (i
= 0; i
< bw2
; i
++){
274 if (mx
+ i
< 0 || mx
+ i
>= c
->width
) {
279 out
[i
* 3 + 0] = tprev
[i
* 3 + 0];
280 out
[i
* 3 + 1] = tprev
[i
* 3 + 1];
281 out
[i
* 3 + 2] = tprev
[i
* 3 + 2];
289 if (d
) { /* apply XOR'ed difference */
290 out
= output
+ x
* 3;
291 for (j
= 0; j
< bh2
; j
++) {
292 for (i
= 0; i
< bw2
; i
++) {
293 out
[i
* 3 + 0] ^= *src
++;
294 out
[i
* 3 + 1] ^= *src
++;
295 out
[i
* 3 + 2] ^= *src
++;
301 output
+= stride
* c
->bh
;
302 prev
+= stride
* c
->bh
;
304 if (src
- c
->decomp_buf
!= c
->decomp_len
)
305 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %i of %i bytes\n",
306 src
-c
->decomp_buf
, c
->decomp_len
);
309 #endif //ZMBV_ENABLE_24BPP
312 * Decode XOR'ed frame - 32bpp version
315 static int zmbv_decode_xor_32(ZmbvContext
*c
)
317 uint8_t *src
= c
->decomp_buf
;
318 uint32_t *output
, *prev
;
321 int d
, dx
, dy
, bw2
, bh2
;
326 output
= (uint32_t*)c
->cur
;
327 prev
= (uint32_t*)c
->prev
;
330 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
333 for (y
= 0; y
< c
->height
; y
+= c
->bh
) {
334 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
335 for (x
= 0; x
< c
->width
; x
+= c
->bw
) {
336 uint32_t *out
, *tprev
;
339 dx
= mvec
[block
] >> 1;
340 dy
= mvec
[block
+ 1] >> 1;
343 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
345 /* copy block - motion vectors out of bounds are used to zero blocks */
347 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
350 for (j
= 0; j
< bh2
; j
++) {
351 if (my
+ j
< 0 || my
+ j
>= c
->height
) {
352 memset(out
, 0, bw2
* 4);
354 for (i
= 0; i
< bw2
; i
++){
355 if (mx
+ i
< 0 || mx
+ i
>= c
->width
)
365 if (d
) { /* apply XOR'ed difference */
367 for (j
= 0; j
< bh2
; j
++){
368 for (i
= 0; i
< bw2
; i
++) {
369 out
[i
] ^= *((uint32_t *) src
);
376 output
+= c
->width
* c
->bh
;
377 prev
+= c
->width
* c
->bh
;
379 if (src
- c
->decomp_buf
!= c
->decomp_len
)
380 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %"PTRDIFF_SPECIFIER
" of %i bytes\n",
381 src
-c
->decomp_buf
, c
->decomp_len
);
388 static int zmbv_decode_intra(ZmbvContext
*c
)
390 uint8_t *src
= c
->decomp_buf
;
392 /* make the palette available on the way out */
393 if (c
->fmt
== ZMBV_FMT_8BPP
) {
394 memcpy(c
->pal
, src
, 768);
398 memcpy(c
->cur
, src
, c
->width
* c
->height
* (c
->bpp
/ 8));
402 static int decode_frame(AVCodecContext
*avctx
, void *data
, int *got_frame
, AVPacket
*avpkt
)
404 AVFrame
*frame
= data
;
405 const uint8_t *buf
= avpkt
->data
;
406 int buf_size
= avpkt
->size
;
407 ZmbvContext
* const c
= avctx
->priv_data
;
408 int zret
= Z_OK
; // Zlib return code
410 int hi_ver
, lo_ver
, ret
;
415 if (c
->flags
& ZMBV_KEYFRAME
) {
416 void *decode_intra
= NULL
;
417 c
->decode_intra
= NULL
;
424 c
->decode_intra
= NULL
;
425 c
->decode_xor
= NULL
;
429 av_log(avctx
, AV_LOG_DEBUG
,
430 "Flags=%X ver=%i.%i comp=%i fmt=%i blk=%ix%i\n",
431 c
->flags
,hi_ver
,lo_ver
,c
->comp
,c
->fmt
,c
->bw
,c
->bh
);
432 if (hi_ver
!= 0 || lo_ver
!= 1) {
433 avpriv_request_sample(avctx
, "Version %i.%i", hi_ver
, lo_ver
);
434 return AVERROR_PATCHWELCOME
;
436 if (c
->bw
== 0 || c
->bh
== 0) {
437 avpriv_request_sample(avctx
, "Block size %ix%i", c
->bw
, c
->bh
);
438 return AVERROR_PATCHWELCOME
;
440 if (c
->comp
!= 0 && c
->comp
!= 1) {
441 avpriv_request_sample(avctx
, "Compression type %i", c
->comp
);
442 return AVERROR_PATCHWELCOME
;
448 decode_intra
= zmbv_decode_intra
;
449 c
->decode_xor
= zmbv_decode_xor_8
;
450 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
451 c
->stride
= c
->width
;
456 decode_intra
= zmbv_decode_intra
;
457 c
->decode_xor
= zmbv_decode_xor_16
;
458 if (c
->fmt
== ZMBV_FMT_15BPP
)
459 avctx
->pix_fmt
= AV_PIX_FMT_RGB555LE
;
461 avctx
->pix_fmt
= AV_PIX_FMT_RGB565LE
;
462 c
->stride
= c
->width
* 2;
464 #ifdef ZMBV_ENABLE_24BPP
467 decode_intra
= zmbv_decode_intra
;
468 c
->decode_xor
= zmbv_decode_xor_24
;
469 avctx
->pix_fmt
= AV_PIX_FMT_RGB24
;
470 c
->stride
= c
->width
* 3;
472 #endif //ZMBV_ENABLE_24BPP
475 decode_intra
= zmbv_decode_intra
;
476 c
->decode_xor
= zmbv_decode_xor_32
;
477 avctx
->pix_fmt
= AV_PIX_FMT_BGR0
;
478 c
->stride
= c
->width
* 4;
481 c
->decode_xor
= NULL
;
482 avpriv_request_sample(avctx
, "Format %i", c
->fmt
);
483 return AVERROR_PATCHWELCOME
;
486 zret
= inflateReset(&c
->zstream
);
488 av_log(avctx
, AV_LOG_ERROR
, "Inflate reset error: %d\n", zret
);
489 return AVERROR_UNKNOWN
;
492 c
->cur
= av_realloc_f(c
->cur
, avctx
->width
* avctx
->height
, (c
->bpp
/ 8));
493 c
->prev
= av_realloc_f(c
->prev
, avctx
->width
* avctx
->height
, (c
->bpp
/ 8));
494 c
->bx
= (c
->width
+ c
->bw
- 1) / c
->bw
;
495 c
->by
= (c
->height
+ c
->bh
- 1) / c
->bh
;
496 if (!c
->cur
|| !c
->prev
)
497 return AVERROR(ENOMEM
);
498 memset(c
->cur
, 0, avctx
->width
* avctx
->height
* (c
->bpp
/ 8));
499 memset(c
->prev
, 0, avctx
->width
* avctx
->height
* (c
->bpp
/ 8));
500 c
->decode_intra
= decode_intra
;
503 if (!c
->decode_intra
) {
504 av_log(avctx
, AV_LOG_ERROR
, "Error! Got no format or no keyframe!\n");
505 return AVERROR_INVALIDDATA
;
508 if ((ret
= ff_get_buffer(avctx
, frame
, 0)) < 0)
511 if (c
->comp
== 0) { //Uncompressed data
512 if (c
->decomp_size
< len
) {
513 av_log(avctx
, AV_LOG_ERROR
, "Buffer too small\n");
514 return AVERROR_INVALIDDATA
;
516 memcpy(c
->decomp_buf
, buf
, len
);
517 } else { // ZLIB-compressed data
518 c
->zstream
.total_in
= c
->zstream
.total_out
= 0;
519 c
->zstream
.next_in
= (uint8_t*)buf
;
520 c
->zstream
.avail_in
= len
;
521 c
->zstream
.next_out
= c
->decomp_buf
;
522 c
->zstream
.avail_out
= c
->decomp_size
;
523 zret
= inflate(&c
->zstream
, Z_SYNC_FLUSH
);
524 if (zret
!= Z_OK
&& zret
!= Z_STREAM_END
) {
525 av_log(avctx
, AV_LOG_ERROR
, "inflate error %d\n", zret
);
526 return AVERROR_INVALIDDATA
;
528 c
->decomp_len
= c
->zstream
.total_out
;
530 if (c
->flags
& ZMBV_KEYFRAME
) {
531 frame
->key_frame
= 1;
532 frame
->pict_type
= AV_PICTURE_TYPE_I
;
535 frame
->key_frame
= 0;
536 frame
->pict_type
= AV_PICTURE_TYPE_P
;
546 out
= frame
->data
[0];
550 for (j
= 0; j
< 256; j
++)
551 AV_WN32(&frame
->data
[1][j
* 4], 0xFFU
<< 24 | AV_RB24(&c
->pal
[j
* 3]));
554 #ifdef ZMBV_ENABLE_24BPP
558 av_image_copy_plane(out
, frame
->linesize
[0], src
, c
->stride
,
559 c
->stride
, c
->height
);
562 av_log(avctx
, AV_LOG_ERROR
, "Cannot handle format %i\n", c
->fmt
);
564 FFSWAP(uint8_t *, c
->cur
, c
->prev
);
568 /* always report that the buffer was completely consumed */
572 static av_cold
int decode_init(AVCodecContext
*avctx
)
574 ZmbvContext
* const c
= avctx
->priv_data
;
575 int zret
; // Zlib return code
579 c
->width
= avctx
->width
;
580 c
->height
= avctx
->height
;
582 c
->bpp
= avctx
->bits_per_coded_sample
;
584 // Needed if zlib unused or init aborted before inflateInit
585 memset(&c
->zstream
, 0, sizeof(z_stream
));
587 c
->decomp_size
= (avctx
->width
+ 255) * 4 * (avctx
->height
+ 64);
589 /* Allocate decompression buffer */
590 if (c
->decomp_size
) {
591 if (!(c
->decomp_buf
= av_mallocz(c
->decomp_size
))) {
592 av_log(avctx
, AV_LOG_ERROR
,
593 "Can't allocate decompression buffer.\n");
594 return AVERROR(ENOMEM
);
598 c
->zstream
.zalloc
= Z_NULL
;
599 c
->zstream
.zfree
= Z_NULL
;
600 c
->zstream
.opaque
= Z_NULL
;
601 zret
= inflateInit(&c
->zstream
);
603 av_log(avctx
, AV_LOG_ERROR
, "Inflate init error: %d\n", zret
);
604 return AVERROR_UNKNOWN
;
610 static av_cold
int decode_end(AVCodecContext
*avctx
)
612 ZmbvContext
* const c
= avctx
->priv_data
;
614 av_freep(&c
->decomp_buf
);
616 inflateEnd(&c
->zstream
);
623 AVCodec ff_zmbv_decoder
= {
625 .long_name
= NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
626 .type
= AVMEDIA_TYPE_VIDEO
,
627 .id
= AV_CODEC_ID_ZMBV
,
628 .priv_data_size
= sizeof(ZmbvContext
),
631 .decode
= decode_frame
,
632 .capabilities
= CODEC_CAP_DR1
,