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
34 #define ZMBV_KEYFRAME 1
35 #define ZMBV_DELTAPAL 2
52 typedef struct ZmbvContext
{
53 AVCodecContext
*avctx
;
57 unsigned int decomp_size
;
68 int (*decode_intra
)(struct ZmbvContext
*c
);
69 int (*decode_xor
)(struct ZmbvContext
*c
);
73 * Decode XOR'ed frame - 8bpp version
76 static int zmbv_decode_xor_8(ZmbvContext
*c
)
78 uint8_t *src
= c
->decomp_buf
;
79 uint8_t *output
, *prev
;
82 int d
, dx
, dy
, bw2
, bh2
;
90 if(c
->flags
& ZMBV_DELTAPAL
){
91 for(i
= 0; i
< 768; i
++)
96 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
99 for(y
= 0; y
< c
->height
; y
+= c
->bh
) {
100 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
101 for(x
= 0; x
< c
->width
; x
+= c
->bw
) {
102 uint8_t *out
, *tprev
;
105 dx
= mvec
[block
] >> 1;
106 dy
= mvec
[block
+ 1] >> 1;
109 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
111 /* copy block - motion vectors out of bounds are used to zero blocks */
113 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
116 for(j
= 0; j
< bh2
; j
++){
117 if((my
+ j
< 0) || (my
+ j
>= c
->height
)) {
120 for(i
= 0; i
< bw2
; i
++){
121 if((mx
+ i
< 0) || (mx
+ i
>= c
->width
))
131 if(d
) { /* apply XOR'ed difference */
133 for(j
= 0; j
< bh2
; j
++){
134 for(i
= 0; i
< bw2
; i
++)
140 output
+= c
->width
* c
->bh
;
141 prev
+= c
->width
* c
->bh
;
143 if(src
- c
->decomp_buf
!= c
->decomp_len
)
144 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %ti of %i bytes\n", src
-c
->decomp_buf
, c
->decomp_len
);
149 * Decode XOR'ed frame - 15bpp and 16bpp version
152 static int zmbv_decode_xor_16(ZmbvContext
*c
)
154 uint8_t *src
= c
->decomp_buf
;
155 uint16_t *output
, *prev
;
158 int d
, dx
, dy
, bw2
, bh2
;
163 output
= (uint16_t*)c
->cur
;
164 prev
= (uint16_t*)c
->prev
;
167 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
170 for(y
= 0; y
< c
->height
; y
+= c
->bh
) {
171 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
172 for(x
= 0; x
< c
->width
; x
+= c
->bw
) {
173 uint16_t *out
, *tprev
;
176 dx
= mvec
[block
] >> 1;
177 dy
= mvec
[block
+ 1] >> 1;
180 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
182 /* copy block - motion vectors out of bounds are used to zero blocks */
184 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
187 for(j
= 0; j
< bh2
; j
++){
188 if((my
+ j
< 0) || (my
+ j
>= c
->height
)) {
189 memset(out
, 0, bw2
* 2);
191 for(i
= 0; i
< bw2
; i
++){
192 if((mx
+ i
< 0) || (mx
+ i
>= c
->width
))
202 if(d
) { /* apply XOR'ed difference */
204 for(j
= 0; j
< bh2
; j
++){
205 for(i
= 0; i
< bw2
; i
++) {
206 out
[i
] ^= *((uint16_t*)src
);
213 output
+= c
->width
* c
->bh
;
214 prev
+= c
->width
* c
->bh
;
216 if(src
- c
->decomp_buf
!= c
->decomp_len
)
217 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %ti of %i bytes\n", src
-c
->decomp_buf
, c
->decomp_len
);
221 #ifdef ZMBV_ENABLE_24BPP
223 * Decode XOR'ed frame - 24bpp version
226 static int zmbv_decode_xor_24(ZmbvContext
*c
)
228 uint8_t *src
= c
->decomp_buf
;
229 uint8_t *output
, *prev
;
232 int d
, dx
, dy
, bw2
, bh2
;
241 stride
= c
->width
* 3;
243 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
246 for(y
= 0; y
< c
->height
; y
+= c
->bh
) {
247 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
248 for(x
= 0; x
< c
->width
; x
+= c
->bw
) {
249 uint8_t *out
, *tprev
;
252 dx
= mvec
[block
] >> 1;
253 dy
= mvec
[block
+ 1] >> 1;
256 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
258 /* copy block - motion vectors out of bounds are used to zero blocks */
259 out
= output
+ x
* 3;
260 tprev
= prev
+ (x
+ dx
) * 3 + dy
* stride
;
263 for(j
= 0; j
< bh2
; j
++){
264 if((my
+ j
< 0) || (my
+ j
>= c
->height
)) {
265 memset(out
, 0, bw2
* 3);
267 for(i
= 0; i
< bw2
; i
++){
268 if((mx
+ i
< 0) || (mx
+ i
>= c
->width
)) {
273 out
[i
* 3 + 0] = tprev
[i
* 3 + 0];
274 out
[i
* 3 + 1] = tprev
[i
* 3 + 1];
275 out
[i
* 3 + 2] = tprev
[i
* 3 + 2];
283 if(d
) { /* apply XOR'ed difference */
284 out
= output
+ x
* 3;
285 for(j
= 0; j
< bh2
; j
++){
286 for(i
= 0; i
< bw2
; i
++) {
287 out
[i
* 3 + 0] ^= *src
++;
288 out
[i
* 3 + 1] ^= *src
++;
289 out
[i
* 3 + 2] ^= *src
++;
295 output
+= stride
* c
->bh
;
296 prev
+= stride
* c
->bh
;
298 if(src
- c
->decomp_buf
!= c
->decomp_len
)
299 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %i of %i bytes\n", src
-c
->decomp_buf
, c
->decomp_len
);
302 #endif //ZMBV_ENABLE_24BPP
305 * Decode XOR'ed frame - 32bpp version
308 static int zmbv_decode_xor_32(ZmbvContext
*c
)
310 uint8_t *src
= c
->decomp_buf
;
311 uint32_t *output
, *prev
;
314 int d
, dx
, dy
, bw2
, bh2
;
319 output
= (uint32_t*)c
->cur
;
320 prev
= (uint32_t*)c
->prev
;
323 src
+= ((c
->bx
* c
->by
* 2 + 3) & ~3);
326 for(y
= 0; y
< c
->height
; y
+= c
->bh
) {
327 bh2
= ((c
->height
- y
) > c
->bh
) ? c
->bh
: (c
->height
- y
);
328 for(x
= 0; x
< c
->width
; x
+= c
->bw
) {
329 uint32_t *out
, *tprev
;
332 dx
= mvec
[block
] >> 1;
333 dy
= mvec
[block
+ 1] >> 1;
336 bw2
= ((c
->width
- x
) > c
->bw
) ? c
->bw
: (c
->width
- x
);
338 /* copy block - motion vectors out of bounds are used to zero blocks */
340 tprev
= prev
+ x
+ dx
+ dy
* c
->width
;
343 for(j
= 0; j
< bh2
; j
++){
344 if((my
+ j
< 0) || (my
+ j
>= c
->height
)) {
345 memset(out
, 0, bw2
* 4);
347 for(i
= 0; i
< bw2
; i
++){
348 if((mx
+ i
< 0) || (mx
+ i
>= c
->width
))
358 if(d
) { /* apply XOR'ed difference */
360 for(j
= 0; j
< bh2
; j
++){
361 for(i
= 0; i
< bw2
; i
++) {
362 out
[i
] ^= *((uint32_t*)src
);
369 output
+= c
->width
* c
->bh
;
370 prev
+= c
->width
* c
->bh
;
372 if(src
- c
->decomp_buf
!= c
->decomp_len
)
373 av_log(c
->avctx
, AV_LOG_ERROR
, "Used %ti of %i bytes\n", src
-c
->decomp_buf
, c
->decomp_len
);
380 static int zmbv_decode_intra(ZmbvContext
*c
)
382 uint8_t *src
= c
->decomp_buf
;
384 /* make the palette available on the way out */
385 if (c
->fmt
== ZMBV_FMT_8BPP
) {
386 memcpy(c
->pal
, src
, 768);
390 memcpy(c
->cur
, src
, c
->width
* c
->height
* (c
->bpp
/ 8));
394 static int decode_frame(AVCodecContext
*avctx
, void *data
, int *data_size
, const uint8_t *buf
, int buf_size
)
396 ZmbvContext
* const c
= avctx
->priv_data
;
398 int zret
= Z_OK
; // Zlib return code
403 avctx
->release_buffer(avctx
, &c
->pic
);
405 c
->pic
.reference
= 1;
406 c
->pic
.buffer_hints
= FF_BUFFER_HINTS_VALID
;
407 if(avctx
->get_buffer(avctx
, &c
->pic
) < 0){
408 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
412 outptr
= c
->pic
.data
[0]; // Output image pointer
417 if(c
->flags
& ZMBV_KEYFRAME
) {
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
);
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
);
435 if(c
->comp
!= 0 && c
->comp
!= 1) {
436 av_log(avctx
, AV_LOG_ERROR
, "Unsupported compression type %i\n", c
->comp
);
443 c
->decode_intra
= zmbv_decode_intra
;
444 c
->decode_xor
= zmbv_decode_xor_8
;
449 c
->decode_intra
= zmbv_decode_intra
;
450 c
->decode_xor
= zmbv_decode_xor_16
;
452 #ifdef ZMBV_ENABLE_24BPP
455 c
->decode_intra
= zmbv_decode_intra
;
456 c
->decode_xor
= zmbv_decode_xor_24
;
458 #endif //ZMBV_ENABLE_24BPP
461 c
->decode_intra
= zmbv_decode_intra
;
462 c
->decode_xor
= zmbv_decode_xor_32
;
465 c
->decode_intra
= NULL
;
466 c
->decode_xor
= NULL
;
467 av_log(avctx
, AV_LOG_ERROR
, "Unsupported (for now) format %i\n", c
->fmt
);
471 zret
= inflateReset(&c
->zstream
);
473 av_log(avctx
, AV_LOG_ERROR
, "Inflate reset error: %d\n", zret
);
477 c
->cur
= av_realloc(c
->cur
, avctx
->width
* avctx
->height
* (c
->bpp
/ 8));
478 c
->prev
= av_realloc(c
->prev
, avctx
->width
* avctx
->height
* (c
->bpp
/ 8));
479 c
->bx
= (c
->width
+ c
->bw
- 1) / c
->bw
;
480 c
->by
= (c
->height
+ c
->bh
- 1) / c
->bh
;
483 if(c
->decode_intra
== NULL
) {
484 av_log(avctx
, AV_LOG_ERROR
, "Error! Got no format or no keyframe!\n");
488 if(c
->comp
== 0) { //Uncompressed data
489 memcpy(c
->decomp_buf
, buf
, len
);
491 } else { // ZLIB-compressed data
492 c
->zstream
.total_in
= c
->zstream
.total_out
= 0;
493 c
->zstream
.next_in
= buf
;
494 c
->zstream
.avail_in
= len
;
495 c
->zstream
.next_out
= c
->decomp_buf
;
496 c
->zstream
.avail_out
= c
->decomp_size
;
497 inflate(&c
->zstream
, Z_FINISH
);
498 c
->decomp_len
= c
->zstream
.total_out
;
500 if(c
->flags
& ZMBV_KEYFRAME
) {
501 c
->pic
.key_frame
= 1;
502 c
->pic
.pict_type
= FF_I_TYPE
;
505 c
->pic
.key_frame
= 0;
506 c
->pic
.pict_type
= FF_P_TYPE
;
516 out
= c
->pic
.data
[0];
520 for(j
= 0; j
< c
->height
; j
++) {
521 for(i
= 0; i
< c
->width
; i
++) {
522 out
[i
* 3 + 0] = c
->pal
[(*src
) * 3 + 0];
523 out
[i
* 3 + 1] = c
->pal
[(*src
) * 3 + 1];
524 out
[i
* 3 + 2] = c
->pal
[(*src
) * 3 + 2];
527 out
+= c
->pic
.linesize
[0];
531 for(j
= 0; j
< c
->height
; j
++) {
532 for(i
= 0; i
< c
->width
; i
++) {
533 uint16_t tmp
= AV_RL16(src
);
535 out
[i
* 3 + 0] = (tmp
& 0x7C00) >> 7;
536 out
[i
* 3 + 1] = (tmp
& 0x03E0) >> 2;
537 out
[i
* 3 + 2] = (tmp
& 0x001F) << 3;
539 out
+= c
->pic
.linesize
[0];
543 for(j
= 0; j
< c
->height
; j
++) {
544 for(i
= 0; i
< c
->width
; i
++) {
545 uint16_t tmp
= AV_RL16(src
);
547 out
[i
* 3 + 0] = (tmp
& 0xF800) >> 8;
548 out
[i
* 3 + 1] = (tmp
& 0x07E0) >> 3;
549 out
[i
* 3 + 2] = (tmp
& 0x001F) << 3;
551 out
+= c
->pic
.linesize
[0];
554 #ifdef ZMBV_ENABLE_24BPP
556 for(j
= 0; j
< c
->height
; j
++) {
557 memcpy(out
, src
, c
->width
* 3);
559 out
+= c
->pic
.linesize
[0];
562 #endif //ZMBV_ENABLE_24BPP
564 for(j
= 0; j
< c
->height
; j
++) {
565 for(i
= 0; i
< c
->width
; i
++) {
566 uint32_t tmp
= AV_RL32(src
);
568 AV_WB24(out
+(i
*3), tmp
);
570 out
+= c
->pic
.linesize
[0];
574 av_log(avctx
, AV_LOG_ERROR
, "Cannot handle format %i\n", c
->fmt
);
576 memcpy(c
->prev
, c
->cur
, c
->width
* c
->height
* (c
->bpp
/ 8));
578 *data_size
= sizeof(AVFrame
);
579 *(AVFrame
*)data
= c
->pic
;
581 /* always report that the buffer was completely consumed */
592 static av_cold
int decode_init(AVCodecContext
*avctx
)
594 ZmbvContext
* const c
= avctx
->priv_data
;
595 int zret
; // Zlib return code
599 c
->pic
.data
[0] = NULL
;
600 c
->width
= avctx
->width
;
601 c
->height
= avctx
->height
;
603 if (avcodec_check_dimensions(avctx
, avctx
->width
, avctx
->height
) < 0) {
606 c
->bpp
= avctx
->bits_per_sample
;
608 // Needed if zlib unused or init aborted before inflateInit
609 memset(&(c
->zstream
), 0, sizeof(z_stream
));
611 avctx
->pix_fmt
= PIX_FMT_RGB24
;
612 c
->decomp_size
= (avctx
->width
+ 255) * 4 * (avctx
->height
+ 64);
614 /* Allocate decompression buffer */
615 if (c
->decomp_size
) {
616 if ((c
->decomp_buf
= av_malloc(c
->decomp_size
)) == NULL
) {
617 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate decompression buffer.\n");
622 c
->zstream
.zalloc
= Z_NULL
;
623 c
->zstream
.zfree
= Z_NULL
;
624 c
->zstream
.opaque
= Z_NULL
;
625 zret
= inflateInit(&(c
->zstream
));
627 av_log(avctx
, AV_LOG_ERROR
, "Inflate init error: %d\n", zret
);
638 * Uninit zmbv decoder
641 static av_cold
int decode_end(AVCodecContext
*avctx
)
643 ZmbvContext
* const c
= avctx
->priv_data
;
645 av_freep(&c
->decomp_buf
);
648 avctx
->release_buffer(avctx
, &c
->pic
);
649 inflateEnd(&(c
->zstream
));
656 AVCodec zmbv_decoder
= {
665 .long_name
= "Zip Motion Blocks Video",