FFmpeg
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 
75 #include "libavutil/intreadwrite.h"
76 #include "avcodec.h"
77 #include "bytestream.h"
78 #include "codec_internal.h"
79 #include "decode.h"
80 
81 #define PALETTE_COUNT 256
82 #define VQA_HEADER_SIZE 0x2A
83 
84 /* allocate the maximum vector space, regardless of the file version:
85  * (0xFF00 codebook vectors + 0x100 solid pixel vectors) * (4x4 pixels/block) */
86 #define MAX_CODEBOOK_VECTORS 0xFF00
87 #define SOLID_PIXEL_VECTORS 0x100
88 #define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS)
89 #define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4 * sizeof(uint16_t))
90 
91 #define CBF0_TAG MKBETAG('C', 'B', 'F', '0')
92 #define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z')
93 #define CBP0_TAG MKBETAG('C', 'B', 'P', '0')
94 #define CBPZ_TAG MKBETAG('C', 'B', 'P', 'Z')
95 #define CPL0_TAG MKBETAG('C', 'P', 'L', '0')
96 #define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z')
97 #define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z')
98 #define VPTR_TAG MKBETAG('V', 'P', 'T', 'R')
99 #define VPRZ_TAG MKBETAG('V', 'P', 'R', 'Z')
100 
101 typedef struct VqaContext {
105 
107 
108  int width; /* width of a frame */
109  int height; /* height of a frame */
110  int vector_width; /* width of individual vector */
111  int vector_height; /* height of individual vector */
112  int vqa_version; /* this should be either 1, 2 or 3 */
113 
114  unsigned char *codebook; /* the current codebook */
116  unsigned char *next_codebook_buffer; /* accumulator for next codebook */
118 
119  unsigned char *decode_buffer;
121 
122  /* number of frames to go before replacing codebook */
125 } VqaContext;
126 
128 {
129  VqaContext *s = avctx->priv_data;
130  int i, j, codebook_index, ret;
131  int colors;
132 
133  s->avctx = avctx;
134 
135  /* make sure the extradata made it */
136  if (s->avctx->extradata_size != VQA_HEADER_SIZE) {
137  av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n", VQA_HEADER_SIZE);
138  return AVERROR(EINVAL);
139  }
140 
141  /* load up the VQA parameters from the header */
142  s->vqa_version = s->avctx->extradata[0];
143 
144  if (s->vqa_version < 1 || s->vqa_version > 3) {
145  avpriv_request_sample(avctx, "VQA Version %i", s->vqa_version);
146  return AVERROR_INVALIDDATA;
147  }
148 
149  s->width = AV_RL16(&s->avctx->extradata[6]);
150  s->height = AV_RL16(&s->avctx->extradata[8]);
151  if ((ret = ff_set_dimensions(avctx, s->width, s->height)) < 0) {
152  s->width= s->height= 0;
153  return ret;
154  }
155  s->vector_width = s->avctx->extradata[10];
156  s->vector_height = s->avctx->extradata[11];
157  s->partial_count = s->partial_countdown = s->avctx->extradata[13];
158 
159  colors = (s->avctx->extradata[14] << 8) | s->avctx->extradata[15];
160 
161  if (colors > 0) {
162  avctx->pix_fmt = AV_PIX_FMT_PAL8;
163  } else {
164  avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
165  }
166 
167  /* the vector dimensions have to meet very stringent requirements */
168  if ((s->vector_width != 4) ||
169  ((s->vector_height != 2) && (s->vector_height != 4))) {
170  /* return without further initialization */
171  return AVERROR_INVALIDDATA;
172  }
173 
174  if (s->width % s->vector_width || s->height % s->vector_height) {
175  av_log(avctx, AV_LOG_ERROR, "Image size not multiple of block size\n");
176  return AVERROR_INVALIDDATA;
177  }
178 
179  s->frame = av_frame_alloc();
180  if (!s->frame)
181  return AVERROR(ENOMEM);
182 
183  /* allocate codebooks */
184  s->codebook_size = MAX_CODEBOOK_SIZE;
185  s->codebook = av_malloc(s->codebook_size);
186  if (!s->codebook)
187  return AVERROR(ENOMEM);
188  s->next_codebook_buffer = av_malloc(s->codebook_size);
189  if (!s->next_codebook_buffer)
190  return AVERROR(ENOMEM);
191 
192  /* allocate decode buffer */
193  s->decode_buffer_size = (s->width / s->vector_width) *
194  (s->height / s->vector_height) * 2;
195  s->decode_buffer = av_mallocz(s->decode_buffer_size);
196  if (!s->decode_buffer)
197  return AVERROR(ENOMEM);
198 
199  /* initialize the solid-color vectors */
200  if (s->vector_height == 4) {
201  codebook_index = 0xFF00 * 16;
202  for (i = 0; i < 256; i++)
203  for (j = 0; j < 16; j++)
204  s->codebook[codebook_index++] = i;
205  } else {
206  codebook_index = 0xF00 * 8;
207  for (i = 0; i < 256; i++)
208  for (j = 0; j < 8; j++)
209  s->codebook[codebook_index++] = i;
210  }
211  s->next_codebook_buffer_index = 0;
212 
213  return 0;
214 }
215 
216 #define CHECK_COUNT() \
217  if (dest_index + count > dest_size) { \
218  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
219  av_log(s->avctx, AV_LOG_ERROR, "current dest_index = %d, count = %d, dest_size = %d\n", \
220  dest_index, count, dest_size); \
221  return AVERROR_INVALIDDATA; \
222  }
223 
224 #define CHECK_COPY(idx) \
225  if (idx < 0 || idx + count > dest_size) { \
226  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
227  av_log(s->avctx, AV_LOG_ERROR, "current src_pos = %d, count = %d, dest_size = %d\n", \
228  src_pos, count, dest_size); \
229  return AVERROR_INVALIDDATA; \
230  }
231 
232 
233 static int decode_format80(VqaContext *s, int src_size,
234  unsigned char *dest, int dest_size, int check_size) {
235 
236  int dest_index = 0;
237  int count, opcode, start;
238  int src_pos;
239  unsigned char color;
240  int i;
241  int relative = 0;
242 
243  if (src_size < 0 || src_size > bytestream2_get_bytes_left(&s->gb)) {
244  av_log(s->avctx, AV_LOG_ERROR, "Chunk size %d is out of range\n",
245  src_size);
246  return AVERROR_INVALIDDATA;
247  }
248 
249  /* the "new" scheme makes references relative to destination pointer */
250  if (bytestream2_peek_byte(&s->gb) == 0x00) {
251  relative = 1;
252  bytestream2_get_byte(&s->gb);
253  ff_tlog(s->avctx, "found new format stream ");
254  }
255 
256  start = bytestream2_tell(&s->gb);
257  while (bytestream2_tell(&s->gb) - start < src_size) {
258  opcode = bytestream2_get_byte(&s->gb);
259  ff_tlog(s->avctx, "opcode %02X: ", opcode);
260 
261  /* 0x80 means that frame is finished */
262  if (opcode == 0x80)
263  break;
264 
265  if (dest_index >= dest_size) {
266  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
267  dest_index, dest_size);
268  return AVERROR_INVALIDDATA;
269  }
270 
271  if (opcode == 0xFF) {
272 
273  count = bytestream2_get_le16(&s->gb);
274  src_pos = bytestream2_get_le16(&s->gb);
275  if (relative)
276  src_pos = dest_index - src_pos;
277  ff_tlog(s->avctx, "(1) copy %X bytes from pos %X\n", count, src_pos);
278  CHECK_COUNT();
279  CHECK_COPY(src_pos);
280  for (i = 0; i < count; i++)
281  dest[dest_index + i] = dest[src_pos + i];
282  dest_index += count;
283 
284  } else if (opcode == 0xFE) {
285 
286  count = bytestream2_get_le16(&s->gb);
287  color = bytestream2_get_byte(&s->gb);
288  ff_tlog(s->avctx, "(2) set %X bytes to %02X\n", count, color);
289  CHECK_COUNT();
290  memset(&dest[dest_index], color, count);
291  dest_index += count;
292 
293  } else if ((opcode & 0xC0) == 0xC0) {
294 
295  count = (opcode & 0x3F) + 3;
296  src_pos = bytestream2_get_le16(&s->gb);
297  if (relative)
298  src_pos = dest_index - src_pos;
299  ff_tlog(s->avctx, "(3) copy %X bytes from pos %X\n", count, src_pos);
300  CHECK_COUNT();
301  CHECK_COPY(src_pos);
302  for (i = 0; i < count; i++)
303  dest[dest_index + i] = dest[src_pos + i];
304  dest_index += count;
305 
306  } else if (opcode > 0x80) {
307 
308  count = opcode & 0x3F;
309  ff_tlog(s->avctx, "(4) copy %X bytes from source to dest\n", count);
310  CHECK_COUNT();
311  bytestream2_get_buffer(&s->gb, &dest[dest_index], count);
312  dest_index += count;
313 
314  } else {
315 
316  count = ((opcode & 0x70) >> 4) + 3;
317  src_pos = bytestream2_get_byte(&s->gb) | ((opcode & 0x0F) << 8);
318  ff_tlog(s->avctx, "(5) copy %X bytes from relpos %X\n", count, src_pos);
319  CHECK_COUNT();
320  CHECK_COPY(dest_index - src_pos);
321  for (i = 0; i < count; i++)
322  dest[dest_index + i] = dest[dest_index - src_pos + i];
323  dest_index += count;
324  }
325  }
326 
327  /* validate that the entire destination buffer was filled; this is
328  * important for decoding frame maps since each vector needs to have a
329  * codebook entry; it is not important for compressed codebooks because
330  * not every entry needs to be filled */
331  if (check_size)
332  if (dest_index < dest_size) {
333  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n",
334  dest_index, dest_size);
335  memset(dest + dest_index, 0, dest_size - dest_index);
336  }
337 
338  return 0; // let's display what we decoded anyway
339 }
340 
342 {
343  unsigned int chunk_type;
344  unsigned int chunk_size;
345  int byte_skip;
346  unsigned int index = 0;
347  int i;
348  unsigned char r, g, b;
349  int index_shift;
350  int res;
351 
352  int cbf0_chunk = -1;
353  int cbfz_chunk = -1;
354  int cbp0_chunk = -1;
355  int cbpz_chunk = -1;
356  int cpl0_chunk = -1;
357  int cplz_chunk = -1;
358  int vptz_chunk = -1;
359 
360  int x, y;
361  int lines = 0;
362  int pixel_ptr;
363  int vector_index = 0;
364  int lobyte = 0;
365  int hibyte = 0;
366  int lobytes = 0;
367  int hibytes = s->decode_buffer_size / 2;
368 
369  /* first, traverse through the frame and find the subchunks */
370  while (bytestream2_get_bytes_left(&s->gb) >= 8) {
371 
372  chunk_type = bytestream2_get_be32u(&s->gb);
373  index = bytestream2_tell(&s->gb);
374  chunk_size = bytestream2_get_be32u(&s->gb);
375 
376  switch (chunk_type) {
377 
378  case CBF0_TAG:
379  cbf0_chunk = index;
380  break;
381 
382  case CBFZ_TAG:
383  cbfz_chunk = index;
384  break;
385 
386  case CBP0_TAG:
387  cbp0_chunk = index;
388  break;
389 
390  case CBPZ_TAG:
391  cbpz_chunk = index;
392  break;
393 
394  case CPL0_TAG:
395  cpl0_chunk = index;
396  break;
397 
398  case CPLZ_TAG:
399  cplz_chunk = index;
400  break;
401 
402  case VPTZ_TAG:
403  vptz_chunk = index;
404  break;
405 
406  default:
407  av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
408  av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
409  break;
410  }
411 
412  byte_skip = chunk_size & 0x01;
413  bytestream2_skip(&s->gb, chunk_size + byte_skip);
414  }
415 
416  /* next, deal with the palette */
417  if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
418 
419  /* a chunk should not have both chunk types */
420  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CPL0 and CPLZ chunks\n");
421  return AVERROR_INVALIDDATA;
422  }
423 
424  /* decompress the palette chunk */
425  if (cplz_chunk != -1) {
426 
427 /* yet to be handled */
428 
429  }
430 
431  /* convert the RGB palette into the machine's endian format */
432  if (cpl0_chunk != -1) {
433 
434  bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET);
435  chunk_size = bytestream2_get_be32(&s->gb);
436  /* sanity check the palette size */
437  if (chunk_size / 3 > 256 || chunk_size > bytestream2_get_bytes_left(&s->gb)) {
438  av_log(s->avctx, AV_LOG_ERROR, "problem: found a palette chunk with %d colors\n",
439  chunk_size / 3);
440  return AVERROR_INVALIDDATA;
441  }
442  for (i = 0; i < chunk_size / 3; i++) {
443  /* scale by 4 to transform 6-bit palette -> 8-bit */
444  r = bytestream2_get_byteu(&s->gb) * 4;
445  g = bytestream2_get_byteu(&s->gb) * 4;
446  b = bytestream2_get_byteu(&s->gb) * 4;
447  s->palette[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
448  s->palette[i] |= s->palette[i] >> 6 & 0x30303;
449  }
450  }
451 
452  /* next, look for a full codebook */
453  if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
454 
455  /* a chunk should not have both chunk types */
456  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
457  return AVERROR_INVALIDDATA;
458  }
459 
460  /* decompress the full codebook chunk */
461  if (cbfz_chunk != -1) {
462 
463  bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
464  chunk_size = bytestream2_get_be32(&s->gb);
465  if ((res = decode_format80(s, chunk_size, s->codebook,
466  s->codebook_size, 0)) < 0)
467  return res;
468  }
469 
470  /* copy a full codebook */
471  if (cbf0_chunk != -1) {
472 
473  bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
474  chunk_size = bytestream2_get_be32(&s->gb);
475  /* sanity check the full codebook size */
476  if (chunk_size > MAX_CODEBOOK_SIZE) {
477  av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
478  chunk_size);
479  return AVERROR_INVALIDDATA;
480  }
481 
482  bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
483  }
484 
485  /* decode the frame */
486  if (vptz_chunk == -1) {
487 
488  /* something is wrong if there is no VPTZ chunk */
489  av_log(s->avctx, AV_LOG_ERROR, "problem: no VPTZ chunk found\n");
490  return AVERROR_INVALIDDATA;
491  }
492 
493  bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET);
494  chunk_size = bytestream2_get_be32(&s->gb);
495  if ((res = decode_format80(s, chunk_size,
496  s->decode_buffer, s->decode_buffer_size, 1)) < 0)
497  return res;
498 
499  /* render the final PAL8 frame */
500  if (s->vector_height == 4)
501  index_shift = 4;
502  else
503  index_shift = 3;
504  for (y = 0; y < s->height; y += s->vector_height) {
505  for (x = 0; x < s->width; x += 4, lobytes++, hibytes++) {
506  pixel_ptr = y * frame->linesize[0] + x;
507 
508  /* get the vector index, the method for which varies according to
509  * VQA file version */
510  switch (s->vqa_version) {
511 
512  case 1:
513  lobyte = s->decode_buffer[lobytes * 2];
514  hibyte = s->decode_buffer[(lobytes * 2) + 1];
515  vector_index = ((hibyte << 8) | lobyte) >> 3;
516  vector_index <<= index_shift;
517  lines = s->vector_height;
518  /* uniform color fill - a quick hack */
519  if (hibyte == 0xFF) {
520  while (lines--) {
521  frame->data[0][pixel_ptr + 0] = 255 - lobyte;
522  frame->data[0][pixel_ptr + 1] = 255 - lobyte;
523  frame->data[0][pixel_ptr + 2] = 255 - lobyte;
524  frame->data[0][pixel_ptr + 3] = 255 - lobyte;
525  pixel_ptr += frame->linesize[0];
526  }
527  lines=0;
528  }
529  break;
530 
531  case 2:
532  lobyte = s->decode_buffer[lobytes];
533  hibyte = s->decode_buffer[hibytes];
534  vector_index = (hibyte << 8) | lobyte;
535  vector_index <<= index_shift;
536  lines = s->vector_height;
537  break;
538 
539  case 3:
540  av_log(s->avctx, AV_LOG_ERROR, "VQA3 shouldn't have a color palette");
541  return AVERROR_INVALIDDATA;
542  }
543 
544  while (lines--) {
545  frame->data[0][pixel_ptr + 0] = s->codebook[vector_index++];
546  frame->data[0][pixel_ptr + 1] = s->codebook[vector_index++];
547  frame->data[0][pixel_ptr + 2] = s->codebook[vector_index++];
548  frame->data[0][pixel_ptr + 3] = s->codebook[vector_index++];
549  pixel_ptr += frame->linesize[0];
550  }
551  }
552  }
553 
554  /* handle partial codebook */
555  if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
556  /* a chunk should not have both chunk types */
557  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBP0 and CBPZ chunks\n");
558  return AVERROR_INVALIDDATA;
559  }
560 
561  if (cbp0_chunk != -1) {
562 
563  bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET);
564  chunk_size = bytestream2_get_be32(&s->gb);
565 
566  if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
567  av_log(s->avctx, AV_LOG_ERROR, "cbp0 chunk too large (%u bytes)\n",
568  chunk_size);
569  return AVERROR_INVALIDDATA;
570  }
571 
572  /* accumulate partial codebook */
573  bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
574  chunk_size);
575  s->next_codebook_buffer_index += chunk_size;
576 
577  s->partial_countdown--;
578  if (s->partial_countdown <= 0) {
579 
580  /* time to replace codebook */
581  memcpy(s->codebook, s->next_codebook_buffer,
582  s->next_codebook_buffer_index);
583 
584  /* reset accounting */
585  s->next_codebook_buffer_index = 0;
586  s->partial_countdown = s->partial_count;
587  }
588  }
589 
590  if (cbpz_chunk != -1) {
591 
592  bytestream2_seek(&s->gb, cbpz_chunk, SEEK_SET);
593  chunk_size = bytestream2_get_be32(&s->gb);
594 
595  if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
596  av_log(s->avctx, AV_LOG_ERROR, "cbpz chunk too large (%u bytes)\n",
597  chunk_size);
598  return AVERROR_INVALIDDATA;
599  }
600 
601  /* accumulate partial codebook */
602  bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
603  chunk_size);
604  s->next_codebook_buffer_index += chunk_size;
605 
606  s->partial_countdown--;
607  if (s->partial_countdown <= 0) {
608  bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index);
609  /* decompress codebook */
610  res = decode_format80(s, s->next_codebook_buffer_index,
611  s->codebook, s->codebook_size, 0);
612 
613  /* reset accounting */
614  s->next_codebook_buffer_index = 0;
615  s->partial_countdown = s->partial_count;
616  if (res < 0)
617  return res;
618  }
619  }
620 
621  return 0;
622 }
623 
625 {
626  unsigned int chunk_type;
627  unsigned int chunk_size;
628  unsigned int index = 0;
629  int res;
630 
631  int cbf0_chunk = -1;
632  int cbfz_chunk = -1;
633  int vptr_chunk = -1;
634  int vprz_chunk = -1;
635 
636  GetByteContext gb_stream;
637 
638  while (bytestream2_get_bytes_left(&s->gb) >= 8) {
639  chunk_type = bytestream2_get_be32u(&s->gb);
640  index = bytestream2_tell(&s->gb);
641  chunk_size = bytestream2_get_be32u(&s->gb);
642 
643  switch (chunk_type) {
644  case CBF0_TAG:
645  cbf0_chunk = index;
646  break;
647  case CBFZ_TAG:
648  cbfz_chunk = index;
649  break;
650  case VPTR_TAG:
651  vptr_chunk = index;
652  break;
653  case VPRZ_TAG:
654  vprz_chunk = index;
655  break;
656  default:
657  av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
658  av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
659  break;
660  }
661 
662  bytestream2_skip(&s->gb, chunk_size + (chunk_size & 0x01));
663  }
664 
665  /* next, look for a full codebook */
666  if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
667  /* a chunk should not have both chunk types */
668  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
669  return AVERROR_INVALIDDATA;
670  }
671 
672  /* decompress the full codebook chunk */
673  if (cbfz_chunk != -1) {
674  bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
675  chunk_size = bytestream2_get_be32(&s->gb);
676  if ((res = decode_format80(s, chunk_size, s->codebook,
677  s->codebook_size, 0)) < 0)
678  return res;
679  }
680 
681  /* copy a full codebook */
682  if (cbf0_chunk != -1) {
683  bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
684  chunk_size = bytestream2_get_be32(&s->gb);
685  /* sanity check the full codebook size */
686  if (chunk_size > MAX_CODEBOOK_SIZE) {
687  av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
688  chunk_size);
689  return AVERROR_INVALIDDATA;
690  }
691 
692  bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
693  }
694 
695  /* decode the frame */
696 
697  if (vptr_chunk != -1) {
698  /* copy uncompressed tile data */
699  bytestream2_seek(&s->gb, vptr_chunk, SEEK_SET);
700  chunk_size = bytestream2_get_be32(&s->gb);
701  if (chunk_size > s->decode_buffer_size) {
702  av_log(s->avctx, AV_LOG_ERROR, "VPTR chunk didn't fit in decode buffer");
703  return AVERROR_INVALIDDATA;
704  }
705  bytestream2_get_buffer(&s->gb, s->decode_buffer, chunk_size);
706  } else if (vprz_chunk != -1) {
707  /* decompress the tile data */
708  bytestream2_seek(&s->gb, vprz_chunk, SEEK_SET);
709 
710  chunk_size = bytestream2_get_be32(&s->gb);
711  if ((res = decode_format80(s, chunk_size, s->decode_buffer, s->decode_buffer_size, 0)) < 0)
712  return res;
713  } else {
714  av_log(s->avctx, AV_LOG_ERROR, "frame has no block data\n");
715  return AVERROR_INVALIDDATA;
716  }
717 
718  /* now uncompress the per-row RLE of the decode buffer and draw the blocks in framebuffer */
719 
720  bytestream2_init(&gb_stream, s->decode_buffer, s->decode_buffer_size);
721 
722  for (int y_pos = 0; y_pos < s->height; y_pos += s->vector_height) {
723  int x_pos = 0;
724 
725  while (x_pos < s->width) {
726  int vector_index = 0;
727  int count = 0;
728  uint16_t code;
729  int type;
730 
731  if (bytestream2_get_bytes_left(&gb_stream) < 2)
732  return AVERROR_INVALIDDATA;
733 
734  code = bytestream2_get_le16(&gb_stream);
735 
736  type = code >> 13;
737  code &= 0x1fff;
738 
739  if (type == 0) {
740  x_pos += 4 * code;
741  continue;
742  } else if (type < 3) {
743  vector_index = code & 0xff;
744  count = ((code & 0x1f00) >> 7) + 1 + type;
745  } else if (type < 5) {
746  vector_index = code;
747  count = 1;
748  } else if (type < 7) {
749  vector_index = code;
750  count = bytestream2_get_byte(&gb_stream);
751  } else {
752  av_log(s->avctx, AV_LOG_ERROR, " unknown type in VPTR chunk (%d)\n",type);
753  return AVERROR_INVALIDDATA;
754  }
755 
756  if (count < 0 || count > (s->width - x_pos) / s->vector_width) {
757  av_log(s->avctx, AV_LOG_ERROR, "invalid count: %d\n", count);
758  return AVERROR_INVALIDDATA;
759  }
760 
761  while (count-- && x_pos < s->width) {
762  const int bytes_per_vector = 4 * s->vector_height * sizeof(uint16_t);
763  unsigned char *src = s->codebook + vector_index * bytes_per_vector;
764  unsigned char *dst = s->frame->data[0] + y_pos * s->frame->linesize[0]
765  + sizeof(uint16_t) * x_pos;
766 
767  if (vector_index >= MAX_VECTORS)
768  return AVERROR_INVALIDDATA;
769 
770  for (int y = 0; y < s->vector_height; y++) {
771  int size = 4 * sizeof(uint16_t);
772  memcpy(dst, src, size);
773  dst += s->frame->linesize[0];
774  src += size;
775  }
776 
777  /* we might want to read the next block index from stream */
778  if ((type == 2) && count > 0) {
779  vector_index = bytestream2_get_byte(&gb_stream);
780  }
781 
782  x_pos += 4;
783  }
784 
785  if (count > 0) {
786  av_log(s->avctx, AV_LOG_ERROR, "had %d leftover vectors\n", count);
787  return AVERROR_BUG;
788  }
789  }
790  }
791 
792  return 0;
793 }
794 
795 static int vqa_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
796  int *got_frame, AVPacket *avpkt)
797 {
798  VqaContext *s = avctx->priv_data;
799  int res;
800 
801  if ((res = ff_reget_buffer(avctx, s->frame, 0)) < 0)
802  return res;
803 
804  bytestream2_init(&s->gb, avpkt->data, avpkt->size);
805 
806  if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
807  if ((res = vqa_decode_frame_pal8(s, s->frame)) < 0)
808  return res;
809 
810  /* make the palette available on the way out */
811  memcpy(s->frame->data[1], s->palette, PALETTE_COUNT * 4);
812 #if FF_API_PALETTE_HAS_CHANGED
814  s->frame->palette_has_changed = 1;
816 #endif
817  } else if (avctx->pix_fmt == AV_PIX_FMT_RGB555LE) {
818  if ((res = vqa_decode_frame_hicolor(s, s->frame)) < 0)
819  return res;
820  } else {
821  av_log(s->avctx, AV_LOG_ERROR, "unsupported pixel format\n");
822  return AVERROR_BUG;
823  }
824 
825  if ((res = av_frame_ref(rframe, s->frame)) < 0)
826  return res;
827 
828  *got_frame = 1;
829 
830  /* report that the buffer was completely consumed */
831  return avpkt->size;
832 }
833 
835 {
836  VqaContext *s = avctx->priv_data;
837 
838  av_frame_free(&s->frame);
839  av_freep(&s->codebook);
840  av_freep(&s->next_codebook_buffer);
841  av_freep(&s->decode_buffer);
842 
843  return 0;
844 }
845 
846 static const FFCodecDefault vqa_defaults[] = {
847  { "max_pixels", "640*480" },
848  { NULL },
849 };
850 
852  .p.name = "vqavideo",
853  CODEC_LONG_NAME("Westwood Studios VQA (Vector Quantized Animation) video"),
854  .p.type = AVMEDIA_TYPE_VIDEO,
855  .p.id = AV_CODEC_ID_WS_VQA,
856  .priv_data_size = sizeof(VqaContext),
858  .close = vqa_decode_end,
860  .p.capabilities = AV_CODEC_CAP_DR1,
861  .defaults = vqa_defaults,
862  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
863 };
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:73
check_size
static int check_size(TiffEncoderContext *s, uint64_t need)
Check free space in buffer.
Definition: tiffenc.c:88
VqaContext::decode_buffer_size
int decode_buffer_size
Definition: vqavideo.c:120
FF_CODEC_CAP_INIT_CLEANUP
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: codec_internal.h:42
r
const char * r
Definition: vf_curves.c:126
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
color
Definition: vf_paletteuse.c:511
GetByteContext
Definition: bytestream.h:33
VqaContext::next_codebook_buffer
unsigned char * next_codebook_buffer
Definition: vqavideo.c:116
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:130
bytestream2_seek
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:212
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:344
AVPacket::data
uint8_t * data
Definition: packet.h:522
VqaContext::codebook_size
int codebook_size
Definition: vqavideo.c:115
b
#define b
Definition: input.c:41
FFCodec
Definition: codec_internal.h:127
CHECK_COUNT
#define CHECK_COUNT()
Definition: vqavideo.c:216
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:94
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:365
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
PALETTE_COUNT
#define PALETTE_COUNT
Definition: vqavideo.c:81
VqaContext
Definition: vqavideo.c:101
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
FFCodecDefault
Definition: codec_internal.h:97
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
VqaContext::width
int width
Definition: vqavideo.c:108
VqaContext::partial_count
int partial_count
Definition: vqavideo.c:124
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:118
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
VqaContext::vector_width
int vector_width
Definition: vqavideo.c:110
width
#define width
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:287
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
vqa_decode_init
static av_cold int vqa_decode_init(AVCodecContext *avctx)
Definition: vqavideo.c:127
VqaContext::decode_buffer
unsigned char * decode_buffer
Definition: vqavideo.c:119
g
const char * g
Definition: vf_curves.c:127
VPRZ_TAG
#define VPRZ_TAG
Definition: vqavideo.c:99
AV_CODEC_ID_WS_VQA
@ AV_CODEC_ID_WS_VQA
Definition: codec_id.h:96
CBFZ_TAG
#define CBFZ_TAG
Definition: vqavideo.c:92
decode.h
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
frame
static AVFrame * frame
Definition: demux_decode.c:54
if
if(ret)
Definition: filter_design.txt:179
NULL
#define NULL
Definition: coverity.c:32
CBP0_TAG
#define CBP0_TAG
Definition: vqavideo.c:93
VqaContext::avctx
AVCodecContext * avctx
Definition: vqavideo.c:103
MAX_CODEBOOK_SIZE
#define MAX_CODEBOOK_SIZE
Definition: vqavideo.c:89
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
VqaContext::palette
uint32_t palette[PALETTE_COUNT]
Definition: vqavideo.c:106
vqa_defaults
static const FFCodecDefault vqa_defaults[]
Definition: vqavideo.c:846
MAX_VECTORS
#define MAX_VECTORS
Definition: vqavideo.c:88
decode_format80
static int decode_format80(VqaContext *s, int src_size, unsigned char *dest, int dest_size, int check_size)
Definition: vqavideo.c:233
index
int index
Definition: gxfenc.c:89
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:192
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:365
vqa_decode_frame_pal8
static int vqa_decode_frame_pal8(VqaContext *s, AVFrame *frame)
Definition: vqavideo.c:341
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
vqa_decode_frame
static int vqa_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt)
Definition: vqavideo.c:795
AVPacket::size
int size
Definition: packet.h:523
CPL0_TAG
#define CPL0_TAG
Definition: vqavideo.c:95
av_frame_ref
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:354
codec_internal.h
VqaContext::height
int height
Definition: vqavideo.c:109
av_bswap32
#define av_bswap32
Definition: bswap.h:28
ff_vqa_decoder
const FFCodec ff_vqa_decoder
Definition: vqavideo.c:851
size
int size
Definition: twinvq_data.h:10344
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
VqaContext::frame
AVFrame * frame
Definition: vqavideo.c:102
CPLZ_TAG
#define CPLZ_TAG
Definition: vqavideo.c:96
VqaContext::next_codebook_buffer_index
int next_codebook_buffer_index
Definition: vqavideo.c:117
vqa_decode_end
static av_cold int vqa_decode_end(AVCodecContext *avctx)
Definition: vqavideo.c:834
vqa_decode_frame_hicolor
static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame)
Definition: vqavideo.c:624
CHECK_COPY
#define CHECK_COPY(idx)
Definition: vqavideo.c:224
VqaContext::partial_countdown
int partial_countdown
Definition: vqavideo.c:123
VqaContext::vqa_version
int vqa_version
Definition: vqavideo.c:112
VPTZ_TAG
#define VPTZ_TAG
Definition: vqavideo.c:97
AV_PIX_FMT_RGB555LE
@ 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
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
code
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some it can consider them to be part of the FIFO and delay acknowledging a status change accordingly Example code
Definition: filter_design.txt:178
VPTR_TAG
#define VPTR_TAG
Definition: vqavideo.c:98
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:657
VqaContext::vector_height
int vector_height
Definition: vqavideo.c:111
avcodec.h
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:84
ff_reget_buffer
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:1678
ret
ret
Definition: filter_design.txt:187
U
#define U(x)
Definition: vpx_arith.h:37
AVCodecContext
main external API structure.
Definition: avcodec.h:445
CBF0_TAG
#define CBF0_TAG
Definition: vqavideo.c:91
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:72
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:36
ff_tlog
#define ff_tlog(ctx,...)
Definition: internal.h:153
AVPacket
This structure stores compressed data.
Definition: packet.h:499
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
VqaContext::codebook
unsigned char * codebook
Definition: vqavideo.c:114
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:389
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
VQA_HEADER_SIZE
#define VQA_HEADER_SIZE
Definition: vqavideo.c:82
VqaContext::gb
GetByteContext gb
Definition: vqavideo.c:104
CBPZ_TAG
#define CBPZ_TAG
Definition: vqavideo.c:94
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:345