comparison vqavideo.c @ 1501:dc6f46cd4a7b libavcodec

added solid color vectors; basic PAL8, 4x2-vector video (as in Command & Conquer) looks great now; also added compressed codebook support, but files using these (Lands of Lore) are not correct yet
author tmmm
date Sat, 04 Oct 2003 17:47:22 +0000
parents b78a9ba6a568
children e0c02032d0f2
comparison
equal deleted inserted replaced
1500:726a81d83ddd 1501:dc6f46cd4a7b
22 * @file vqavideo.c 22 * @file vqavideo.c
23 * VQA Video Decoder by Mike Melanson (melanson@pcisys.net) 23 * VQA Video Decoder by Mike Melanson (melanson@pcisys.net)
24 * For more information about the RPZA format, visit: 24 * For more information about the RPZA format, visit:
25 * http://www.pcisys.net/~melanson/codecs/ 25 * http://www.pcisys.net/~melanson/codecs/
26 * 26 *
27 * The VQA video decoder outputs PAL8 colorspace data. 27 * The VQA video decoder outputs PAL8 or RGB555 colorspace data, depending
28 * on the type of data in the file.
28 * 29 *
29 * This decoder needs the 42-byte VQHD header from the beginning 30 * This decoder needs the 42-byte VQHD header from the beginning
30 * of the VQA file passed through the extradata field. The VQHD header 31 * of the VQA file passed through the extradata field. The VQHD header
31 * is laid out as: 32 * is laid out as:
32 * 33 *
33 * bytes 0-3 chunk fourcc: 'VQHD' 34 * bytes 0-3 chunk fourcc: 'VQHD'
34 * bytes 4-7 chunk size in big-endian format, should be 0x0000002A 35 * bytes 4-7 chunk size in big-endian format, should be 0x0000002A
35 * bytes 8-50 VQHD chunk data 36 * bytes 8-49 VQHD chunk data
36 * 37 *
37 * Bytes 8-50 are what this decoder expects to see. 38 * Bytes 8-49 are what this decoder expects to see.
38 * 39 *
39 * Briefly, VQA is a vector quantized animation format that operates in a 40 * Briefly, VQA is a vector quantized animation format that operates in a
40 * 6-bit VGA palettized colorspace. It operates on pixel vectors (blocks) 41 * VGA palettized colorspace. It operates on pixel vectors (blocks)
41 * of either 4x2 or 4x4 in size. Compressed VQA chunks can contain vector 42 * of either 4x2 or 4x4 in size. Compressed VQA chunks can contain vector
42 * codebooks, palette information, and code maps for rendering vectors onto 43 * codebooks, palette information, and code maps for rendering vectors onto
43 * frames. Any of these components can also be compressed with a run-length 44 * frames. Any of these components can also be compressed with a run-length
44 * encoding (RLE) algorithm commonly referred to as "format80". 45 * encoding (RLE) algorithm commonly referred to as "format80".
45 * 46 *
53 * seeking difficult despite the fact that the frames are all intracoded. 54 * seeking difficult despite the fact that the frames are all intracoded.
54 * 55 *
55 * V1,2 VQA uses 12-bit codebook indices. If the 12-bit indices were 56 * V1,2 VQA uses 12-bit codebook indices. If the 12-bit indices were
56 * packed into bytes and then RLE compressed, bytewise, the results would 57 * packed into bytes and then RLE compressed, bytewise, the results would
57 * be poor. That is why the coding method divides each index into 2 parts, 58 * be poor. That is why the coding method divides each index into 2 parts,
58 * the top 4 bits and the bottom 8 bits, the RL encodes the 4-bit pieces 59 * the top 4 bits and the bottom 8 bits, then RL encodes the 4-bit pieces
59 * together and the 8-bit pieces together. If most of the vectors are 60 * together and the 8-bit pieces together. If most of the vectors are
60 * clustered into one group of 256 vectors, most of the 4-bit index pieces 61 * clustered into one group of 256 vectors, most of the 4-bit index pieces
61 * should be the same. 62 * should be the same.
62 */ 63 */
63 64
72 73
73 #define PALETTE_COUNT 256 74 #define PALETTE_COUNT 256
74 #define VQA_HEADER_SIZE 0x2A 75 #define VQA_HEADER_SIZE 0x2A
75 #define CHUNK_PREAMBLE_SIZE 8 76 #define CHUNK_PREAMBLE_SIZE 8
76 77
77 /* v1, v2 files: each vector codebook entry is 4x2=8 pixels = 8 bytes */ 78 /* allocate the maximum vector space, regardless of the file version:
78 #define V1_2_VECTOR_SIZE 8 79 * (0xFF00 codebook vectors + 0x100 solid pixel vectors) * (4x4 pixels/block) */
79 #define V1_2_MAX_VECTORS 0xF00 80 #define MAX_CODEBOOK_VECTORS 0xFF00
80 /* v3 files: each vector codebook entry is 4x4=16 pixels = 16 bytes */ 81 #define SOLID_PIXEL_VECTORS 0x100
81 #define V3_VECTOR_SIZE 16 82 #define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS)
82 #define V3_MAX_VECTORS 0xFF00 83 #define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4)
83 84
84 #define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0]) 85 #define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
85 #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1]) 86 #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
86 #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \ 87 #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
87 (((uint8_t*)(x))[1] << 16) | \ 88 (((uint8_t*)(x))[1] << 16) | \
126 int vector_width; /* width of individual vector */ 127 int vector_width; /* width of individual vector */
127 int vector_height; /* height of individual vector */ 128 int vector_height; /* height of individual vector */
128 int vqa_version; /* this should be either 1, 2 or 3 */ 129 int vqa_version; /* this should be either 1, 2 or 3 */
129 130
130 unsigned char *codebook; /* the current codebook */ 131 unsigned char *codebook; /* the current codebook */
132 int codebook_size;
131 unsigned char *next_codebook_buffer; /* accumulator for next codebook */ 133 unsigned char *next_codebook_buffer; /* accumulator for next codebook */
132 int next_codebook_buffer_index; 134 int next_codebook_buffer_index;
133 135
134 unsigned char *decode_buffer; 136 unsigned char *decode_buffer;
135 int decode_buffer_size; 137 int decode_buffer_size;
142 144
143 static int vqa_decode_init(AVCodecContext *avctx) 145 static int vqa_decode_init(AVCodecContext *avctx)
144 { 146 {
145 VqaContext *s = (VqaContext *)avctx->priv_data; 147 VqaContext *s = (VqaContext *)avctx->priv_data;
146 unsigned char *vqa_header; 148 unsigned char *vqa_header;
149 int i, j, codebook_index;;
147 150
148 s->avctx = avctx; 151 s->avctx = avctx;
149 avctx->pix_fmt = PIX_FMT_PAL8; 152 avctx->pix_fmt = PIX_FMT_PAL8;
150 avctx->has_b_frames = 0; 153 avctx->has_b_frames = 0;
151 dsputil_init(&s->dsp, avctx); 154 dsputil_init(&s->dsp, avctx);
171 /* return without further initialization */ 174 /* return without further initialization */
172 return -1; 175 return -1;
173 } 176 }
174 177
175 /* allocate codebooks */ 178 /* allocate codebooks */
176 if (s->vqa_version == 3) { 179 s->codebook_size = MAX_CODEBOOK_SIZE;
177 s->codebook = av_malloc(V3_VECTOR_SIZE * V3_MAX_VECTORS); 180 s->codebook = av_malloc(s->codebook_size);
178 s->next_codebook_buffer = av_malloc(V3_VECTOR_SIZE * V3_MAX_VECTORS); 181 s->next_codebook_buffer = av_malloc(s->codebook_size);
182
183 /* initialize the solid-color vectors */
184 if (s->vector_height == 4) {
185 codebook_index = 0xFF00 * 16;
186 for (i = 0; i < 256; i++)
187 for (j = 0; j < 16; j++)
188 s->codebook[codebook_index++] = i;
179 } else { 189 } else {
180 s->codebook = av_malloc(V1_2_VECTOR_SIZE * V1_2_MAX_VECTORS); 190 codebook_index = 0xF00 * 8;
181 s->next_codebook_buffer = av_malloc(V1_2_VECTOR_SIZE * V1_2_MAX_VECTORS); 191 for (i = 0; i < 256; i++)
192 for (j = 0; j < 8; j++)
193 s->codebook[codebook_index++] = i;
182 } 194 }
183 s->next_codebook_buffer_index = 0; 195 s->next_codebook_buffer_index = 0;
184 196
185 /* allocate decode buffer */ 197 /* allocate decode buffer */
186 s->decode_buffer_size = (s->width / s->vector_width) * 198 s->decode_buffer_size = (s->width / s->vector_width) *
192 return 0; 204 return 0;
193 } 205 }
194 206
195 #define CHECK_COUNT() \ 207 #define CHECK_COUNT() \
196 if (dest_index + count > dest_size) { \ 208 if (dest_index + count > dest_size) { \
197 printf ("vqavideo: decode_format80 problem: next op would overflow dest_index\n"); \ 209 printf (" VQA video: decode_format80 problem: next op would overflow dest_index\n"); \
198 printf ("vqavideo: current dest_index = %d, count = %d, dest_size = %d\n", \ 210 printf (" VQA video: current dest_index = %d, count = %d, dest_size = %d\n", \
199 dest_index, count, dest_size); \ 211 dest_index, count, dest_size); \
200 return; \ 212 return; \
201 } 213 }
202 214
203 static void decode_format80(unsigned char *src, int src_size, 215 static void decode_format80(unsigned char *src, int src_size,
204 unsigned char *dest, int dest_size) { 216 unsigned char *dest, int dest_size, int check_size) {
205 217
206 int src_index = 0; 218 int src_index = 0;
207 int dest_index = 0; 219 int dest_index = 0;
208 int count; 220 int count;
209 int src_pos; 221 int src_pos;
217 /* 0x80 means that frame is finished */ 229 /* 0x80 means that frame is finished */
218 if (src[src_index] == 0x80) 230 if (src[src_index] == 0x80)
219 return; 231 return;
220 232
221 if (dest_index >= dest_size) { 233 if (dest_index >= dest_size) {
222 printf ("vqavideo: decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n", 234 printf (" VQA video: decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
223 dest_index, dest_size); 235 dest_index, dest_size);
224 return; 236 return;
225 } 237 }
226 238
227 if (src[src_index] == 0xFF) { 239 if (src[src_index] == 0xFF) {
279 dest[dest_index + i] = dest[dest_index - src_pos + i]; 291 dest[dest_index + i] = dest[dest_index - src_pos + i];
280 dest_index += count; 292 dest_index += count;
281 } 293 }
282 } 294 }
283 295
284 if (dest_index < dest_size) 296 /* validate that the entire destination buffer was filled; this is
285 printf ("vqavideo: decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n", 297 * important for decoding frame maps since each vector needs to have a
286 dest_index, dest_size); 298 * codebook entry; it is not important for compressed codebooks because
299 * not every entry needs to be filled */
300 if (check_size)
301 if (dest_index < dest_size)
302 printf (" VQA video: decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n",
303 dest_index, dest_size);
287 } 304 }
288 305
289 static void vqa_decode_chunk(VqaContext *s) 306 static void vqa_decode_chunk(VqaContext *s)
290 { 307 {
291
292 //static int frame = 0;
293 unsigned int chunk_type; 308 unsigned int chunk_type;
294 unsigned int chunk_size; 309 unsigned int chunk_size;
295 int byte_skip; 310 int byte_skip;
296 unsigned int index = 0; 311 unsigned int index = 0;
297 int i; 312 int i;
313 int lobyte = 0; 328 int lobyte = 0;
314 int hibyte = 0; 329 int hibyte = 0;
315 int lobytes = 0; 330 int lobytes = 0;
316 int hibytes = s->decode_buffer_size / 2; 331 int hibytes = s->decode_buffer_size / 2;
317 332
318 //printf (" **** decoding frame #%d, stride = %d\n", frame++, s->frame.linesize[0]);
319 /* first, traverse through the frame and find the subchunks */ 333 /* first, traverse through the frame and find the subchunks */
320 while (index < s->size) { 334 while (index < s->size) {
321 335
322 chunk_type = BE_32(&s->buf[index]); 336 chunk_type = BE_32(&s->buf[index]);
323 chunk_size = BE_32(&s->buf[index + 4]); 337 chunk_size = BE_32(&s->buf[index + 4]);
385 if (cpl0_chunk != -1) { 399 if (cpl0_chunk != -1) {
386 400
387 chunk_size = BE_32(&s->buf[cpl0_chunk + 4]); 401 chunk_size = BE_32(&s->buf[cpl0_chunk + 4]);
388 /* sanity check the palette size */ 402 /* sanity check the palette size */
389 if (chunk_size / 3 > 256) { 403 if (chunk_size / 3 > 256) {
390 printf ("vqavideo: problem: found a palette chunk with %d colors\n", 404 printf (" VQA video: problem: found a palette chunk with %d colors\n",
391 chunk_size / 3); 405 chunk_size / 3);
392 return; 406 return;
393 } 407 }
394 cpl0_chunk += CHUNK_PREAMBLE_SIZE; 408 cpl0_chunk += CHUNK_PREAMBLE_SIZE;
395 palette32 = (unsigned int *)s->palette; 409 palette32 = (unsigned int *)s->palette;
408 /* a chunk should not have both chunk types */ 422 /* a chunk should not have both chunk types */
409 printf (" VQA video: problem: found both CBF0 and CBFZ chunks\n"); 423 printf (" VQA video: problem: found both CBF0 and CBFZ chunks\n");
410 return; 424 return;
411 } 425 }
412 426
413 /* decompress the full codebook chunk into the codebook accumulation 427 /* decompress the full codebook chunk */
414 * buffer; this is safe since only the first frame is supposed to have
415 * a full codebook */
416 if (cbfz_chunk != -1) { 428 if (cbfz_chunk != -1) {
417 429
418 /* yet to be handled */ 430 chunk_size = BE_32(&s->buf[cbfz_chunk + 4]);
419 431 cbfz_chunk += CHUNK_PREAMBLE_SIZE;
432 decode_format80(&s->buf[cbfz_chunk], chunk_size,
433 s->codebook, s->codebook_size, 0);
420 } 434 }
421 435
422 /* copy a full codebook */ 436 /* copy a full codebook */
423 if (cbf0_chunk != -1) { 437 if (cbf0_chunk != -1) {
424 438
425 index = cbf0_chunk;
426
427 chunk_size = BE_32(&s->buf[cbf0_chunk + 4]); 439 chunk_size = BE_32(&s->buf[cbf0_chunk + 4]);
428 /* sanity check the full codebook size */ 440 /* sanity check the full codebook size */
429 if (s->vqa_version == 3) { 441 if (chunk_size > MAX_CODEBOOK_SIZE) {
430 if (chunk_size / (V3_VECTOR_SIZE) > V3_MAX_VECTORS) { 442 printf (" VQA video: problem: CBF0 chunk too large (0x%X bytes)\n",
431 printf (" VQA video: problem: CBF0 chunk too large (0x%X bytes)\n", 443 chunk_size);
432 chunk_size); 444 return;
433 return;
434 }
435 } else {
436 if (chunk_size / (V1_2_VECTOR_SIZE) > V1_2_MAX_VECTORS) {
437 printf (" VQA video: problem: CBF0 chunk too large (0x%X bytes)\n",
438 chunk_size);
439 return;
440 }
441 } 445 }
442 cbf0_chunk += CHUNK_PREAMBLE_SIZE; 446 cbf0_chunk += CHUNK_PREAMBLE_SIZE;
443 447
444 memcpy(s->codebook, &s->buf[cbf0_chunk], chunk_size); 448 memcpy(s->codebook, &s->buf[cbf0_chunk], chunk_size);
445 } 449 }
450 /* something is wrong if there is no VPTZ chunk */ 454 /* something is wrong if there is no VPTZ chunk */
451 printf (" VQA video: problem: no VPTZ chunk found\n"); 455 printf (" VQA video: problem: no VPTZ chunk found\n");
452 return; 456 return;
453 } 457 }
454 458
455 /* decode frame */
456 chunk_size = BE_32(&s->buf[vptz_chunk + 4]); 459 chunk_size = BE_32(&s->buf[vptz_chunk + 4]);
457 vptz_chunk += CHUNK_PREAMBLE_SIZE; 460 vptz_chunk += CHUNK_PREAMBLE_SIZE;
458 decode_format80(&s->buf[vptz_chunk], chunk_size, 461 decode_format80(&s->buf[vptz_chunk], chunk_size,
459 s->decode_buffer, s->decode_buffer_size); 462 s->decode_buffer, s->decode_buffer_size, 1);
460
461
462 if (0)
463 {
464 int count = 0;
465 printf (" finished decoding frame...");
466 for (index = 8000; index < 16000; index++)
467 if (s->decode_buffer[index] > 0x0F)
468 count++;
469 printf (" %d/8000 hibytes exceeded 0x0F\n", count);
470 }
471
472 463
473 /* render the final PAL8 frame */ 464 /* render the final PAL8 frame */
474 for (y = 0; y < s->frame.linesize[0] * s->height; 465 for (y = 0; y < s->frame.linesize[0] * s->height;
475 y += s->frame.linesize[0] * s->vector_height) { 466 y += s->frame.linesize[0] * s->vector_height) {
476 467
488 break; 479 break;
489 480
490 case 2: 481 case 2:
491 lobyte = s->decode_buffer[lobytes]; 482 lobyte = s->decode_buffer[lobytes];
492 hibyte = s->decode_buffer[hibytes]; 483 hibyte = s->decode_buffer[hibytes];
493 if (hibyte > 0x0F) {
494 printf (" VQA video: problem: vector #%d/%d high byte out of range (0x%X >= 0x0F)\n",
495 lobytes, s->decode_buffer_size / 2, hibyte);
496 hibyte = lobyte = 0;
497 } else if (hibyte == 0x0F)
498 hibyte = 0;
499 vector_index = (hibyte << 8) | lobyte; 484 vector_index = (hibyte << 8) | lobyte;
500 vector_index *= V1_2_VECTOR_SIZE; 485 vector_index *= 8;
501 lines = 2; 486 lines = s->vector_height;
502 break; 487 break;
503 488
504 case 3: 489 case 3:
505 /* not implemented yet */ 490 /* not implemented yet */
506 lines = 0; 491 lines = 0;
547 } 532 }
548 } 533 }
549 534
550 if (cbpz_chunk != -1) { 535 if (cbpz_chunk != -1) {
551 536
552 /* more partial codebook handling ... */ 537 chunk_size = BE_32(&s->buf[cbpz_chunk + 4]);
553 538 cbpz_chunk += CHUNK_PREAMBLE_SIZE;
539
540 /* accumulate partial codebook */
541 memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index],
542 &s->buf[cbpz_chunk], chunk_size);
543 s->next_codebook_buffer_index += chunk_size;
544
545 s->partial_countdown--;
546 if (s->partial_countdown == 0) {
547
548 /* decompress codebook */
549 decode_format80(s->next_codebook_buffer,
550 s->next_codebook_buffer_index,
551 s->codebook, s->codebook_size, 0);
552
553 /* reset accounting */
554 s->next_codebook_buffer_index = 0;
555 s->partial_countdown = s->partial_count;
556 }
554 } 557 }
555 } 558 }
556 559
557 static int vqa_decode_frame(AVCodecContext *avctx, 560 static int vqa_decode_frame(AVCodecContext *avctx,
558 void *data, int *data_size, 561 void *data, int *data_size,