1/* 2 * Westwood Studios VQA Video Decoder 3 * Copyright (C) 2003 the ffmpeg project 4 * 5 * This file is part of FFmpeg. 6 * 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. 11 * 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. 16 * 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 20 */ 21 22/** 23 * @file libavcodec/vqavideo.c 24 * VQA Video Decoder by Mike Melanson (melanson@pcisys.net) 25 * For more information about the VQA format, visit: 26 * http://wiki.multimedia.cx/index.php?title=VQA 27 * 28 * The VQA video decoder outputs PAL8 or RGB555 colorspace data, depending 29 * on the type of data in the file. 30 * 31 * This decoder needs the 42-byte VQHD header from the beginning 32 * of the VQA file passed through the extradata field. The VQHD header 33 * is laid out as: 34 * 35 * bytes 0-3 chunk fourcc: 'VQHD' 36 * bytes 4-7 chunk size in big-endian format, should be 0x0000002A 37 * bytes 8-49 VQHD chunk data 38 * 39 * Bytes 8-49 are what this decoder expects to see. 40 * 41 * Briefly, VQA is a vector quantized animation format that operates in a 42 * VGA palettized colorspace. It operates on pixel vectors (blocks) 43 * of either 4x2 or 4x4 in size. Compressed VQA chunks can contain vector 44 * codebooks, palette information, and code maps for rendering vectors onto 45 * frames. Any of these components can also be compressed with a run-length 46 * encoding (RLE) algorithm commonly referred to as "format80". 47 * 48 * VQA takes a novel approach to rate control. Each group of n frames 49 * (usually, n = 8) relies on a different vector codebook. Rather than 50 * transporting an entire codebook every 8th frame, the new codebook is 51 * broken up into 8 pieces and sent along with the compressed video chunks 52 * for each of the 8 frames preceding the 8 frames which require the 53 * codebook. A full codebook is also sent on the very first frame of a 54 * file. This is an interesting technique, although it makes random file 55 * seeking difficult despite the fact that the frames are all intracoded. 56 * 57 * V1,2 VQA uses 12-bit codebook indexes. If the 12-bit indexes were 58 * packed into bytes and then RLE compressed, bytewise, the results would 59 * be poor. That is why the coding method divides each index into 2 parts, 60 * the top 4 bits and the bottom 8 bits, then RL encodes the 4-bit pieces 61 * together and the 8-bit pieces together. If most of the vectors are 62 * clustered into one group of 256 vectors, most of the 4-bit index pieces 63 * should be the same. 64 */ 65 66#include <stdio.h> 67#include <stdlib.h> 68#include <string.h> 69#include <unistd.h> 70 71#include "libavutil/intreadwrite.h" 72#include "avcodec.h" 73 74#define PALETTE_COUNT 256 75#define VQA_HEADER_SIZE 0x2A 76#define CHUNK_PREAMBLE_SIZE 8 77 78/* allocate the maximum vector space, regardless of the file version: 79 * (0xFF00 codebook vectors + 0x100 solid pixel vectors) * (4x4 pixels/block) */ 80#define MAX_CODEBOOK_VECTORS 0xFF00 81#define SOLID_PIXEL_VECTORS 0x100 82#define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS) 83#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4) 84 85#define CBF0_TAG MKBETAG('C', 'B', 'F', '0') 86#define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z') 87#define CBP0_TAG MKBETAG('C', 'B', 'P', '0') 88#define CBPZ_TAG MKBETAG('C', 'B', 'P', 'Z') 89#define CPL0_TAG MKBETAG('C', 'P', 'L', '0') 90#define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z') 91#define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z') 92 93#define VQA_DEBUG 0 94 95#if VQA_DEBUG 96#define vqa_debug printf 97#else 98static inline void vqa_debug(const char *format, ...) { } 99#endif 100 101typedef struct VqaContext { 102 103 AVCodecContext *avctx; 104 AVFrame frame; 105 106 const unsigned char *buf; 107 int size; 108 109 uint32_t palette[PALETTE_COUNT]; 110 111 int width; /* width of a frame */ 112 int height; /* height of a frame */ 113 int vector_width; /* width of individual vector */ 114 int vector_height; /* height of individual vector */ 115 int vqa_version; /* this should be either 1, 2 or 3 */ 116 117 unsigned char *codebook; /* the current codebook */ 118 int codebook_size; 119 unsigned char *next_codebook_buffer; /* accumulator for next codebook */ 120 int next_codebook_buffer_index; 121 122 unsigned char *decode_buffer; 123 int decode_buffer_size; 124 125 /* number of frames to go before replacing codebook */ 126 int partial_countdown; 127 int partial_count; 128 129} VqaContext; 130 131static av_cold int vqa_decode_init(AVCodecContext *avctx) 132{ 133 VqaContext *s = avctx->priv_data; 134 unsigned char *vqa_header; 135 int i, j, codebook_index; 136 137 s->avctx = avctx; 138 avctx->pix_fmt = PIX_FMT_PAL8; 139 140 /* make sure the extradata made it */ 141 if (s->avctx->extradata_size != VQA_HEADER_SIZE) { 142 av_log(s->avctx, AV_LOG_ERROR, " VQA video: expected extradata size of %d\n", VQA_HEADER_SIZE); 143 return -1; 144 } 145 146 /* load up the VQA parameters from the header */ 147 vqa_header = (unsigned char *)s->avctx->extradata; 148 s->vqa_version = vqa_header[0]; 149 s->width = AV_RL16(&vqa_header[6]); 150 s->height = AV_RL16(&vqa_header[8]); 151 if(avcodec_check_dimensions(avctx, s->width, s->height)){ 152 s->width= s->height= 0; 153 return -1; 154 } 155 s->vector_width = vqa_header[10]; 156 s->vector_height = vqa_header[11]; 157 s->partial_count = s->partial_countdown = vqa_header[13]; 158 159 /* the vector dimensions have to meet very stringent requirements */ 160 if ((s->vector_width != 4) || 161 ((s->vector_height != 2) && (s->vector_height != 4))) { 162 /* return without further initialization */ 163 return -1; 164 } 165 166 /* allocate codebooks */ 167 s->codebook_size = MAX_CODEBOOK_SIZE; 168 s->codebook = av_malloc(s->codebook_size); 169 s->next_codebook_buffer = av_malloc(s->codebook_size); 170 171 /* initialize the solid-color vectors */ 172 if (s->vector_height == 4) { 173 codebook_index = 0xFF00 * 16; 174 for (i = 0; i < 256; i++) 175 for (j = 0; j < 16; j++) 176 s->codebook[codebook_index++] = i; 177 } else { 178 codebook_index = 0xF00 * 8; 179 for (i = 0; i < 256; i++) 180 for (j = 0; j < 8; j++) 181 s->codebook[codebook_index++] = i; 182 } 183 s->next_codebook_buffer_index = 0; 184 185 /* allocate decode buffer */ 186 s->decode_buffer_size = (s->width / s->vector_width) * 187 (s->height / s->vector_height) * 2; 188 s->decode_buffer = av_malloc(s->decode_buffer_size); 189 190 s->frame.data[0] = NULL; 191 192 return 0; 193} 194 195#define CHECK_COUNT() \ 196 if (dest_index + count > dest_size) { \ 197 av_log(NULL, AV_LOG_ERROR, " VQA video: decode_format80 problem: next op would overflow dest_index\n"); \ 198 av_log(NULL, AV_LOG_ERROR, " VQA video: current dest_index = %d, count = %d, dest_size = %d\n", \ 199 dest_index, count, dest_size); \ 200 return; \ 201 } 202 203static void decode_format80(const unsigned char *src, int src_size, 204 unsigned char *dest, int dest_size, int check_size) { 205 206 int src_index = 0; 207 int dest_index = 0; 208 int count; 209 int src_pos; 210 unsigned char color; 211 int i; 212 213 while (src_index < src_size) { 214 215 vqa_debug(" opcode %02X: ", src[src_index]); 216 217 /* 0x80 means that frame is finished */ 218 if (src[src_index] == 0x80) 219 return; 220 221 if (dest_index >= dest_size) { 222 av_log(NULL, AV_LOG_ERROR, " VQA video: decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n", 223 dest_index, dest_size); 224 return; 225 } 226 227 if (src[src_index] == 0xFF) { 228 229 src_index++; 230 count = AV_RL16(&src[src_index]); 231 src_index += 2; 232 src_pos = AV_RL16(&src[src_index]); 233 src_index += 2; 234 vqa_debug("(1) copy %X bytes from absolute pos %X\n", count, src_pos); 235 CHECK_COUNT(); 236 for (i = 0; i < count; i++) 237 dest[dest_index + i] = dest[src_pos + i]; 238 dest_index += count; 239 240 } else if (src[src_index] == 0xFE) { 241 242 src_index++; 243 count = AV_RL16(&src[src_index]); 244 src_index += 2; 245 color = src[src_index++]; 246 vqa_debug("(2) set %X bytes to %02X\n", count, color); 247 CHECK_COUNT(); 248 memset(&dest[dest_index], color, count); 249 dest_index += count; 250 251 } else if ((src[src_index] & 0xC0) == 0xC0) { 252 253 count = (src[src_index++] & 0x3F) + 3; 254 src_pos = AV_RL16(&src[src_index]); 255 src_index += 2; 256 vqa_debug("(3) copy %X bytes from absolute pos %X\n", count, src_pos); 257 CHECK_COUNT(); 258 for (i = 0; i < count; i++) 259 dest[dest_index + i] = dest[src_pos + i]; 260 dest_index += count; 261 262 } else if (src[src_index] > 0x80) { 263 264 count = src[src_index++] & 0x3F; 265 vqa_debug("(4) copy %X bytes from source to dest\n", count); 266 CHECK_COUNT(); 267 memcpy(&dest[dest_index], &src[src_index], count); 268 src_index += count; 269 dest_index += count; 270 271 } else { 272 273 count = ((src[src_index] & 0x70) >> 4) + 3; 274 src_pos = AV_RB16(&src[src_index]) & 0x0FFF; 275 src_index += 2; 276 vqa_debug("(5) copy %X bytes from relpos %X\n", count, src_pos); 277 CHECK_COUNT(); 278 for (i = 0; i < count; i++) 279 dest[dest_index + i] = dest[dest_index - src_pos + i]; 280 dest_index += count; 281 } 282 } 283 284 /* validate that the entire destination buffer was filled; this is 285 * important for decoding frame maps since each vector needs to have a 286 * codebook entry; it is not important for compressed codebooks because 287 * not every entry needs to be filled */ 288 if (check_size) 289 if (dest_index < dest_size) 290 av_log(NULL, AV_LOG_ERROR, " VQA video: decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n", 291 dest_index, dest_size); 292} 293 294static void vqa_decode_chunk(VqaContext *s) 295{ 296 unsigned int chunk_type; 297 unsigned int chunk_size; 298 int byte_skip; 299 unsigned int index = 0; 300 int i; 301 unsigned char r, g, b; 302 int index_shift; 303 304 int cbf0_chunk = -1; 305 int cbfz_chunk = -1; 306 int cbp0_chunk = -1; 307 int cbpz_chunk = -1; 308 int cpl0_chunk = -1; 309 int cplz_chunk = -1; 310 int vptz_chunk = -1; 311 312 int x, y; 313 int lines = 0; 314 int pixel_ptr; 315 int vector_index = 0; 316 int lobyte = 0; 317 int hibyte = 0; 318 int lobytes = 0; 319 int hibytes = s->decode_buffer_size / 2; 320 321 /* first, traverse through the frame and find the subchunks */ 322 while (index < s->size) { 323 324 chunk_type = AV_RB32(&s->buf[index]); 325 chunk_size = AV_RB32(&s->buf[index + 4]); 326 327 switch (chunk_type) { 328 329 case CBF0_TAG: 330 cbf0_chunk = index; 331 break; 332 333 case CBFZ_TAG: 334 cbfz_chunk = index; 335 break; 336 337 case CBP0_TAG: 338 cbp0_chunk = index; 339 break; 340 341 case CBPZ_TAG: 342 cbpz_chunk = index; 343 break; 344 345 case CPL0_TAG: 346 cpl0_chunk = index; 347 break; 348 349 case CPLZ_TAG: 350 cplz_chunk = index; 351 break; 352 353 case VPTZ_TAG: 354 vptz_chunk = index; 355 break; 356 357 default: 358 av_log(s->avctx, AV_LOG_ERROR, " VQA video: Found unknown chunk type: %c%c%c%c (%08X)\n", 359 (chunk_type >> 24) & 0xFF, 360 (chunk_type >> 16) & 0xFF, 361 (chunk_type >> 8) & 0xFF, 362 (chunk_type >> 0) & 0xFF, 363 chunk_type); 364 break; 365 } 366 367 byte_skip = chunk_size & 0x01; 368 index += (CHUNK_PREAMBLE_SIZE + chunk_size + byte_skip); 369 } 370 371 /* next, deal with the palette */ 372 if ((cpl0_chunk != -1) && (cplz_chunk != -1)) { 373 374 /* a chunk should not have both chunk types */ 375 av_log(s->avctx, AV_LOG_ERROR, " VQA video: problem: found both CPL0 and CPLZ chunks\n"); 376 return; 377 } 378 379 /* decompress the palette chunk */ 380 if (cplz_chunk != -1) { 381 382/* yet to be handled */ 383 384 } 385 386 /* convert the RGB palette into the machine's endian format */ 387 if (cpl0_chunk != -1) { 388 389 chunk_size = AV_RB32(&s->buf[cpl0_chunk + 4]); 390 /* sanity check the palette size */ 391 if (chunk_size / 3 > 256) { 392 av_log(s->avctx, AV_LOG_ERROR, " VQA video: problem: found a palette chunk with %d colors\n", 393 chunk_size / 3); 394 return; 395 } 396 cpl0_chunk += CHUNK_PREAMBLE_SIZE; 397 for (i = 0; i < chunk_size / 3; i++) { 398 /* scale by 4 to transform 6-bit palette -> 8-bit */ 399 r = s->buf[cpl0_chunk++] * 4; 400 g = s->buf[cpl0_chunk++] * 4; 401 b = s->buf[cpl0_chunk++] * 4; 402 s->palette[i] = (r << 16) | (g << 8) | (b); 403 } 404 } 405 406 /* next, look for a full codebook */ 407 if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) { 408 409 /* a chunk should not have both chunk types */ 410 av_log(s->avctx, AV_LOG_ERROR, " VQA video: problem: found both CBF0 and CBFZ chunks\n"); 411 return; 412 } 413 414 /* decompress the full codebook chunk */ 415 if (cbfz_chunk != -1) { 416 417 chunk_size = AV_RB32(&s->buf[cbfz_chunk + 4]); 418 cbfz_chunk += CHUNK_PREAMBLE_SIZE; 419 decode_format80(&s->buf[cbfz_chunk], chunk_size, 420 s->codebook, s->codebook_size, 0); 421 } 422 423 /* copy a full codebook */ 424 if (cbf0_chunk != -1) { 425 426 chunk_size = AV_RB32(&s->buf[cbf0_chunk + 4]); 427 /* sanity check the full codebook size */ 428 if (chunk_size > MAX_CODEBOOK_SIZE) { 429 av_log(s->avctx, AV_LOG_ERROR, " VQA video: problem: CBF0 chunk too large (0x%X bytes)\n", 430 chunk_size); 431 return; 432 } 433 cbf0_chunk += CHUNK_PREAMBLE_SIZE; 434 435 memcpy(s->codebook, &s->buf[cbf0_chunk], chunk_size); 436 } 437 438 /* decode the frame */ 439 if (vptz_chunk == -1) { 440 441 /* something is wrong if there is no VPTZ chunk */ 442 av_log(s->avctx, AV_LOG_ERROR, " VQA video: problem: no VPTZ chunk found\n"); 443 return; 444 } 445 446 chunk_size = AV_RB32(&s->buf[vptz_chunk + 4]); 447 vptz_chunk += CHUNK_PREAMBLE_SIZE; 448 decode_format80(&s->buf[vptz_chunk], chunk_size, 449 s->decode_buffer, s->decode_buffer_size, 1); 450 451 /* render the final PAL8 frame */ 452 if (s->vector_height == 4) 453 index_shift = 4; 454 else 455 index_shift = 3; 456 for (y = 0; y < s->frame.linesize[0] * s->height; 457 y += s->frame.linesize[0] * s->vector_height) { 458 459 for (x = y; x < y + s->width; x += 4, lobytes++, hibytes++) { 460 pixel_ptr = x; 461 462 /* get the vector index, the method for which varies according to 463 * VQA file version */ 464 switch (s->vqa_version) { 465 466 case 1: 467/* still need sample media for this case (only one game, "Legend of 468 * Kyrandia III : Malcolm's Revenge", is known to use this version) */ 469 lobyte = s->decode_buffer[lobytes * 2]; 470 hibyte = s->decode_buffer[(lobytes * 2) + 1]; 471 vector_index = ((hibyte << 8) | lobyte) >> 3; 472 vector_index <<= index_shift; 473 lines = s->vector_height; 474 /* uniform color fill - a quick hack */ 475 if (hibyte == 0xFF) { 476 while (lines--) { 477 s->frame.data[0][pixel_ptr + 0] = 255 - lobyte; 478 s->frame.data[0][pixel_ptr + 1] = 255 - lobyte; 479 s->frame.data[0][pixel_ptr + 2] = 255 - lobyte; 480 s->frame.data[0][pixel_ptr + 3] = 255 - lobyte; 481 pixel_ptr += s->frame.linesize[0]; 482 } 483 lines=0; 484 } 485 break; 486 487 case 2: 488 lobyte = s->decode_buffer[lobytes]; 489 hibyte = s->decode_buffer[hibytes]; 490 vector_index = (hibyte << 8) | lobyte; 491 vector_index <<= index_shift; 492 lines = s->vector_height; 493 break; 494 495 case 3: 496/* not implemented yet */ 497 lines = 0; 498 break; 499 } 500 501 while (lines--) { 502 s->frame.data[0][pixel_ptr + 0] = s->codebook[vector_index++]; 503 s->frame.data[0][pixel_ptr + 1] = s->codebook[vector_index++]; 504 s->frame.data[0][pixel_ptr + 2] = s->codebook[vector_index++]; 505 s->frame.data[0][pixel_ptr + 3] = s->codebook[vector_index++]; 506 pixel_ptr += s->frame.linesize[0]; 507 } 508 } 509 } 510 511 /* handle partial codebook */ 512 if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) { 513 /* a chunk should not have both chunk types */ 514 av_log(s->avctx, AV_LOG_ERROR, " VQA video: problem: found both CBP0 and CBPZ chunks\n"); 515 return; 516 } 517 518 if (cbp0_chunk != -1) { 519 520 chunk_size = AV_RB32(&s->buf[cbp0_chunk + 4]); 521 cbp0_chunk += CHUNK_PREAMBLE_SIZE; 522 523 /* accumulate partial codebook */ 524 memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index], 525 &s->buf[cbp0_chunk], chunk_size); 526 s->next_codebook_buffer_index += chunk_size; 527 528 s->partial_countdown--; 529 if (s->partial_countdown == 0) { 530 531 /* time to replace codebook */ 532 memcpy(s->codebook, s->next_codebook_buffer, 533 s->next_codebook_buffer_index); 534 535 /* reset accounting */ 536 s->next_codebook_buffer_index = 0; 537 s->partial_countdown = s->partial_count; 538 } 539 } 540 541 if (cbpz_chunk != -1) { 542 543 chunk_size = AV_RB32(&s->buf[cbpz_chunk + 4]); 544 cbpz_chunk += CHUNK_PREAMBLE_SIZE; 545 546 /* accumulate partial codebook */ 547 memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index], 548 &s->buf[cbpz_chunk], chunk_size); 549 s->next_codebook_buffer_index += chunk_size; 550 551 s->partial_countdown--; 552 if (s->partial_countdown == 0) { 553 554 /* decompress codebook */ 555 decode_format80(s->next_codebook_buffer, 556 s->next_codebook_buffer_index, 557 s->codebook, s->codebook_size, 0); 558 559 /* reset accounting */ 560 s->next_codebook_buffer_index = 0; 561 s->partial_countdown = s->partial_count; 562 } 563 } 564} 565 566static int vqa_decode_frame(AVCodecContext *avctx, 567 void *data, int *data_size, 568 const uint8_t *buf, int buf_size) 569{ 570 VqaContext *s = avctx->priv_data; 571 572 s->buf = buf; 573 s->size = buf_size; 574 575 if (s->frame.data[0]) 576 avctx->release_buffer(avctx, &s->frame); 577 578 if (avctx->get_buffer(avctx, &s->frame)) { 579 av_log(s->avctx, AV_LOG_ERROR, " VQA Video: get_buffer() failed\n"); 580 return -1; 581 } 582 583 vqa_decode_chunk(s); 584 585 /* make the palette available on the way out */ 586 memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4); 587 s->frame.palette_has_changed = 1; 588 589 *data_size = sizeof(AVFrame); 590 *(AVFrame*)data = s->frame; 591 592 /* report that the buffer was completely consumed */ 593 return buf_size; 594} 595 596static av_cold int vqa_decode_end(AVCodecContext *avctx) 597{ 598 VqaContext *s = avctx->priv_data; 599 600 av_free(s->codebook); 601 av_free(s->next_codebook_buffer); 602 av_free(s->decode_buffer); 603 604 if (s->frame.data[0]) 605 avctx->release_buffer(avctx, &s->frame); 606 607 return 0; 608} 609 610AVCodec vqa_decoder = { 611 "vqavideo", 612 CODEC_TYPE_VIDEO, 613 CODEC_ID_WS_VQA, 614 sizeof(VqaContext), 615 vqa_decode_init, 616 NULL, 617 vqa_decode_end, 618 vqa_decode_frame, 619 CODEC_CAP_DR1, 620 .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"), 621}; 622