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  return AVERROR(ENOMEM);
175  s->next_codebook_buffer = av_malloc(s->codebook_size);
176  if (!s->next_codebook_buffer)
177  return AVERROR(ENOMEM);
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  return AVERROR(ENOMEM);
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 }
202 
203 #define CHECK_COUNT() \
204  if (dest_index + count > dest_size) { \
205  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
206  av_log(s->avctx, AV_LOG_ERROR, "current dest_index = %d, count = %d, dest_size = %d\n", \
207  dest_index, count, dest_size); \
208  return AVERROR_INVALIDDATA; \
209  }
210 
211 #define CHECK_COPY(idx) \
212  if (idx < 0 || idx + count > dest_size) { \
213  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
214  av_log(s->avctx, AV_LOG_ERROR, "current src_pos = %d, count = %d, dest_size = %d\n", \
215  src_pos, count, dest_size); \
216  return AVERROR_INVALIDDATA; \
217  }
218 
219 
220 static int decode_format80(VqaContext *s, int src_size,
221  unsigned char *dest, int dest_size, int check_size) {
222 
223  int dest_index = 0;
224  int count, opcode, start;
225  int src_pos;
226  unsigned char color;
227  int i;
228 
229  if (src_size < 0 || src_size > bytestream2_get_bytes_left(&s->gb)) {
230  av_log(s->avctx, AV_LOG_ERROR, "Chunk size %d is out of range\n",
231  src_size);
232  return AVERROR_INVALIDDATA;
233  }
234 
235  start = bytestream2_tell(&s->gb);
236  while (bytestream2_tell(&s->gb) - start < src_size) {
237  opcode = bytestream2_get_byte(&s->gb);
238  ff_tlog(s->avctx, "opcode %02X: ", opcode);
239 
240  /* 0x80 means that frame is finished */
241  if (opcode == 0x80)
242  break;
243 
244  if (dest_index >= dest_size) {
245  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
246  dest_index, dest_size);
247  return AVERROR_INVALIDDATA;
248  }
249 
250  if (opcode == 0xFF) {
251 
252  count = bytestream2_get_le16(&s->gb);
253  src_pos = bytestream2_get_le16(&s->gb);
254  ff_tlog(s->avctx, "(1) copy %X bytes from absolute pos %X\n", count, src_pos);
255  CHECK_COUNT();
256  CHECK_COPY(src_pos);
257  for (i = 0; i < count; i++)
258  dest[dest_index + i] = dest[src_pos + i];
259  dest_index += count;
260 
261  } else if (opcode == 0xFE) {
262 
263  count = bytestream2_get_le16(&s->gb);
264  color = bytestream2_get_byte(&s->gb);
265  ff_tlog(s->avctx, "(2) set %X bytes to %02X\n", count, color);
266  CHECK_COUNT();
267  memset(&dest[dest_index], color, count);
268  dest_index += count;
269 
270  } else if ((opcode & 0xC0) == 0xC0) {
271 
272  count = (opcode & 0x3F) + 3;
273  src_pos = bytestream2_get_le16(&s->gb);
274  ff_tlog(s->avctx, "(3) copy %X bytes from absolute pos %X\n", count, src_pos);
275  CHECK_COUNT();
276  CHECK_COPY(src_pos);
277  for (i = 0; i < count; i++)
278  dest[dest_index + i] = dest[src_pos + i];
279  dest_index += count;
280 
281  } else if (opcode > 0x80) {
282 
283  count = opcode & 0x3F;
284  ff_tlog(s->avctx, "(4) copy %X bytes from source to dest\n", count);
285  CHECK_COUNT();
286  bytestream2_get_buffer(&s->gb, &dest[dest_index], count);
287  dest_index += count;
288 
289  } else {
290 
291  count = ((opcode & 0x70) >> 4) + 3;
292  src_pos = bytestream2_get_byte(&s->gb) | ((opcode & 0x0F) << 8);
293  ff_tlog(s->avctx, "(5) copy %X bytes from relpos %X\n", count, src_pos);
294  CHECK_COUNT();
295  CHECK_COPY(dest_index - src_pos);
296  for (i = 0; i < count; i++)
297  dest[dest_index + i] = dest[dest_index - src_pos + i];
298  dest_index += count;
299  }
300  }
301 
302  /* validate that the entire destination buffer was filled; this is
303  * important for decoding frame maps since each vector needs to have a
304  * codebook entry; it is not important for compressed codebooks because
305  * not every entry needs to be filled */
306  if (check_size)
307  if (dest_index < dest_size) {
308  av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n",
309  dest_index, dest_size);
310  memset(dest + dest_index, 0, dest_size - dest_index);
311  }
312 
313  return 0; // let's display what we decoded anyway
314 }
315 
317 {
318  unsigned int chunk_type;
319  unsigned int chunk_size;
320  int byte_skip;
321  unsigned int index = 0;
322  int i;
323  unsigned char r, g, b;
324  int index_shift;
325  int res;
326 
327  int cbf0_chunk = -1;
328  int cbfz_chunk = -1;
329  int cbp0_chunk = -1;
330  int cbpz_chunk = -1;
331  int cpl0_chunk = -1;
332  int cplz_chunk = -1;
333  int vptz_chunk = -1;
334 
335  int x, y;
336  int lines = 0;
337  int pixel_ptr;
338  int vector_index = 0;
339  int lobyte = 0;
340  int hibyte = 0;
341  int lobytes = 0;
342  int hibytes = s->decode_buffer_size / 2;
343 
344  /* first, traverse through the frame and find the subchunks */
345  while (bytestream2_get_bytes_left(&s->gb) >= 8) {
346 
347  chunk_type = bytestream2_get_be32u(&s->gb);
348  index = bytestream2_tell(&s->gb);
349  chunk_size = bytestream2_get_be32u(&s->gb);
350 
351  switch (chunk_type) {
352 
353  case CBF0_TAG:
354  cbf0_chunk = index;
355  break;
356 
357  case CBFZ_TAG:
358  cbfz_chunk = index;
359  break;
360 
361  case CBP0_TAG:
362  cbp0_chunk = index;
363  break;
364 
365  case CBPZ_TAG:
366  cbpz_chunk = index;
367  break;
368 
369  case CPL0_TAG:
370  cpl0_chunk = index;
371  break;
372 
373  case CPLZ_TAG:
374  cplz_chunk = index;
375  break;
376 
377  case VPTZ_TAG:
378  vptz_chunk = index;
379  break;
380 
381  default:
382  av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n",
383  av_fourcc2str(av_bswap32(chunk_type)), chunk_type);
384  break;
385  }
386 
387  byte_skip = chunk_size & 0x01;
388  bytestream2_skip(&s->gb, chunk_size + byte_skip);
389  }
390 
391  /* next, deal with the palette */
392  if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
393 
394  /* a chunk should not have both chunk types */
395  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CPL0 and CPLZ chunks\n");
396  return AVERROR_INVALIDDATA;
397  }
398 
399  /* decompress the palette chunk */
400  if (cplz_chunk != -1) {
401 
402 /* yet to be handled */
403 
404  }
405 
406  /* convert the RGB palette into the machine's endian format */
407  if (cpl0_chunk != -1) {
408 
409  bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET);
410  chunk_size = bytestream2_get_be32(&s->gb);
411  /* sanity check the palette size */
412  if (chunk_size / 3 > 256 || chunk_size > bytestream2_get_bytes_left(&s->gb)) {
413  av_log(s->avctx, AV_LOG_ERROR, "problem: found a palette chunk with %d colors\n",
414  chunk_size / 3);
415  return AVERROR_INVALIDDATA;
416  }
417  for (i = 0; i < chunk_size / 3; i++) {
418  /* scale by 4 to transform 6-bit palette -> 8-bit */
419  r = bytestream2_get_byteu(&s->gb) * 4;
420  g = bytestream2_get_byteu(&s->gb) * 4;
421  b = bytestream2_get_byteu(&s->gb) * 4;
422  s->palette[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
423  s->palette[i] |= s->palette[i] >> 6 & 0x30303;
424  }
425  }
426 
427  /* next, look for a full codebook */
428  if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
429 
430  /* a chunk should not have both chunk types */
431  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
432  return AVERROR_INVALIDDATA;
433  }
434 
435  /* decompress the full codebook chunk */
436  if (cbfz_chunk != -1) {
437 
438  bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
439  chunk_size = bytestream2_get_be32(&s->gb);
440  if ((res = decode_format80(s, chunk_size, s->codebook,
441  s->codebook_size, 0)) < 0)
442  return res;
443  }
444 
445  /* copy a full codebook */
446  if (cbf0_chunk != -1) {
447 
448  bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
449  chunk_size = bytestream2_get_be32(&s->gb);
450  /* sanity check the full codebook size */
451  if (chunk_size > MAX_CODEBOOK_SIZE) {
452  av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
453  chunk_size);
454  return AVERROR_INVALIDDATA;
455  }
456 
457  bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
458  }
459 
460  /* decode the frame */
461  if (vptz_chunk == -1) {
462 
463  /* something is wrong if there is no VPTZ chunk */
464  av_log(s->avctx, AV_LOG_ERROR, "problem: no VPTZ chunk found\n");
465  return AVERROR_INVALIDDATA;
466  }
467 
468  bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET);
469  chunk_size = bytestream2_get_be32(&s->gb);
470  if ((res = decode_format80(s, chunk_size,
471  s->decode_buffer, s->decode_buffer_size, 1)) < 0)
472  return res;
473 
474  /* render the final PAL8 frame */
475  if (s->vector_height == 4)
476  index_shift = 4;
477  else
478  index_shift = 3;
479  for (y = 0; y < s->height; y += s->vector_height) {
480  for (x = 0; x < s->width; x += 4, lobytes++, hibytes++) {
481  pixel_ptr = y * frame->linesize[0] + x;
482 
483  /* get the vector index, the method for which varies according to
484  * VQA file version */
485  switch (s->vqa_version) {
486 
487  case 1:
488  lobyte = s->decode_buffer[lobytes * 2];
489  hibyte = s->decode_buffer[(lobytes * 2) + 1];
490  vector_index = ((hibyte << 8) | lobyte) >> 3;
491  vector_index <<= index_shift;
492  lines = s->vector_height;
493  /* uniform color fill - a quick hack */
494  if (hibyte == 0xFF) {
495  while (lines--) {
496  frame->data[0][pixel_ptr + 0] = 255 - lobyte;
497  frame->data[0][pixel_ptr + 1] = 255 - lobyte;
498  frame->data[0][pixel_ptr + 2] = 255 - lobyte;
499  frame->data[0][pixel_ptr + 3] = 255 - lobyte;
500  pixel_ptr += frame->linesize[0];
501  }
502  lines=0;
503  }
504  break;
505 
506  case 2:
507  lobyte = s->decode_buffer[lobytes];
508  hibyte = s->decode_buffer[hibytes];
509  vector_index = (hibyte << 8) | lobyte;
510  vector_index <<= index_shift;
511  lines = s->vector_height;
512  break;
513 
514  case 3:
515 /* not implemented yet */
516  lines = 0;
517  break;
518  }
519 
520  while (lines--) {
521  frame->data[0][pixel_ptr + 0] = s->codebook[vector_index++];
522  frame->data[0][pixel_ptr + 1] = s->codebook[vector_index++];
523  frame->data[0][pixel_ptr + 2] = s->codebook[vector_index++];
524  frame->data[0][pixel_ptr + 3] = s->codebook[vector_index++];
525  pixel_ptr += frame->linesize[0];
526  }
527  }
528  }
529 
530  /* handle partial codebook */
531  if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
532  /* a chunk should not have both chunk types */
533  av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBP0 and CBPZ chunks\n");
534  return AVERROR_INVALIDDATA;
535  }
536 
537  if (cbp0_chunk != -1) {
538 
539  bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET);
540  chunk_size = bytestream2_get_be32(&s->gb);
541 
542  if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
543  av_log(s->avctx, AV_LOG_ERROR, "cbp0 chunk too large (%u bytes)\n",
544  chunk_size);
545  return AVERROR_INVALIDDATA;
546  }
547 
548  /* accumulate partial codebook */
549  bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
550  chunk_size);
551  s->next_codebook_buffer_index += chunk_size;
552 
553  s->partial_countdown--;
554  if (s->partial_countdown <= 0) {
555 
556  /* time to replace codebook */
557  memcpy(s->codebook, s->next_codebook_buffer,
558  s->next_codebook_buffer_index);
559 
560  /* reset accounting */
561  s->next_codebook_buffer_index = 0;
562  s->partial_countdown = s->partial_count;
563  }
564  }
565 
566  if (cbpz_chunk != -1) {
567 
568  bytestream2_seek(&s->gb, cbpz_chunk, SEEK_SET);
569  chunk_size = bytestream2_get_be32(&s->gb);
570 
571  if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
572  av_log(s->avctx, AV_LOG_ERROR, "cbpz chunk too large (%u bytes)\n",
573  chunk_size);
574  return AVERROR_INVALIDDATA;
575  }
576 
577  /* accumulate partial codebook */
578  bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
579  chunk_size);
580  s->next_codebook_buffer_index += chunk_size;
581 
582  s->partial_countdown--;
583  if (s->partial_countdown <= 0) {
584  bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index);
585  /* decompress codebook */
586  if ((res = decode_format80(s, s->next_codebook_buffer_index,
587  s->codebook, s->codebook_size, 0)) < 0)
588  return res;
589 
590  /* reset accounting */
591  s->next_codebook_buffer_index = 0;
592  s->partial_countdown = s->partial_count;
593  }
594  }
595 
596  return 0;
597 }
598 
600  void *data, int *got_frame,
601  AVPacket *avpkt)
602 {
603  VqaContext *s = avctx->priv_data;
604  AVFrame *frame = data;
605  int res;
606 
607  if ((res = ff_get_buffer(avctx, frame, 0)) < 0)
608  return res;
609 
610  bytestream2_init(&s->gb, avpkt->data, avpkt->size);
611  if ((res = vqa_decode_chunk(s, frame)) < 0)
612  return res;
613 
614  /* make the palette available on the way out */
615  memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
616  frame->palette_has_changed = 1;
617 
618  *got_frame = 1;
619 
620  /* report that the buffer was completely consumed */
621  return avpkt->size;
622 }
623 
625 {
626  VqaContext *s = avctx->priv_data;
627 
628  av_freep(&s->codebook);
629  av_freep(&s->next_codebook_buffer);
630  av_freep(&s->decode_buffer);
631 
632  return 0;
633 }
634 
635 static const AVCodecDefault vqa_defaults[] = {
636  { "max_pixels", "320*240" },
637  { NULL },
638 };
639 
641  .name = "vqavideo",
642  .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"),
643  .type = AVMEDIA_TYPE_VIDEO,
644  .id = AV_CODEC_ID_WS_VQA,
645  .priv_data_size = sizeof(VqaContext),
647  .close = vqa_decode_end,
649  .capabilities = AV_CODEC_CAP_DR1,
652 };
AVCodec
AVCodec.
Definition: codec.h:197
FF_CODEC_CAP_INIT_THREADSAFE
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: internal.h:41
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:113
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
r
const char * r
Definition: vf_curves.c:116
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:583
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:212
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
index
fg index
Definition: ffmpeg_filter.c:168
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:365
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:142
ff_tlog
#define ff_tlog(ctx,...)
Definition: internal.h:96
CHECK_COUNT
#define CHECK_COUNT()
Definition: vqavideo.c:203
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:168
U
#define U(x)
Definition: vp56_arith.h:37
VqaContext::width
int width
Definition: vqavideo.c:101
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:181
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:117
AV_CODEC_ID_WS_VQA
@ AV_CODEC_ID_WS_VQA
Definition: codec_id.h:94
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:94
AVCodecDefault
Definition: internal.h:212
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:267
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:220
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
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1645
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
AVPacket::size
int size
Definition: packet.h:366
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:117
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:624
CHECK_COPY
#define CHECK_COPY(idx)
Definition: vqavideo.c:211
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
ff_vqa_decoder
const AVCodec ff_vqa_decoder
Definition: vqavideo.c:640
i
int i
Definition: input.c:407
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: internal.h:49
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:244
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:204
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:594
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:384
CBF0_TAG
#define CBF0_TAG
Definition: vqavideo.c:86
vqa_decode_chunk
static int vqa_decode_chunk(VqaContext *s, AVFrame *frame)
Definition: vqavideo.c:316
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:86
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:39
AVPacket
This structure stores compressed data.
Definition: packet.h:342
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:411
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:137
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:635
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:599
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:348