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
, const uint8_t *buf
, int buf_size
)
397 ZmbvContext
* const c
= avctx
->priv_data
;
399 int zret
= Z_OK
; // Zlib return code
404 avctx
->release_buffer(avctx
, &c
->pic
);
406 c
->pic
.reference
= 1;
407 c
->pic
.buffer_hints
= FF_BUFFER_HINTS_VALID
;
408 if(avctx
->get_buffer(avctx
, &c
->pic
) < 0){
409 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
413 outptr
= c
->pic
.data
[0]; // Output image pointer
418 if(c
->flags
& ZMBV_KEYFRAME
) {
428 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
);
429 if(hi_ver
!= 0 || lo_ver
!= 1) {
430 av_log(avctx
, AV_LOG_ERROR
, "Unsupported version %i.%i\n", hi_ver
, lo_ver
);
433 if(c
->bw
== 0 || c
->bh
== 0) {
434 av_log(avctx
, AV_LOG_ERROR
, "Unsupported block size %ix%i\n", c
->bw
, c
->bh
);
436 if(c
->comp
!= 0 && c
->comp
!= 1) {
437 av_log(avctx
, AV_LOG_ERROR
, "Unsupported compression type %i\n", c
->comp
);
444 c
->decode_intra
= zmbv_decode_intra
;
445 c
->decode_xor
= zmbv_decode_xor_8
;
450 c
->decode_intra
= zmbv_decode_intra
;
451 c
->decode_xor
= zmbv_decode_xor_16
;
453 #ifdef ZMBV_ENABLE_24BPP
456 c
->decode_intra
= zmbv_decode_intra
;
457 c
->decode_xor
= zmbv_decode_xor_24
;
459 #endif //ZMBV_ENABLE_24BPP
462 c
->decode_intra
= zmbv_decode_intra
;
463 c
->decode_xor
= zmbv_decode_xor_32
;
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
);
472 zret
= inflateReset(&c
->zstream
);
474 av_log(avctx
, AV_LOG_ERROR
, "Inflate reset error: %d\n", zret
);
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
;
484 if(c
->decode_intra
== NULL
) {
485 av_log(avctx
, AV_LOG_ERROR
, "Error! Got no format or no keyframe!\n");
489 if(c
->comp
== 0) { //Uncompressed data
490 memcpy(c
->decomp_buf
, buf
, len
);
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
;
501 if(c
->flags
& ZMBV_KEYFRAME
) {
502 c
->pic
.key_frame
= 1;
503 c
->pic
.pict_type
= FF_I_TYPE
;
506 c
->pic
.key_frame
= 0;
507 c
->pic
.pict_type
= FF_P_TYPE
;
517 out
= c
->pic
.data
[0];
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];
528 out
+= c
->pic
.linesize
[0];
532 for(j
= 0; j
< c
->height
; j
++) {
533 for(i
= 0; i
< c
->width
; i
++) {
534 uint16_t tmp
= AV_RL16(src
);
536 out
[i
* 3 + 0] = (tmp
& 0x7C00) >> 7;
537 out
[i
* 3 + 1] = (tmp
& 0x03E0) >> 2;
538 out
[i
* 3 + 2] = (tmp
& 0x001F) << 3;
540 out
+= c
->pic
.linesize
[0];
544 for(j
= 0; j
< c
->height
; j
++) {
545 for(i
= 0; i
< c
->width
; i
++) {
546 uint16_t tmp
= AV_RL16(src
);
548 out
[i
* 3 + 0] = (tmp
& 0xF800) >> 8;
549 out
[i
* 3 + 1] = (tmp
& 0x07E0) >> 3;
550 out
[i
* 3 + 2] = (tmp
& 0x001F) << 3;
552 out
+= c
->pic
.linesize
[0];
555 #ifdef ZMBV_ENABLE_24BPP
557 for(j
= 0; j
< c
->height
; j
++) {
558 memcpy(out
, src
, c
->width
* 3);
560 out
+= c
->pic
.linesize
[0];
563 #endif //ZMBV_ENABLE_24BPP
565 for(j
= 0; j
< c
->height
; j
++) {
566 for(i
= 0; i
< c
->width
; i
++) {
567 uint32_t tmp
= AV_RL32(src
);
569 AV_WB24(out
+(i
*3), tmp
);
571 out
+= c
->pic
.linesize
[0];
575 av_log(avctx
, AV_LOG_ERROR
, "Cannot handle format %i\n", c
->fmt
);
577 memcpy(c
->prev
, c
->cur
, c
->width
* c
->height
* (c
->bpp
/ 8));
579 *data_size
= sizeof(AVFrame
);
580 *(AVFrame
*)data
= c
->pic
;
582 /* always report that the buffer was completely consumed */
593 static av_cold
int decode_init(AVCodecContext
*avctx
)
595 ZmbvContext
* const c
= avctx
->priv_data
;
596 int zret
; // Zlib return code
600 c
->pic
.data
[0] = NULL
;
601 c
->width
= avctx
->width
;
602 c
->height
= avctx
->height
;
604 if (avcodec_check_dimensions(avctx
, avctx
->width
, avctx
->height
) < 0) {
607 c
->bpp
= avctx
->bits_per_coded_sample
;
609 // Needed if zlib unused or init aborted before inflateInit
610 memset(&(c
->zstream
), 0, sizeof(z_stream
));
612 avctx
->pix_fmt
= PIX_FMT_RGB24
;
613 c
->decomp_size
= (avctx
->width
+ 255) * 4 * (avctx
->height
+ 64);
615 /* Allocate decompression buffer */
616 if (c
->decomp_size
) {
617 if ((c
->decomp_buf
= av_malloc(c
->decomp_size
)) == NULL
) {
618 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate decompression buffer.\n");
623 c
->zstream
.zalloc
= Z_NULL
;
624 c
->zstream
.zfree
= Z_NULL
;
625 c
->zstream
.opaque
= Z_NULL
;
626 zret
= inflateInit(&(c
->zstream
));
628 av_log(avctx
, AV_LOG_ERROR
, "Inflate init error: %d\n", zret
);
639 * Uninit zmbv decoder
642 static av_cold
int decode_end(AVCodecContext
*avctx
)
644 ZmbvContext
* const c
= avctx
->priv_data
;
646 av_freep(&c
->decomp_buf
);
649 avctx
->release_buffer(avctx
, &c
->pic
);
650 inflateEnd(&(c
->zstream
));
657 AVCodec zmbv_decoder
= {
666 .long_name
= NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),