Libav
|
00001 /* 00002 * Zip Motion Blocks Video (ZMBV) decoder 00003 * Copyright (c) 2006 Konstantin Shishkov 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 00030 #include "libavutil/intreadwrite.h" 00031 #include "avcodec.h" 00032 00033 #include <zlib.h> 00034 00035 #define ZMBV_KEYFRAME 1 00036 #define ZMBV_DELTAPAL 2 00037 00038 enum ZmbvFormat { 00039 ZMBV_FMT_NONE = 0, 00040 ZMBV_FMT_1BPP = 1, 00041 ZMBV_FMT_2BPP = 2, 00042 ZMBV_FMT_4BPP = 3, 00043 ZMBV_FMT_8BPP = 4, 00044 ZMBV_FMT_15BPP = 5, 00045 ZMBV_FMT_16BPP = 6, 00046 ZMBV_FMT_24BPP = 7, 00047 ZMBV_FMT_32BPP = 8 00048 }; 00049 00050 /* 00051 * Decoder context 00052 */ 00053 typedef struct ZmbvContext { 00054 AVCodecContext *avctx; 00055 AVFrame pic; 00056 00057 int bpp; 00058 unsigned int decomp_size; 00059 uint8_t* decomp_buf; 00060 uint8_t pal[768]; 00061 uint8_t *prev, *cur; 00062 int width, height; 00063 int fmt; 00064 int comp; 00065 int flags; 00066 int bw, bh, bx, by; 00067 int decomp_len; 00068 z_stream zstream; 00069 int (*decode_intra)(struct ZmbvContext *c); 00070 int (*decode_xor)(struct ZmbvContext *c); 00071 } ZmbvContext; 00072 00077 static int zmbv_decode_xor_8(ZmbvContext *c) 00078 { 00079 uint8_t *src = c->decomp_buf; 00080 uint8_t *output, *prev; 00081 int8_t *mvec; 00082 int x, y; 00083 int d, dx, dy, bw2, bh2; 00084 int block; 00085 int i, j; 00086 int mx, my; 00087 00088 output = c->cur; 00089 prev = c->prev; 00090 00091 if(c->flags & ZMBV_DELTAPAL){ 00092 for(i = 0; i < 768; i++) 00093 c->pal[i] ^= *src++; 00094 } 00095 00096 mvec = (int8_t*)src; 00097 src += ((c->bx * c->by * 2 + 3) & ~3); 00098 00099 block = 0; 00100 for(y = 0; y < c->height; y += c->bh) { 00101 bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); 00102 for(x = 0; x < c->width; x += c->bw) { 00103 uint8_t *out, *tprev; 00104 00105 d = mvec[block] & 1; 00106 dx = mvec[block] >> 1; 00107 dy = mvec[block + 1] >> 1; 00108 block += 2; 00109 00110 bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); 00111 00112 /* copy block - motion vectors out of bounds are used to zero blocks */ 00113 out = output + x; 00114 tprev = prev + x + dx + dy * c->width; 00115 mx = x + dx; 00116 my = y + dy; 00117 for(j = 0; j < bh2; j++){ 00118 if((my + j < 0) || (my + j >= c->height)) { 00119 memset(out, 0, bw2); 00120 } else { 00121 for(i = 0; i < bw2; i++){ 00122 if((mx + i < 0) || (mx + i >= c->width)) 00123 out[i] = 0; 00124 else 00125 out[i] = tprev[i]; 00126 } 00127 } 00128 out += c->width; 00129 tprev += c->width; 00130 } 00131 00132 if(d) { /* apply XOR'ed difference */ 00133 out = output + x; 00134 for(j = 0; j < bh2; j++){ 00135 for(i = 0; i < bw2; i++) 00136 out[i] ^= *src++; 00137 out += c->width; 00138 } 00139 } 00140 } 00141 output += c->width * c->bh; 00142 prev += c->width * c->bh; 00143 } 00144 if(src - c->decomp_buf != c->decomp_len) 00145 av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n", src-c->decomp_buf, c->decomp_len); 00146 return 0; 00147 } 00148 00153 static int zmbv_decode_xor_16(ZmbvContext *c) 00154 { 00155 uint8_t *src = c->decomp_buf; 00156 uint16_t *output, *prev; 00157 int8_t *mvec; 00158 int x, y; 00159 int d, dx, dy, bw2, bh2; 00160 int block; 00161 int i, j; 00162 int mx, my; 00163 00164 output = (uint16_t*)c->cur; 00165 prev = (uint16_t*)c->prev; 00166 00167 mvec = (int8_t*)src; 00168 src += ((c->bx * c->by * 2 + 3) & ~3); 00169 00170 block = 0; 00171 for(y = 0; y < c->height; y += c->bh) { 00172 bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); 00173 for(x = 0; x < c->width; x += c->bw) { 00174 uint16_t *out, *tprev; 00175 00176 d = mvec[block] & 1; 00177 dx = mvec[block] >> 1; 00178 dy = mvec[block + 1] >> 1; 00179 block += 2; 00180 00181 bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); 00182 00183 /* copy block - motion vectors out of bounds are used to zero blocks */ 00184 out = output + x; 00185 tprev = prev + x + dx + dy * c->width; 00186 mx = x + dx; 00187 my = y + dy; 00188 for(j = 0; j < bh2; j++){ 00189 if((my + j < 0) || (my + j >= c->height)) { 00190 memset(out, 0, bw2 * 2); 00191 } else { 00192 for(i = 0; i < bw2; i++){ 00193 if((mx + i < 0) || (mx + i >= c->width)) 00194 out[i] = 0; 00195 else 00196 out[i] = tprev[i]; 00197 } 00198 } 00199 out += c->width; 00200 tprev += c->width; 00201 } 00202 00203 if(d) { /* apply XOR'ed difference */ 00204 out = output + x; 00205 for(j = 0; j < bh2; j++){ 00206 for(i = 0; i < bw2; i++) { 00207 out[i] ^= *((uint16_t*)src); 00208 src += 2; 00209 } 00210 out += c->width; 00211 } 00212 } 00213 } 00214 output += c->width * c->bh; 00215 prev += c->width * c->bh; 00216 } 00217 if(src - c->decomp_buf != c->decomp_len) 00218 av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n", src-c->decomp_buf, c->decomp_len); 00219 return 0; 00220 } 00221 00222 #ifdef ZMBV_ENABLE_24BPP 00223 00227 static int zmbv_decode_xor_24(ZmbvContext *c) 00228 { 00229 uint8_t *src = c->decomp_buf; 00230 uint8_t *output, *prev; 00231 int8_t *mvec; 00232 int x, y; 00233 int d, dx, dy, bw2, bh2; 00234 int block; 00235 int i, j; 00236 int mx, my; 00237 int stride; 00238 00239 output = c->cur; 00240 prev = c->prev; 00241 00242 stride = c->width * 3; 00243 mvec = (int8_t*)src; 00244 src += ((c->bx * c->by * 2 + 3) & ~3); 00245 00246 block = 0; 00247 for(y = 0; y < c->height; y += c->bh) { 00248 bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); 00249 for(x = 0; x < c->width; x += c->bw) { 00250 uint8_t *out, *tprev; 00251 00252 d = mvec[block] & 1; 00253 dx = mvec[block] >> 1; 00254 dy = mvec[block + 1] >> 1; 00255 block += 2; 00256 00257 bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); 00258 00259 /* copy block - motion vectors out of bounds are used to zero blocks */ 00260 out = output + x * 3; 00261 tprev = prev + (x + dx) * 3 + dy * stride; 00262 mx = x + dx; 00263 my = y + dy; 00264 for(j = 0; j < bh2; j++){ 00265 if((my + j < 0) || (my + j >= c->height)) { 00266 memset(out, 0, bw2 * 3); 00267 } else { 00268 for(i = 0; i < bw2; i++){ 00269 if((mx + i < 0) || (mx + i >= c->width)) { 00270 out[i * 3 + 0] = 0; 00271 out[i * 3 + 1] = 0; 00272 out[i * 3 + 2] = 0; 00273 } else { 00274 out[i * 3 + 0] = tprev[i * 3 + 0]; 00275 out[i * 3 + 1] = tprev[i * 3 + 1]; 00276 out[i * 3 + 2] = tprev[i * 3 + 2]; 00277 } 00278 } 00279 } 00280 out += stride; 00281 tprev += stride; 00282 } 00283 00284 if(d) { /* apply XOR'ed difference */ 00285 out = output + x * 3; 00286 for(j = 0; j < bh2; j++){ 00287 for(i = 0; i < bw2; i++) { 00288 out[i * 3 + 0] ^= *src++; 00289 out[i * 3 + 1] ^= *src++; 00290 out[i * 3 + 2] ^= *src++; 00291 } 00292 out += stride; 00293 } 00294 } 00295 } 00296 output += stride * c->bh; 00297 prev += stride * c->bh; 00298 } 00299 if(src - c->decomp_buf != c->decomp_len) 00300 av_log(c->avctx, AV_LOG_ERROR, "Used %i of %i bytes\n", src-c->decomp_buf, c->decomp_len); 00301 return 0; 00302 } 00303 #endif //ZMBV_ENABLE_24BPP 00304 00309 static int zmbv_decode_xor_32(ZmbvContext *c) 00310 { 00311 uint8_t *src = c->decomp_buf; 00312 uint32_t *output, *prev; 00313 int8_t *mvec; 00314 int x, y; 00315 int d, dx, dy, bw2, bh2; 00316 int block; 00317 int i, j; 00318 int mx, my; 00319 00320 output = (uint32_t*)c->cur; 00321 prev = (uint32_t*)c->prev; 00322 00323 mvec = (int8_t*)src; 00324 src += ((c->bx * c->by * 2 + 3) & ~3); 00325 00326 block = 0; 00327 for(y = 0; y < c->height; y += c->bh) { 00328 bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); 00329 for(x = 0; x < c->width; x += c->bw) { 00330 uint32_t *out, *tprev; 00331 00332 d = mvec[block] & 1; 00333 dx = mvec[block] >> 1; 00334 dy = mvec[block + 1] >> 1; 00335 block += 2; 00336 00337 bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); 00338 00339 /* copy block - motion vectors out of bounds are used to zero blocks */ 00340 out = output + x; 00341 tprev = prev + x + dx + dy * c->width; 00342 mx = x + dx; 00343 my = y + dy; 00344 for(j = 0; j < bh2; j++){ 00345 if((my + j < 0) || (my + j >= c->height)) { 00346 memset(out, 0, bw2 * 4); 00347 } else { 00348 for(i = 0; i < bw2; i++){ 00349 if((mx + i < 0) || (mx + i >= c->width)) 00350 out[i] = 0; 00351 else 00352 out[i] = tprev[i]; 00353 } 00354 } 00355 out += c->width; 00356 tprev += c->width; 00357 } 00358 00359 if(d) { /* apply XOR'ed difference */ 00360 out = output + x; 00361 for(j = 0; j < bh2; j++){ 00362 for(i = 0; i < bw2; i++) { 00363 out[i] ^= *((uint32_t*)src); 00364 src += 4; 00365 } 00366 out += c->width; 00367 } 00368 } 00369 } 00370 output += c->width * c->bh; 00371 prev += c->width * c->bh; 00372 } 00373 if(src - c->decomp_buf != c->decomp_len) 00374 av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n", src-c->decomp_buf, c->decomp_len); 00375 return 0; 00376 } 00377 00381 static int zmbv_decode_intra(ZmbvContext *c) 00382 { 00383 uint8_t *src = c->decomp_buf; 00384 00385 /* make the palette available on the way out */ 00386 if (c->fmt == ZMBV_FMT_8BPP) { 00387 memcpy(c->pal, src, 768); 00388 src += 768; 00389 } 00390 00391 memcpy(c->cur, src, c->width * c->height * (c->bpp / 8)); 00392 return 0; 00393 } 00394 00395 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) 00396 { 00397 const uint8_t *buf = avpkt->data; 00398 int buf_size = avpkt->size; 00399 ZmbvContext * const c = avctx->priv_data; 00400 uint8_t *outptr; 00401 int zret = Z_OK; // Zlib return code 00402 int len = buf_size; 00403 int hi_ver, lo_ver; 00404 00405 if(c->pic.data[0]) 00406 avctx->release_buffer(avctx, &c->pic); 00407 00408 c->pic.reference = 1; 00409 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID; 00410 if(avctx->get_buffer(avctx, &c->pic) < 0){ 00411 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00412 return -1; 00413 } 00414 00415 outptr = c->pic.data[0]; // Output image pointer 00416 00417 /* parse header */ 00418 c->flags = buf[0]; 00419 buf++; len--; 00420 if(c->flags & ZMBV_KEYFRAME) { 00421 hi_ver = buf[0]; 00422 lo_ver = buf[1]; 00423 c->comp = buf[2]; 00424 c->fmt = buf[3]; 00425 c->bw = buf[4]; 00426 c->bh = buf[5]; 00427 00428 buf += 6; 00429 len -= 6; 00430 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); 00431 if(hi_ver != 0 || lo_ver != 1) { 00432 av_log(avctx, AV_LOG_ERROR, "Unsupported version %i.%i\n", hi_ver, lo_ver); 00433 return -1; 00434 } 00435 if(c->bw == 0 || c->bh == 0) { 00436 av_log(avctx, AV_LOG_ERROR, "Unsupported block size %ix%i\n", c->bw, c->bh); 00437 return -1; 00438 } 00439 if(c->comp != 0 && c->comp != 1) { 00440 av_log(avctx, AV_LOG_ERROR, "Unsupported compression type %i\n", c->comp); 00441 return -1; 00442 } 00443 00444 switch(c->fmt) { 00445 case ZMBV_FMT_8BPP: 00446 c->bpp = 8; 00447 c->decode_intra = zmbv_decode_intra; 00448 c->decode_xor = zmbv_decode_xor_8; 00449 break; 00450 case ZMBV_FMT_15BPP: 00451 case ZMBV_FMT_16BPP: 00452 c->bpp = 16; 00453 c->decode_intra = zmbv_decode_intra; 00454 c->decode_xor = zmbv_decode_xor_16; 00455 break; 00456 #ifdef ZMBV_ENABLE_24BPP 00457 case ZMBV_FMT_24BPP: 00458 c->bpp = 24; 00459 c->decode_intra = zmbv_decode_intra; 00460 c->decode_xor = zmbv_decode_xor_24; 00461 break; 00462 #endif //ZMBV_ENABLE_24BPP 00463 case ZMBV_FMT_32BPP: 00464 c->bpp = 32; 00465 c->decode_intra = zmbv_decode_intra; 00466 c->decode_xor = zmbv_decode_xor_32; 00467 break; 00468 default: 00469 c->decode_intra = NULL; 00470 c->decode_xor = NULL; 00471 av_log(avctx, AV_LOG_ERROR, "Unsupported (for now) format %i\n", c->fmt); 00472 return -1; 00473 } 00474 00475 zret = inflateReset(&c->zstream); 00476 if (zret != Z_OK) { 00477 av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); 00478 return -1; 00479 } 00480 00481 c->cur = av_realloc(c->cur, avctx->width * avctx->height * (c->bpp / 8)); 00482 c->prev = av_realloc(c->prev, avctx->width * avctx->height * (c->bpp / 8)); 00483 c->bx = (c->width + c->bw - 1) / c->bw; 00484 c->by = (c->height+ c->bh - 1) / c->bh; 00485 } 00486 00487 if(c->decode_intra == NULL) { 00488 av_log(avctx, AV_LOG_ERROR, "Error! Got no format or no keyframe!\n"); 00489 return -1; 00490 } 00491 00492 if(c->comp == 0) { //Uncompressed data 00493 memcpy(c->decomp_buf, buf, len); 00494 c->decomp_size = 1; 00495 } else { // ZLIB-compressed data 00496 c->zstream.total_in = c->zstream.total_out = 0; 00497 c->zstream.next_in = buf; 00498 c->zstream.avail_in = len; 00499 c->zstream.next_out = c->decomp_buf; 00500 c->zstream.avail_out = c->decomp_size; 00501 inflate(&c->zstream, Z_FINISH); 00502 c->decomp_len = c->zstream.total_out; 00503 } 00504 if(c->flags & ZMBV_KEYFRAME) { 00505 c->pic.key_frame = 1; 00506 c->pic.pict_type = FF_I_TYPE; 00507 c->decode_intra(c); 00508 } else { 00509 c->pic.key_frame = 0; 00510 c->pic.pict_type = FF_P_TYPE; 00511 if(c->decomp_len) 00512 c->decode_xor(c); 00513 } 00514 00515 /* update frames */ 00516 { 00517 uint8_t *out, *src; 00518 int i, j; 00519 00520 out = c->pic.data[0]; 00521 src = c->cur; 00522 switch(c->fmt) { 00523 case ZMBV_FMT_8BPP: 00524 for(j = 0; j < c->height; j++) { 00525 for(i = 0; i < c->width; i++) { 00526 out[i * 3 + 0] = c->pal[(*src) * 3 + 0]; 00527 out[i * 3 + 1] = c->pal[(*src) * 3 + 1]; 00528 out[i * 3 + 2] = c->pal[(*src) * 3 + 2]; 00529 src++; 00530 } 00531 out += c->pic.linesize[0]; 00532 } 00533 break; 00534 case ZMBV_FMT_15BPP: 00535 for(j = 0; j < c->height; j++) { 00536 for(i = 0; i < c->width; i++) { 00537 uint16_t tmp = AV_RL16(src); 00538 src += 2; 00539 out[i * 3 + 0] = (tmp & 0x7C00) >> 7; 00540 out[i * 3 + 1] = (tmp & 0x03E0) >> 2; 00541 out[i * 3 + 2] = (tmp & 0x001F) << 3; 00542 } 00543 out += c->pic.linesize[0]; 00544 } 00545 break; 00546 case ZMBV_FMT_16BPP: 00547 for(j = 0; j < c->height; j++) { 00548 for(i = 0; i < c->width; i++) { 00549 uint16_t tmp = AV_RL16(src); 00550 src += 2; 00551 out[i * 3 + 0] = (tmp & 0xF800) >> 8; 00552 out[i * 3 + 1] = (tmp & 0x07E0) >> 3; 00553 out[i * 3 + 2] = (tmp & 0x001F) << 3; 00554 } 00555 out += c->pic.linesize[0]; 00556 } 00557 break; 00558 #ifdef ZMBV_ENABLE_24BPP 00559 case ZMBV_FMT_24BPP: 00560 for(j = 0; j < c->height; j++) { 00561 memcpy(out, src, c->width * 3); 00562 src += c->width * 3; 00563 out += c->pic.linesize[0]; 00564 } 00565 break; 00566 #endif //ZMBV_ENABLE_24BPP 00567 case ZMBV_FMT_32BPP: 00568 for(j = 0; j < c->height; j++) { 00569 for(i = 0; i < c->width; i++) { 00570 uint32_t tmp = AV_RL32(src); 00571 src += 4; 00572 AV_WB24(out+(i*3), tmp); 00573 } 00574 out += c->pic.linesize[0]; 00575 } 00576 break; 00577 default: 00578 av_log(avctx, AV_LOG_ERROR, "Cannot handle format %i\n", c->fmt); 00579 } 00580 memcpy(c->prev, c->cur, c->width * c->height * (c->bpp / 8)); 00581 } 00582 *data_size = sizeof(AVFrame); 00583 *(AVFrame*)data = c->pic; 00584 00585 /* always report that the buffer was completely consumed */ 00586 return buf_size; 00587 } 00588 00589 00590 00591 /* 00592 * 00593 * Init zmbv decoder 00594 * 00595 */ 00596 static av_cold int decode_init(AVCodecContext *avctx) 00597 { 00598 ZmbvContext * const c = avctx->priv_data; 00599 int zret; // Zlib return code 00600 00601 c->avctx = avctx; 00602 00603 c->width = avctx->width; 00604 c->height = avctx->height; 00605 00606 c->bpp = avctx->bits_per_coded_sample; 00607 00608 // Needed if zlib unused or init aborted before inflateInit 00609 memset(&(c->zstream), 0, sizeof(z_stream)); 00610 00611 avctx->pix_fmt = PIX_FMT_RGB24; 00612 c->decomp_size = (avctx->width + 255) * 4 * (avctx->height + 64); 00613 00614 /* Allocate decompression buffer */ 00615 if (c->decomp_size) { 00616 if ((c->decomp_buf = av_malloc(c->decomp_size)) == NULL) { 00617 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); 00618 return 1; 00619 } 00620 } 00621 00622 c->zstream.zalloc = Z_NULL; 00623 c->zstream.zfree = Z_NULL; 00624 c->zstream.opaque = Z_NULL; 00625 zret = inflateInit(&(c->zstream)); 00626 if (zret != Z_OK) { 00627 av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); 00628 return 1; 00629 } 00630 00631 return 0; 00632 } 00633 00634 00635 00636 /* 00637 * 00638 * Uninit zmbv decoder 00639 * 00640 */ 00641 static av_cold int decode_end(AVCodecContext *avctx) 00642 { 00643 ZmbvContext * const c = avctx->priv_data; 00644 00645 av_freep(&c->decomp_buf); 00646 00647 if (c->pic.data[0]) 00648 avctx->release_buffer(avctx, &c->pic); 00649 inflateEnd(&(c->zstream)); 00650 av_freep(&c->cur); 00651 av_freep(&c->prev); 00652 00653 return 0; 00654 } 00655 00656 AVCodec zmbv_decoder = { 00657 "zmbv", 00658 AVMEDIA_TYPE_VIDEO, 00659 CODEC_ID_ZMBV, 00660 sizeof(ZmbvContext), 00661 decode_init, 00662 NULL, 00663 decode_end, 00664 decode_frame, 00665 CODEC_CAP_DR1, 00666 .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), 00667 }; 00668