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