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 
103 typedef 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 
vqa_decode_init(AVCodecContext *avctx)129 static 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 
decode_format80(VqaContext *s, int src_size, unsigned char *dest, int dest_size, int check_size)235 static 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 
vqa_decode_frame_pal8(VqaContext *s, AVFrame *frame)343 static 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 
vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame)626 static 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 
vqa_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt)797 static 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 
vqa_decode_end(AVCodecContext *avctx)832 static 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 
844 static const FFCodecDefault vqa_defaults[] = {
845     { "max_pixels", "640*480" },
846     { NULL },
847 };
848 
849 const 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