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 "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 
102 typedef 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 {
165  avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
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 
234 static 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 
798 static 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 
844 static 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 };
check_size
static int check_size(TiffEncoderContext *s, uint64_t need)
Check free space in buffer.
Definition: tiffenc.c:89
VqaContext::decode_buffer_size
int decode_buffer_size
Definition: vqavideo.c:121
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:127
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
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition: bytestream.h:158
color
Definition: vf_paletteuse.c:513
GetByteContext
Definition: bytestream.h:33
bytestream2_tell
static av_always_inline int bytestream2_tell(const GetByteContext *g)
Definition: bytestream.h:192
VqaContext::next_codebook_buffer
unsigned char * next_codebook_buffer
Definition: vqavideo.c:117
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
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:427
AVPacket::data
uint8_t * data
Definition: packet.h:558
VqaContext::codebook_size
int codebook_size
Definition: vqavideo.c:116
b
#define b
Definition: input.c:42
FFCodec
Definition: codec_internal.h:127
CHECK_COUNT
#define CHECK_COUNT()
Definition: vqavideo.c:217
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:91
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
PALETTE_COUNT
#define PALETTE_COUNT
Definition: vqavideo.c:82
VqaContext
Definition: vqavideo.c:102
close
static av_cold void close(AVCodecParserContext *s)
Definition: apv_parser.c:135
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
FFCodecDefault
Definition: codec_internal.h:96
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
VqaContext::width
int width
Definition: vqavideo.c:109
VqaContext::partial_count
int partial_count
Definition: vqavideo.c:125
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:52
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:90
VqaContext::vector_width
int vector_width
Definition: vqavideo.c:111
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:346
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:128
VqaContext::decode_buffer
unsigned char * decode_buffer
Definition: vqavideo.c:120
g
const char * g
Definition: vf_curves.c:128
VPRZ_TAG
#define VPRZ_TAG
Definition: vqavideo.c:100
AV_CODEC_ID_WS_VQA
@ AV_CODEC_ID_WS_VQA
Definition: codec_id.h:96
CBFZ_TAG
#define CBFZ_TAG
Definition: vqavideo.c:93
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:331
if
if(ret)
Definition: filter_design.txt:179
NULL
#define NULL
Definition: coverity.c:32
CBP0_TAG
#define CBP0_TAG
Definition: vqavideo.c:94
VqaContext::avctx
AVCodecContext * avctx
Definition: vqavideo.c:104
MAX_CODEBOOK_SIZE
#define MAX_CODEBOOK_SIZE
Definition: vqavideo.c:90
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:107
vqa_defaults
static const FFCodecDefault vqa_defaults[]
Definition: vqavideo.c:844
MAX_VECTORS
#define MAX_VECTORS
Definition: vqavideo.c:89
decode_format80
static int decode_format80(VqaContext *s, int src_size, unsigned char *dest, int dest_size, int check_size)
Definition: vqavideo.c:234
index
int index
Definition: gxfenc.c:90
relative
static IPT relative(const CmsCtx *ctx, IPT ipt)
Definition: cms.c:544
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:368
vqa_decode_frame_pal8
static int vqa_decode_frame_pal8(VqaContext *s, AVFrame *frame)
Definition: vqavideo.c:342
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:798
AVPacket::size
int size
Definition: packet.h:559
CPL0_TAG
#define CPL0_TAG
Definition: vqavideo.c:96
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:278
codec_internal.h
VqaContext::height
int height
Definition: vqavideo.c:110
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
av_bswap32
#define av_bswap32
Definition: bswap.h:47
ff_vqa_decoder
const FFCodec ff_vqa_decoder
Definition: vqavideo.c:849
size
int size
Definition: twinvq_data.h:10344
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:97
VqaContext::frame
AVFrame * frame
Definition: vqavideo.c:103
CPLZ_TAG
#define CPLZ_TAG
Definition: vqavideo.c:97
VqaContext::next_codebook_buffer_index
int next_codebook_buffer_index
Definition: vqavideo.c:118
vqa_decode_end
static av_cold int vqa_decode_end(AVCodecContext *avctx)
Definition: vqavideo.c:832
vqa_decode_frame_hicolor
static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame)
Definition: vqavideo.c:627
CHECK_COPY
#define CHECK_COPY(idx)
Definition: vqavideo.c:225
VqaContext::partial_countdown
int partial_countdown
Definition: vqavideo.c:124
VqaContext::vqa_version
int vqa_version
Definition: vqavideo.c:113
VPTZ_TAG
#define VPTZ_TAG
Definition: vqavideo.c:98
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:256
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:99
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:256
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:179
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:631
VqaContext::vector_height
int vector_height
Definition: vqavideo.c:112
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:1840
ret
ret
Definition: filter_design.txt:187
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
U
#define U(x)
Definition: vpx_arith.h:37
AVCodecContext
main external API structure.
Definition: avcodec.h:431
CBF0_TAG
#define CBF0_TAG
Definition: vqavideo.c:92
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
mem.h
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:37
ff_tlog
#define ff_tlog(a,...)
Definition: tableprint_vlc.h:29
AVPacket
This structure stores compressed data.
Definition: packet.h:535
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:458
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
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:115
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:83
VqaContext::gb
GetByteContext gb
Definition: vqavideo.c:105
CBPZ_TAG
#define CBPZ_TAG
Definition: vqavideo.c:95
width
#define width
Definition: dsp.h:89
src
#define src
Definition: vp8dsp.c:248
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:347