]> git.sesse.net Git - ffmpeg/blob - libavcodec/vqavideo.c
support a few more types of VQA files
[ffmpeg] / libavcodec / vqavideo.c
1 /*
2  * Westwood Studios VQA Video Decoder
3  * Copyright (C) 2003 the ffmpeg project
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 /**
22  * @file vqavideo.c
23  * VQA Video Decoder by Mike Melanson (melanson@pcisys.net)
24  * For more information about the RPZA format, visit:
25  *   http://www.pcisys.net/~melanson/codecs/
26  *
27  * The VQA video decoder outputs PAL8 or RGB555 colorspace data, depending
28  * on the type of data in the file.
29  *
30  * This decoder needs the 42-byte VQHD header from the beginning
31  * of the VQA file passed through the extradata field. The VQHD header
32  * is laid out as:
33  *
34  *   bytes 0-3   chunk fourcc: 'VQHD'
35  *   bytes 4-7   chunk size in big-endian format, should be 0x0000002A
36  *   bytes 8-49  VQHD chunk data
37  *
38  * Bytes 8-49 are what this decoder expects to see.
39  *
40  * Briefly, VQA is a vector quantized animation format that operates in a
41  * VGA palettized colorspace. It operates on pixel vectors (blocks)
42  * of either 4x2 or 4x4 in size. Compressed VQA chunks can contain vector
43  * codebooks, palette information, and code maps for rendering vectors onto
44  * frames. Any of these components can also be compressed with a run-length
45  * encoding (RLE) algorithm commonly referred to as "format80".
46  *
47  * VQA takes a novel approach to rate control. Each group of n frames
48  * (usually, n = 8) relies on a different vector codebook. Rather than
49  * transporting an entire codebook every 8th frame, the new codebook is
50  * broken up into 8 pieces and sent along with the compressed video chunks
51  * for each of the 8 frames preceding the 8 frames which require the
52  * codebook. A full codebook is also sent on the very first frame of a
53  * file. This is an interesting technique, although it makes random file
54  * seeking difficult despite the fact that the frames are all intracoded.
55  *
56  * V1,2 VQA uses 12-bit codebook indices. If the 12-bit indices were
57  * packed into bytes and then RLE compressed, bytewise, the results would
58  * be poor. That is why the coding method divides each index into 2 parts,
59  * the top 4 bits and the bottom 8 bits, then RL encodes the 4-bit pieces
60  * together and the 8-bit pieces together. If most of the vectors are
61  * clustered into one group of 256 vectors, most of the 4-bit index pieces
62  * should be the same.
63  */
64
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <unistd.h>
69
70 #include "common.h"
71 #include "avcodec.h"
72 #include "dsputil.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 LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
86 #define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
87 #define BE_32(x)  ((((uint8_t*)(x))[0] << 24) | \
88                    (((uint8_t*)(x))[1] << 16) | \
89                    (((uint8_t*)(x))[2] << 8) | \
90                     ((uint8_t*)(x))[3])
91
92 #define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \
93         ( (long)(unsigned char)(ch3) | \
94         ( (long)(unsigned char)(ch2) << 8 ) | \
95         ( (long)(unsigned char)(ch1) << 16 ) | \
96         ( (long)(unsigned char)(ch0) << 24 ) )
97
98 #define CBF0_TAG FOURCC_TAG('C', 'B', 'F', '0')
99 #define CBFZ_TAG FOURCC_TAG('C', 'B', 'F', 'Z')
100 #define CBP0_TAG FOURCC_TAG('C', 'B', 'P', '0')
101 #define CBPZ_TAG FOURCC_TAG('C', 'B', 'P', 'Z')
102 #define CPL0_TAG FOURCC_TAG('C', 'P', 'L', '0')
103 #define CPLZ_TAG FOURCC_TAG('C', 'P', 'L', 'Z')
104 #define VPTZ_TAG FOURCC_TAG('V', 'P', 'T', 'Z')
105
106 #define VQA_DEBUG 0
107
108 #if VQA_DEBUG
109 #define vqa_debug printf
110 #else
111 static inline void vqa_debug(const char *format, ...) { }
112 #endif
113
114 typedef struct VqaContext {
115
116     AVCodecContext *avctx;
117     DSPContext dsp;
118     AVFrame frame;
119
120     unsigned char *buf;
121     int size;
122
123     unsigned char palette[PALETTE_COUNT * 4];
124
125     int width;   /* width of a frame */
126     int height;   /* height of a frame */
127     int vector_width;  /* width of individual vector */
128     int vector_height;  /* height of individual vector */
129     int vqa_version;  /* this should be either 1, 2 or 3 */
130
131     unsigned char *codebook;         /* the current codebook */
132     int codebook_size;
133     unsigned char *next_codebook_buffer;  /* accumulator for next codebook */
134     int next_codebook_buffer_index;
135
136     unsigned char *decode_buffer;
137     int decode_buffer_size;
138
139     /* number of frames to go before replacing codebook */
140     int partial_countdown;
141     int partial_count;
142
143 } VqaContext;
144
145 static int vqa_decode_init(AVCodecContext *avctx)
146 {
147     VqaContext *s = (VqaContext *)avctx->priv_data;
148     unsigned char *vqa_header;
149     int i, j, codebook_index;;
150
151     s->avctx = avctx;
152     avctx->pix_fmt = PIX_FMT_PAL8;
153     avctx->has_b_frames = 0;
154     dsputil_init(&s->dsp, avctx);
155
156     /* make sure the extradata made it */
157     if (s->avctx->extradata_size != VQA_HEADER_SIZE) {
158         printf("  VQA video: expected extradata size of %d\n", VQA_HEADER_SIZE);
159         return -1;
160     }
161
162     /* load up the VQA parameters from the header */
163     vqa_header = (unsigned char *)s->avctx->extradata;
164     s->vqa_version = vqa_header[0];
165     s->width = LE_16(&vqa_header[6]);
166     s->height = LE_16(&vqa_header[8]);
167     s->vector_width = vqa_header[10];
168     s->vector_height = vqa_header[11];
169     s->partial_count = s->partial_countdown = vqa_header[13];
170
171     /* the vector dimensions have to meet very stringent requirements */
172     if ((s->vector_width != 4) ||
173         ((s->vector_height != 2) && (s->vector_height != 4))) {
174         /* return without further initialization */
175         return -1;
176     }
177
178     /* allocate codebooks */
179     s->codebook_size = MAX_CODEBOOK_SIZE;
180     s->codebook = av_malloc(s->codebook_size);
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;
189     } else {
190         codebook_index = 0xF00 * 8;
191         for (i = 0; i < 256; i++)
192             for (j = 0; j < 8; j++)
193                 s->codebook[codebook_index++] = i;
194     }
195     s->next_codebook_buffer_index = 0;
196
197     /* allocate decode buffer */
198     s->decode_buffer_size = (s->width / s->vector_width) *
199         (s->height / s->vector_height) * 2;
200     s->decode_buffer = av_malloc(s->decode_buffer_size);
201
202     s->frame.data[0] = NULL;
203
204     return 0;
205 }
206
207 #define CHECK_COUNT() \
208     if (dest_index + count > dest_size) { \
209         printf ("  VQA video: decode_format80 problem: next op would overflow dest_index\n"); \
210         printf ("  VQA video: current dest_index = %d, count = %d, dest_size = %d\n", \
211             dest_index, count, dest_size); \
212         return; \
213     }
214
215 static void decode_format80(unsigned char *src, int src_size,
216     unsigned char *dest, int dest_size, int check_size) {
217
218     int src_index = 0;
219     int dest_index = 0;
220     int count;
221     int src_pos;
222     unsigned char color;
223     int i;
224
225     while (src_index < src_size) {
226
227         vqa_debug("      opcode %02X: ", src[src_index]);
228
229         /* 0x80 means that frame is finished */
230         if (src[src_index] == 0x80)
231             return;
232
233         if (dest_index >= dest_size) {
234             printf ("  VQA video: decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
235                 dest_index, dest_size);
236             return;
237         }
238
239         if (src[src_index] == 0xFF) {
240
241             src_index++;
242             count = LE_16(&src[src_index]);
243             src_index += 2;
244             src_pos = LE_16(&src[src_index]);
245             src_index += 2;
246             vqa_debug("(1) copy %X bytes from absolute pos %X\n", count, src_pos);
247             CHECK_COUNT();
248             for (i = 0; i < count; i++)
249                 dest[dest_index + i] = dest[src_pos + i];
250             dest_index += count;
251
252         } else if (src[src_index] == 0xFE) {
253
254             src_index++;
255             count = LE_16(&src[src_index]);
256             src_index += 2;
257             color = src[src_index++];
258             vqa_debug("(2) set %X bytes to %02X\n", count, color);
259             CHECK_COUNT();
260             memset(&dest[dest_index], color, count);
261             dest_index += count;
262
263         } else if ((src[src_index] & 0xC0) == 0xC0) {
264
265             count = (src[src_index++] & 0x3F) + 3;
266             src_pos = LE_16(&src[src_index]);
267             src_index += 2;
268             vqa_debug("(3) copy %X bytes from absolute pos %X\n", count, src_pos);
269             CHECK_COUNT();
270             for (i = 0; i < count; i++)
271                 dest[dest_index + i] = dest[src_pos + i];
272             dest_index += count;
273
274         } else if (src[src_index] > 0x80) {
275
276             count = src[src_index++] & 0x3F;
277             vqa_debug("(4) copy %X bytes from source to dest\n", count);
278             CHECK_COUNT();
279             memcpy(&dest[dest_index], &src[src_index], count);
280             src_index += count;
281             dest_index += count;
282
283         } else {
284
285             count = ((src[src_index] & 0x70) >> 4) + 3;
286             src_pos = BE_16(&src[src_index]) & 0x0FFF;
287             src_index += 2;
288             vqa_debug("(5) copy %X bytes from relpos %X\n", count, src_pos);
289             CHECK_COUNT();
290             for (i = 0; i < count; i++)
291                 dest[dest_index + i] = dest[dest_index - src_pos + i];
292             dest_index += count;
293         }
294     }
295
296     /* validate that the entire destination buffer was filled; this is
297      * important for decoding frame maps since each vector needs to have a
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);
304 }
305
306 static void vqa_decode_chunk(VqaContext *s)
307 {
308     unsigned int chunk_type;
309     unsigned int chunk_size;
310     int byte_skip;
311     unsigned int index = 0;
312     int i;
313     unsigned char r, g, b;
314     unsigned int *palette32;
315     int index_shift;
316
317     int cbf0_chunk = -1;
318     int cbfz_chunk = -1;
319     int cbp0_chunk = -1;
320     int cbpz_chunk = -1;
321     int cpl0_chunk = -1;
322     int cplz_chunk = -1;
323     int vptz_chunk = -1;
324
325     int x, y;
326     int lines = 0;
327     int pixel_ptr;
328     int vector_index = 0;
329     int lobyte = 0;
330     int hibyte = 0;
331     int lobytes = 0;
332     int hibytes = s->decode_buffer_size / 2;
333
334     /* first, traverse through the frame and find the subchunks */
335     while (index < s->size) {
336
337         chunk_type = BE_32(&s->buf[index]);
338         chunk_size = BE_32(&s->buf[index + 4]);
339
340         switch (chunk_type) {
341
342         case CBF0_TAG:
343             cbf0_chunk = index;
344             break;
345
346         case CBFZ_TAG:
347             cbfz_chunk = index;
348             break;
349
350         case CBP0_TAG:
351             cbp0_chunk = index;
352             break;
353
354         case CBPZ_TAG:
355             cbpz_chunk = index;
356             break;
357
358         case CPL0_TAG:
359             cpl0_chunk = index;
360             break;
361
362         case CPLZ_TAG:
363             cplz_chunk = index;
364             break;
365
366         case VPTZ_TAG:
367             vptz_chunk = index;
368             break;
369
370         default:
371             printf ("  VQA video: Found unknown chunk type: %c%c%c%c (%08X)\n",
372             (chunk_type >> 24) & 0xFF,
373             (chunk_type >> 16) & 0xFF,
374             (chunk_type >>  8) & 0xFF,
375             (chunk_type >>  0) & 0xFF,
376             chunk_type);
377             break;
378         }
379
380         byte_skip = chunk_size & 0x01;
381         index += (CHUNK_PREAMBLE_SIZE + chunk_size + byte_skip);
382     }
383
384     /* next, deal with the palette */
385     if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
386
387         /* a chunk should not have both chunk types */
388         printf ("  VQA video: problem: found both CPL0 and CPLZ chunks\n");
389         return;
390     }
391
392     /* decompress the palette chunk */
393     if (cplz_chunk != -1) {
394
395 /* yet to be handled */
396
397     }
398
399     /* convert the RGB palette into the machine's endian format */
400     if (cpl0_chunk != -1) {
401
402         chunk_size = BE_32(&s->buf[cpl0_chunk + 4]);
403         /* sanity check the palette size */
404         if (chunk_size / 3 > 256) {
405             printf ("  VQA video: problem: found a palette chunk with %d colors\n",
406                 chunk_size / 3);
407             return;
408         }
409         cpl0_chunk += CHUNK_PREAMBLE_SIZE;
410         palette32 = (unsigned int *)s->palette;
411         for (i = 0; i < chunk_size / 3; i++) {
412             /* scale by 4 to transform 6-bit palette -> 8-bit */
413             r = s->buf[cpl0_chunk++] * 4;
414             g = s->buf[cpl0_chunk++] * 4;
415             b = s->buf[cpl0_chunk++] * 4;
416             palette32[i] = (r << 16) | (g << 8) | (b);
417         }
418     }
419
420     /* next, look for a full codebook */
421     if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
422
423         /* a chunk should not have both chunk types */
424         printf ("  VQA video: problem: found both CBF0 and CBFZ chunks\n");
425         return;
426     }
427
428     /* decompress the full codebook chunk */
429     if (cbfz_chunk != -1) {
430
431         chunk_size = BE_32(&s->buf[cbfz_chunk + 4]);
432         cbfz_chunk += CHUNK_PREAMBLE_SIZE;
433         decode_format80(&s->buf[cbfz_chunk], chunk_size,
434             s->codebook, s->codebook_size, 0);
435     }
436
437     /* copy a full codebook */
438     if (cbf0_chunk != -1) {
439
440         chunk_size = BE_32(&s->buf[cbf0_chunk + 4]);
441         /* sanity check the full codebook size */
442         if (chunk_size > MAX_CODEBOOK_SIZE) {
443             printf ("  VQA video: problem: CBF0 chunk too large (0x%X bytes)\n",
444                 chunk_size);
445             return;
446         }
447         cbf0_chunk += CHUNK_PREAMBLE_SIZE;
448
449         memcpy(s->codebook, &s->buf[cbf0_chunk], chunk_size);
450     }
451
452     /* decode the frame */
453     if (vptz_chunk == -1) {
454
455         /* something is wrong if there is no VPTZ chunk */
456         printf ("  VQA video: problem: no VPTZ chunk found\n");
457         return;
458     }
459
460     chunk_size = BE_32(&s->buf[vptz_chunk + 4]);
461     vptz_chunk += CHUNK_PREAMBLE_SIZE;
462     decode_format80(&s->buf[vptz_chunk], chunk_size,
463         s->decode_buffer, s->decode_buffer_size, 1);
464
465     /* render the final PAL8 frame */
466     if (s->vector_height == 4)
467         index_shift = 4;
468     else
469         index_shift = 3;
470     for (y = 0; y < s->frame.linesize[0] * s->height; 
471         y += s->frame.linesize[0] * s->vector_height) {
472
473         for (x = y; x < y + s->width; x += 4, lobytes++, hibytes++) {
474             pixel_ptr = x;
475
476             /* get the vector index, the method for which varies according to
477              * VQA file version */
478             switch (s->vqa_version) {
479
480             case 1:
481 /* still need sample media for this case (only one game, "Legend of 
482  * Kyrandia III : Malcolm's Revenge", is known to use this version) */
483                 lines = 0;
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         printf ("  VQA video: problem: found both CBP0 and CBPZ chunks\n");
514         return;
515     }
516
517     if (cbp0_chunk != -1) {
518
519         chunk_size = BE_32(&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 = BE_32(&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
565 static int vqa_decode_frame(AVCodecContext *avctx,
566                             void *data, int *data_size,
567                             uint8_t *buf, int buf_size)
568 {
569     VqaContext *s = (VqaContext *)avctx->priv_data;
570
571     s->buf = buf;
572     s->size = buf_size;
573
574     if (s->frame.data[0])
575         avctx->release_buffer(avctx, &s->frame);
576
577     if (avctx->get_buffer(avctx, &s->frame)) {
578         printf ("  VQA Video: get_buffer() failed\n");
579         return -1;
580     }
581
582     vqa_decode_chunk(s);
583
584     /* make the palette available on the way out */
585     memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
586
587     *data_size = sizeof(AVFrame);
588     *(AVFrame*)data = s->frame;
589
590     /* report that the buffer was completely consumed */
591     return buf_size;
592 }
593
594 static int vqa_decode_end(AVCodecContext *avctx)
595 {
596     VqaContext *s = (VqaContext *)avctx->priv_data;
597
598     av_free(s->codebook);
599     av_free(s->next_codebook_buffer);
600     av_free(s->decode_buffer);
601
602     if (s->frame.data[0])
603         avctx->release_buffer(avctx, &s->frame);
604
605     return 0;
606 }
607
608 AVCodec vqa_decoder = {
609     "vqavideo",
610     CODEC_TYPE_VIDEO,
611     CODEC_ID_WS_VQA,
612     sizeof(VqaContext),
613     vqa_decode_init,
614     NULL,
615     vqa_decode_end,
616     vqa_decode_frame,
617     CODEC_CAP_DR1,
618 };