vqavideo.c 21.1 KB
Newer Older
1 2 3 4
/*
 * Westwood Studios VQA Video Decoder
 * Copyright (C) 2003 the ffmpeg project
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * 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 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * 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 25 26
 * VQA Video Decoder
 * @author Mike Melanson (melanson@pcisys.net)
 * @see http://wiki.multimedia.cx/index.php?title=VQA
27
 *
28 29
 * The VQA video decoder outputs PAL8 or RGB555 colorspace data, depending
 * on the type of data in the file.
30 31 32 33 34 35 36
 *
 * This decoder needs the 42-byte VQHD header from the beginning
 * of the VQA file passed through the extradata field. The VQHD header
 * is laid out as:
 *
 *   bytes 0-3   chunk fourcc: 'VQHD'
 *   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 44 45 46 47 48 49 50 51 52 53 54 55 56
 * of either 4x2 or 4x4 in size. Compressed VQA chunks can contain vector
 * codebooks, palette information, and code maps for rendering vectors onto
 * frames. Any of these components can also be compressed with a run-length
 * encoding (RLE) algorithm commonly referred to as "format80".
 *
 * VQA takes a novel approach to rate control. Each group of n frames
 * (usually, n = 8) relies on a different vector codebook. Rather than
 * transporting an entire codebook every 8th frame, the new codebook is
 * broken up into 8 pieces and sent along with the compressed video chunks
 * for each of the 8 frames preceding the 8 frames which require the
 * codebook. A full codebook is also sent on the very first frame of a
 * file. This is an interesting technique, although it makes random file
 * seeking difficult despite the fact that the frames are all intracoded.
 *
57
 * V1,2 VQA uses 12-bit codebook indexes. If the 12-bit indexes were
58 59
 * packed into bytes and then RLE compressed, bytewise, the results would
 * 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 62 63 64 65 66 67 68 69
 * together and the 8-bit pieces together. If most of the vectors are
 * clustered into one group of 256 vectors, most of the 4-bit index pieces
 * should be the same.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

70
#include "libavutil/intreadwrite.h"
71
#include "libavutil/imgutils.h"
72
#include "avcodec.h"
73
#include "bytestream.h"
74 75 76 77

#define PALETTE_COUNT 256
#define VQA_HEADER_SIZE 0x2A

78 79 80 81 82 83
/* allocate the maximum vector space, regardless of the file version:
 * (0xFF00 codebook vectors + 0x100 solid pixel vectors) * (4x4 pixels/block) */
#define MAX_CODEBOOK_VECTORS 0xFF00
#define SOLID_PIXEL_VECTORS 0x100
#define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS)
#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4)
84

85 86 87 88 89 90 91
#define CBF0_TAG MKBETAG('C', 'B', 'F', '0')
#define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z')
#define CBP0_TAG MKBETAG('C', 'B', 'P', '0')
#define CBPZ_TAG MKBETAG('C', 'B', 'P', 'Z')
#define CPL0_TAG MKBETAG('C', 'P', 'L', '0')
#define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z')
#define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z')
92 93 94 95 96

typedef struct VqaContext {

    AVCodecContext *avctx;
    AVFrame frame;
97
    GetByteContext gb;
98

99
    uint32_t palette[PALETTE_COUNT];
100 101 102 103 104 105 106 107

    int width;   /* width of a frame */
    int height;   /* height of a frame */
    int vector_width;  /* width of individual vector */
    int vector_height;  /* height of individual vector */
    int vqa_version;  /* this should be either 1, 2 or 3 */

    unsigned char *codebook;         /* the current codebook */
108
    int codebook_size;
109 110 111 112 113 114 115 116 117 118 119 120
    unsigned char *next_codebook_buffer;  /* accumulator for next codebook */
    int next_codebook_buffer_index;

    unsigned char *decode_buffer;
    int decode_buffer_size;

    /* number of frames to go before replacing codebook */
    int partial_countdown;
    int partial_count;

} VqaContext;

121
static av_cold int vqa_decode_init(AVCodecContext *avctx)
122
{
123
    VqaContext *s = avctx->priv_data;
Michael Niedermayer's avatar
Michael Niedermayer committed
124
    int i, j, codebook_index;
125 126

    s->avctx = avctx;
127
    avctx->pix_fmt = AV_PIX_FMT_PAL8;
128 129 130

    /* make sure the extradata made it */
    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 133 134 135
        return -1;
    }

    /* load up the VQA parameters from the header */
136
    s->vqa_version = s->avctx->extradata[0];
137
    if (s->vqa_version < 1 || s->vqa_version > 3) {
138
        av_log(s->avctx, AV_LOG_ERROR, "unsupported version %d\n", s->vqa_version);
139 140
        return -1;
    }
141 142
    s->width = AV_RL16(&s->avctx->extradata[6]);
    s->height = AV_RL16(&s->avctx->extradata[8]);
143
    if(av_image_check_size(s->width, s->height, 0, avctx)){
144 145 146
        s->width= s->height= 0;
        return -1;
    }
147 148 149
    s->vector_width = s->avctx->extradata[10];
    s->vector_height = s->avctx->extradata[11];
    s->partial_count = s->partial_countdown = s->avctx->extradata[13];
150 151 152 153 154 155 156 157

    /* the vector dimensions have to meet very stringent requirements */
    if ((s->vector_width != 4) ||
        ((s->vector_height != 2) && (s->vector_height != 4))) {
        /* return without further initialization */
        return -1;
    }

158
    if (s->width % s->vector_width || s->height % s->vector_height) {
159 160 161 162
        av_log(avctx, AV_LOG_ERROR, "Image size not multiple of block size\n");
        return AVERROR_INVALIDDATA;
    }

163
    /* allocate codebooks */
164 165
    s->codebook_size = MAX_CODEBOOK_SIZE;
    s->codebook = av_malloc(s->codebook_size);
166 167
    if (!s->codebook)
        goto fail;
168
    s->next_codebook_buffer = av_malloc(s->codebook_size);
169 170 171 172 173 174 175 176 177
    if (!s->next_codebook_buffer)
        goto fail;

    /* allocate decode buffer */
    s->decode_buffer_size = (s->width / s->vector_width) *
        (s->height / s->vector_height) * 2;
    s->decode_buffer = av_malloc(s->decode_buffer_size);
    if (!s->decode_buffer)
        goto fail;
178 179 180 181 182 183 184

    /* initialize the solid-color vectors */
    if (s->vector_height == 4) {
        codebook_index = 0xFF00 * 16;
        for (i = 0; i < 256; i++)
            for (j = 0; j < 16; j++)
                s->codebook[codebook_index++] = i;
185
    } else {
186 187 188 189
        codebook_index = 0xF00 * 8;
        for (i = 0; i < 256; i++)
            for (j = 0; j < 8; j++)
                s->codebook[codebook_index++] = i;
190 191 192
    }
    s->next_codebook_buffer_index = 0;

193
    avcodec_get_frame_defaults(&s->frame);
194 195 196
    s->frame.data[0] = NULL;

    return 0;
197 198 199 200 201
fail:
    av_freep(&s->codebook);
    av_freep(&s->next_codebook_buffer);
    av_freep(&s->decode_buffer);
    return AVERROR(ENOMEM);
202 203 204 205
}

#define CHECK_COUNT() \
    if (dest_index + count > dest_size) { \
206 207
        av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
        av_log(s->avctx, AV_LOG_ERROR, "current dest_index = %d, count = %d, dest_size = %d\n", \
208
            dest_index, count, dest_size); \
209
        return AVERROR_INVALIDDATA; \
210 211
    }

212 213
#define CHECK_COPY(idx) \
    if (idx < 0 || idx + count > dest_size) { \
214 215
        av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \
        av_log(s->avctx, AV_LOG_ERROR, "current src_pos = %d, count = %d, dest_size = %d\n", \
216 217
            src_pos, count, dest_size); \
        return AVERROR_INVALIDDATA; \
218 219
    }

220

221
static int decode_format80(VqaContext *s, int src_size,
222
    unsigned char *dest, int dest_size, int check_size) {
223 224

    int dest_index = 0;
225
    int count, opcode, start;
226 227 228 229
    int src_pos;
    unsigned char color;
    int i;

230 231 232 233
    start = bytestream2_tell(&s->gb);
    while (bytestream2_tell(&s->gb) - start < src_size) {
        opcode = bytestream2_get_byte(&s->gb);
        av_dlog(s->avctx, "opcode %02X: ", opcode);
234 235

        /* 0x80 means that frame is finished */
236 237
        if (opcode == 0x80)
            return 0;
238 239

        if (dest_index >= dest_size) {
240
            av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
241
                dest_index, dest_size);
242
            return AVERROR_INVALIDDATA;
243 244
        }

245
        if (opcode == 0xFF) {
246

247 248 249
            count   = bytestream2_get_le16(&s->gb);
            src_pos = bytestream2_get_le16(&s->gb);
            av_dlog(s->avctx, "(1) copy %X bytes from absolute pos %X\n", count, src_pos);
250
            CHECK_COUNT();
251
            CHECK_COPY(src_pos);
252 253 254 255
            for (i = 0; i < count; i++)
                dest[dest_index + i] = dest[src_pos + i];
            dest_index += count;

256
        } else if (opcode == 0xFE) {
257

258 259 260
            count = bytestream2_get_le16(&s->gb);
            color = bytestream2_get_byte(&s->gb);
            av_dlog(s->avctx, "(2) set %X bytes to %02X\n", count, color);
261 262 263 264
            CHECK_COUNT();
            memset(&dest[dest_index], color, count);
            dest_index += count;

265
        } else if ((opcode & 0xC0) == 0xC0) {
266

267
            count = (opcode & 0x3F) + 3;
268 269
            src_pos = bytestream2_get_le16(&s->gb);
            av_dlog(s->avctx, "(3) copy %X bytes from absolute pos %X\n", count, src_pos);
270
            CHECK_COUNT();
271
            CHECK_COPY(src_pos);
272 273 274 275
            for (i = 0; i < count; i++)
                dest[dest_index + i] = dest[src_pos + i];
            dest_index += count;

276
        } else if (opcode > 0x80) {
277

278
            count = opcode & 0x3F;
279
            av_dlog(s->avctx, "(4) copy %X bytes from source to dest\n", count);
280
            CHECK_COUNT();
281
            bytestream2_get_buffer(&s->gb, &dest[dest_index], count);
282 283 284 285
            dest_index += count;

        } else {

286
            count = ((opcode & 0x70) >> 4) + 3;
287 288
            src_pos = bytestream2_get_byte(&s->gb) | ((opcode & 0x0F) << 8);
            av_dlog(s->avctx, "(5) copy %X bytes from relpos %X\n", count, src_pos);
289
            CHECK_COUNT();
290
            CHECK_COPY(dest_index - src_pos);
291 292 293 294 295 296
            for (i = 0; i < count; i++)
                dest[dest_index + i] = dest[dest_index - src_pos + i];
            dest_index += count;
        }
    }

297 298 299 300 301 302
    /* validate that the entire destination buffer was filled; this is
     * important for decoding frame maps since each vector needs to have a
     * codebook entry; it is not important for compressed codebooks because
     * not every entry needs to be filled */
    if (check_size)
        if (dest_index < dest_size)
303
            av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n",
304
                dest_index, dest_size);
305 306

    return 0; // let's display what we decoded anyway
307 308
}

309
static int vqa_decode_chunk(VqaContext *s)
310 311 312 313 314 315 316
{
    unsigned int chunk_type;
    unsigned int chunk_size;
    int byte_skip;
    unsigned int index = 0;
    int i;
    unsigned char r, g, b;
317
    int index_shift;
318
    int res;
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337

    int cbf0_chunk = -1;
    int cbfz_chunk = -1;
    int cbp0_chunk = -1;
    int cbpz_chunk = -1;
    int cpl0_chunk = -1;
    int cplz_chunk = -1;
    int vptz_chunk = -1;

    int x, y;
    int lines = 0;
    int pixel_ptr;
    int vector_index = 0;
    int lobyte = 0;
    int hibyte = 0;
    int lobytes = 0;
    int hibytes = s->decode_buffer_size / 2;

    /* first, traverse through the frame and find the subchunks */
338
    while (bytestream2_get_bytes_left(&s->gb) >= 8) {
339

340 341 342
        chunk_type = bytestream2_get_be32u(&s->gb);
        index      = bytestream2_tell(&s->gb);
        chunk_size = bytestream2_get_be32u(&s->gb);
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374

        switch (chunk_type) {

        case CBF0_TAG:
            cbf0_chunk = index;
            break;

        case CBFZ_TAG:
            cbfz_chunk = index;
            break;

        case CBP0_TAG:
            cbp0_chunk = index;
            break;

        case CBPZ_TAG:
            cbpz_chunk = index;
            break;

        case CPL0_TAG:
            cpl0_chunk = index;
            break;

        case CPLZ_TAG:
            cplz_chunk = index;
            break;

        case VPTZ_TAG:
            vptz_chunk = index;
            break;

        default:
375
            av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %c%c%c%c (%08X)\n",
376 377 378 379 380 381 382 383 384
            (chunk_type >> 24) & 0xFF,
            (chunk_type >> 16) & 0xFF,
            (chunk_type >>  8) & 0xFF,
            (chunk_type >>  0) & 0xFF,
            chunk_type);
            break;
        }

        byte_skip = chunk_size & 0x01;
385
        bytestream2_skip(&s->gb, chunk_size + byte_skip);
386 387 388 389 390 391
    }

    /* next, deal with the palette */
    if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {

        /* a chunk should not have both chunk types */
392
        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CPL0 and CPLZ chunks\n");
393
        return AVERROR_INVALIDDATA;
394 395 396 397 398 399 400 401 402 403 404 405
    }

    /* decompress the palette chunk */
    if (cplz_chunk != -1) {

/* yet to be handled */

    }

    /* convert the RGB palette into the machine's endian format */
    if (cpl0_chunk != -1) {

406 407
        bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET);
        chunk_size = bytestream2_get_be32(&s->gb);
408
        /* sanity check the palette size */
409
        if (chunk_size / 3 > 256 || chunk_size > bytestream2_get_bytes_left(&s->gb)) {
410
            av_log(s->avctx, AV_LOG_ERROR, "problem: found a palette chunk with %d colors\n",
411
                chunk_size / 3);
412
            return AVERROR_INVALIDDATA;
413 414 415
        }
        for (i = 0; i < chunk_size / 3; i++) {
            /* scale by 4 to transform 6-bit palette -> 8-bit */
416 417 418
            r = bytestream2_get_byteu(&s->gb) * 4;
            g = bytestream2_get_byteu(&s->gb) * 4;
            b = bytestream2_get_byteu(&s->gb) * 4;
419
            s->palette[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
420
            s->palette[i] |= s->palette[i] >> 6 & 0x30303;
421 422 423 424 425 426 427
        }
    }

    /* next, look for a full codebook */
    if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {

        /* a chunk should not have both chunk types */
428
        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n");
429
        return AVERROR_INVALIDDATA;
430 431
    }

432
    /* decompress the full codebook chunk */
433 434
    if (cbfz_chunk != -1) {

435 436
        bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
        chunk_size = bytestream2_get_be32(&s->gb);
437
        if ((res = decode_format80(s, chunk_size, s->codebook,
438 439
                                   s->codebook_size, 0)) < 0)
            return res;
440 441 442 443 444
    }

    /* copy a full codebook */
    if (cbf0_chunk != -1) {

445 446
        bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
        chunk_size = bytestream2_get_be32(&s->gb);
447
        /* sanity check the full codebook size */
448
        if (chunk_size > MAX_CODEBOOK_SIZE) {
449
            av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n",
450
                chunk_size);
451
            return AVERROR_INVALIDDATA;
452 453
        }

454
        bytestream2_get_buffer(&s->gb, s->codebook, chunk_size);
455 456 457 458 459 460
    }

    /* decode the frame */
    if (vptz_chunk == -1) {

        /* something is wrong if there is no VPTZ chunk */
461
        av_log(s->avctx, AV_LOG_ERROR, "problem: no VPTZ chunk found\n");
462
        return AVERROR_INVALIDDATA;
463 464
    }

465 466
    bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET);
    chunk_size = bytestream2_get_be32(&s->gb);
467
    if ((res = decode_format80(s, chunk_size,
468 469
                               s->decode_buffer, s->decode_buffer_size, 1)) < 0)
        return res;
470 471

    /* render the final PAL8 frame */
472 473 474 475
    if (s->vector_height == 4)
        index_shift = 4;
    else
        index_shift = 3;
476 477 478
    for (y = 0; y < s->height; y += s->vector_height) {
        for (x = 0; x < s->width; x += 4, lobytes++, hibytes++) {
            pixel_ptr = y * s->frame.linesize[0] + x;
479 480 481 482 483 484

            /* get the vector index, the method for which varies according to
             * VQA file version */
            switch (s->vqa_version) {

            case 1:
Kostya Shishkov's avatar
Kostya Shishkov committed
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
                lobyte = s->decode_buffer[lobytes * 2];
                hibyte = s->decode_buffer[(lobytes * 2) + 1];
                vector_index = ((hibyte << 8) | lobyte) >> 3;
                vector_index <<= index_shift;
                lines = s->vector_height;
                /* uniform color fill - a quick hack */
                if (hibyte == 0xFF) {
                    while (lines--) {
                        s->frame.data[0][pixel_ptr + 0] = 255 - lobyte;
                        s->frame.data[0][pixel_ptr + 1] = 255 - lobyte;
                        s->frame.data[0][pixel_ptr + 2] = 255 - lobyte;
                        s->frame.data[0][pixel_ptr + 3] = 255 - lobyte;
                        pixel_ptr += s->frame.linesize[0];
                    }
                    lines=0;
                }
501 502 503 504 505 506
                break;

            case 2:
                lobyte = s->decode_buffer[lobytes];
                hibyte = s->decode_buffer[hibytes];
                vector_index = (hibyte << 8) | lobyte;
507
                vector_index <<= index_shift;
508
                lines = s->vector_height;
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
                break;

            case 3:
/* not implemented yet */
                lines = 0;
                break;
            }

            while (lines--) {
                s->frame.data[0][pixel_ptr + 0] = s->codebook[vector_index++];
                s->frame.data[0][pixel_ptr + 1] = s->codebook[vector_index++];
                s->frame.data[0][pixel_ptr + 2] = s->codebook[vector_index++];
                s->frame.data[0][pixel_ptr + 3] = s->codebook[vector_index++];
                pixel_ptr += s->frame.linesize[0];
            }
        }
    }

    /* handle partial codebook */
    if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
        /* a chunk should not have both chunk types */
530
        av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBP0 and CBPZ chunks\n");
531
        return AVERROR_INVALIDDATA;
532 533 534 535
    }

    if (cbp0_chunk != -1) {

536 537
        bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET);
        chunk_size = bytestream2_get_be32(&s->gb);
538 539

        /* accumulate partial codebook */
540 541
        bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
                               chunk_size);
542 543 544
        s->next_codebook_buffer_index += chunk_size;

        s->partial_countdown--;
545
        if (s->partial_countdown <= 0) {
546 547

            /* time to replace codebook */
548
            memcpy(s->codebook, s->next_codebook_buffer,
549 550 551 552 553 554 555 556 557 558
                s->next_codebook_buffer_index);

            /* reset accounting */
            s->next_codebook_buffer_index = 0;
            s->partial_countdown = s->partial_count;
        }
    }

    if (cbpz_chunk != -1) {

559 560
        bytestream2_seek(&s->gb, cbpz_chunk, SEEK_SET);
        chunk_size = bytestream2_get_be32(&s->gb);
561

562
        /* accumulate partial codebook */
563 564
        bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
                               chunk_size);
565 566 567
        s->next_codebook_buffer_index += chunk_size;

        s->partial_countdown--;
568
        if (s->partial_countdown <= 0) {
569
            GetByteContext gb;
570

571
            bytestream2_init(&gb, s->next_codebook_buffer, s->next_codebook_buffer_index);
572
            /* decompress codebook */
573
            if ((res = decode_format80(s, s->next_codebook_buffer_index,
574 575
                                       s->codebook, s->codebook_size, 0)) < 0)
                return res;
576 577 578 579 580

            /* reset accounting */
            s->next_codebook_buffer_index = 0;
            s->partial_countdown = s->partial_count;
        }
581
    }
582 583

    return 0;
584 585 586 587
}

static int vqa_decode_frame(AVCodecContext *avctx,
                            void *data, int *data_size,
588
                            AVPacket *avpkt)
589
{
590
    VqaContext *s = avctx->priv_data;
591
    int res;
592 593 594 595 596

    if (s->frame.data[0])
        avctx->release_buffer(avctx, &s->frame);

    if (avctx->get_buffer(avctx, &s->frame)) {
597
        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
598 599 600
        return -1;
    }

601 602 603
    bytestream2_init(&s->gb, avpkt->data, avpkt->size);
    if ((res = vqa_decode_chunk(s)) < 0)
        return res;
604 605 606

    /* make the palette available on the way out */
    memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
607
    s->frame.palette_has_changed = 1;
608 609 610 611 612

    *data_size = sizeof(AVFrame);
    *(AVFrame*)data = s->frame;

    /* report that the buffer was completely consumed */
613
    return avpkt->size;
614 615
}

616
static av_cold int vqa_decode_end(AVCodecContext *avctx)
617
{
618
    VqaContext *s = avctx->priv_data;
619

620 621 622
    av_freep(&s->codebook);
    av_freep(&s->next_codebook_buffer);
    av_freep(&s->decode_buffer);
623 624 625 626 627 628 629

    if (s->frame.data[0])
        avctx->release_buffer(avctx, &s->frame);

    return 0;
}

630
AVCodec ff_vqa_decoder = {
631 632
    .name           = "vqavideo",
    .type           = AVMEDIA_TYPE_VIDEO,
633
    .id             = AV_CODEC_ID_WS_VQA,
634 635 636 637 638
    .priv_data_size = sizeof(VqaContext),
    .init           = vqa_decode_init,
    .close          = vqa_decode_end,
    .decode         = vqa_decode_frame,
    .capabilities   = CODEC_CAP_DR1,
639
    .long_name      = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"),
640
};