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
23 * @file libavcodec/zmbv.c
24 * Zip Motion Blocks Video decoder
30 #include "libavutil/intreadwrite.h"
35 #define ZMBV_KEYFRAME 1
36 #define ZMBV_DELTAPAL 2
53 typedef struct ZmbvContext
{
54 AVCodecContext
*avctx
;
58 unsigned int decomp_size
;
69 int (*decode_intra
)(struct ZmbvContext
*c
);
70 int (*decode_xor
)(struct ZmbvContext
*c
);
74 * Decode XOR'ed frame - 8bpp version
77 static int zmbv_decode_xor_8(ZmbvContext
*c
)
79 uint8_t *src
= c
->decomp_buf
;
80 uint8_t *output
, *prev
;
83 int d
, dx
, dy
, bw2
, bh2
;
91 if(c
->flags
& ZMBV_DELTAPAL
){
92 for(i
= 0; i
< 768; i
++)
97 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
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
;
106 dx
= mvec
[block
] >> 1;
107 dy
= mvec
[block
+ 1] >> 1;
110 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
112 /* copy block - motion vectors out of bounds are used to zero blocks */
114 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
117 for(j
= 0; j
< bh2
; j
++){
118 if((my
+ j
< 0) || (my
+ j
>= c
->height
)) {
121 for(i
= 0; i
< bw2
; i
++){
122 if((mx
+ i
< 0) || (mx
+ i
>= c
->width
))
132 if(d
) { /* apply XOR'ed difference */
134 for(j
= 0; j
< bh2
; j
++){
135 for(i
= 0; i
< bw2
; i
++)
141 output
+= c
->width
* c
->bh
;
142 prev
+= c
->width
* c
->bh
;
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
);
150 * Decode XOR'ed frame - 15bpp and 16bpp version
153 static int zmbv_decode_xor_16(ZmbvContext
*c
)
155 uint8_t *src
= c
->decomp_buf
;
156 uint16_t *output
, *prev
;
159 int d
, dx
, dy
, bw2
, bh2
;
164 output
= (uint16_t*)c
->cur
;
165 prev
= (uint16_t*)c
->prev
;
168 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
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
;
177 dx
= mvec
[block
] >> 1;
178 dy
= mvec
[block
+ 1] >> 1;
181 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
183 /* copy block - motion vectors out of bounds are used to zero blocks */
185 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
188 for(j
= 0; j
< bh2
; j
++){
189 if((my
+ j
< 0) || (my
+ j
>= c
->height
)) {
190 memset(out
, 0, bw2
* 2);
192 for(i
= 0; i
< bw2
; i
++){
193 if((mx
+ i
< 0) || (mx
+ i
>= c
->width
))
203 if(d
) { /* apply XOR'ed difference */
205 for(j
= 0; j
< bh2
; j
++){
206 for(i
= 0; i
< bw2
; i
++) {
207 out
[i
] ^= *((uint16_t*)src
);
214 output
+= c
->width
* c
->bh
;
215 prev
+= c
->width
* c
->bh
;
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
);
222 #ifdef ZMBV_ENABLE_24BPP
224 * Decode XOR'ed frame - 24bpp version
227 static int zmbv_decode_xor_24(ZmbvContext
*c
)
229 uint8_t *src
= c
->decomp_buf
;
230 uint8_t *output
, *prev
;
233 int d
, dx
, dy
, bw2
, bh2
;
242 stride
= c
->width
* 3;
244 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
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
;
253 dx
= mvec
[block
] >> 1;
254 dy
= mvec
[block
+ 1] >> 1;
257 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
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
;
264 for(j
= 0; j
< bh2
; j
++){
265 if((my
+ j
< 0) || (my
+ j
>= c
->height
)) {
266 memset(out
, 0, bw2
* 3);
268 for(i
= 0; i
< bw2
; i
++){
269 if((mx
+ i
< 0) || (mx
+ i
>= c
->width
)) {
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];
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
++;
296 output
+= stride
* c
->bh
;
297 prev
+= stride
* c
->bh
;
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
);
303 #endif //ZMBV_ENABLE_24BPP
306 * Decode XOR'ed frame - 32bpp version
309 static int zmbv_decode_xor_32(ZmbvContext
*c
)
311 uint8_t *src
= c
->decomp_buf
;
312 uint32_t *output
, *prev
;
315 int d
, dx
, dy
, bw2
, bh2
;
320 output
= (uint32_t*)c
->cur
;
321 prev
= (uint32_t*)c
->prev
;
324 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
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
;
333 dx
= mvec
[block
] >> 1;
334 dy
= mvec
[block
+ 1] >> 1;
337 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
339 /* copy block - motion vectors out of bounds are used to zero blocks */
341 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
344 for(j
= 0; j
< bh2
; j
++){
345 if((my
+ j
< 0) || (my
+ j
>= c
->height
)) {
346 memset(out
, 0, bw2
* 4);
348 for(i
= 0; i
< bw2
; i
++){
349 if((mx
+ i
< 0) || (mx
+ i
>= c
->width
))
359 if(d
) { /* apply XOR'ed difference */
361 for(j
= 0; j
< bh2
; j
++){
362 for(i
= 0; i
< bw2
; i
++) {
363 out
[i
] ^= *((uint32_t*)src
);
370 output
+= c
->width
* c
->bh
;
371 prev
+= c
->width
* c
->bh
;
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
);
381 static int zmbv_decode_intra(ZmbvContext
*c
)
383 uint8_t *src
= c
->decomp_buf
;
385 /* make the palette available on the way out */
386 if (c
->fmt
== ZMBV_FMT_8BPP
) {
387 memcpy(c
->pal
, src
, 768);
391 memcpy(c
->cur
, src
, c
->width
* c
->height
* (c
->bpp
/ 8));
395 static int decode_frame(AVCodecContext
*avctx
, void *data
, int *data_size
, AVPacket
*avpkt
)
397 const uint8_t *buf
= avpkt
->data
;
398 int buf_size
= avpkt
->size
;
399 ZmbvContext
* const c
= avctx
->priv_data
;
401 int zret
= Z_OK
; // Zlib return code
406 avctx
->release_buffer(avctx
, &c
->pic
);
408 c
->pic
.reference
= 1;
409 c
->pic
.buffer_hints
= FF_BUFFER_HINTS_VALID
;
410 if(avctx
->get_buffer(avctx
, &c
->pic
) < 0){
411 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
415 outptr
= c
->pic
.data
[0]; // Output image pointer
420 if(c
->flags
& ZMBV_KEYFRAME
) {
430 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
);
431 if(hi_ver
!= 0 || lo_ver
!= 1) {
432 av_log(avctx
, AV_LOG_ERROR
, "Unsupported version %i.%i\n", hi_ver
, lo_ver
);
435 if(c
->bw
== 0 || c
->bh
== 0) {
436 av_log(avctx
, AV_LOG_ERROR
, "Unsupported block size %ix%i\n", c
->bw
, c
->bh
);
438 if(c
->comp
!= 0 && c
->comp
!= 1) {
439 av_log(avctx
, AV_LOG_ERROR
, "Unsupported compression type %i\n", c
->comp
);
446 c
->decode_intra
= zmbv_decode_intra
;
447 c
->decode_xor
= zmbv_decode_xor_8
;
452 c
->decode_intra
= zmbv_decode_intra
;
453 c
->decode_xor
= zmbv_decode_xor_16
;
455 #ifdef ZMBV_ENABLE_24BPP
458 c
->decode_intra
= zmbv_decode_intra
;
459 c
->decode_xor
= zmbv_decode_xor_24
;
461 #endif //ZMBV_ENABLE_24BPP
464 c
->decode_intra
= zmbv_decode_intra
;
465 c
->decode_xor
= zmbv_decode_xor_32
;
468 c
->decode_intra
= NULL
;
469 c
->decode_xor
= NULL
;
470 av_log(avctx
, AV_LOG_ERROR
, "Unsupported (for now) format %i\n", c
->fmt
);
474 zret
= inflateReset(&c
->zstream
);
476 av_log(avctx
, AV_LOG_ERROR
, "Inflate reset error: %d\n", zret
);
480 c
->cur
= av_realloc(c
->cur
, avctx
->width
* avctx
->height
* (c
->bpp
/ 8));
481 c
->prev
= av_realloc(c
->prev
, avctx
->width
* avctx
->height
* (c
->bpp
/ 8));
482 c
->bx
= (c
->width
+ c
->bw
- 1) / c
->bw
;
483 c
->by
= (c
->height
+ c
->bh
- 1) / c
->bh
;
486 if(c
->decode_intra
== NULL
) {
487 av_log(avctx
, AV_LOG_ERROR
, "Error! Got no format or no keyframe!\n");
491 if(c
->comp
== 0) { //Uncompressed data
492 memcpy(c
->decomp_buf
, buf
, len
);
494 } else { // ZLIB-compressed data
495 c
->zstream
.total_in
= c
->zstream
.total_out
= 0;
496 c
->zstream
.next_in
= buf
;
497 c
->zstream
.avail_in
= len
;
498 c
->zstream
.next_out
= c
->decomp_buf
;
499 c
->zstream
.avail_out
= c
->decomp_size
;
500 inflate(&c
->zstream
, Z_FINISH
);
501 c
->decomp_len
= c
->zstream
.total_out
;
503 if(c
->flags
& ZMBV_KEYFRAME
) {
504 c
->pic
.key_frame
= 1;
505 c
->pic
.pict_type
= FF_I_TYPE
;
508 c
->pic
.key_frame
= 0;
509 c
->pic
.pict_type
= FF_P_TYPE
;
519 out
= c
->pic
.data
[0];
523 for(j
= 0; j
< c
->height
; j
++) {
524 for(i
= 0; i
< c
->width
; i
++) {
525 out
[i
* 3 + 0] = c
->pal
[(*src
) * 3 + 0];
526 out
[i
* 3 + 1] = c
->pal
[(*src
) * 3 + 1];
527 out
[i
* 3 + 2] = c
->pal
[(*src
) * 3 + 2];
530 out
+= c
->pic
.linesize
[0];
534 for(j
= 0; j
< c
->height
; j
++) {
535 for(i
= 0; i
< c
->width
; i
++) {
536 uint16_t tmp
= AV_RL16(src
);
538 out
[i
* 3 + 0] = (tmp
& 0x7C00) >> 7;
539 out
[i
* 3 + 1] = (tmp
& 0x03E0) >> 2;
540 out
[i
* 3 + 2] = (tmp
& 0x001F) << 3;
542 out
+= c
->pic
.linesize
[0];
546 for(j
= 0; j
< c
->height
; j
++) {
547 for(i
= 0; i
< c
->width
; i
++) {
548 uint16_t tmp
= AV_RL16(src
);
550 out
[i
* 3 + 0] = (tmp
& 0xF800) >> 8;
551 out
[i
* 3 + 1] = (tmp
& 0x07E0) >> 3;
552 out
[i
* 3 + 2] = (tmp
& 0x001F) << 3;
554 out
+= c
->pic
.linesize
[0];
557 #ifdef ZMBV_ENABLE_24BPP
559 for(j
= 0; j
< c
->height
; j
++) {
560 memcpy(out
, src
, c
->width
* 3);
562 out
+= c
->pic
.linesize
[0];
565 #endif //ZMBV_ENABLE_24BPP
567 for(j
= 0; j
< c
->height
; j
++) {
568 for(i
= 0; i
< c
->width
; i
++) {
569 uint32_t tmp
= AV_RL32(src
);
571 AV_WB24(out
+(i
*3), tmp
);
573 out
+= c
->pic
.linesize
[0];
577 av_log(avctx
, AV_LOG_ERROR
, "Cannot handle format %i\n", c
->fmt
);
579 memcpy(c
->prev
, c
->cur
, c
->width
* c
->height
* (c
->bpp
/ 8));
581 *data_size
= sizeof(AVFrame
);
582 *(AVFrame
*)data
= c
->pic
;
584 /* always report that the buffer was completely consumed */
595 static av_cold
int decode_init(AVCodecContext
*avctx
)
597 ZmbvContext
* const c
= avctx
->priv_data
;
598 int zret
; // Zlib return code
602 c
->width
= avctx
->width
;
603 c
->height
= avctx
->height
;
605 if (avcodec_check_dimensions(avctx
, avctx
->width
, avctx
->height
) < 0) {
608 c
->bpp
= avctx
->bits_per_coded_sample
;
610 // Needed if zlib unused or init aborted before inflateInit
611 memset(&(c
->zstream
), 0, sizeof(z_stream
));
613 avctx
->pix_fmt
= PIX_FMT_RGB24
;
614 c
->decomp_size
= (avctx
->width
+ 255) * 4 * (avctx
->height
+ 64);
616 /* Allocate decompression buffer */
617 if (c
->decomp_size
) {
618 if ((c
->decomp_buf
= av_malloc(c
->decomp_size
)) == NULL
) {
619 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate decompression buffer.\n");
624 c
->zstream
.zalloc
= Z_NULL
;
625 c
->zstream
.zfree
= Z_NULL
;
626 c
->zstream
.opaque
= Z_NULL
;
627 zret
= inflateInit(&(c
->zstream
));
629 av_log(avctx
, AV_LOG_ERROR
, "Inflate init error: %d\n", zret
);
640 * Uninit zmbv decoder
643 static av_cold
int decode_end(AVCodecContext
*avctx
)
645 ZmbvContext
* const c
= avctx
->priv_data
;
647 av_freep(&c
->decomp_buf
);
650 avctx
->release_buffer(avctx
, &c
->pic
);
651 inflateEnd(&(c
->zstream
));
658 AVCodec zmbv_decoder
= {
668 .long_name
= NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),