Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.  
  96.     AVCodecContext *avctx;
  97.     GetByteContext gb;
  98.  
  99.     uint32_t palette[PALETTE_COUNT];
  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 */
  108.     int codebook_size;
  109.     unsigned char *next_codebook_buffer;  /* accumulator for next codebook */
  110.     int next_codebook_buffer_index;
  111.  
  112.     unsigned char *decode_buffer;
  113.     int decode_buffer_size;
  114.  
  115.     /* number of frames to go before replacing codebook */
  116.     int partial_countdown;
  117.     int partial_count;
  118.  
  119. } VqaContext;
  120.  
  121. static av_cold int vqa_decode_init(AVCodecContext *avctx)
  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 = av_image_check_size(s->width, s->height, 0, avctx)) < 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.  
  321. static int vqa_decode_chunk(VqaContext *s, AVFrame *frame)
  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: %c%c%c%c (%08X)\n",
  388.             (chunk_type >> 24) & 0xFF,
  389.             (chunk_type >> 16) & 0xFF,
  390.             (chunk_type >>  8) & 0xFF,
  391.             (chunk_type >>  0) & 0xFF,
  392.             chunk_type);
  393.             break;
  394.         }
  395.  
  396.         byte_skip = chunk_size & 0x01;
  397.         bytestream2_skip(&s->gb, chunk_size + byte_skip);
  398.     }
  399.  
  400.     /* next, deal with the palette */
  401.     if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
  402.  
  403.         /* a chunk should not have both chunk types */
  404.         av_log(s->avctx, AV_LOG_ERROR, "problem: found both CPL0 and CPLZ chunks\n");
  405.         return AVERROR_INVALIDDATA;
  406.     }
  407.  
  408.     /* decompress the palette chunk */
  409.     if (cplz_chunk != -1) {
  410.  
  411. /* yet to be handled */
  412.  
  413.     }
  414.  
  415.     /* convert the RGB palette into the machine's endian format */
  416.     if (cpl0_chunk != -1) {
  417.  
  418.         bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET);
  419.         chunk_size = bytestream2_get_be32(&s->gb);
  420.         /* sanity check the palette size */
  421.         if (chunk_size / 3 > 256 || chunk_size > bytestream2_get_bytes_left(&s->gb)) {
  422.             av_log(s->avctx, AV_LOG_ERROR, "problem: found a palette chunk with %d colors\n",
  423.                 chunk_size / 3);
  424.             return AVERROR_INVALIDDATA;
  425.         }
  426.         for (i = 0; i < chunk_size / 3; i++) {
  427.             /* scale by 4 to transform 6-bit palette -> 8-bit */
  428.             r = bytestream2_get_byteu(&s->gb) * 4;
  429.             g = bytestream2_get_byteu(&s->gb) * 4;
  430.             b = bytestream2_get_byteu(&s->gb) * 4;
  431.             s->palette[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
  432.             s->palette[i] |= s->palette[i] >> 6 & 0x30303;
  433.         }
  434.     }
  435.  
  436.     /* next, look for a full codebook */
  437.     if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
  438.  
  439.         /* a chunk should not have both chunk types */
  440.         av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
  441.         return AVERROR_INVALIDDATA;
  442.     }
  443.  
  444.     /* decompress the full codebook chunk */
  445.     if (cbfz_chunk != -1) {
  446.  
  447.         bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
  448.         chunk_size = bytestream2_get_be32(&s->gb);
  449.         if ((res = decode_format80(s, chunk_size, s->codebook,
  450.                                    s->codebook_size, 0)) < 0)
  451.             return res;
  452.     }
  453.  
  454.     /* copy a full codebook */
  455.     if (cbf0_chunk != -1) {
  456.  
  457.         bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
  458.         chunk_size = bytestream2_get_be32(&s->gb);
  459.         /* sanity check the full codebook size */
  460.         if (chunk_size > MAX_CODEBOOK_SIZE) {
  461.             av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
  462.                 chunk_size);
  463.             return AVERROR_INVALIDDATA;
  464.         }
  465.  
  466.         bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
  467.     }
  468.  
  469.     /* decode the frame */
  470.     if (vptz_chunk == -1) {
  471.  
  472.         /* something is wrong if there is no VPTZ chunk */
  473.         av_log(s->avctx, AV_LOG_ERROR, "problem: no VPTZ chunk found\n");
  474.         return AVERROR_INVALIDDATA;
  475.     }
  476.  
  477.     bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET);
  478.     chunk_size = bytestream2_get_be32(&s->gb);
  479.     if ((res = decode_format80(s, chunk_size,
  480.                                s->decode_buffer, s->decode_buffer_size, 1)) < 0)
  481.         return res;
  482.  
  483.     /* render the final PAL8 frame */
  484.     if (s->vector_height == 4)
  485.         index_shift = 4;
  486.     else
  487.         index_shift = 3;
  488.     for (y = 0; y < s->height; y += s->vector_height) {
  489.         for (x = 0; x < s->width; x += 4, lobytes++, hibytes++) {
  490.             pixel_ptr = y * frame->linesize[0] + x;
  491.  
  492.             /* get the vector index, the method for which varies according to
  493.              * VQA file version */
  494.             switch (s->vqa_version) {
  495.  
  496.             case 1:
  497.                 lobyte = s->decode_buffer[lobytes * 2];
  498.                 hibyte = s->decode_buffer[(lobytes * 2) + 1];
  499.                 vector_index = ((hibyte << 8) | lobyte) >> 3;
  500.                 vector_index <<= index_shift;
  501.                 lines = s->vector_height;
  502.                 /* uniform color fill - a quick hack */
  503.                 if (hibyte == 0xFF) {
  504.                     while (lines--) {
  505.                         frame->data[0][pixel_ptr + 0] = 255 - lobyte;
  506.                         frame->data[0][pixel_ptr + 1] = 255 - lobyte;
  507.                         frame->data[0][pixel_ptr + 2] = 255 - lobyte;
  508.                         frame->data[0][pixel_ptr + 3] = 255 - lobyte;
  509.                         pixel_ptr += frame->linesize[0];
  510.                     }
  511.                     lines=0;
  512.                 }
  513.                 break;
  514.  
  515.             case 2:
  516.                 lobyte = s->decode_buffer[lobytes];
  517.                 hibyte = s->decode_buffer[hibytes];
  518.                 vector_index = (hibyte << 8) | lobyte;
  519.                 vector_index <<= index_shift;
  520.                 lines = s->vector_height;
  521.                 break;
  522.  
  523.             case 3:
  524. /* not implemented yet */
  525.                 lines = 0;
  526.                 break;
  527.             }
  528.  
  529.             while (lines--) {
  530.                 frame->data[0][pixel_ptr + 0] = s->codebook[vector_index++];
  531.                 frame->data[0][pixel_ptr + 1] = s->codebook[vector_index++];
  532.                 frame->data[0][pixel_ptr + 2] = s->codebook[vector_index++];
  533.                 frame->data[0][pixel_ptr + 3] = s->codebook[vector_index++];
  534.                 pixel_ptr += frame->linesize[0];
  535.             }
  536.         }
  537.     }
  538.  
  539.     /* handle partial codebook */
  540.     if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
  541.         /* a chunk should not have both chunk types */
  542.         av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBP0 and CBPZ chunks\n");
  543.         return AVERROR_INVALIDDATA;
  544.     }
  545.  
  546.     if (cbp0_chunk != -1) {
  547.  
  548.         bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET);
  549.         chunk_size = bytestream2_get_be32(&s->gb);
  550.  
  551.         if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
  552.             av_log(s->avctx, AV_LOG_ERROR, "cbp0 chunk too large (%u bytes)\n",
  553.                    chunk_size);
  554.             return AVERROR_INVALIDDATA;
  555.         }
  556.  
  557.         /* accumulate partial codebook */
  558.         bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
  559.                                chunk_size);
  560.         s->next_codebook_buffer_index += chunk_size;
  561.  
  562.         s->partial_countdown--;
  563.         if (s->partial_countdown <= 0) {
  564.  
  565.             /* time to replace codebook */
  566.             memcpy(s->codebook, s->next_codebook_buffer,
  567.                 s->next_codebook_buffer_index);
  568.  
  569.             /* reset accounting */
  570.             s->next_codebook_buffer_index = 0;
  571.             s->partial_countdown = s->partial_count;
  572.         }
  573.     }
  574.  
  575.     if (cbpz_chunk != -1) {
  576.  
  577.         bytestream2_seek(&s->gb, cbpz_chunk, SEEK_SET);
  578.         chunk_size = bytestream2_get_be32(&s->gb);
  579.  
  580.         if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
  581.             av_log(s->avctx, AV_LOG_ERROR, "cbpz chunk too large (%u bytes)\n",
  582.                    chunk_size);
  583.             return AVERROR_INVALIDDATA;
  584.         }
  585.  
  586.         /* accumulate partial codebook */
  587.         bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
  588.                                chunk_size);
  589.         s->next_codebook_buffer_index += chunk_size;
  590.  
  591.         s->partial_countdown--;
  592.         if (s->partial_countdown <= 0) {
  593.             bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index);
  594.             /* decompress codebook */
  595.             if ((res = decode_format80(s, s->next_codebook_buffer_index,
  596.                                        s->codebook, s->codebook_size, 0)) < 0)
  597.                 return res;
  598.  
  599.             /* reset accounting */
  600.             s->next_codebook_buffer_index = 0;
  601.             s->partial_countdown = s->partial_count;
  602.         }
  603.     }
  604.  
  605.     return 0;
  606. }
  607.  
  608. static int vqa_decode_frame(AVCodecContext *avctx,
  609.                             void *data, int *got_frame,
  610.                             AVPacket *avpkt)
  611. {
  612.     VqaContext *s = avctx->priv_data;
  613.     AVFrame *frame = data;
  614.     int res;
  615.  
  616.     if ((res = ff_get_buffer(avctx, frame, 0)) < 0)
  617.         return res;
  618.  
  619.     bytestream2_init(&s->gb, avpkt->data, avpkt->size);
  620.     if ((res = vqa_decode_chunk(s, frame)) < 0)
  621.         return res;
  622.  
  623.     /* make the palette available on the way out */
  624.     memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
  625.     frame->palette_has_changed = 1;
  626.  
  627.     *got_frame      = 1;
  628.  
  629.     /* report that the buffer was completely consumed */
  630.     return avpkt->size;
  631. }
  632.  
  633. static av_cold int vqa_decode_end(AVCodecContext *avctx)
  634. {
  635.     VqaContext *s = avctx->priv_data;
  636.  
  637.     av_freep(&s->codebook);
  638.     av_freep(&s->next_codebook_buffer);
  639.     av_freep(&s->decode_buffer);
  640.  
  641.     return 0;
  642. }
  643.  
  644. AVCodec ff_vqa_decoder = {
  645.     .name           = "vqavideo",
  646.     .long_name      = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"),
  647.     .type           = AVMEDIA_TYPE_VIDEO,
  648.     .id             = AV_CODEC_ID_WS_VQA,
  649.     .priv_data_size = sizeof(VqaContext),
  650.     .init           = vqa_decode_init,
  651.     .close          = vqa_decode_end,
  652.     .decode         = vqa_decode_frame,
  653.     .capabilities   = AV_CODEC_CAP_DR1,
  654. };
  655.