Subversion Repositories Kolibri OS

Rev

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