FFmpeg
Loading...
Searching...
No Matches
vqavideo.c
Go to the documentation of this file.
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
76#include "libavutil/mem.h"
77#include "avcodec.h"
78#include "bytestream.h"
79#include "codec_internal.h"
80#include "decode.h"
81
82#define PALETTE_COUNT 256
83#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#define MAX_CODEBOOK_VECTORS 0xFF00
88#define SOLID_PIXEL_VECTORS 0x100
89#define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS)
90#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4 * sizeof(uint16_t))
91
92#define CBF0_TAG MKBETAG('C', 'B', 'F', '0')
93#define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z')
94#define CBP0_TAG MKBETAG('C', 'B', 'P', '0')
95#define CBPZ_TAG MKBETAG('C', 'B', 'P', 'Z')
96#define CPL0_TAG MKBETAG('C', 'P', 'L', '0')
97#define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z')
98#define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z')
99#define VPTR_TAG MKBETAG('V', 'P', 'T', 'R')
100#define VPRZ_TAG MKBETAG('V', 'P', 'R', 'Z')
101
102typedef struct VqaContext {
106
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 */
117 unsigned char *next_codebook_buffer; /* accumulator for next codebook */
119
120 unsigned char *decode_buffer;
122
123 /* number of frames to go before replacing codebook */
126} VqaContext;
127
129{
130 VqaContext *s = avctx->priv_data;
131 int i, j, codebook_index, ret;
132 int colors;
133
134 s->avctx = avctx;
135
136 /* make sure the extradata made it */
137 if (s->avctx->extradata_size != VQA_HEADER_SIZE) {
138 av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n", VQA_HEADER_SIZE);
139 return AVERROR(EINVAL);
140 }
141
142 /* load up the VQA parameters from the header */
143 s->vqa_version = s->avctx->extradata[0];
144
145 if (s->vqa_version < 1 || s->vqa_version > 3) {
146 avpriv_request_sample(avctx, "VQA Version %i", s->vqa_version);
147 return AVERROR_INVALIDDATA;
148 }
149
150 s->width = AV_RL16(&s->avctx->extradata[6]);
151 s->height = AV_RL16(&s->avctx->extradata[8]);
152 if ((ret = ff_set_dimensions(avctx, s->width, s->height)) < 0) {
153 s->width= s->height= 0;
154 return ret;
155 }
156 s->vector_width = s->avctx->extradata[10];
157 s->vector_height = s->avctx->extradata[11];
158 s->partial_count = s->partial_countdown = s->avctx->extradata[13];
159
160 colors = (s->avctx->extradata[14] << 8) | s->avctx->extradata[15];
161
162 if (colors > 0) {
163 avctx->pix_fmt = AV_PIX_FMT_PAL8;
164 } else {
166 }
167
168 /* the vector dimensions have to meet very stringent requirements */
169 if ((s->vector_width != 4) ||
170 ((s->vector_height != 2) && (s->vector_height != 4))) {
171 /* return without further initialization */
172 return AVERROR_INVALIDDATA;
173 }
174
175 if (s->width % s->vector_width || s->height % s->vector_height) {
176 av_log(avctx, AV_LOG_ERROR, "Image size not multiple of block size\n");
177 return AVERROR_INVALIDDATA;
178 }
179
180 s->frame = av_frame_alloc();
181 if (!s->frame)
182 return AVERROR(ENOMEM);
183
184 /* allocate codebooks */
185 s->codebook_size = MAX_CODEBOOK_SIZE;
186 s->codebook = av_malloc(s->codebook_size);
187 if (!s->codebook)
188 return AVERROR(ENOMEM);
189 s->next_codebook_buffer = av_malloc(s->codebook_size);
190 if (!s->next_codebook_buffer)
191 return AVERROR(ENOMEM);
192
193 /* allocate decode buffer */
194 s->decode_buffer_size = (s->width / s->vector_width) *
195 (s->height / s->vector_height) * 2;
196 s->decode_buffer = av_mallocz(s->decode_buffer_size);
197 if (!s->decode_buffer)
198 return AVERROR(ENOMEM);
199
200 /* initialize the solid-color vectors */
201 if (s->vector_height == 4) {
202 codebook_index = 0xFF00 * 16;
203 for (i = 0; i < 256; i++)
204 for (j = 0; j < 16; j++)
205 s->codebook[codebook_index++] = i;
206 } else {
207 codebook_index = 0xF00 * 8;
208 for (i = 0; i < 256; i++)
209 for (j = 0; j < 8; j++)
210 s->codebook[codebook_index++] = i;
211 }
212 s->next_codebook_buffer_index = 0;
213
214 return 0;
215}
216
217#define CHECK_COUNT() \
218 if (dest_index + count > dest_size) { \
219 av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
220 av_log(s->avctx, AV_LOG_ERROR, "current dest_index = %d, count = %d, dest_size = %d\n", \
221 dest_index, count, dest_size); \
222 return AVERROR_INVALIDDATA; \
223 }
224
225#define CHECK_COPY(idx) \
226 if (idx < 0 || idx + count > dest_size) { \
227 av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
228 av_log(s->avctx, AV_LOG_ERROR, "current src_pos = %d, count = %d, dest_size = %d\n", \
229 src_pos, count, dest_size); \
230 return AVERROR_INVALIDDATA; \
231 }
232
233
234static int decode_format80(VqaContext *s, int src_size,
235 unsigned char *dest, int dest_size, int check_size) {
236
237 int dest_index = 0;
238 int count, opcode, start;
239 int src_pos;
240 unsigned char color;
241 int i;
242 int relative = 0;
243
244 if (src_size < 0 || src_size > bytestream2_get_bytes_left(&s->gb)) {
245 av_log(s->avctx, AV_LOG_ERROR, "Chunk size %d is out of range\n",
246 src_size);
247 return AVERROR_INVALIDDATA;
248 }
249
250 /* the "new" scheme makes references relative to destination pointer */
251 if (bytestream2_peek_byte(&s->gb) == 0x00) {
252 relative = 1;
253 bytestream2_get_byte(&s->gb);
254 ff_tlog(s->avctx, "found new format stream ");
255 }
256
257 start = bytestream2_tell(&s->gb);
258 while (bytestream2_tell(&s->gb) - start < src_size) {
259 opcode = bytestream2_get_byte(&s->gb);
260 ff_tlog(s->avctx, "opcode %02X: ", opcode);
261
262 /* 0x80 means that frame is finished */
263 if (opcode == 0x80)
264 break;
265
266 if (dest_index >= dest_size) {
267 av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
268 dest_index, dest_size);
269 return AVERROR_INVALIDDATA;
270 }
271
272 if (opcode == 0xFF) {
273
274 count = bytestream2_get_le16(&s->gb);
275 src_pos = bytestream2_get_le16(&s->gb);
276 if (relative)
277 src_pos = dest_index - src_pos;
278 ff_tlog(s->avctx, "(1) copy %X bytes from pos %X\n", count, src_pos);
279 CHECK_COUNT();
280 CHECK_COPY(src_pos);
281 for (i = 0; i < count; i++)
282 dest[dest_index + i] = dest[src_pos + i];
283 dest_index += count;
284
285 } else if (opcode == 0xFE) {
286
287 count = bytestream2_get_le16(&s->gb);
288 color = bytestream2_get_byte(&s->gb);
289 ff_tlog(s->avctx, "(2) set %X bytes to %02X\n", count, color);
290 CHECK_COUNT();
291 memset(&dest[dest_index], color, count);
292 dest_index += count;
293
294 } else if ((opcode & 0xC0) == 0xC0) {
295
296 count = (opcode & 0x3F) + 3;
297 src_pos = bytestream2_get_le16(&s->gb);
298 if (relative)
299 src_pos = dest_index - src_pos;
300 ff_tlog(s->avctx, "(3) copy %X bytes from pos %X\n", count, src_pos);
301 CHECK_COUNT();
302 CHECK_COPY(src_pos);
303 for (i = 0; i < count; i++)
304 dest[dest_index + i] = dest[src_pos + i];
305 dest_index += count;
306
307 } else if (opcode > 0x80) {
308
309 count = opcode & 0x3F;
310 ff_tlog(s->avctx, "(4) copy %X bytes from source to dest\n", count);
311 CHECK_COUNT();
312 bytestream2_get_buffer(&s->gb, &dest[dest_index], count);
313 dest_index += count;
314
315 } else {
316
317 count = ((opcode & 0x70) >> 4) + 3;
318 src_pos = bytestream2_get_byte(&s->gb) | ((opcode & 0x0F) << 8);
319 ff_tlog(s->avctx, "(5) copy %X bytes from relpos %X\n", count, src_pos);
320 CHECK_COUNT();
321 CHECK_COPY(dest_index - src_pos);
322 for (i = 0; i < count; i++)
323 dest[dest_index + i] = dest[dest_index - src_pos + i];
324 dest_index += count;
325 }
326 }
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 if (check_size)
333 if (dest_index < dest_size) {
334 av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n",
335 dest_index, dest_size);
336 memset(dest + dest_index, 0, dest_size - dest_index);
337 }
338
339 return 0; // let's display what we decoded anyway
340}
341
343{
344 unsigned int chunk_type;
345 unsigned int chunk_size;
346 int byte_skip;
347 unsigned int index = 0;
348 int i;
349 unsigned char r, g, b;
350 int index_shift;
351 int res;
352
353 int cbf0_chunk = -1;
354 int cbfz_chunk = -1;
355 int cbp0_chunk = -1;
356 int cbpz_chunk = -1;
357 int cpl0_chunk = -1;
358 int cplz_chunk = -1;
359 int vptz_chunk = -1;
360
361 int x, y;
362 int lines = 0;
363 int pixel_ptr;
364 int vector_index = 0;
365 int lobyte = 0;
366 int hibyte = 0;
367 int lobytes = 0;
368 int hibytes = s->decode_buffer_size / 2;
369
370 /* first, traverse through the frame and find the subchunks */
371 while (bytestream2_get_bytes_left(&s->gb) >= 8) {
372
373 chunk_type = bytestream2_get_be32u(&s->gb);
374 index = bytestream2_tell(&s->gb);
375 chunk_size = bytestream2_get_be32u(&s->gb);
376
377 switch (chunk_type) {
378
379 case CBF0_TAG:
380 cbf0_chunk = index;
381 break;
382
383 case CBFZ_TAG:
384 cbfz_chunk = index;
385 break;
386
387 case CBP0_TAG:
388 cbp0_chunk = index;
389 break;
390
391 case CBPZ_TAG:
392 cbpz_chunk = index;
393 break;
394
395 case CPL0_TAG:
396 cpl0_chunk = index;
397 break;
398
399 case CPLZ_TAG:
400 cplz_chunk = index;
401 break;
402
403 case VPTZ_TAG:
404 vptz_chunk = index;
405 break;
406
407 default:
408 av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
409 av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
410 break;
411 }
412
413 byte_skip = chunk_size & 0x01;
414 bytestream2_skip(&s->gb, chunk_size + byte_skip);
415 }
416
417 /* next, deal with the palette */
418 if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
419
420 /* a chunk should not have both chunk types */
421 av_log(s->avctx, AV_LOG_ERROR, "problem: found both CPL0 and CPLZ chunks\n");
422 return AVERROR_INVALIDDATA;
423 }
424
425 /* decompress the palette chunk */
426 if (cplz_chunk != -1) {
427
428/* yet to be handled */
429
430 }
431
432 /* convert the RGB palette into the machine's endian format */
433 if (cpl0_chunk != -1) {
434
435 bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET);
436 chunk_size = bytestream2_get_be32(&s->gb);
437 /* sanity check the palette size */
438 if (chunk_size / 3 > 256 || chunk_size > bytestream2_get_bytes_left(&s->gb)) {
439 av_log(s->avctx, AV_LOG_ERROR, "problem: found a palette chunk with %d colors\n",
440 chunk_size / 3);
441 return AVERROR_INVALIDDATA;
442 }
443 for (i = 0; i < chunk_size / 3; i++) {
444 /* scale by 4 to transform 6-bit palette -> 8-bit */
445 r = bytestream2_get_byteu(&s->gb) * 4;
446 g = bytestream2_get_byteu(&s->gb) * 4;
447 b = bytestream2_get_byteu(&s->gb) * 4;
448 s->palette[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
449 s->palette[i] |= s->palette[i] >> 6 & 0x30303;
450 }
451 }
452
453 /* next, look for a full codebook */
454 if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
455
456 /* a chunk should not have both chunk types */
457 av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
458 return AVERROR_INVALIDDATA;
459 }
460
461 /* decompress the full codebook chunk */
462 if (cbfz_chunk != -1) {
463
464 bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
465 chunk_size = bytestream2_get_be32(&s->gb);
466 if ((res = decode_format80(s, chunk_size, s->codebook,
467 s->codebook_size, 0)) < 0)
468 return res;
469 }
470
471 /* copy a full codebook */
472 if (cbf0_chunk != -1) {
473
474 bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
475 chunk_size = bytestream2_get_be32(&s->gb);
476 /* sanity check the full codebook size */
477 if (chunk_size > MAX_CODEBOOK_SIZE) {
478 av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
479 chunk_size);
480 return AVERROR_INVALIDDATA;
481 }
482
483 bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
484 }
485
486 /* decode the frame */
487 if (vptz_chunk == -1) {
488
489 /* something is wrong if there is no VPTZ chunk */
490 av_log(s->avctx, AV_LOG_ERROR, "problem: no VPTZ chunk found\n");
491 return AVERROR_INVALIDDATA;
492 }
493
494 bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET);
495 chunk_size = bytestream2_get_be32(&s->gb);
496 if ((res = decode_format80(s, chunk_size,
497 s->decode_buffer, s->decode_buffer_size, 1)) < 0)
498 return res;
499
500 /* render the final PAL8 frame */
501 if (s->vector_height == 4)
502 index_shift = 4;
503 else
504 index_shift = 3;
505 for (y = 0; y < s->height; y += s->vector_height) {
506 for (x = 0; x < s->width; x += 4, lobytes++, hibytes++) {
507 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 switch (s->vqa_version) {
512
513 case 1:
514 lobyte = s->decode_buffer[lobytes * 2];
515 hibyte = s->decode_buffer[(lobytes * 2) + 1];
516 vector_index = ((hibyte << 8) | lobyte) >> 3;
517 vector_index <<= index_shift;
518 lines = s->vector_height;
519 /* uniform color fill - a quick hack */
520 if (hibyte == 0xFF) {
521 while (lines--) {
522 frame->data[0][pixel_ptr + 0] = 255 - lobyte;
523 frame->data[0][pixel_ptr + 1] = 255 - lobyte;
524 frame->data[0][pixel_ptr + 2] = 255 - lobyte;
525 frame->data[0][pixel_ptr + 3] = 255 - lobyte;
526 pixel_ptr += frame->linesize[0];
527 }
528 lines=0;
529 }
530 break;
531
532 case 2:
533 lobyte = s->decode_buffer[lobytes];
534 hibyte = s->decode_buffer[hibytes];
535 vector_index = (hibyte << 8) | lobyte;
536 vector_index <<= index_shift;
537 lines = s->vector_height;
538 break;
539
540 case 3:
541 av_log(s->avctx, AV_LOG_ERROR, "VQA3 shouldn't have a color palette");
542 return AVERROR_INVALIDDATA;
543 }
544
545 while (lines--) {
546 frame->data[0][pixel_ptr + 0] = s->codebook[vector_index++];
547 frame->data[0][pixel_ptr + 1] = s->codebook[vector_index++];
548 frame->data[0][pixel_ptr + 2] = s->codebook[vector_index++];
549 frame->data[0][pixel_ptr + 3] = s->codebook[vector_index++];
550 pixel_ptr += frame->linesize[0];
551 }
552 }
553 }
554
555 /* handle partial codebook */
556 if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
557 /* a chunk should not have both chunk types */
558 av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBP0 and CBPZ chunks\n");
559 return AVERROR_INVALIDDATA;
560 }
561
562 if (cbp0_chunk != -1) {
563
564 bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET);
565 chunk_size = bytestream2_get_be32(&s->gb);
566
567 if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
568 av_log(s->avctx, AV_LOG_ERROR, "cbp0 chunk too large (%u bytes)\n",
569 chunk_size);
570 return AVERROR_INVALIDDATA;
571 }
572
573 /* accumulate partial codebook */
574 if (chunk_size != bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
575 chunk_size))
576 return AVERROR_INVALIDDATA;
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 if (chunk_size != bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
605 chunk_size))
606 return AVERROR_INVALIDDATA;
607 s->next_codebook_buffer_index += chunk_size;
608
609 s->partial_countdown--;
610 if (s->partial_countdown <= 0) {
611 bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index);
612 /* decompress codebook */
613 res = decode_format80(s, s->next_codebook_buffer_index,
614 s->codebook, s->codebook_size, 0);
615
616 /* reset accounting */
617 s->next_codebook_buffer_index = 0;
618 s->partial_countdown = s->partial_count;
619 if (res < 0)
620 return res;
621 }
622 }
623
624 return 0;
625}
626
628{
629 unsigned int chunk_type;
630 unsigned int chunk_size;
631 unsigned int index = 0;
632 int res;
633
634 int cbf0_chunk = -1;
635 int cbfz_chunk = -1;
636 int vptr_chunk = -1;
637 int vprz_chunk = -1;
638
639 GetByteContext gb_stream;
640
641 while (bytestream2_get_bytes_left(&s->gb) >= 8) {
642 chunk_type = bytestream2_get_be32u(&s->gb);
643 index = bytestream2_tell(&s->gb);
644 chunk_size = bytestream2_get_be32u(&s->gb);
645
646 switch (chunk_type) {
647 case CBF0_TAG:
648 cbf0_chunk = index;
649 break;
650 case CBFZ_TAG:
651 cbfz_chunk = index;
652 break;
653 case VPTR_TAG:
654 vptr_chunk = index;
655 break;
656 case VPRZ_TAG:
657 vprz_chunk = index;
658 break;
659 default:
660 av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
661 av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
662 break;
663 }
664
665 bytestream2_skip(&s->gb, chunk_size + (chunk_size & 0x01));
666 }
667
668 /* next, look for a full codebook */
669 if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
670 /* a chunk should not have both chunk types */
671 av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
672 return AVERROR_INVALIDDATA;
673 }
674
675 /* decompress the full codebook chunk */
676 if (cbfz_chunk != -1) {
677 bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
678 chunk_size = bytestream2_get_be32(&s->gb);
679 if ((res = decode_format80(s, chunk_size, s->codebook,
680 s->codebook_size, 0)) < 0)
681 return res;
682 }
683
684 /* copy a full codebook */
685 if (cbf0_chunk != -1) {
686 bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
687 chunk_size = bytestream2_get_be32(&s->gb);
688 /* sanity check the full codebook size */
689 if (chunk_size > MAX_CODEBOOK_SIZE) {
690 av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
691 chunk_size);
692 return AVERROR_INVALIDDATA;
693 }
694
695 bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
696 }
697
698 /* decode the frame */
699
700 if (vptr_chunk != -1) {
701 /* copy uncompressed tile data */
702 bytestream2_seek(&s->gb, vptr_chunk, SEEK_SET);
703 chunk_size = bytestream2_get_be32(&s->gb);
704 if (chunk_size > s->decode_buffer_size) {
705 av_log(s->avctx, AV_LOG_ERROR, "VPTR chunk didn't fit in decode buffer");
706 return AVERROR_INVALIDDATA;
707 }
708 bytestream2_get_buffer(&s->gb, s->decode_buffer, chunk_size);
709 } else if (vprz_chunk != -1) {
710 /* decompress the tile data */
711 bytestream2_seek(&s->gb, vprz_chunk, SEEK_SET);
712
713 chunk_size = bytestream2_get_be32(&s->gb);
714 if ((res = decode_format80(s, chunk_size, s->decode_buffer, s->decode_buffer_size, 0)) < 0)
715 return res;
716 } else {
717 av_log(s->avctx, AV_LOG_ERROR, "frame has no block data\n");
718 return AVERROR_INVALIDDATA;
719 }
720
721 /* now uncompress the per-row RLE of the decode buffer and draw the blocks in framebuffer */
722
723 bytestream2_init(&gb_stream, s->decode_buffer, s->decode_buffer_size);
724
725 for (int y_pos = 0; y_pos < s->height; y_pos += s->vector_height) {
726 int x_pos = 0;
727
728 while (x_pos < s->width) {
729 int vector_index = 0;
730 int count = 0;
731 uint16_t code;
732 int type;
733
734 if (bytestream2_get_bytes_left(&gb_stream) < 2)
735 return AVERROR_INVALIDDATA;
736
737 code = bytestream2_get_le16(&gb_stream);
738
739 type = code >> 13;
740 code &= 0x1fff;
741
742 if (type == 0) {
743 x_pos += 4 * code;
744 continue;
745 } else if (type < 3) {
746 vector_index = code & 0xff;
747 count = ((code & 0x1f00) >> 7) + 1 + type;
748 } else if (type < 5) {
749 vector_index = code;
750 count = 1;
751 } else if (type < 7) {
752 vector_index = code;
753 count = bytestream2_get_byte(&gb_stream);
754 } else {
755 av_log(s->avctx, AV_LOG_ERROR, " unknown type in VPTR chunk (%d)\n",type);
756 return AVERROR_INVALIDDATA;
757 }
758
759 if (count < 0 || count > (s->width - x_pos) / s->vector_width) {
760 av_log(s->avctx, AV_LOG_ERROR, "invalid count: %d\n", count);
761 return AVERROR_INVALIDDATA;
762 }
763
764 while (count-- && x_pos < s->width) {
765 const int bytes_per_vector = 4 * s->vector_height * sizeof(uint16_t);
766 unsigned char *src = s->codebook + vector_index * bytes_per_vector;
767 unsigned char *dst = s->frame->data[0] + y_pos * s->frame->linesize[0]
768 + sizeof(uint16_t) * x_pos;
769
770 if (vector_index >= MAX_VECTORS)
771 return AVERROR_INVALIDDATA;
772
773 for (int y = 0; y < s->vector_height; y++) {
774 int size = 4 * sizeof(uint16_t);
775 memcpy(dst, src, size);
776 dst += s->frame->linesize[0];
777 src += size;
778 }
779
780 /* we might want to read the next block index from stream */
781 if ((type == 2) && count > 0) {
782 vector_index = bytestream2_get_byte(&gb_stream);
783 }
784
785 x_pos += 4;
786 }
787
788 if (count > 0) {
789 av_log(s->avctx, AV_LOG_ERROR, "had %d leftover vectors\n", count);
790 return AVERROR_BUG;
791 }
792 }
793 }
794
795 return 0;
796}
797
798static int vqa_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
799 int *got_frame, AVPacket *avpkt)
800{
801 VqaContext *s = avctx->priv_data;
802 int res;
803
804 if ((res = ff_reget_buffer(avctx, s->frame, 0)) < 0)
805 return res;
806
807 bytestream2_init(&s->gb, avpkt->data, avpkt->size);
808
809 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
810 if ((res = vqa_decode_frame_pal8(s, s->frame)) < 0)
811 return res;
812
813 /* make the palette available on the way out */
814 memcpy(s->frame->data[1], s->palette, PALETTE_COUNT * 4);
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
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
850 .p.name = "vqavideo",
851 CODEC_LONG_NAME("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),
858 .p.capabilities = AV_CODEC_CAP_DR1,
859 .defaults = vqa_defaults,
860 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
861};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
const FFCodec ff_vqa_decoder
Definition vqavideo.c:849
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
Libavcodec external API header.
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition bytestream.h:267
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition bytestream.h:158
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition bytestream.h:137
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition bytestream.h:168
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition bytestream.h:212
static av_always_inline int bytestream2_tell(const GetByteContext *g)
Definition bytestream.h:192
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
static IPT relative(const CmsCtx *ctx, IPT ipt)
Definition cms.c:544
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
#define NULL
Definition coverity.c:32
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Identical in function to ff_get_buffer(), except it reuses the existing buffer if available.
Definition decode.c:1906
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Definition utils.c:91
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
@ AV_CODEC_ID_WS_VQA
Definition codec_id.h:94
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition frame.c:278
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
#define av_fourcc2str(fourcc)
Definition avutil.h:323
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int index
Definition gxfenc.c:90
cl_device_type type
#define PALETTE_COUNT
Definition idcinvideo.c:57
#define r
Definition input.c:42
#define b
Definition input.c:43
#define AV_RL16(p)
#define av_cold
Definition attributes.h:117
Memory handling functions.
#define av_malloc(s)
Definition ops_static.c:52
@ AV_PIX_FMT_RGB555LE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
Definition pixfmt.h:115
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition pixfmt.h:84
#define av_bswap32
Definition bswap.h:47
const uint8_t * code
Definition spdifenc.c:433
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
int vector_width
Definition vqavideo.c:111
int decode_buffer_size
Definition vqavideo.c:121
int partial_countdown
Definition vqavideo.c:124
int vector_height
Definition vqavideo.c:112
AVFrame * frame
Definition vqavideo.c:103
GetByteContext gb
Definition vqavideo.c:105
int vqa_version
Definition vqavideo.c:113
AVCodecContext * avctx
Definition vqavideo.c:104
int next_codebook_buffer_index
Definition vqavideo.c:118
int codebook_size
Definition vqavideo.c:116
unsigned char * decode_buffer
Definition vqavideo.c:120
unsigned char * codebook
Definition vqavideo.c:115
unsigned char * next_codebook_buffer
Definition vqavideo.c:117
int partial_count
Definition vqavideo.c:125
uint32_t palette[PALETTE_COUNT]
Definition vqavideo.c:107
#define av_mallocz(s)
#define avpriv_request_sample(...)
#define av_freep(p)
#define ff_tlog(a,...)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
#define width
Definition dsp.h:89
static int check_size(TiffEncoderContext *s, uint64_t need)
Check free space in buffer.
Definition tiffenc.c:90
int size
const char * g
Definition vf_curves.c:128
#define VPRZ_TAG
Definition vqavideo.c:100
#define CPLZ_TAG
Definition vqavideo.c:97
#define VPTR_TAG
Definition vqavideo.c:99
static av_cold int vqa_decode_end(AVCodecContext *avctx)
Definition vqavideo.c:832
static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame)
Definition vqavideo.c:627
static const FFCodecDefault vqa_defaults[]
Definition vqavideo.c:844
#define CHECK_COUNT()
Definition vqavideo.c:217
static int vqa_decode_frame_pal8(VqaContext *s, AVFrame *frame)
Definition vqavideo.c:342
#define PALETTE_COUNT
Definition vqavideo.c:82
#define VQA_HEADER_SIZE
Definition vqavideo.c:83
#define CBF0_TAG
Definition vqavideo.c:92
#define CPL0_TAG
Definition vqavideo.c:96
#define CBFZ_TAG
Definition vqavideo.c:93
#define CBP0_TAG
Definition vqavideo.c:94
static int vqa_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt)
Definition vqavideo.c:798
#define CBPZ_TAG
Definition vqavideo.c:95
static int decode_format80(VqaContext *s, int src_size, unsigned char *dest, int dest_size, int check_size)
Definition vqavideo.c:234
#define CHECK_COPY(idx)
Definition vqavideo.c:225
#define MAX_CODEBOOK_SIZE
Definition vqavideo.c:90
static av_cold int vqa_decode_init(AVCodecContext *avctx)
Definition vqavideo.c:128
#define VPTZ_TAG
Definition vqavideo.c:98
#define MAX_VECTORS
Definition vqavideo.c:89