Libav 0.7.1
|
00001 /* 00002 * Zip Motion Blocks Video (ZMBV) decoder 00003 * Copyright (c) 2006 Konstantin Shishkov 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; 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 int zret = Z_OK; // Zlib return code 00401 int len = buf_size; 00402 int hi_ver, lo_ver; 00403 00404 if(c->pic.data[0]) 00405 avctx->release_buffer(avctx, &c->pic); 00406 00407 c->pic.reference = 1; 00408 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID; 00409 if(avctx->get_buffer(avctx, &c->pic) < 0){ 00410 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00411 return -1; 00412 } 00413 00414 /* parse header */ 00415 c->flags = buf[0]; 00416 buf++; len--; 00417 if(c->flags & ZMBV_KEYFRAME) { 00418 hi_ver = buf[0]; 00419 lo_ver = buf[1]; 00420 c->comp = buf[2]; 00421 c->fmt = buf[3]; 00422 c->bw = buf[4]; 00423 c->bh = buf[5]; 00424 00425 buf += 6; 00426 len -= 6; 00427 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); 00428 if(hi_ver != 0 || lo_ver != 1) { 00429 av_log(avctx, AV_LOG_ERROR, "Unsupported version %i.%i\n", hi_ver, lo_ver); 00430 return -1; 00431 } 00432 if(c->bw == 0 || c->bh == 0) { 00433 av_log(avctx, AV_LOG_ERROR, "Unsupported block size %ix%i\n", c->bw, c->bh); 00434 return -1; 00435 } 00436 if(c->comp != 0 && c->comp != 1) { 00437 av_log(avctx, AV_LOG_ERROR, "Unsupported compression type %i\n", c->comp); 00438 return -1; 00439 } 00440 00441 switch(c->fmt) { 00442 case ZMBV_FMT_8BPP: 00443 c->bpp = 8; 00444 c->decode_intra = zmbv_decode_intra; 00445 c->decode_xor = zmbv_decode_xor_8; 00446 break; 00447 case ZMBV_FMT_15BPP: 00448 case ZMBV_FMT_16BPP: 00449 c->bpp = 16; 00450 c->decode_intra = zmbv_decode_intra; 00451 c->decode_xor = zmbv_decode_xor_16; 00452 break; 00453 #ifdef ZMBV_ENABLE_24BPP 00454 case ZMBV_FMT_24BPP: 00455 c->bpp = 24; 00456 c->decode_intra = zmbv_decode_intra; 00457 c->decode_xor = zmbv_decode_xor_24; 00458 break; 00459 #endif //ZMBV_ENABLE_24BPP 00460 case ZMBV_FMT_32BPP: 00461 c->bpp = 32; 00462 c->decode_intra = zmbv_decode_intra; 00463 c->decode_xor = zmbv_decode_xor_32; 00464 break; 00465 default: 00466 c->decode_intra = NULL; 00467 c->decode_xor = NULL; 00468 av_log(avctx, AV_LOG_ERROR, "Unsupported (for now) format %i\n", c->fmt); 00469 return -1; 00470 } 00471 00472 zret = inflateReset(&c->zstream); 00473 if (zret != Z_OK) { 00474 av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); 00475 return -1; 00476 } 00477 00478 c->cur = av_realloc(c->cur, avctx->width * avctx->height * (c->bpp / 8)); 00479 c->prev = av_realloc(c->prev, avctx->width * avctx->height * (c->bpp / 8)); 00480 c->bx = (c->width + c->bw - 1) / c->bw; 00481 c->by = (c->height+ c->bh - 1) / c->bh; 00482 } 00483 00484 if(c->decode_intra == NULL) { 00485 av_log(avctx, AV_LOG_ERROR, "Error! Got no format or no keyframe!\n"); 00486 return -1; 00487 } 00488 00489 if(c->comp == 0) { //Uncompressed data 00490 memcpy(c->decomp_buf, buf, len); 00491 c->decomp_size = 1; 00492 } else { // ZLIB-compressed data 00493 c->zstream.total_in = c->zstream.total_out = 0; 00494 c->zstream.next_in = buf; 00495 c->zstream.avail_in = len; 00496 c->zstream.next_out = c->decomp_buf; 00497 c->zstream.avail_out = c->decomp_size; 00498 inflate(&c->zstream, Z_FINISH); 00499 c->decomp_len = c->zstream.total_out; 00500 } 00501 if(c->flags & ZMBV_KEYFRAME) { 00502 c->pic.key_frame = 1; 00503 c->pic.pict_type = AV_PICTURE_TYPE_I; 00504 c->decode_intra(c); 00505 } else { 00506 c->pic.key_frame = 0; 00507 c->pic.pict_type = AV_PICTURE_TYPE_P; 00508 if(c->decomp_len) 00509 c->decode_xor(c); 00510 } 00511 00512 /* update frames */ 00513 { 00514 uint8_t *out, *src; 00515 int i, j; 00516 00517 out = c->pic.data[0]; 00518 src = c->cur; 00519 switch(c->fmt) { 00520 case ZMBV_FMT_8BPP: 00521 for(j = 0; j < c->height; j++) { 00522 for(i = 0; i < c->width; i++) { 00523 out[i * 3 + 0] = c->pal[(*src) * 3 + 0]; 00524 out[i * 3 + 1] = c->pal[(*src) * 3 + 1]; 00525 out[i * 3 + 2] = c->pal[(*src) * 3 + 2]; 00526 src++; 00527 } 00528 out += c->pic.linesize[0]; 00529 } 00530 break; 00531 case ZMBV_FMT_15BPP: 00532 for(j = 0; j < c->height; j++) { 00533 for(i = 0; i < c->width; i++) { 00534 uint16_t tmp = AV_RL16(src); 00535 src += 2; 00536 out[i * 3 + 0] = (tmp & 0x7C00) >> 7; 00537 out[i * 3 + 1] = (tmp & 0x03E0) >> 2; 00538 out[i * 3 + 2] = (tmp & 0x001F) << 3; 00539 } 00540 out += c->pic.linesize[0]; 00541 } 00542 break; 00543 case ZMBV_FMT_16BPP: 00544 for(j = 0; j < c->height; j++) { 00545 for(i = 0; i < c->width; i++) { 00546 uint16_t tmp = AV_RL16(src); 00547 src += 2; 00548 out[i * 3 + 0] = (tmp & 0xF800) >> 8; 00549 out[i * 3 + 1] = (tmp & 0x07E0) >> 3; 00550 out[i * 3 + 2] = (tmp & 0x001F) << 3; 00551 } 00552 out += c->pic.linesize[0]; 00553 } 00554 break; 00555 #ifdef ZMBV_ENABLE_24BPP 00556 case ZMBV_FMT_24BPP: 00557 for(j = 0; j < c->height; j++) { 00558 memcpy(out, src, c->width * 3); 00559 src += c->width * 3; 00560 out += c->pic.linesize[0]; 00561 } 00562 break; 00563 #endif //ZMBV_ENABLE_24BPP 00564 case ZMBV_FMT_32BPP: 00565 for(j = 0; j < c->height; j++) { 00566 for(i = 0; i < c->width; i++) { 00567 uint32_t tmp = AV_RL32(src); 00568 src += 4; 00569 AV_WB24(out+(i*3), tmp); 00570 } 00571 out += c->pic.linesize[0]; 00572 } 00573 break; 00574 default: 00575 av_log(avctx, AV_LOG_ERROR, "Cannot handle format %i\n", c->fmt); 00576 } 00577 memcpy(c->prev, c->cur, c->width * c->height * (c->bpp / 8)); 00578 } 00579 *data_size = sizeof(AVFrame); 00580 *(AVFrame*)data = c->pic; 00581 00582 /* always report that the buffer was completely consumed */ 00583 return buf_size; 00584 } 00585 00586 00587 00588 /* 00589 * 00590 * Init zmbv decoder 00591 * 00592 */ 00593 static av_cold int decode_init(AVCodecContext *avctx) 00594 { 00595 ZmbvContext * const c = avctx->priv_data; 00596 int zret; // Zlib return code 00597 00598 c->avctx = avctx; 00599 00600 c->width = avctx->width; 00601 c->height = avctx->height; 00602 00603 c->bpp = avctx->bits_per_coded_sample; 00604 00605 // Needed if zlib unused or init aborted before inflateInit 00606 memset(&(c->zstream), 0, sizeof(z_stream)); 00607 00608 avctx->pix_fmt = PIX_FMT_RGB24; 00609 c->decomp_size = (avctx->width + 255) * 4 * (avctx->height + 64); 00610 00611 /* Allocate decompression buffer */ 00612 if (c->decomp_size) { 00613 if ((c->decomp_buf = av_malloc(c->decomp_size)) == NULL) { 00614 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); 00615 return 1; 00616 } 00617 } 00618 00619 c->zstream.zalloc = Z_NULL; 00620 c->zstream.zfree = Z_NULL; 00621 c->zstream.opaque = Z_NULL; 00622 zret = inflateInit(&(c->zstream)); 00623 if (zret != Z_OK) { 00624 av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); 00625 return 1; 00626 } 00627 00628 return 0; 00629 } 00630 00631 00632 00633 /* 00634 * 00635 * Uninit zmbv decoder 00636 * 00637 */ 00638 static av_cold int decode_end(AVCodecContext *avctx) 00639 { 00640 ZmbvContext * const c = avctx->priv_data; 00641 00642 av_freep(&c->decomp_buf); 00643 00644 if (c->pic.data[0]) 00645 avctx->release_buffer(avctx, &c->pic); 00646 inflateEnd(&(c->zstream)); 00647 av_freep(&c->cur); 00648 av_freep(&c->prev); 00649 00650 return 0; 00651 } 00652 00653 AVCodec ff_zmbv_decoder = { 00654 "zmbv", 00655 AVMEDIA_TYPE_VIDEO, 00656 CODEC_ID_ZMBV, 00657 sizeof(ZmbvContext), 00658 decode_init, 00659 NULL, 00660 decode_end, 00661 decode_frame, 00662 CODEC_CAP_DR1, 00663 .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), 00664 }; 00665