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