]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - libavcodec/vqavideo.c
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
[frescor/ffmpeg.git] / 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 int palette[PALETTE_COUNT];
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     int index_shift;
315
316     int cbf0_chunk = -1;
317     int cbfz_chunk = -1;
318     int cbp0_chunk = -1;
319     int cbpz_chunk = -1;
320     int cpl0_chunk = -1;
321     int cplz_chunk = -1;
322     int vptz_chunk = -1;
323
324     int x, y;
325     int lines = 0;
326     int pixel_ptr;
327     int vector_index = 0;
328     int lobyte = 0;
329     int hibyte = 0;
330     int lobytes = 0;
331     int hibytes = s->decode_buffer_size / 2;
332
333     /* first, traverse through the frame and find the subchunks */
334     while (index < s->size) {
335
336         chunk_type = BE_32(&s->buf[index]);
337         chunk_size = BE_32(&s->buf[index + 4]);
338
339         switch (chunk_type) {
340
341         case CBF0_TAG:
342             cbf0_chunk = index;
343             break;
344
345         case CBFZ_TAG:
346             cbfz_chunk = index;
347             break;
348
349         case CBP0_TAG:
350             cbp0_chunk = index;
351             break;
352
353         case CBPZ_TAG:
354             cbpz_chunk = index;
355             break;
356
357         case CPL0_TAG:
358             cpl0_chunk = index;
359             break;
360
361         case CPLZ_TAG:
362             cplz_chunk = index;
363             break;
364
365         case VPTZ_TAG:
366             vptz_chunk = index;
367             break;
368
369         default:
370             printf ("  VQA video: Found unknown chunk type: %c%c%c%c (%08X)\n",
371             (chunk_type >> 24) & 0xFF,
372             (chunk_type >> 16) & 0xFF,
373             (chunk_type >>  8) & 0xFF,
374             (chunk_type >>  0) & 0xFF,
375             chunk_type);
376             break;
377         }
378
379         byte_skip = chunk_size & 0x01;
380         index += (CHUNK_PREAMBLE_SIZE + chunk_size + byte_skip);
381     }
382
383     /* next, deal with the palette */
384     if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
385
386         /* a chunk should not have both chunk types */
387         printf ("  VQA video: problem: found both CPL0 and CPLZ chunks\n");
388         return;
389     }
390
391     /* decompress the palette chunk */
392     if (cplz_chunk != -1) {
393
394 /* yet to be handled */
395
396     }
397
398     /* convert the RGB palette into the machine's endian format */
399     if (cpl0_chunk != -1) {
400
401         chunk_size = BE_32(&s->buf[cpl0_chunk + 4]);
402         /* sanity check the palette size */
403         if (chunk_size / 3 > 256) {
404             printf ("  VQA video: problem: found a palette chunk with %d colors\n",
405                 chunk_size / 3);
406             return;
407         }
408         cpl0_chunk += CHUNK_PREAMBLE_SIZE;
409         for (i = 0; i < chunk_size / 3; i++) {
410             /* scale by 4 to transform 6-bit palette -> 8-bit */
411             r = s->buf[cpl0_chunk++] * 4;
412             g = s->buf[cpl0_chunk++] * 4;
413             b = s->buf[cpl0_chunk++] * 4;
414             s->palette[i] = (r << 16) | (g << 8) | (b);
415         }
416     }
417
418     /* next, look for a full codebook */
419     if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
420
421         /* a chunk should not have both chunk types */
422         printf ("  VQA video: problem: found both CBF0 and CBFZ chunks\n");
423         return;
424     }
425
426     /* decompress the full codebook chunk */
427     if (cbfz_chunk != -1) {
428
429         chunk_size = BE_32(&s->buf[cbfz_chunk + 4]);
430         cbfz_chunk += CHUNK_PREAMBLE_SIZE;
431         decode_format80(&s->buf[cbfz_chunk], chunk_size,
432             s->codebook, s->codebook_size, 0);
433     }
434
435     /* copy a full codebook */
436     if (cbf0_chunk != -1) {
437
438         chunk_size = BE_32(&s->buf[cbf0_chunk + 4]);
439         /* sanity check the full codebook size */
440         if (chunk_size > MAX_CODEBOOK_SIZE) {
441             printf ("  VQA video: problem: CBF0 chunk too large (0x%X bytes)\n",
442                 chunk_size);
443             return;
444         }
445         cbf0_chunk += CHUNK_PREAMBLE_SIZE;
446
447         memcpy(s->codebook, &s->buf[cbf0_chunk], chunk_size);
448     }
449
450     /* decode the frame */
451     if (vptz_chunk == -1) {
452
453         /* something is wrong if there is no VPTZ chunk */
454         printf ("  VQA video: problem: no VPTZ chunk found\n");
455         return;
456     }
457
458     chunk_size = BE_32(&s->buf[vptz_chunk + 4]);
459     vptz_chunk += CHUNK_PREAMBLE_SIZE;
460     decode_format80(&s->buf[vptz_chunk], chunk_size,
461         s->decode_buffer, s->decode_buffer_size, 1);
462
463     /* render the final PAL8 frame */
464     if (s->vector_height == 4)
465         index_shift = 4;
466     else
467         index_shift = 3;
468     for (y = 0; y < s->frame.linesize[0] * s->height; 
469         y += s->frame.linesize[0] * s->vector_height) {
470
471         for (x = y; x < y + s->width; x += 4, lobytes++, hibytes++) {
472             pixel_ptr = x;
473
474             /* get the vector index, the method for which varies according to
475              * VQA file version */
476             switch (s->vqa_version) {
477
478             case 1:
479 /* still need sample media for this case (only one game, "Legend of 
480  * Kyrandia III : Malcolm's Revenge", is known to use this version) */
481                 lines = 0;
482                 break;
483
484             case 2:
485                 lobyte = s->decode_buffer[lobytes];
486                 hibyte = s->decode_buffer[hibytes];
487                 vector_index = (hibyte << 8) | lobyte;
488                 vector_index <<= index_shift;
489                 lines = s->vector_height;
490                 break;
491
492             case 3:
493 /* not implemented yet */
494                 lines = 0;
495                 break;
496             }
497
498             while (lines--) {
499                 s->frame.data[0][pixel_ptr + 0] = s->codebook[vector_index++];
500                 s->frame.data[0][pixel_ptr + 1] = s->codebook[vector_index++];
501                 s->frame.data[0][pixel_ptr + 2] = s->codebook[vector_index++];
502                 s->frame.data[0][pixel_ptr + 3] = s->codebook[vector_index++];
503                 pixel_ptr += s->frame.linesize[0];
504             }
505         }
506     }
507
508     /* handle partial codebook */
509     if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
510         /* a chunk should not have both chunk types */
511         printf ("  VQA video: problem: found both CBP0 and CBPZ chunks\n");
512         return;
513     }
514
515     if (cbp0_chunk != -1) {
516
517         chunk_size = BE_32(&s->buf[cbp0_chunk + 4]);
518         cbp0_chunk += CHUNK_PREAMBLE_SIZE;
519
520         /* accumulate partial codebook */
521         memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index],
522             &s->buf[cbp0_chunk], chunk_size);
523         s->next_codebook_buffer_index += chunk_size;
524
525         s->partial_countdown--;
526         if (s->partial_countdown == 0) {
527
528             /* time to replace codebook */
529             memcpy(s->codebook, s->next_codebook_buffer, 
530                 s->next_codebook_buffer_index);
531
532             /* reset accounting */
533             s->next_codebook_buffer_index = 0;
534             s->partial_countdown = s->partial_count;
535         }
536     }
537
538     if (cbpz_chunk != -1) {
539
540         chunk_size = BE_32(&s->buf[cbpz_chunk + 4]);
541         cbpz_chunk += CHUNK_PREAMBLE_SIZE;
542
543         /* accumulate partial codebook */
544         memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index],
545             &s->buf[cbpz_chunk], chunk_size);
546         s->next_codebook_buffer_index += chunk_size;
547
548         s->partial_countdown--;
549         if (s->partial_countdown == 0) {
550
551             /* decompress codebook */
552             decode_format80(s->next_codebook_buffer, 
553                 s->next_codebook_buffer_index, 
554                 s->codebook, s->codebook_size, 0);
555
556             /* reset accounting */
557             s->next_codebook_buffer_index = 0;
558             s->partial_countdown = s->partial_count;
559         }
560     }
561 }
562
563 static int vqa_decode_frame(AVCodecContext *avctx,
564                             void *data, int *data_size,
565                             uint8_t *buf, int buf_size)
566 {
567     VqaContext *s = (VqaContext *)avctx->priv_data;
568
569     s->buf = buf;
570     s->size = buf_size;
571
572     if (s->frame.data[0])
573         avctx->release_buffer(avctx, &s->frame);
574
575     if (avctx->get_buffer(avctx, &s->frame)) {
576         printf ("  VQA Video: get_buffer() failed\n");
577         return -1;
578     }
579
580     vqa_decode_chunk(s);
581
582     /* make the palette available on the way out */
583     memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
584     s->frame.palette_has_changed = 1;
585
586     *data_size = sizeof(AVFrame);
587     *(AVFrame*)data = s->frame;
588
589     /* report that the buffer was completely consumed */
590     return buf_size;
591 }
592
593 static int vqa_decode_end(AVCodecContext *avctx)
594 {
595     VqaContext *s = (VqaContext *)avctx->priv_data;
596
597     av_free(s->codebook);
598     av_free(s->next_codebook_buffer);
599     av_free(s->decode_buffer);
600
601     if (s->frame.data[0])
602         avctx->release_buffer(avctx, &s->frame);
603
604     return 0;
605 }
606
607 AVCodec vqa_decoder = {
608     "vqavideo",
609     CODEC_TYPE_VIDEO,
610     CODEC_ID_WS_VQA,
611     sizeof(VqaContext),
612     vqa_decode_init,
613     NULL,
614     vqa_decode_end,
615     vqa_decode_frame,
616     CODEC_CAP_DR1,
617 };