FFmpeg
vqavideo.c
Go to the documentation of this file.
1 /*
2  * Westwood Studios VQA Video Decoder
3  * Copyright (C) 2003 The FFmpeg project
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * VQA Video Decoder
25  * @author Mike Melanson (melanson@pcisys.net)
26  * @see http://wiki.multimedia.cx/index.php?title=VQA
27  *
28  * The VQA video decoder outputs PAL8 or RGB555 colorspace data, depending
29  * on the type of data in the file.
30  *
31  * This decoder needs the 42-byte VQHD header from the beginning
32  * of the VQA file passed through the extradata field. The VQHD header
33  * is laid out as:
34  *
35  * bytes 0-3 chunk fourcc: 'VQHD'
36  * bytes 4-7 chunk size in big-endian format, should be 0x0000002A
37  * bytes 8-49 VQHD chunk data
38  *
39  * Bytes 8-49 are what this decoder expects to see.
40  *
41  * Briefly, VQA is a vector quantized animation format that operates in a
42  * VGA palettized colorspace. It operates on pixel vectors (blocks)
43  * of either 4x2 or 4x4 in size. Compressed VQA chunks can contain vector
44  * codebooks, palette information, and code maps for rendering vectors onto
45  * frames. Any of these components can also be compressed with a run-length
46  * encoding (RLE) algorithm commonly referred to as "format80".
47  *
48  * VQA takes a novel approach to rate control. Each group of n frames
49  * (usually, n = 8) relies on a different vector codebook. Rather than
50  * transporting an entire codebook every 8th frame, the new codebook is
51  * broken up into 8 pieces and sent along with the compressed video chunks
52  * for each of the 8 frames preceding the 8 frames which require the
53  * codebook. A full codebook is also sent on the very first frame of a
54  * file. This is an interesting technique, although it makes random file
55  * seeking difficult despite the fact that the frames are all intracoded.
56  *
57  * V1,2 VQA uses 12-bit codebook indexes. If the 12-bit indexes were
58  * packed into bytes and then RLE compressed, bytewise, the results would
59  * be poor. That is why the coding method divides each index into 2 parts,
60  * the top 4 bits and the bottom 8 bits, then RL encodes the 4-bit pieces
61  * together and the 8-bit pieces together. If most of the vectors are
62  * clustered into one group of 256 vectors, most of the 4-bit index pieces
63  * should be the same.
64  */
65 
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 
70 #include "libavutil/intreadwrite.h"
71 #include "libavutil/imgutils.h"
72 #include "avcodec.h"
73 #include "bytestream.h"
74 #include "internal.h"
75 
76 #define PALETTE_COUNT 256
77 #define VQA_HEADER_SIZE 0x2A
78 
79 /* allocate the maximum vector space, regardless of the file version:
80  * (0xFF00 codebook vectors + 0x100 solid pixel vectors) * (4x4 pixels/block) */
81 #define MAX_CODEBOOK_VECTORS 0xFF00
82 #define SOLID_PIXEL_VECTORS 0x100
83 #define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS)
84 #define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4)
85 
86 #define CBF0_TAG MKBETAG('C', 'B', 'F', '0')
87 #define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z')
88 #define CBP0_TAG MKBETAG('C', 'B', 'P', '0')
89 #define CBPZ_TAG MKBETAG('C', 'B', 'P', 'Z')
90 #define CPL0_TAG MKBETAG('C', 'P', 'L', '0')
91 #define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z')
92 #define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z')
93 
94 typedef struct VqaContext {
95 
98 
100 
101  int width; /* width of a frame */
102  int height; /* height of a frame */
103  int vector_width; /* width of individual vector */
104  int vector_height; /* height of individual vector */
105  int vqa_version; /* this should be either 1, 2 or 3 */
106 
107  unsigned char *codebook; /* the current codebook */
109  unsigned char *next_codebook_buffer; /* accumulator for next codebook */
111 
112  unsigned char *decode_buffer;
114 
115  /* number of frames to go before replacing codebook */
118 
119 } VqaContext;
120 
122 {
123  VqaContext *s = avctx->priv_data;
124  int i, j, codebook_index, ret;
125 
126  s->avctx = avctx;
127  avctx->pix_fmt = AV_PIX_FMT_PAL8;
128 
129  /* make sure the extradata made it */
130  if (s->avctx->extradata_size != VQA_HEADER_SIZE) {
131  av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n", VQA_HEADER_SIZE);
132  return AVERROR(EINVAL);
133  }
134 
135  /* load up the VQA parameters from the header */
136  s->vqa_version = s->avctx->extradata[0];
137  switch (s->vqa_version) {
138  case 1:
139  case 2:
140  break;
141  case 3:
142  avpriv_report_missing_feature(avctx, "VQA Version %d", s->vqa_version);
143  return AVERROR_PATCHWELCOME;
144  default:
145  avpriv_request_sample(avctx, "VQA Version %i", s->vqa_version);
146  return AVERROR_PATCHWELCOME;
147  }
148  s->width = AV_RL16(&s->avctx->extradata[6]);
149  s->height = AV_RL16(&s->avctx->extradata[8]);
150  if ((ret = ff_set_dimensions(avctx, s->width, s->height)) < 0) {
151  s->width= s->height= 0;
152  return ret;
153  }
154  s->vector_width = s->avctx->extradata[10];
155  s->vector_height = s->avctx->extradata[11];
156  s->partial_count = s->partial_countdown = s->avctx->extradata[13];
157 
158  /* the vector dimensions have to meet very stringent requirements */
159  if ((s->vector_width != 4) ||
160  ((s->vector_height != 2) && (s->vector_height != 4))) {
161  /* return without further initialization */
162  return AVERROR_INVALIDDATA;
163  }
164 
165  if (s->width % s->vector_width || s->height % s->vector_height) {
166  av_log(avctx, AV_LOG_ERROR, "Image size not multiple of block size\n");
167  return AVERROR_INVALIDDATA;
168  }
169 
170  /* allocate codebooks */
171  s->codebook_size = MAX_CODEBOOK_SIZE;
172  s->codebook = av_malloc(s->codebook_size);
173  if (!s->codebook)
174  goto fail;
175  s->next_codebook_buffer = av_malloc(s->codebook_size);
176  if (!s->next_codebook_buffer)
177  goto fail;
178 
179  /* allocate decode buffer */
180  s->decode_buffer_size = (s->width / s->vector_width) *
181  (s->height / s->vector_height) * 2;
182  s->decode_buffer = av_mallocz(s->decode_buffer_size);
183  if (!s->decode_buffer)
184  goto fail;
185 
186  /* initialize the solid-color vectors */
187  if (s->vector_height == 4) {
188  codebook_index = 0xFF00 * 16;
189  for (i = 0; i < 256; i++)
190  for (j = 0; j < 16; j++)
191  s->codebook[codebook_index++] = i;
192  } else {
193  codebook_index = 0xF00 * 8;
194  for (i = 0; i < 256; i++)
195  for (j = 0; j < 8; j++)
196  s->codebook[codebook_index++] = i;
197  }
198  s->next_codebook_buffer_index = 0;
199 
200  return 0;
201 fail:
202  av_freep(&s->codebook);
203  av_freep(&s->next_codebook_buffer);
204  av_freep(&s->decode_buffer);
205  return AVERROR(ENOMEM);
206 }
207 
208 #define CHECK_COUNT() \
209  if (dest_index + count > dest_size) { \
210  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
211  av_log(s->avctx, AV_LOG_ERROR, "current dest_index = %d, count = %d, dest_size = %d\n", \
212  dest_index, count, dest_size); \
213  return AVERROR_INVALIDDATA; \
214  }
215 
216 #define CHECK_COPY(idx) \
217  if (idx < 0 || idx + 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 src_pos = %d, count = %d, dest_size = %d\n", \
220  src_pos, count, dest_size); \
221  return AVERROR_INVALIDDATA; \
222  }
223 
224 
225 static int decode_format80(VqaContext *s, int src_size,
226  unsigned char *dest, int dest_size, int check_size) {
227 
228  int dest_index = 0;
229  int count, opcode, start;
230  int src_pos;
231  unsigned char color;
232  int i;
233 
234  if (src_size < 0 || src_size > bytestream2_get_bytes_left(&s->gb)) {
235  av_log(s->avctx, AV_LOG_ERROR, "Chunk size %d is out of range\n",
236  src_size);
237  return AVERROR_INVALIDDATA;
238  }
239 
240  start = bytestream2_tell(&s->gb);
241  while (bytestream2_tell(&s->gb) - start < src_size) {
242  opcode = bytestream2_get_byte(&s->gb);
243  ff_tlog(s->avctx, "opcode %02X: ", opcode);
244 
245  /* 0x80 means that frame is finished */
246  if (opcode == 0x80)
247  break;
248 
249  if (dest_index >= dest_size) {
250  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
251  dest_index, dest_size);
252  return AVERROR_INVALIDDATA;
253  }
254 
255  if (opcode == 0xFF) {
256 
257  count = bytestream2_get_le16(&s->gb);
258  src_pos = bytestream2_get_le16(&s->gb);
259  ff_tlog(s->avctx, "(1) copy %X bytes from absolute pos %X\n", count, src_pos);
260  CHECK_COUNT();
261  CHECK_COPY(src_pos);
262  for (i = 0; i < count; i++)
263  dest[dest_index + i] = dest[src_pos + i];
264  dest_index += count;
265 
266  } else if (opcode == 0xFE) {
267 
268  count = bytestream2_get_le16(&s->gb);
269  color = bytestream2_get_byte(&s->gb);
270  ff_tlog(s->avctx, "(2) set %X bytes to %02X\n", count, color);
271  CHECK_COUNT();
272  memset(&dest[dest_index], color, count);
273  dest_index += count;
274 
275  } else if ((opcode & 0xC0) == 0xC0) {
276 
277  count = (opcode & 0x3F) + 3;
278  src_pos = bytestream2_get_le16(&s->gb);
279  ff_tlog(s->avctx, "(3) copy %X bytes from absolute pos %X\n", count, src_pos);
280  CHECK_COUNT();
281  CHECK_COPY(src_pos);
282  for (i = 0; i < count; i++)
283  dest[dest_index + i] = dest[src_pos + i];
284  dest_index += count;
285 
286  } else if (opcode > 0x80) {
287 
288  count = opcode & 0x3F;
289  ff_tlog(s->avctx, "(4) copy %X bytes from source to dest\n", count);
290  CHECK_COUNT();
291  bytestream2_get_buffer(&s->gb, &dest[dest_index], count);
292  dest_index += count;
293 
294  } else {
295 
296  count = ((opcode & 0x70) >> 4) + 3;
297  src_pos = bytestream2_get_byte(&s->gb) | ((opcode & 0x0F) << 8);
298  ff_tlog(s->avctx, "(5) copy %X bytes from relpos %X\n", count, src_pos);
299  CHECK_COUNT();
300  CHECK_COPY(dest_index - src_pos);
301  for (i = 0; i < count; i++)
302  dest[dest_index + i] = dest[dest_index - src_pos + i];
303  dest_index += count;
304  }
305  }
306 
307  /* validate that the entire destination buffer was filled; this is
308  * important for decoding frame maps since each vector needs to have a
309  * codebook entry; it is not important for compressed codebooks because
310  * not every entry needs to be filled */
311  if (check_size)
312  if (dest_index < dest_size) {
313  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n",
314  dest_index, dest_size);
315  memset(dest + dest_index, 0, dest_size - dest_index);
316  }
317 
318  return 0; // let's display what we decoded anyway
319 }
320 
322 {
323  unsigned int chunk_type;
324  unsigned int chunk_size;
325  int byte_skip;
326  unsigned int index = 0;
327  int i;
328  unsigned char r, g, b;
329  int index_shift;
330  int res;
331 
332  int cbf0_chunk = -1;
333  int cbfz_chunk = -1;
334  int cbp0_chunk = -1;
335  int cbpz_chunk = -1;
336  int cpl0_chunk = -1;
337  int cplz_chunk = -1;
338  int vptz_chunk = -1;
339 
340  int x, y;
341  int lines = 0;
342  int pixel_ptr;
343  int vector_index = 0;
344  int lobyte = 0;
345  int hibyte = 0;
346  int lobytes = 0;
347  int hibytes = s->decode_buffer_size / 2;
348 
349  /* first, traverse through the frame and find the subchunks */
350  while (bytestream2_get_bytes_left(&s->gb) >= 8) {
351 
352  chunk_type = bytestream2_get_be32u(&s->gb);
353  index = bytestream2_tell(&s->gb);
354  chunk_size = bytestream2_get_be32u(&s->gb);
355 
356  switch (chunk_type) {
357 
358  case CBF0_TAG:
359  cbf0_chunk = index;
360  break;
361 
362  case CBFZ_TAG:
363  cbfz_chunk = index;
364  break;
365 
366  case CBP0_TAG:
367  cbp0_chunk = index;
368  break;
369 
370  case CBPZ_TAG:
371  cbpz_chunk = index;
372  break;
373 
374  case CPL0_TAG:
375  cpl0_chunk = index;
376  break;
377 
378  case CPLZ_TAG:
379  cplz_chunk = index;
380  break;
381 
382  case VPTZ_TAG:
383  vptz_chunk = index;
384  break;
385 
386  default:
387  av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
388  av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
389  break;
390  }
391 
392  byte_skip = chunk_size & 0x01;
393  bytestream2_skip(&s->gb, chunk_size + byte_skip);
394  }
395 
396  /* next, deal with the palette */
397  if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
398 
399  /* a chunk should not have both chunk types */
400  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CPL0 and CPLZ chunks\n");
401  return AVERROR_INVALIDDATA;
402  }
403 
404  /* decompress the palette chunk */
405  if (cplz_chunk != -1) {
406 
407 /* yet to be handled */
408 
409  }
410 
411  /* convert the RGB palette into the machine's endian format */
412  if (cpl0_chunk != -1) {
413 
414  bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET);
415  chunk_size = bytestream2_get_be32(&s->gb);
416  /* sanity check the palette size */
417  if (chunk_size / 3 > 256 || chunk_size > bytestream2_get_bytes_left(&s->gb)) {
418  av_log(s->avctx, AV_LOG_ERROR, "problem: found a palette chunk with %d colors\n",
419  chunk_size / 3);
420  return AVERROR_INVALIDDATA;
421  }
422  for (i = 0; i < chunk_size / 3; i++) {
423  /* scale by 4 to transform 6-bit palette -> 8-bit */
424  r = bytestream2_get_byteu(&s->gb) * 4;
425  g = bytestream2_get_byteu(&s->gb) * 4;
426  b = bytestream2_get_byteu(&s->gb) * 4;
427  s->palette[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
428  s->palette[i] |= s->palette[i] >> 6 & 0x30303;
429  }
430  }
431 
432  /* next, look for a full codebook */
433  if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
434 
435  /* a chunk should not have both chunk types */
436  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
437  return AVERROR_INVALIDDATA;
438  }
439 
440  /* decompress the full codebook chunk */
441  if (cbfz_chunk != -1) {
442 
443  bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
444  chunk_size = bytestream2_get_be32(&s->gb);
445  if ((res = decode_format80(s, chunk_size, s->codebook,
446  s->codebook_size, 0)) < 0)
447  return res;
448  }
449 
450  /* copy a full codebook */
451  if (cbf0_chunk != -1) {
452 
453  bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
454  chunk_size = bytestream2_get_be32(&s->gb);
455  /* sanity check the full codebook size */
456  if (chunk_size > MAX_CODEBOOK_SIZE) {
457  av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
458  chunk_size);
459  return AVERROR_INVALIDDATA;
460  }
461 
462  bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
463  }
464 
465  /* decode the frame */
466  if (vptz_chunk == -1) {
467 
468  /* something is wrong if there is no VPTZ chunk */
469  av_log(s->avctx, AV_LOG_ERROR, "problem: no VPTZ chunk found\n");
470  return AVERROR_INVALIDDATA;
471  }
472 
473  bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET);
474  chunk_size = bytestream2_get_be32(&s->gb);
475  if ((res = decode_format80(s, chunk_size,
476  s->decode_buffer, s->decode_buffer_size, 1)) < 0)
477  return res;
478 
479  /* render the final PAL8 frame */
480  if (s->vector_height == 4)
481  index_shift = 4;
482  else
483  index_shift = 3;
484  for (y = 0; y < s->height; y += s->vector_height) {
485  for (x = 0; x < s->width; x += 4, lobytes++, hibytes++) {
486  pixel_ptr = y * frame->linesize[0] + x;
487 
488  /* get the vector index, the method for which varies according to
489  * VQA file version */
490  switch (s->vqa_version) {
491 
492  case 1:
493  lobyte = s->decode_buffer[lobytes * 2];
494  hibyte = s->decode_buffer[(lobytes * 2) + 1];
495  vector_index = ((hibyte << 8) | lobyte) >> 3;
496  vector_index <<= index_shift;
497  lines = s->vector_height;
498  /* uniform color fill - a quick hack */
499  if (hibyte == 0xFF) {
500  while (lines--) {
501  frame->data[0][pixel_ptr + 0] = 255 - lobyte;
502  frame->data[0][pixel_ptr + 1] = 255 - lobyte;
503  frame->data[0][pixel_ptr + 2] = 255 - lobyte;
504  frame->data[0][pixel_ptr + 3] = 255 - lobyte;
505  pixel_ptr += frame->linesize[0];
506  }
507  lines=0;
508  }
509  break;
510 
511  case 2:
512  lobyte = s->decode_buffer[lobytes];
513  hibyte = s->decode_buffer[hibytes];
514  vector_index = (hibyte << 8) | lobyte;
515  vector_index <<= index_shift;
516  lines = s->vector_height;
517  break;
518 
519  case 3:
520 /* not implemented yet */
521  lines = 0;
522  break;
523  }
524 
525  while (lines--) {
526  frame->data[0][pixel_ptr + 0] = s->codebook[vector_index++];
527  frame->data[0][pixel_ptr + 1] = s->codebook[vector_index++];
528  frame->data[0][pixel_ptr + 2] = s->codebook[vector_index++];
529  frame->data[0][pixel_ptr + 3] = s->codebook[vector_index++];
530  pixel_ptr += frame->linesize[0];
531  }
532  }
533  }
534 
535  /* handle partial codebook */
536  if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
537  /* a chunk should not have both chunk types */
538  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBP0 and CBPZ chunks\n");
539  return AVERROR_INVALIDDATA;
540  }
541 
542  if (cbp0_chunk != -1) {
543 
544  bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET);
545  chunk_size = bytestream2_get_be32(&s->gb);
546 
547  if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
548  av_log(s->avctx, AV_LOG_ERROR, "cbp0 chunk too large (%u bytes)\n",
549  chunk_size);
550  return AVERROR_INVALIDDATA;
551  }
552 
553  /* accumulate partial codebook */
554  bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
555  chunk_size);
556  s->next_codebook_buffer_index += chunk_size;
557 
558  s->partial_countdown--;
559  if (s->partial_countdown <= 0) {
560 
561  /* time to replace codebook */
562  memcpy(s->codebook, s->next_codebook_buffer,
563  s->next_codebook_buffer_index);
564 
565  /* reset accounting */
566  s->next_codebook_buffer_index = 0;
567  s->partial_countdown = s->partial_count;
568  }
569  }
570 
571  if (cbpz_chunk != -1) {
572 
573  bytestream2_seek(&s->gb, cbpz_chunk, SEEK_SET);
574  chunk_size = bytestream2_get_be32(&s->gb);
575 
576  if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
577  av_log(s->avctx, AV_LOG_ERROR, "cbpz chunk too large (%u bytes)\n",
578  chunk_size);
579  return AVERROR_INVALIDDATA;
580  }
581 
582  /* accumulate partial codebook */
583  bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
584  chunk_size);
585  s->next_codebook_buffer_index += chunk_size;
586 
587  s->partial_countdown--;
588  if (s->partial_countdown <= 0) {
589  bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index);
590  /* decompress codebook */
591  res = decode_format80(s, s->next_codebook_buffer_index,
592  s->codebook, s->codebook_size, 0);
593 
594  /* reset accounting */
595  s->next_codebook_buffer_index = 0;
596  s->partial_countdown = s->partial_count;
597  if (res < 0)
598  return res;
599  }
600  }
601 
602  return 0;
603 }
604 
606  void *data, int *got_frame,
607  AVPacket *avpkt)
608 {
609  VqaContext *s = avctx->priv_data;
610  AVFrame *frame = data;
611  int res;
612 
613  if ((res = ff_get_buffer(avctx, frame, 0)) < 0)
614  return res;
615 
616  bytestream2_init(&s->gb, avpkt->data, avpkt->size);
617  if ((res = vqa_decode_chunk(s, frame)) < 0)
618  return res;
619 
620  /* make the palette available on the way out */
621  memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
622  frame->palette_has_changed = 1;
623 
624  *got_frame = 1;
625 
626  /* report that the buffer was completely consumed */
627  return avpkt->size;
628 }
629 
631 {
632  VqaContext *s = avctx->priv_data;
633 
634  av_freep(&s->codebook);
635  av_freep(&s->next_codebook_buffer);
636  av_freep(&s->decode_buffer);
637 
638  return 0;
639 }
640 
641 static const AVCodecDefault vqa_defaults[] = {
642  { "max_pixels", "320*240" },
643  { NULL },
644 };
645 
647  .name = "vqavideo",
648  .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"),
649  .type = AVMEDIA_TYPE_VIDEO,
650  .id = AV_CODEC_ID_WS_VQA,
651  .priv_data_size = sizeof(VqaContext),
653  .close = vqa_decode_end,
655  .capabilities = AV_CODEC_CAP_DR1,
657 };
AVCodec
AVCodec.
Definition: codec.h:190
check_size
static int check_size(TiffEncoderContext *s, uint64_t need)
Check free space in buffer.
Definition: tiffenc.c:87
VqaContext::decode_buffer_size
int decode_buffer_size
Definition: vqavideo.c:113
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
r
const char * r
Definition: vf_curves.c:114
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:582
GetByteContext
Definition: bytestream.h:33
VqaContext::next_codebook_buffer
unsigned char * next_codebook_buffer
Definition: vqavideo.c:109
bytestream2_seek
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:208
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:300
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:355
VqaContext::codebook_size
int codebook_size
Definition: vqavideo.c:108
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:91
ff_tlog
#define ff_tlog(ctx,...)
Definition: internal.h:86
CHECK_COUNT
#define CHECK_COUNT()
Definition: vqavideo.c:208
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
PALETTE_COUNT
#define PALETTE_COUNT
Definition: vqavideo.c:76
VqaContext
Definition: vqavideo.c:94
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:164
U
#define U(x)
Definition: vp56_arith.h:37
VqaContext::width
int width
Definition: vqavideo.c:101
fail
#define fail()
Definition: checkasm.h:123
VqaContext::partial_count
int partial_count
Definition: vqavideo.c:117
defaults
static const AVCodecDefault defaults[]
Definition: amfenc_h264.c:361
av_bswap32
#define av_bswap32
Definition: bswap.h:33
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
av_cold
#define av_cold
Definition: attributes.h:90
VqaContext::vector_width
int vector_width
Definition: vqavideo.c:103
decode
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
vqa_decode_init
static av_cold int vqa_decode_init(AVCodecContext *avctx)
Definition: vqavideo.c:121
VqaContext::decode_buffer
unsigned char * decode_buffer
Definition: vqavideo.c:112
g
const char * g
Definition: vf_curves.c:115
AV_CODEC_ID_WS_VQA
@ AV_CODEC_ID_WS_VQA
Definition: codec_id.h:93
CBFZ_TAG
#define CBFZ_TAG
Definition: vqavideo.c:87
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:90
AVCodecDefault
Definition: internal.h:201
NULL
#define NULL
Definition: coverity.c:32
CBP0_TAG
#define CBP0_TAG
Definition: vqavideo.c:88
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
VqaContext::avctx
AVCodecContext * avctx
Definition: vqavideo.c:96
MAX_CODEBOOK_SIZE
#define MAX_CODEBOOK_SIZE
Definition: vqavideo.c:84
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:263
VqaContext::palette
uint32_t palette[PALETTE_COUNT]
Definition: vqavideo.c:99
decode_format80
static int decode_format80(VqaContext *s, int src_size, unsigned char *dest, int dest_size, int check_size)
Definition: vqavideo.c:225
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:154
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:188
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1854
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:50
AVPacket::size
int size
Definition: packet.h:356
CPL0_TAG
#define CPL0_TAG
Definition: vqavideo.c:90
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:188
VqaContext::height
int height
Definition: vqavideo.c:102
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:92
avpriv_report_missing_feature
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
CPLZ_TAG
#define CPLZ_TAG
Definition: vqavideo.c:91
VqaContext::next_codebook_buffer_index
int next_codebook_buffer_index
Definition: vqavideo.c:110
vqa_decode_end
static av_cold int vqa_decode_end(AVCodecContext *avctx)
Definition: vqavideo.c:630
CHECK_COPY
#define CHECK_COPY(idx)
Definition: vqavideo.c:216
VqaContext::partial_countdown
int partial_countdown
Definition: vqavideo.c:116
VqaContext::vqa_version
int vqa_version
Definition: vqavideo.c:105
VPTZ_TAG
#define VPTZ_TAG
Definition: vqavideo.c:92
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
ff_vqa_decoder
AVCodec ff_vqa_decoder
Definition: vqavideo.c:646
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:237
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:197
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:736
VqaContext::vector_height
int vector_height
Definition: vqavideo.c:104
avcodec.h
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
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:264
AVCodecContext
main external API structure.
Definition: avcodec.h:526
CBF0_TAG
#define CBF0_TAG
Definition: vqavideo.c:86
vqa_decode_chunk
static int vqa_decode_chunk(VqaContext *s, AVFrame *frame)
Definition: vqavideo.c:321
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
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:104
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:39
AVPacket
This structure stores compressed data.
Definition: packet.h:332
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:553
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
bytestream.h
imgutils.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
VqaContext::codebook
unsigned char * codebook
Definition: vqavideo.c:107
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
vqa_defaults
static const AVCodecDefault vqa_defaults[]
Definition: vqavideo.c:641
VQA_HEADER_SIZE
#define VQA_HEADER_SIZE
Definition: vqavideo.c:77
VqaContext::gb
GetByteContext gb
Definition: vqavideo.c:97
CBPZ_TAG
#define CBPZ_TAG
Definition: vqavideo.c:89
vqa_decode_frame
static int vqa_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: vqavideo.c:605
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:348