xref: /third_party/ffmpeg/libavcodec/vqavideo.c (revision cabdff1a)
1/*
2 * Westwood Studios VQA Video Decoder
3 * Copyright (c) 2003 Mike Melanson <melanson@pcisys.net>
4 * Copyright (c) 2021 Pekka Väänänen <pekka.vaananen@iki.fi>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23/**
24 * @file
25 * VQA Video Decoder
26 * @author Mike Melanson (melanson@pcisys.net)
27 * @see http://wiki.multimedia.cx/index.php?title=VQA
28 *
29 * The VQA video decoder outputs PAL8 or RGB555 colorspace data, depending
30 * on the type of data in the file.
31 *
32 * This decoder needs the 42-byte VQHD header from the beginning
33 * of the VQA file passed through the extradata field. The VQHD header
34 * is laid out as:
35 *
36 *   bytes 0-3   chunk fourcc: 'VQHD'
37 *   bytes 4-7   chunk size in big-endian format, should be 0x0000002A
38 *   bytes 8-49  VQHD chunk data
39 *
40 * Bytes 8-49 are what this decoder expects to see.
41 *
42 * Briefly, VQA is a vector quantized animation format that operates in a
43 * VGA palettized colorspace. It operates on pixel vectors (blocks)
44 * of either 4x2 or 4x4 in size. Compressed VQA chunks can contain vector
45 * codebooks, palette information, and code maps for rendering vectors onto
46 * frames. Any of these components can also be compressed with a run-length
47 * encoding (RLE) algorithm commonly referred to as "format80".
48 *
49 * VQA takes a novel approach to rate control. Each group of n frames
50 * (usually, n = 8) relies on a different vector codebook. Rather than
51 * transporting an entire codebook every 8th frame, the new codebook is
52 * broken up into 8 pieces and sent along with the compressed video chunks
53 * for each of the 8 frames preceding the 8 frames which require the
54 * codebook. A full codebook is also sent on the very first frame of a
55 * file. This is an interesting technique, although it makes random file
56 * seeking difficult despite the fact that the frames are all intracoded.
57 *
58 * V1,2 VQA uses 12-bit codebook indexes. If the 12-bit indexes were
59 * packed into bytes and then RLE compressed, bytewise, the results would
60 * be poor. That is why the coding method divides each index into 2 parts,
61 * the top 4 bits and the bottom 8 bits, then RL encodes the 4-bit pieces
62 * together and the 8-bit pieces together. If most of the vectors are
63 * clustered into one group of 256 vectors, most of the 4-bit index pieces
64 * should be the same.
65 *
66 * VQA3 introduces a 15-bit high color codebook, delta coding, replaces
67 * the above "split byte" scheme with RLE compression, and extends the
68 * "format80" compression with relative references. In VQA3 the whole
69 * codebook is always updated as a whole without splitting it into pieces.
70 */
71
72#include <stdio.h>
73#include <stdlib.h>
74#include <string.h>
75
76#include "libavutil/intreadwrite.h"
77#include "libavutil/imgutils.h"
78#include "avcodec.h"
79#include "bytestream.h"
80#include "codec_internal.h"
81#include "internal.h"
82
83#define PALETTE_COUNT 256
84#define VQA_HEADER_SIZE 0x2A
85
86/* allocate the maximum vector space, regardless of the file version:
87 * (0xFF00 codebook vectors + 0x100 solid pixel vectors) * (4x4 pixels/block) */
88#define MAX_CODEBOOK_VECTORS 0xFF00
89#define SOLID_PIXEL_VECTORS 0x100
90#define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS)
91#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4 * sizeof(uint16_t))
92
93#define CBF0_TAG MKBETAG('C', 'B', 'F', '0')
94#define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z')
95#define CBP0_TAG MKBETAG('C', 'B', 'P', '0')
96#define CBPZ_TAG MKBETAG('C', 'B', 'P', 'Z')
97#define CPL0_TAG MKBETAG('C', 'P', 'L', '0')
98#define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z')
99#define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z')
100#define VPTR_TAG MKBETAG('V', 'P', 'T', 'R')
101#define VPRZ_TAG MKBETAG('V', 'P', 'R', 'Z')
102
103typedef struct VqaContext {
104    AVFrame *frame;
105    AVCodecContext *avctx;
106    GetByteContext gb;
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} VqaContext;
128
129static av_cold int vqa_decode_init(AVCodecContext *avctx)
130{
131    VqaContext *s = avctx->priv_data;
132    int i, j, codebook_index, ret;
133    int colors;
134
135    s->avctx = avctx;
136
137    /* make sure the extradata made it */
138    if (s->avctx->extradata_size != VQA_HEADER_SIZE) {
139        av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n", VQA_HEADER_SIZE);
140        return AVERROR(EINVAL);
141    }
142
143    /* load up the VQA parameters from the header */
144    s->vqa_version = s->avctx->extradata[0];
145
146    if (s->vqa_version < 1 || s->vqa_version > 3) {
147        avpriv_request_sample(avctx, "VQA Version %i", s->vqa_version);
148        return AVERROR_INVALIDDATA;
149    }
150
151    s->width = AV_RL16(&s->avctx->extradata[6]);
152    s->height = AV_RL16(&s->avctx->extradata[8]);
153    if ((ret = ff_set_dimensions(avctx, s->width, s->height)) < 0) {
154        s->width= s->height= 0;
155        return ret;
156    }
157    s->vector_width = s->avctx->extradata[10];
158    s->vector_height = s->avctx->extradata[11];
159    s->partial_count = s->partial_countdown = s->avctx->extradata[13];
160
161    colors = (s->avctx->extradata[14] << 8) | s->avctx->extradata[15];
162
163    if (colors > 0) {
164        avctx->pix_fmt = AV_PIX_FMT_PAL8;
165    } else {
166        avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
167    }
168
169    /* the vector dimensions have to meet very stringent requirements */
170    if ((s->vector_width != 4) ||
171        ((s->vector_height != 2) && (s->vector_height != 4))) {
172        /* return without further initialization */
173        return AVERROR_INVALIDDATA;
174    }
175
176    if (s->width % s->vector_width || s->height % s->vector_height) {
177        av_log(avctx, AV_LOG_ERROR, "Image size not multiple of block size\n");
178        return AVERROR_INVALIDDATA;
179    }
180
181    s->frame = av_frame_alloc();
182    if (!s->frame)
183        return AVERROR(ENOMEM);
184
185    /* allocate codebooks */
186    s->codebook_size = MAX_CODEBOOK_SIZE;
187    s->codebook = av_malloc(s->codebook_size);
188    if (!s->codebook)
189        return AVERROR(ENOMEM);
190    s->next_codebook_buffer = av_malloc(s->codebook_size);
191    if (!s->next_codebook_buffer)
192        return AVERROR(ENOMEM);
193
194    /* allocate decode buffer */
195    s->decode_buffer_size = (s->width / s->vector_width) *
196        (s->height / s->vector_height) * 2;
197    s->decode_buffer = av_mallocz(s->decode_buffer_size);
198    if (!s->decode_buffer)
199        return AVERROR(ENOMEM);
200
201    /* initialize the solid-color vectors */
202    if (s->vector_height == 4) {
203        codebook_index = 0xFF00 * 16;
204        for (i = 0; i < 256; i++)
205            for (j = 0; j < 16; j++)
206                s->codebook[codebook_index++] = i;
207    } else {
208        codebook_index = 0xF00 * 8;
209        for (i = 0; i < 256; i++)
210            for (j = 0; j < 8; j++)
211                s->codebook[codebook_index++] = i;
212    }
213    s->next_codebook_buffer_index = 0;
214
215    return 0;
216}
217
218#define CHECK_COUNT() \
219    if (dest_index + count > dest_size) { \
220        av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
221        av_log(s->avctx, AV_LOG_ERROR, "current dest_index = %d, count = %d, dest_size = %d\n", \
222            dest_index, count, dest_size); \
223        return AVERROR_INVALIDDATA; \
224    }
225
226#define CHECK_COPY(idx) \
227    if (idx < 0 || idx + count > dest_size) { \
228        av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
229        av_log(s->avctx, AV_LOG_ERROR, "current src_pos = %d, count = %d, dest_size = %d\n", \
230            src_pos, count, dest_size); \
231        return AVERROR_INVALIDDATA; \
232    }
233
234
235static int decode_format80(VqaContext *s, int src_size,
236    unsigned char *dest, int dest_size, int check_size) {
237
238    int dest_index = 0;
239    int count, opcode, start;
240    int src_pos;
241    unsigned char color;
242    int i;
243    int relative = 0;
244
245    if (src_size < 0 || src_size > bytestream2_get_bytes_left(&s->gb)) {
246        av_log(s->avctx, AV_LOG_ERROR, "Chunk size %d is out of range\n",
247               src_size);
248        return AVERROR_INVALIDDATA;
249    }
250
251    /* the "new" scheme makes references relative to destination pointer */
252    if (bytestream2_peek_byte(&s->gb) == 0x00) {
253        relative = 1;
254        bytestream2_get_byte(&s->gb);
255        ff_tlog(s->avctx, "found new format stream ");
256    }
257
258    start = bytestream2_tell(&s->gb);
259    while (bytestream2_tell(&s->gb) - start < src_size) {
260        opcode = bytestream2_get_byte(&s->gb);
261        ff_tlog(s->avctx, "opcode %02X: ", opcode);
262
263        /* 0x80 means that frame is finished */
264        if (opcode == 0x80)
265            break;
266
267        if (dest_index >= dest_size) {
268            av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
269                dest_index, dest_size);
270            return AVERROR_INVALIDDATA;
271        }
272
273        if (opcode == 0xFF) {
274
275            count   = bytestream2_get_le16(&s->gb);
276            src_pos = bytestream2_get_le16(&s->gb);
277            if (relative)
278                src_pos = dest_index - src_pos;
279            ff_tlog(s->avctx, "(1) copy %X bytes from pos %X\n", count, src_pos);
280            CHECK_COUNT();
281            CHECK_COPY(src_pos);
282            for (i = 0; i < count; i++)
283                dest[dest_index + i] = dest[src_pos + i];
284            dest_index += count;
285
286        } else if (opcode == 0xFE) {
287
288            count = bytestream2_get_le16(&s->gb);
289            color = bytestream2_get_byte(&s->gb);
290            ff_tlog(s->avctx, "(2) set %X bytes to %02X\n", count, color);
291            CHECK_COUNT();
292            memset(&dest[dest_index], color, count);
293            dest_index += count;
294
295        } else if ((opcode & 0xC0) == 0xC0) {
296
297            count = (opcode & 0x3F) + 3;
298            src_pos = bytestream2_get_le16(&s->gb);
299            if (relative)
300                src_pos = dest_index - src_pos;
301            ff_tlog(s->avctx, "(3) copy %X bytes from pos %X\n", count, src_pos);
302            CHECK_COUNT();
303            CHECK_COPY(src_pos);
304            for (i = 0; i < count; i++)
305                dest[dest_index + i] = dest[src_pos + i];
306            dest_index += count;
307
308        } else if (opcode > 0x80) {
309
310            count = opcode & 0x3F;
311            ff_tlog(s->avctx, "(4) copy %X bytes from source to dest\n", count);
312            CHECK_COUNT();
313            bytestream2_get_buffer(&s->gb, &dest[dest_index], count);
314            dest_index += count;
315
316        } else {
317
318            count = ((opcode & 0x70) >> 4) + 3;
319            src_pos = bytestream2_get_byte(&s->gb) | ((opcode & 0x0F) << 8);
320            ff_tlog(s->avctx, "(5) copy %X bytes from relpos %X\n", count, src_pos);
321            CHECK_COUNT();
322            CHECK_COPY(dest_index - src_pos);
323            for (i = 0; i < count; i++)
324                dest[dest_index + i] = dest[dest_index - src_pos + i];
325            dest_index += count;
326        }
327    }
328
329    /* validate that the entire destination buffer was filled; this is
330     * important for decoding frame maps since each vector needs to have a
331     * codebook entry; it is not important for compressed codebooks because
332     * not every entry needs to be filled */
333    if (check_size)
334        if (dest_index < dest_size) {
335            av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n",
336                dest_index, dest_size);
337            memset(dest + dest_index, 0, dest_size - dest_index);
338        }
339
340    return 0; // let's display what we decoded anyway
341}
342
343static int vqa_decode_frame_pal8(VqaContext *s, AVFrame *frame)
344{
345    unsigned int chunk_type;
346    unsigned int chunk_size;
347    int byte_skip;
348    unsigned int index = 0;
349    int i;
350    unsigned char r, g, b;
351    int index_shift;
352    int res;
353
354    int cbf0_chunk = -1;
355    int cbfz_chunk = -1;
356    int cbp0_chunk = -1;
357    int cbpz_chunk = -1;
358    int cpl0_chunk = -1;
359    int cplz_chunk = -1;
360    int vptz_chunk = -1;
361
362    int x, y;
363    int lines = 0;
364    int pixel_ptr;
365    int vector_index = 0;
366    int lobyte = 0;
367    int hibyte = 0;
368    int lobytes = 0;
369    int hibytes = s->decode_buffer_size / 2;
370
371    /* first, traverse through the frame and find the subchunks */
372    while (bytestream2_get_bytes_left(&s->gb) >= 8) {
373
374        chunk_type = bytestream2_get_be32u(&s->gb);
375        index      = bytestream2_tell(&s->gb);
376        chunk_size = bytestream2_get_be32u(&s->gb);
377
378        switch (chunk_type) {
379
380        case CBF0_TAG:
381            cbf0_chunk = index;
382            break;
383
384        case CBFZ_TAG:
385            cbfz_chunk = index;
386            break;
387
388        case CBP0_TAG:
389            cbp0_chunk = index;
390            break;
391
392        case CBPZ_TAG:
393            cbpz_chunk = index;
394            break;
395
396        case CPL0_TAG:
397            cpl0_chunk = index;
398            break;
399
400        case CPLZ_TAG:
401            cplz_chunk = index;
402            break;
403
404        case VPTZ_TAG:
405            vptz_chunk = index;
406            break;
407
408        default:
409            av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
410                   av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
411            break;
412        }
413
414        byte_skip = chunk_size & 0x01;
415        bytestream2_skip(&s->gb, chunk_size + byte_skip);
416    }
417
418    /* next, deal with the palette */
419    if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
420
421        /* a chunk should not have both chunk types */
422        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CPL0 and CPLZ chunks\n");
423        return AVERROR_INVALIDDATA;
424    }
425
426    /* decompress the palette chunk */
427    if (cplz_chunk != -1) {
428
429/* yet to be handled */
430
431    }
432
433    /* convert the RGB palette into the machine's endian format */
434    if (cpl0_chunk != -1) {
435
436        bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET);
437        chunk_size = bytestream2_get_be32(&s->gb);
438        /* sanity check the palette size */
439        if (chunk_size / 3 > 256 || chunk_size > bytestream2_get_bytes_left(&s->gb)) {
440            av_log(s->avctx, AV_LOG_ERROR, "problem: found a palette chunk with %d colors\n",
441                chunk_size / 3);
442            return AVERROR_INVALIDDATA;
443        }
444        for (i = 0; i < chunk_size / 3; i++) {
445            /* scale by 4 to transform 6-bit palette -> 8-bit */
446            r = bytestream2_get_byteu(&s->gb) * 4;
447            g = bytestream2_get_byteu(&s->gb) * 4;
448            b = bytestream2_get_byteu(&s->gb) * 4;
449            s->palette[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
450            s->palette[i] |= s->palette[i] >> 6 & 0x30303;
451        }
452    }
453
454    /* next, look for a full codebook */
455    if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
456
457        /* a chunk should not have both chunk types */
458        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
459        return AVERROR_INVALIDDATA;
460    }
461
462    /* decompress the full codebook chunk */
463    if (cbfz_chunk != -1) {
464
465        bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
466        chunk_size = bytestream2_get_be32(&s->gb);
467        if ((res = decode_format80(s, chunk_size, s->codebook,
468                                   s->codebook_size, 0)) < 0)
469            return res;
470    }
471
472    /* copy a full codebook */
473    if (cbf0_chunk != -1) {
474
475        bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
476        chunk_size = bytestream2_get_be32(&s->gb);
477        /* sanity check the full codebook size */
478        if (chunk_size > MAX_CODEBOOK_SIZE) {
479            av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
480                chunk_size);
481            return AVERROR_INVALIDDATA;
482        }
483
484        bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
485    }
486
487    /* decode the frame */
488    if (vptz_chunk == -1) {
489
490        /* something is wrong if there is no VPTZ chunk */
491        av_log(s->avctx, AV_LOG_ERROR, "problem: no VPTZ chunk found\n");
492        return AVERROR_INVALIDDATA;
493    }
494
495    bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET);
496    chunk_size = bytestream2_get_be32(&s->gb);
497    if ((res = decode_format80(s, chunk_size,
498                               s->decode_buffer, s->decode_buffer_size, 1)) < 0)
499        return res;
500
501    /* render the final PAL8 frame */
502    if (s->vector_height == 4)
503        index_shift = 4;
504    else
505        index_shift = 3;
506    for (y = 0; y < s->height; y += s->vector_height) {
507        for (x = 0; x < s->width; x += 4, lobytes++, hibytes++) {
508            pixel_ptr = y * frame->linesize[0] + x;
509
510            /* get the vector index, the method for which varies according to
511             * VQA file version */
512            switch (s->vqa_version) {
513
514            case 1:
515                lobyte = s->decode_buffer[lobytes * 2];
516                hibyte = s->decode_buffer[(lobytes * 2) + 1];
517                vector_index = ((hibyte << 8) | lobyte) >> 3;
518                vector_index <<= index_shift;
519                lines = s->vector_height;
520                /* uniform color fill - a quick hack */
521                if (hibyte == 0xFF) {
522                    while (lines--) {
523                        frame->data[0][pixel_ptr + 0] = 255 - lobyte;
524                        frame->data[0][pixel_ptr + 1] = 255 - lobyte;
525                        frame->data[0][pixel_ptr + 2] = 255 - lobyte;
526                        frame->data[0][pixel_ptr + 3] = 255 - lobyte;
527                        pixel_ptr += frame->linesize[0];
528                    }
529                    lines=0;
530                }
531                break;
532
533            case 2:
534                lobyte = s->decode_buffer[lobytes];
535                hibyte = s->decode_buffer[hibytes];
536                vector_index = (hibyte << 8) | lobyte;
537                vector_index <<= index_shift;
538                lines = s->vector_height;
539                break;
540
541            case 3:
542                av_log(s->avctx, AV_LOG_ERROR, "VQA3 shouldn't have a color palette");
543                return AVERROR_INVALIDDATA;
544            }
545
546            while (lines--) {
547                frame->data[0][pixel_ptr + 0] = s->codebook[vector_index++];
548                frame->data[0][pixel_ptr + 1] = s->codebook[vector_index++];
549                frame->data[0][pixel_ptr + 2] = s->codebook[vector_index++];
550                frame->data[0][pixel_ptr + 3] = s->codebook[vector_index++];
551                pixel_ptr += frame->linesize[0];
552            }
553        }
554    }
555
556    /* handle partial codebook */
557    if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
558        /* a chunk should not have both chunk types */
559        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBP0 and CBPZ chunks\n");
560        return AVERROR_INVALIDDATA;
561    }
562
563    if (cbp0_chunk != -1) {
564
565        bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET);
566        chunk_size = bytestream2_get_be32(&s->gb);
567
568        if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
569            av_log(s->avctx, AV_LOG_ERROR, "cbp0 chunk too large (%u bytes)\n",
570                   chunk_size);
571            return AVERROR_INVALIDDATA;
572        }
573
574        /* accumulate partial codebook */
575        bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
576                               chunk_size);
577        s->next_codebook_buffer_index += chunk_size;
578
579        s->partial_countdown--;
580        if (s->partial_countdown <= 0) {
581
582            /* time to replace codebook */
583            memcpy(s->codebook, s->next_codebook_buffer,
584                s->next_codebook_buffer_index);
585
586            /* reset accounting */
587            s->next_codebook_buffer_index = 0;
588            s->partial_countdown = s->partial_count;
589        }
590    }
591
592    if (cbpz_chunk != -1) {
593
594        bytestream2_seek(&s->gb, cbpz_chunk, SEEK_SET);
595        chunk_size = bytestream2_get_be32(&s->gb);
596
597        if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
598            av_log(s->avctx, AV_LOG_ERROR, "cbpz chunk too large (%u bytes)\n",
599                   chunk_size);
600            return AVERROR_INVALIDDATA;
601        }
602
603        /* accumulate partial codebook */
604        bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
605                               chunk_size);
606        s->next_codebook_buffer_index += chunk_size;
607
608        s->partial_countdown--;
609        if (s->partial_countdown <= 0) {
610            bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index);
611            /* decompress codebook */
612            res = decode_format80(s, s->next_codebook_buffer_index,
613                                  s->codebook, s->codebook_size, 0);
614
615            /* reset accounting */
616            s->next_codebook_buffer_index = 0;
617            s->partial_countdown = s->partial_count;
618            if (res < 0)
619                return res;
620        }
621    }
622
623    return 0;
624}
625
626static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame)
627{
628    unsigned int chunk_type;
629    unsigned int chunk_size;
630    unsigned int index = 0;
631    int res;
632
633    int cbf0_chunk = -1;
634    int cbfz_chunk = -1;
635    int vptr_chunk = -1;
636    int vprz_chunk = -1;
637
638    GetByteContext gb_stream;
639
640    while (bytestream2_get_bytes_left(&s->gb) >= 8) {
641        chunk_type = bytestream2_get_be32u(&s->gb);
642        index      = bytestream2_tell(&s->gb);
643        chunk_size = bytestream2_get_be32u(&s->gb);
644
645        switch (chunk_type) {
646        case CBF0_TAG:
647            cbf0_chunk = index;
648            break;
649        case CBFZ_TAG:
650            cbfz_chunk = index;
651            break;
652        case VPTR_TAG:
653            vptr_chunk = index;
654            break;
655        case VPRZ_TAG:
656            vprz_chunk = index;
657            break;
658        default:
659            av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
660                   av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
661            break;
662        }
663
664        bytestream2_skip(&s->gb, chunk_size + (chunk_size & 0x01));
665    }
666
667    /* next, look for a full codebook */
668    if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
669        /* a chunk should not have both chunk types */
670        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
671        return AVERROR_INVALIDDATA;
672    }
673
674    /* decompress the full codebook chunk */
675    if (cbfz_chunk != -1) {
676        bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
677        chunk_size = bytestream2_get_be32(&s->gb);
678        if ((res = decode_format80(s, chunk_size, s->codebook,
679                                   s->codebook_size, 0)) < 0)
680            return res;
681    }
682
683    /* copy a full codebook */
684    if (cbf0_chunk != -1) {
685        bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
686        chunk_size = bytestream2_get_be32(&s->gb);
687        /* sanity check the full codebook size */
688        if (chunk_size > MAX_CODEBOOK_SIZE) {
689            av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
690                chunk_size);
691            return AVERROR_INVALIDDATA;
692        }
693
694        bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
695    }
696
697    /* decode the frame */
698
699    if (vptr_chunk != -1) {
700        /* copy uncompressed tile data */
701        bytestream2_seek(&s->gb, vptr_chunk, SEEK_SET);
702        chunk_size = bytestream2_get_be32(&s->gb);
703        if (chunk_size > s->decode_buffer_size) {
704            av_log(s->avctx, AV_LOG_ERROR, "VPTR chunk didn't fit in decode buffer");
705            return AVERROR_INVALIDDATA;
706        }
707        bytestream2_get_buffer(&s->gb, s->decode_buffer, chunk_size);
708    } else if (vprz_chunk != -1) {
709        /* decompress the tile data */
710        bytestream2_seek(&s->gb, vprz_chunk, SEEK_SET);
711
712        chunk_size = bytestream2_get_be32(&s->gb);
713        if ((res = decode_format80(s, chunk_size, s->decode_buffer, s->decode_buffer_size, 0)) < 0)
714            return res;
715    } else {
716        av_log(s->avctx, AV_LOG_ERROR, "frame has no block data\n");
717        return AVERROR_INVALIDDATA;
718    }
719
720    /* now uncompress the per-row RLE of the decode buffer and draw the blocks in framebuffer */
721
722    bytestream2_init(&gb_stream, s->decode_buffer, s->decode_buffer_size);
723
724    for (int y_pos = 0; y_pos < s->height; y_pos += s->vector_height) {
725        int x_pos = 0;
726
727        while (x_pos < s->width) {
728            int vector_index = 0;
729            int count = 0;
730            uint16_t code;
731            int type;
732
733            if (bytestream2_get_bytes_left(&gb_stream) < 2)
734                return AVERROR_INVALIDDATA;
735
736            code = bytestream2_get_le16(&gb_stream);
737
738            type = code >> 13;
739            code &= 0x1fff;
740
741            if (type == 0) {
742                x_pos += 4 * code;
743                continue;
744            } else if (type < 3) {
745                vector_index = code & 0xff;
746                count = ((code & 0x1f00) >> 7) + 1 + type;
747            } else if (type < 5) {
748                vector_index = code;
749                count = 1;
750            } else if (type < 7) {
751                vector_index = code;
752                count = bytestream2_get_byte(&gb_stream);
753            } else {
754                av_log(s->avctx, AV_LOG_ERROR, " unknown type in VPTR chunk (%d)\n",type);
755                return AVERROR_INVALIDDATA;
756            }
757
758            if (count < 0 || count > (s->width - x_pos) / s->vector_width) {
759                av_log(s->avctx, AV_LOG_ERROR, "invalid count: %d\n", count);
760                return AVERROR_INVALIDDATA;
761            }
762
763            while (count-- && x_pos < s->width) {
764                const int bytes_per_vector = 4 * s->vector_height * sizeof(uint16_t);
765                unsigned char *src = s->codebook + vector_index * bytes_per_vector;
766                unsigned char *dst = s->frame->data[0] + y_pos * s->frame->linesize[0]
767                    + sizeof(uint16_t) * x_pos;
768
769                if (vector_index >= MAX_VECTORS)
770                    return AVERROR_INVALIDDATA;
771
772                for (int y = 0; y < s->vector_height; y++) {
773                    int size = 4 * sizeof(uint16_t);
774                    memcpy(dst, src, size);
775                    dst += s->frame->linesize[0];
776                    src += size;
777                }
778
779                /* we might want to read the next block index from stream */
780                if ((type == 2) && count > 0) {
781                    vector_index = bytestream2_get_byte(&gb_stream);
782                }
783
784                x_pos += 4;
785            }
786
787            if (count > 0) {
788                av_log(s->avctx, AV_LOG_ERROR, "had %d leftover vectors\n", count);
789                return AVERROR_BUG;
790            }
791        }
792    }
793
794    return 0;
795}
796
797static int vqa_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
798                            int *got_frame, AVPacket *avpkt)
799{
800    VqaContext *s = avctx->priv_data;
801    int res;
802
803    if ((res = ff_reget_buffer(avctx, s->frame, 0)) < 0)
804        return res;
805
806    bytestream2_init(&s->gb, avpkt->data, avpkt->size);
807
808    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
809        if ((res = vqa_decode_frame_pal8(s, s->frame)) < 0)
810            return res;
811
812        /* make the palette available on the way out */
813        memcpy(s->frame->data[1], s->palette, PALETTE_COUNT * 4);
814        s->frame->palette_has_changed = 1;
815    } else if (avctx->pix_fmt == AV_PIX_FMT_RGB555LE) {
816        if ((res = vqa_decode_frame_hicolor(s, s->frame)) < 0)
817            return res;
818    } else {
819        av_log(s->avctx, AV_LOG_ERROR, "unsupported pixel format\n");
820        return AVERROR_BUG;
821    }
822
823    if ((res = av_frame_ref(rframe, s->frame)) < 0)
824        return res;
825
826    *got_frame      = 1;
827
828    /* report that the buffer was completely consumed */
829    return avpkt->size;
830}
831
832static av_cold int vqa_decode_end(AVCodecContext *avctx)
833{
834    VqaContext *s = avctx->priv_data;
835
836    av_frame_free(&s->frame);
837    av_freep(&s->codebook);
838    av_freep(&s->next_codebook_buffer);
839    av_freep(&s->decode_buffer);
840
841    return 0;
842}
843
844static const FFCodecDefault vqa_defaults[] = {
845    { "max_pixels", "640*480" },
846    { NULL },
847};
848
849const FFCodec ff_vqa_decoder = {
850    .p.name         = "vqavideo",
851    .p.long_name    = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"),
852    .p.type         = AVMEDIA_TYPE_VIDEO,
853    .p.id           = AV_CODEC_ID_WS_VQA,
854    .priv_data_size = sizeof(VqaContext),
855    .init           = vqa_decode_init,
856    .close          = vqa_decode_end,
857    FF_CODEC_DECODE_CB(vqa_decode_frame),
858    .p.capabilities = AV_CODEC_CAP_DR1,
859    .defaults       = vqa_defaults,
860    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
861};
862