Coverage Report

Created: 2024-09-06 07:53

/src/ffmpeg/libavcodec/vqavideo.c
Line
Count
Source (jump to first uncovered line)
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 <string.h>
74
75
#include "libavutil/intreadwrite.h"
76
#include "libavutil/mem.h"
77
#include "avcodec.h"
78
#include "bytestream.h"
79
#include "codec_internal.h"
80
#include "decode.h"
81
82
37.6k
#define PALETTE_COUNT 256
83
1.49k
#define VQA_HEADER_SIZE 0x2A
84
85
/* allocate the maximum vector space, regardless of the file version:
86
 * (0xFF00 codebook vectors + 0x100 solid pixel vectors) * (4x4 pixels/block) */
87
80.4k
#define MAX_CODEBOOK_VECTORS 0xFF00
88
80.4k
#define SOLID_PIXEL_VECTORS 0x100
89
80.4k
#define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS)
90
8.53k
#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4 * sizeof(uint16_t))
91
92
2.21k
#define CBF0_TAG MKBETAG('C', 'B', 'F', '0')
93
1.54k
#define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z')
94
1.63k
#define CBP0_TAG MKBETAG('C', 'B', 'P', '0')
95
4.61k
#define CBPZ_TAG MKBETAG('C', 'B', 'P', 'Z')
96
1.81k
#define CPL0_TAG MKBETAG('C', 'P', 'L', '0')
97
447
#define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z')
98
45.8k
#define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z')
99
1.27k
#define VPTR_TAG MKBETAG('V', 'P', 'T', 'R')
100
3.26k
#define VPRZ_TAG MKBETAG('V', 'P', 'R', 'Z')
101
102
typedef struct VqaContext {
103
    AVFrame *frame;
104
    AVCodecContext *avctx;
105
    GetByteContext gb;
106
107
    uint32_t palette[PALETTE_COUNT];
108
109
    int width;   /* width of a frame */
110
    int height;   /* height of a frame */
111
    int vector_width;  /* width of individual vector */
112
    int vector_height;  /* height of individual vector */
113
    int vqa_version;  /* this should be either 1, 2 or 3 */
114
115
    unsigned char *codebook; /* the current codebook */
116
    int codebook_size;
117
    unsigned char *next_codebook_buffer; /* accumulator for next codebook */
118
    int next_codebook_buffer_index;
119
120
    unsigned char *decode_buffer;
121
    int decode_buffer_size;
122
123
    /* number of frames to go before replacing codebook */
124
    int partial_countdown;
125
    int partial_count;
126
} VqaContext;
127
128
static av_cold int vqa_decode_init(AVCodecContext *avctx)
129
1.29k
{
130
1.29k
    VqaContext *s = avctx->priv_data;
131
1.29k
    int i, j, codebook_index, ret;
132
1.29k
    int colors;
133
134
1.29k
    s->avctx = avctx;
135
136
    /* make sure the extradata made it */
137
1.29k
    if (s->avctx->extradata_size != VQA_HEADER_SIZE) {
138
202
        av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n", VQA_HEADER_SIZE);
139
202
        return AVERROR(EINVAL);
140
202
    }
141
142
    /* load up the VQA parameters from the header */
143
1.09k
    s->vqa_version = s->avctx->extradata[0];
144
145
1.09k
    if (s->vqa_version < 1 || s->vqa_version > 3) {
146
3
        avpriv_request_sample(avctx, "VQA Version %i", s->vqa_version);
147
3
        return AVERROR_INVALIDDATA;
148
3
    }
149
150
1.09k
    s->width = AV_RL16(&s->avctx->extradata[6]);
151
1.09k
    s->height = AV_RL16(&s->avctx->extradata[8]);
152
1.09k
    if ((ret = ff_set_dimensions(avctx, s->width, s->height)) < 0) {
153
3
        s->width= s->height= 0;
154
3
        return ret;
155
3
    }
156
1.08k
    s->vector_width = s->avctx->extradata[10];
157
1.08k
    s->vector_height = s->avctx->extradata[11];
158
1.08k
    s->partial_count = s->partial_countdown = s->avctx->extradata[13];
159
160
1.08k
    colors = (s->avctx->extradata[14] << 8) | s->avctx->extradata[15];
161
162
1.08k
    if (colors > 0) {
163
751
        avctx->pix_fmt = AV_PIX_FMT_PAL8;
164
751
    } else {
165
336
        avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
166
336
    }
167
168
    /* the vector dimensions have to meet very stringent requirements */
169
1.08k
    if ((s->vector_width != 4) ||
170
1.08k
        ((s->vector_height != 2) && (s->vector_height != 4))) {
171
        /* return without further initialization */
172
12
        return AVERROR_INVALIDDATA;
173
12
    }
174
175
1.07k
    if (s->width % s->vector_width || s->height % s->vector_height) {
176
3
        av_log(avctx, AV_LOG_ERROR, "Image size not multiple of block size\n");
177
3
        return AVERROR_INVALIDDATA;
178
3
    }
179
180
1.07k
    s->frame = av_frame_alloc();
181
1.07k
    if (!s->frame)
182
0
        return AVERROR(ENOMEM);
183
184
    /* allocate codebooks */
185
1.07k
    s->codebook_size = MAX_CODEBOOK_SIZE;
186
1.07k
    s->codebook = av_malloc(s->codebook_size);
187
1.07k
    if (!s->codebook)
188
0
        return AVERROR(ENOMEM);
189
1.07k
    s->next_codebook_buffer = av_malloc(s->codebook_size);
190
1.07k
    if (!s->next_codebook_buffer)
191
0
        return AVERROR(ENOMEM);
192
193
    /* allocate decode buffer */
194
1.07k
    s->decode_buffer_size = (s->width / s->vector_width) *
195
1.07k
        (s->height / s->vector_height) * 2;
196
1.07k
    s->decode_buffer = av_mallocz(s->decode_buffer_size);
197
1.07k
    if (!s->decode_buffer)
198
0
        return AVERROR(ENOMEM);
199
200
    /* initialize the solid-color vectors */
201
1.07k
    if (s->vector_height == 4) {
202
46
        codebook_index = 0xFF00 * 16;
203
11.8k
        for (i = 0; i < 256; i++)
204
200k
            for (j = 0; j < 16; j++)
205
188k
                s->codebook[codebook_index++] = i;
206
1.02k
    } else {
207
1.02k
        codebook_index = 0xF00 * 8;
208
263k
        for (i = 0; i < 256; i++)
209
2.36M
            for (j = 0; j < 8; j++)
210
2.10M
                s->codebook[codebook_index++] = i;
211
1.02k
    }
212
1.07k
    s->next_codebook_buffer_index = 0;
213
214
1.07k
    return 0;
215
1.07k
}
216
217
#define CHECK_COUNT() \
218
11.4M
    if (dest_index + count > dest_size) { \
219
1.10k
        av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
220
1.10k
        av_log(s->avctx, AV_LOG_ERROR, "current dest_index = %d, count = %d, dest_size = %d\n", \
221
1.10k
            dest_index, count, dest_size); \
222
1.10k
        return AVERROR_INVALIDDATA; \
223
1.10k
    }
224
225
#define CHECK_COPY(idx) \
226
11.4M
    if (idx < 0 || idx + count > dest_size) { \
227
2.52k
        av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
228
2.52k
        av_log(s->avctx, AV_LOG_ERROR, "current src_pos = %d, count = %d, dest_size = %d\n", \
229
2.52k
            src_pos, count, dest_size); \
230
2.52k
        return AVERROR_INVALIDDATA; \
231
2.52k
    }
232
233
234
static int decode_format80(VqaContext *s, int src_size,
235
51.4k
    unsigned char *dest, int dest_size, int check_size) {
236
237
51.4k
    int dest_index = 0;
238
51.4k
    int count, opcode, start;
239
51.4k
    int src_pos;
240
51.4k
    unsigned char color;
241
51.4k
    int i;
242
51.4k
    int relative = 0;
243
244
51.4k
    if (src_size < 0 || src_size > bytestream2_get_bytes_left(&s->gb)) {
245
1.95k
        av_log(s->avctx, AV_LOG_ERROR, "Chunk size %d is out of range\n",
246
1.95k
               src_size);
247
1.95k
        return AVERROR_INVALIDDATA;
248
1.95k
    }
249
250
    /* the "new" scheme makes references relative to destination pointer */
251
49.4k
    if (bytestream2_peek_byte(&s->gb) == 0x00) {
252
33.6k
        relative = 1;
253
33.6k
        bytestream2_get_byte(&s->gb);
254
33.6k
        ff_tlog(s->avctx, "found new format stream ");
255
33.6k
    }
256
257
49.4k
    start = bytestream2_tell(&s->gb);
258
11.4M
    while (bytestream2_tell(&s->gb) - start < src_size) {
259
11.4M
        opcode = bytestream2_get_byte(&s->gb);
260
11.4M
        ff_tlog(s->avctx, "opcode %02X: ", opcode);
261
262
        /* 0x80 means that frame is finished */
263
11.4M
        if (opcode == 0x80)
264
212
            break;
265
266
11.4M
        if (dest_index >= dest_size) {
267
220
            av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
268
220
                dest_index, dest_size);
269
220
            return AVERROR_INVALIDDATA;
270
220
        }
271
272
11.4M
        if (opcode == 0xFF) {
273
274
9.15k
            count   = bytestream2_get_le16(&s->gb);
275
9.15k
            src_pos = bytestream2_get_le16(&s->gb);
276
9.15k
            if (relative)
277
1.97k
                src_pos = dest_index - src_pos;
278
9.15k
            ff_tlog(s->avctx, "(1) copy %X bytes from pos %X\n", count, src_pos);
279
9.15k
            CHECK_COUNT();
280
8.90k
            CHECK_COPY(src_pos);
281
387M
            for (i = 0; i < count; i++)
282
387M
                dest[dest_index + i] = dest[src_pos + i];
283
8.39k
            dest_index += count;
284
285
11.4M
        } else if (opcode == 0xFE) {
286
287
2.99k
            count = bytestream2_get_le16(&s->gb);
288
2.99k
            color = bytestream2_get_byte(&s->gb);
289
2.99k
            ff_tlog(s->avctx, "(2) set %X bytes to %02X\n", count, color);
290
2.99k
            CHECK_COUNT();
291
2.77k
            memset(&dest[dest_index], color, count);
292
2.77k
            dest_index += count;
293
294
11.4M
        } else if ((opcode & 0xC0) == 0xC0) {
295
296
5.98k
            count = (opcode & 0x3F) + 3;
297
5.98k
            src_pos = bytestream2_get_le16(&s->gb);
298
5.98k
            if (relative)
299
1.18k
                src_pos = dest_index - src_pos;
300
5.98k
            ff_tlog(s->avctx, "(3) copy %X bytes from pos %X\n", count, src_pos);
301
5.98k
            CHECK_COUNT();
302
5.76k
            CHECK_COPY(src_pos);
303
182k
            for (i = 0; i < count; i++)
304
177k
                dest[dest_index + i] = dest[src_pos + i];
305
5.32k
            dest_index += count;
306
307
11.4M
        } else if (opcode > 0x80) {
308
309
1.04k
            count = opcode & 0x3F;
310
1.04k
            ff_tlog(s->avctx, "(4) copy %X bytes from source to dest\n", count);
311
1.04k
            CHECK_COUNT();
312
841
            bytestream2_get_buffer(&s->gb, &dest[dest_index], count);
313
841
            dest_index += count;
314
315
11.4M
        } else {
316
317
11.4M
            count = ((opcode & 0x70) >> 4) + 3;
318
11.4M
            src_pos = bytestream2_get_byte(&s->gb) | ((opcode & 0x0F) << 8);
319
11.4M
            ff_tlog(s->avctx, "(5) copy %X bytes from relpos %X\n", count, src_pos);
320
11.4M
            CHECK_COUNT();
321
11.4M
            CHECK_COPY(dest_index - src_pos);
322
45.7M
            for (i = 0; i < count; i++)
323
34.3M
                dest[dest_index + i] = dest[dest_index - src_pos + i];
324
11.4M
            dest_index += count;
325
11.4M
        }
326
11.4M
    }
327
328
    /* validate that the entire destination buffer was filled; this is
329
     * important for decoding frame maps since each vector needs to have a
330
     * codebook entry; it is not important for compressed codebooks because
331
     * not every entry needs to be filled */
332
45.6k
    if (check_size)
333
40.3k
        if (dest_index < dest_size) {
334
40.1k
            av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n",
335
40.1k
                dest_index, dest_size);
336
40.1k
            memset(dest + dest_index, 0, dest_size - dest_index);
337
40.1k
        }
338
339
45.6k
    return 0; // let's display what we decoded anyway
340
49.4k
}
341
342
static int vqa_decode_frame_pal8(VqaContext *s, AVFrame *frame)
343
61.4k
{
344
61.4k
    unsigned int chunk_type;
345
61.4k
    unsigned int chunk_size;
346
61.4k
    int byte_skip;
347
61.4k
    unsigned int index = 0;
348
61.4k
    int i;
349
61.4k
    unsigned char r, g, b;
350
61.4k
    int index_shift;
351
61.4k
    int res;
352
353
61.4k
    int cbf0_chunk = -1;
354
61.4k
    int cbfz_chunk = -1;
355
61.4k
    int cbp0_chunk = -1;
356
61.4k
    int cbpz_chunk = -1;
357
61.4k
    int cpl0_chunk = -1;
358
61.4k
    int cplz_chunk = -1;
359
61.4k
    int vptz_chunk = -1;
360
361
61.4k
    int x, y;
362
61.4k
    int lines = 0;
363
61.4k
    int pixel_ptr;
364
61.4k
    int vector_index = 0;
365
61.4k
    int lobyte = 0;
366
61.4k
    int hibyte = 0;
367
61.4k
    int lobytes = 0;
368
61.4k
    int hibytes = s->decode_buffer_size / 2;
369
370
    /* first, traverse through the frame and find the subchunks */
371
197k
    while (bytestream2_get_bytes_left(&s->gb) >= 8) {
372
373
136k
        chunk_type = bytestream2_get_be32u(&s->gb);
374
136k
        index      = bytestream2_tell(&s->gb);
375
136k
        chunk_size = bytestream2_get_be32u(&s->gb);
376
377
136k
        switch (chunk_type) {
378
379
1.10k
        case CBF0_TAG:
380
1.10k
            cbf0_chunk = index;
381
1.10k
            break;
382
383
792
        case CBFZ_TAG:
384
792
            cbfz_chunk = index;
385
792
            break;
386
387
1.63k
        case CBP0_TAG:
388
1.63k
            cbp0_chunk = index;
389
1.63k
            break;
390
391
4.61k
        case CBPZ_TAG:
392
4.61k
            cbpz_chunk = index;
393
4.61k
            break;
394
395
1.81k
        case CPL0_TAG:
396
1.81k
            cpl0_chunk = index;
397
1.81k
            break;
398
399
447
        case CPLZ_TAG:
400
447
            cplz_chunk = index;
401
447
            break;
402
403
45.8k
        case VPTZ_TAG:
404
45.8k
            vptz_chunk = index;
405
45.8k
            break;
406
407
79.7k
        default:
408
79.7k
            av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
409
79.7k
                   av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
410
79.7k
            break;
411
136k
        }
412
413
136k
        byte_skip = chunk_size & 0x01;
414
136k
        bytestream2_skip(&s->gb, chunk_size + byte_skip);
415
136k
    }
416
417
    /* next, deal with the palette */
418
61.4k
    if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
419
420
        /* a chunk should not have both chunk types */
421
236
        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CPL0 and CPLZ chunks\n");
422
236
        return AVERROR_INVALIDDATA;
423
236
    }
424
425
    /* decompress the palette chunk */
426
61.1k
    if (cplz_chunk != -1) {
427
428
/* yet to be handled */
429
430
166
    }
431
432
    /* convert the RGB palette into the machine's endian format */
433
61.1k
    if (cpl0_chunk != -1) {
434
435
1.44k
        bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET);
436
1.44k
        chunk_size = bytestream2_get_be32(&s->gb);
437
        /* sanity check the palette size */
438
1.44k
        if (chunk_size / 3 > 256 || chunk_size > bytestream2_get_bytes_left(&s->gb)) {
439
894
            av_log(s->avctx, AV_LOG_ERROR, "problem: found a palette chunk with %d colors\n",
440
894
                chunk_size / 3);
441
894
            return AVERROR_INVALIDDATA;
442
894
        }
443
2.32k
        for (i = 0; i < chunk_size / 3; i++) {
444
            /* scale by 4 to transform 6-bit palette -> 8-bit */
445
1.77k
            r = bytestream2_get_byteu(&s->gb) * 4;
446
1.77k
            g = bytestream2_get_byteu(&s->gb) * 4;
447
1.77k
            b = bytestream2_get_byteu(&s->gb) * 4;
448
1.77k
            s->palette[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
449
1.77k
            s->palette[i] |= s->palette[i] >> 6 & 0x30303;
450
1.77k
        }
451
549
    }
452
453
    /* next, look for a full codebook */
454
60.3k
    if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
455
456
        /* a chunk should not have both chunk types */
457
245
        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
458
245
        return AVERROR_INVALIDDATA;
459
245
    }
460
461
    /* decompress the full codebook chunk */
462
60.0k
    if (cbfz_chunk != -1) {
463
464
542
        bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
465
542
        chunk_size = bytestream2_get_be32(&s->gb);
466
542
        if ((res = decode_format80(s, chunk_size, s->codebook,
467
542
                                   s->codebook_size, 0)) < 0)
468
288
            return res;
469
542
    }
470
471
    /* copy a full codebook */
472
59.7k
    if (cbf0_chunk != -1) {
473
474
859
        bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
475
859
        chunk_size = bytestream2_get_be32(&s->gb);
476
        /* sanity check the full codebook size */
477
859
        if (chunk_size > MAX_CODEBOOK_SIZE) {
478
361
            av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
479
361
                chunk_size);
480
361
            return AVERROR_INVALIDDATA;
481
361
        }
482
483
498
        bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
484
498
    }
485
486
    /* decode the frame */
487
59.4k
    if (vptz_chunk == -1) {
488
489
        /* something is wrong if there is no VPTZ chunk */
490
15.7k
        av_log(s->avctx, AV_LOG_ERROR, "problem: no VPTZ chunk found\n");
491
15.7k
        return AVERROR_INVALIDDATA;
492
15.7k
    }
493
494
43.6k
    bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET);
495
43.6k
    chunk_size = bytestream2_get_be32(&s->gb);
496
43.6k
    if ((res = decode_format80(s, chunk_size,
497
43.6k
                               s->decode_buffer, s->decode_buffer_size, 1)) < 0)
498
3.24k
        return res;
499
500
    /* render the final PAL8 frame */
501
40.3k
    if (s->vector_height == 4)
502
1.61k
        index_shift = 4;
503
38.7k
    else
504
38.7k
        index_shift = 3;
505
750k
    for (y = 0; y < s->height; y += s->vector_height) {
506
22.0M
        for (x = 0; x < s->width; x += 4, lobytes++, hibytes++) {
507
21.3M
            pixel_ptr = y * frame->linesize[0] + x;
508
509
            /* get the vector index, the method for which varies according to
510
             * VQA file version */
511
21.3M
            switch (s->vqa_version) {
512
513
19.9M
            case 1:
514
19.9M
                lobyte = s->decode_buffer[lobytes * 2];
515
19.9M
                hibyte = s->decode_buffer[(lobytes * 2) + 1];
516
19.9M
                vector_index = ((hibyte << 8) | lobyte) >> 3;
517
19.9M
                vector_index <<= index_shift;
518
19.9M
                lines = s->vector_height;
519
                /* uniform color fill - a quick hack */
520
19.9M
                if (hibyte == 0xFF) {
521
13.7k
                    while (lines--) {
522
9.18k
                        frame->data[0][pixel_ptr + 0] = 255 - lobyte;
523
9.18k
                        frame->data[0][pixel_ptr + 1] = 255 - lobyte;
524
9.18k
                        frame->data[0][pixel_ptr + 2] = 255 - lobyte;
525
9.18k
                        frame->data[0][pixel_ptr + 3] = 255 - lobyte;
526
9.18k
                        pixel_ptr += frame->linesize[0];
527
9.18k
                    }
528
4.57k
                    lines=0;
529
4.57k
                }
530
19.9M
                break;
531
532
1.43M
            case 2:
533
1.43M
                lobyte = s->decode_buffer[lobytes];
534
1.43M
                hibyte = s->decode_buffer[hibytes];
535
1.43M
                vector_index = (hibyte << 8) | lobyte;
536
1.43M
                vector_index <<= index_shift;
537
1.43M
                lines = s->vector_height;
538
1.43M
                break;
539
540
219
            case 3:
541
219
                av_log(s->avctx, AV_LOG_ERROR, "VQA3 shouldn't have a color palette");
542
219
                return AVERROR_INVALIDDATA;
543
21.3M
            }
544
545
67.5M
            while (lines--) {
546
46.2M
                frame->data[0][pixel_ptr + 0] = s->codebook[vector_index++];
547
46.2M
                frame->data[0][pixel_ptr + 1] = s->codebook[vector_index++];
548
46.2M
                frame->data[0][pixel_ptr + 2] = s->codebook[vector_index++];
549
46.2M
                frame->data[0][pixel_ptr + 3] = s->codebook[vector_index++];
550
46.2M
                pixel_ptr += frame->linesize[0];
551
46.2M
            }
552
21.3M
        }
553
710k
    }
554
555
    /* handle partial codebook */
556
40.1k
    if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
557
        /* a chunk should not have both chunk types */
558
207
        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBP0 and CBPZ chunks\n");
559
207
        return AVERROR_INVALIDDATA;
560
207
    }
561
562
39.9k
    if (cbp0_chunk != -1) {
563
564
1.40k
        bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET);
565
1.40k
        chunk_size = bytestream2_get_be32(&s->gb);
566
567
1.40k
        if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
568
245
            av_log(s->avctx, AV_LOG_ERROR, "cbp0 chunk too large (%u bytes)\n",
569
245
                   chunk_size);
570
245
            return AVERROR_INVALIDDATA;
571
245
        }
572
573
        /* accumulate partial codebook */
574
1.15k
        bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
575
1.15k
                               chunk_size);
576
1.15k
        s->next_codebook_buffer_index += chunk_size;
577
578
1.15k
        s->partial_countdown--;
579
1.15k
        if (s->partial_countdown <= 0) {
580
581
            /* time to replace codebook */
582
299
            memcpy(s->codebook, s->next_codebook_buffer,
583
299
                s->next_codebook_buffer_index);
584
585
            /* reset accounting */
586
299
            s->next_codebook_buffer_index = 0;
587
299
            s->partial_countdown = s->partial_count;
588
299
        }
589
1.15k
    }
590
591
39.7k
    if (cbpz_chunk != -1) {
592
593
4.34k
        bytestream2_seek(&s->gb, cbpz_chunk, SEEK_SET);
594
4.34k
        chunk_size = bytestream2_get_be32(&s->gb);
595
596
4.34k
        if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
597
371
            av_log(s->avctx, AV_LOG_ERROR, "cbpz chunk too large (%u bytes)\n",
598
371
                   chunk_size);
599
371
            return AVERROR_INVALIDDATA;
600
371
        }
601
602
        /* accumulate partial codebook */
603
3.97k
        bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
604
3.97k
                               chunk_size);
605
3.97k
        s->next_codebook_buffer_index += chunk_size;
606
607
3.97k
        s->partial_countdown--;
608
3.97k
        if (s->partial_countdown <= 0) {
609
3.47k
            bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index);
610
            /* decompress codebook */
611
3.47k
            res = decode_format80(s, s->next_codebook_buffer_index,
612
3.47k
                                  s->codebook, s->codebook_size, 0);
613
614
            /* reset accounting */
615
3.47k
            s->next_codebook_buffer_index = 0;
616
3.47k
            s->partial_countdown = s->partial_count;
617
3.47k
            if (res < 0)
618
1.72k
                return res;
619
3.47k
        }
620
3.97k
    }
621
622
37.6k
    return 0;
623
39.7k
}
624
625
static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame)
626
11.1k
{
627
11.1k
    unsigned int chunk_type;
628
11.1k
    unsigned int chunk_size;
629
11.1k
    unsigned int index = 0;
630
11.1k
    int res;
631
632
11.1k
    int cbf0_chunk = -1;
633
11.1k
    int cbfz_chunk = -1;
634
11.1k
    int vptr_chunk = -1;
635
11.1k
    int vprz_chunk = -1;
636
637
11.1k
    GetByteContext gb_stream;
638
639
43.0k
    while (bytestream2_get_bytes_left(&s->gb) >= 8) {
640
31.8k
        chunk_type = bytestream2_get_be32u(&s->gb);
641
31.8k
        index      = bytestream2_tell(&s->gb);
642
31.8k
        chunk_size = bytestream2_get_be32u(&s->gb);
643
644
31.8k
        switch (chunk_type) {
645
1.10k
        case CBF0_TAG:
646
1.10k
            cbf0_chunk = index;
647
1.10k
            break;
648
753
        case CBFZ_TAG:
649
753
            cbfz_chunk = index;
650
753
            break;
651
1.27k
        case VPTR_TAG:
652
1.27k
            vptr_chunk = index;
653
1.27k
            break;
654
3.26k
        case VPRZ_TAG:
655
3.26k
            vprz_chunk = index;
656
3.26k
            break;
657
25.4k
        default:
658
25.4k
            av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
659
25.4k
                   av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
660
25.4k
            break;
661
31.8k
        }
662
663
31.8k
        bytestream2_skip(&s->gb, chunk_size + (chunk_size & 0x01));
664
31.8k
    }
665
666
    /* next, look for a full codebook */
667
11.1k
    if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
668
        /* a chunk should not have both chunk types */
669
254
        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
670
254
        return AVERROR_INVALIDDATA;
671
254
    }
672
673
    /* decompress the full codebook chunk */
674
10.9k
    if (cbfz_chunk != -1) {
675
497
        bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
676
497
        chunk_size = bytestream2_get_be32(&s->gb);
677
497
        if ((res = decode_format80(s, chunk_size, s->codebook,
678
497
                                   s->codebook_size, 0)) < 0)
679
247
            return res;
680
497
    }
681
682
    /* copy a full codebook */
683
10.6k
    if (cbf0_chunk != -1) {
684
853
        bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
685
853
        chunk_size = bytestream2_get_be32(&s->gb);
686
        /* sanity check the full codebook size */
687
853
        if (chunk_size > MAX_CODEBOOK_SIZE) {
688
222
            av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
689
222
                chunk_size);
690
222
            return AVERROR_INVALIDDATA;
691
222
        }
692
693
631
        bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
694
631
    }
695
696
    /* decode the frame */
697
698
10.4k
    if (vptr_chunk != -1) {
699
        /* copy uncompressed tile data */
700
1.27k
        bytestream2_seek(&s->gb, vptr_chunk, SEEK_SET);
701
1.27k
        chunk_size = bytestream2_get_be32(&s->gb);
702
1.27k
        if (chunk_size > s->decode_buffer_size) {
703
285
            av_log(s->avctx, AV_LOG_ERROR, "VPTR chunk didn't fit in decode buffer");
704
285
            return AVERROR_INVALIDDATA;
705
285
        }
706
985
        bytestream2_get_buffer(&s->gb, s->decode_buffer, chunk_size);
707
9.16k
    } else if (vprz_chunk != -1) {
708
        /* decompress the tile data */
709
3.26k
        bytestream2_seek(&s->gb, vprz_chunk, SEEK_SET);
710
711
3.26k
        chunk_size = bytestream2_get_be32(&s->gb);
712
3.26k
        if ((res = decode_format80(s, chunk_size, s->decode_buffer, s->decode_buffer_size, 0)) < 0)
713
296
            return res;
714
5.89k
    } else {
715
5.89k
        av_log(s->avctx, AV_LOG_ERROR, "frame has no block data\n");
716
5.89k
        return AVERROR_INVALIDDATA;
717
5.89k
    }
718
719
    /* now uncompress the per-row RLE of the decode buffer and draw the blocks in framebuffer */
720
721
3.95k
    bytestream2_init(&gb_stream, s->decode_buffer, s->decode_buffer_size);
722
723
6.49k
    for (int y_pos = 0; y_pos < s->height; y_pos += s->vector_height) {
724
4.26k
        int x_pos = 0;
725
726
1.47M
        while (x_pos < s->width) {
727
1.46M
            int vector_index = 0;
728
1.46M
            int count = 0;
729
1.46M
            uint16_t code;
730
1.46M
            int type;
731
732
1.46M
            if (bytestream2_get_bytes_left(&gb_stream) < 2)
733
1.11k
                return AVERROR_INVALIDDATA;
734
735
1.46M
            code = bytestream2_get_le16(&gb_stream);
736
737
1.46M
            type = code >> 13;
738
1.46M
            code &= 0x1fff;
739
740
1.46M
            if (type == 0) {
741
1.46M
                x_pos += 4 * code;
742
1.46M
                continue;
743
1.46M
            } else if (type < 3) {
744
1.35k
                vector_index = code & 0xff;
745
1.35k
                count = ((code & 0x1f00) >> 7) + 1 + type;
746
1.88k
            } else if (type < 5) {
747
927
                vector_index = code;
748
927
                count = 1;
749
959
            } else if (type < 7) {
750
722
                vector_index = code;
751
722
                count = bytestream2_get_byte(&gb_stream);
752
722
            } else {
753
237
                av_log(s->avctx, AV_LOG_ERROR, " unknown type in VPTR chunk (%d)\n",type);
754
237
                return AVERROR_INVALIDDATA;
755
237
            }
756
757
3.00k
            if (count < 0 || count > (s->width - x_pos) / s->vector_width) {
758
372
                av_log(s->avctx, AV_LOG_ERROR, "invalid count: %d\n", count);
759
372
                return AVERROR_INVALIDDATA;
760
372
            }
761
762
74.5k
            while (count-- && x_pos < s->width) {
763
71.8k
                const int bytes_per_vector = 4 * s->vector_height * sizeof(uint16_t);
764
71.8k
                unsigned char *src = s->codebook + vector_index * bytes_per_vector;
765
71.8k
                unsigned char *dst = s->frame->data[0] + y_pos * s->frame->linesize[0]
766
71.8k
                    + sizeof(uint16_t) * x_pos;
767
768
71.8k
                if (vector_index >= MAX_VECTORS)
769
0
                    return AVERROR_INVALIDDATA;
770
771
215k
                for (int y = 0; y < s->vector_height; y++) {
772
143k
                    int size = 4 * sizeof(uint16_t);
773
143k
                    memcpy(dst, src, size);
774
143k
                    dst += s->frame->linesize[0];
775
143k
                    src += size;
776
143k
                }
777
778
                /* we might want to read the next block index from stream */
779
71.8k
                if ((type == 2) && count > 0) {
780
9.67k
                    vector_index = bytestream2_get_byte(&gb_stream);
781
9.67k
                }
782
783
71.8k
                x_pos += 4;
784
71.8k
            }
785
786
2.62k
            if (count > 0) {
787
0
                av_log(s->avctx, AV_LOG_ERROR, "had %d leftover vectors\n", count);
788
0
                return AVERROR_BUG;
789
0
            }
790
2.62k
        }
791
4.26k
    }
792
793
2.23k
    return 0;
794
3.95k
}
795
796
static int vqa_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
797
                            int *got_frame, AVPacket *avpkt)
798
72.6k
{
799
72.6k
    VqaContext *s = avctx->priv_data;
800
72.6k
    int res;
801
802
72.6k
    if ((res = ff_reget_buffer(avctx, s->frame, 0)) < 0)
803
89
        return res;
804
805
72.5k
    bytestream2_init(&s->gb, avpkt->data, avpkt->size);
806
807
72.5k
    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
808
61.4k
        if ((res = vqa_decode_frame_pal8(s, s->frame)) < 0)
809
23.8k
            return res;
810
811
        /* make the palette available on the way out */
812
37.6k
        memcpy(s->frame->data[1], s->palette, PALETTE_COUNT * 4);
813
37.6k
#if FF_API_PALETTE_HAS_CHANGED
814
37.6k
FF_DISABLE_DEPRECATION_WARNINGS
815
37.6k
        s->frame->palette_has_changed = 1;
816
37.6k
FF_ENABLE_DEPRECATION_WARNINGS
817
37.6k
#endif
818
37.6k
    } else if (avctx->pix_fmt == AV_PIX_FMT_RGB555LE) {
819
11.1k
        if ((res = vqa_decode_frame_hicolor(s, s->frame)) < 0)
820
8.92k
            return res;
821
11.1k
    } else {
822
0
        av_log(s->avctx, AV_LOG_ERROR, "unsupported pixel format\n");
823
0
        return AVERROR_BUG;
824
0
    }
825
826
39.8k
    if ((res = av_frame_ref(rframe, s->frame)) < 0)
827
0
        return res;
828
829
39.8k
    *got_frame      = 1;
830
831
    /* report that the buffer was completely consumed */
832
39.8k
    return avpkt->size;
833
39.8k
}
834
835
static av_cold int vqa_decode_end(AVCodecContext *avctx)
836
1.29k
{
837
1.29k
    VqaContext *s = avctx->priv_data;
838
839
1.29k
    av_frame_free(&s->frame);
840
1.29k
    av_freep(&s->codebook);
841
1.29k
    av_freep(&s->next_codebook_buffer);
842
1.29k
    av_freep(&s->decode_buffer);
843
844
1.29k
    return 0;
845
1.29k
}
846
847
static const FFCodecDefault vqa_defaults[] = {
848
    { "max_pixels", "640*480" },
849
    { NULL },
850
};
851
852
const FFCodec ff_vqa_decoder = {
853
    .p.name         = "vqavideo",
854
    CODEC_LONG_NAME("Westwood Studios VQA (Vector Quantized Animation) video"),
855
    .p.type         = AVMEDIA_TYPE_VIDEO,
856
    .p.id           = AV_CODEC_ID_WS_VQA,
857
    .priv_data_size = sizeof(VqaContext),
858
    .init           = vqa_decode_init,
859
    .close          = vqa_decode_end,
860
    FF_CODEC_DECODE_CB(vqa_decode_frame),
861
    .p.capabilities = AV_CODEC_CAP_DR1,
862
    .defaults       = vqa_defaults,
863
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
864
};