vqavideo.c 21.5 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
#include "internal.h"
75 76 77 78

#define PALETTE_COUNT 256
#define VQA_HEADER_SIZE 0x2A

79 80 81 82 83 84
/* 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)
85

86 87 88 89 90 91 92
#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')
93 94 95 96

typedef struct VqaContext {

    AVCodecContext *avctx;
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;
124
    int i, j, codebook_index, ret;
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
        return AVERROR(EINVAL);
133 134 135
    }

    /* load up the VQA parameters from the header */
136
    s->vqa_version = s->avctx->extradata[0];
137 138 139 140 141 142 143 144 145
    switch (s->vqa_version) {
    case 1:
    case 2:
        break;
    case 3:
        avpriv_report_missing_feature(avctx, "VQA Version %d", s->vqa_version);
        return AVERROR_PATCHWELCOME;
    default:
        avpriv_request_sample(avctx, "VQA Version %i", s->vqa_version);
146
        return AVERROR_PATCHWELCOME;
147
    }
148 149
    s->width = AV_RL16(&s->avctx->extradata[6]);
    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 155 156
    s->vector_width = s->avctx->extradata[10];
    s->vector_height = s->avctx->extradata[11];
    s->partial_count = s->partial_countdown = s->avctx->extradata[13];
157 158 159 160 161

    /* 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 */
162
        return AVERROR_INVALIDDATA;
163 164
    }

165
    if (s->width % s->vector_width || s->height % s->vector_height) {
166 167 168 169
        av_log(avctx, AV_LOG_ERROR, "Image size not multiple of block size\n");
        return AVERROR_INVALIDDATA;
    }

170
    /* allocate codebooks */
171 172
    s->codebook_size = MAX_CODEBOOK_SIZE;
    s->codebook = av_malloc(s->codebook_size);
173 174
    if (!s->codebook)
        goto fail;
175
    s->next_codebook_buffer = av_malloc(s->codebook_size);
176 177 178 179 180 181 182 183 184
    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;
185 186 187 188 189 190 191

    /* 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;
192
    } else {
193 194 195 196
        codebook_index = 0xF00 * 8;
        for (i = 0; i < 256; i++)
            for (j = 0; j < 8; j++)
                s->codebook[codebook_index++] = i;
197 198 199 200
    }
    s->next_codebook_buffer_index = 0;

    return 0;
201 202 203 204 205
fail:
    av_freep(&s->codebook);
    av_freep(&s->next_codebook_buffer);
    av_freep(&s->decode_buffer);
    return AVERROR(ENOMEM);
206 207 208 209
}

#define CHECK_COUNT() \
    if (dest_index + count > dest_size) { \
210 211
        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", \
212
            dest_index, count, dest_size); \
213
        return AVERROR_INVALIDDATA; \
214 215
    }

216 217
#define CHECK_COPY(idx) \
    if (idx < 0 || idx + count > dest_size) { \
218 219
        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", \
220 221
            src_pos, count, dest_size); \
        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 231 232 233
    int src_pos;
    unsigned char color;
    int i;

234 235 236 237
    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);
238 239

        /* 0x80 means that frame is finished */
240 241
        if (opcode == 0x80)
            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 252 253
            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);
254
            CHECK_COUNT();
255
            CHECK_COPY(src_pos);
256 257 258 259
            for (i = 0; i < count; i++)
                dest[dest_index + i] = dest[src_pos + i];
            dest_index += count;

260
        } else if (opcode == 0xFE) {
261

262 263 264
            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);
265 266 267 268
            CHECK_COUNT();
            memset(&dest[dest_index], color, count);
            dest_index += count;

269
        } else if ((opcode & 0xC0) == 0xC0) {
270

271
            count = (opcode & 0x3F) + 3;
272 273
            src_pos = bytestream2_get_le16(&s->gb);
            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 277 278 279
            for (i = 0; i < count; i++)
                dest[dest_index + i] = dest[src_pos + i];
            dest_index += count;

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 287 288 289
            dest_index += count;

        } else {

290
            count = ((opcode & 0x70) >> 4) + 3;
291 292
            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);
293
            CHECK_COUNT();
294
            CHECK_COPY(dest_index - src_pos);
295 296 297 298 299 300
            for (i = 0; i < count; i++)
                dest[dest_index + i] = dest[dest_index - src_pos + i];
            dest_index += count;
        }
    }

301 302 303 304 305 306
    /* 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)
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 316 317 318 319 320
{
    unsigned int chunk_type;
    unsigned int chunk_size;
    int byte_skip;
    unsigned int index = 0;
    int i;
    unsigned char r, g, b;
321
    int index_shift;
322
    int res;
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341

    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 */
342
    while (bytestream2_get_bytes_left(&s->gb) >= 8) {
343

344 345 346
        chunk_type = bytestream2_get_be32u(&s->gb);
        index      = bytestream2_tell(&s->gb);
        chunk_size = bytestream2_get_be32u(&s->gb);
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 375 376 377 378

        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:
379
            av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %c%c%c%c (%08X)\n",
380 381 382 383 384 385 386 387 388
            (chunk_type >> 24) & 0xFF,
            (chunk_type >> 16) & 0xFF,
            (chunk_type >>  8) & 0xFF,
            (chunk_type >>  0) & 0xFF,
            chunk_type);
            break;
        }

        byte_skip = chunk_size & 0x01;
389
        bytestream2_skip(&s->gb, chunk_size + byte_skip);
390 391 392 393 394 395
    }

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

        /* 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 401 402 403 404 405 406 407 408 409
    }

    /* 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) {

410 411
        bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET);
        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 419
        }
        for (i = 0; i < chunk_size / 3; i++) {
            /* scale by 4 to transform 6-bit palette -> 8-bit */
420 421 422
            r = bytestream2_get_byteu(&s->gb) * 4;
            g = bytestream2_get_byteu(&s->gb) * 4;
            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 429 430 431
        }
    }

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

        /* 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 438
    if (cbfz_chunk != -1) {

439 440
        bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET);
        chunk_size = bytestream2_get_be32(&s->gb);
441
        if ((res = decode_format80(s, chunk_size, s->codebook,
442 443
                                   s->codebook_size, 0)) < 0)
            return res;
444 445 446 447 448
    }

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

449 450
        bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET);
        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 462 463 464
    }

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

        /* 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 470
    bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET);
    chunk_size = bytestream2_get_be32(&s->gb);
471
    if ((res = decode_format80(s, chunk_size,
472 473
                               s->decode_buffer, s->decode_buffer_size, 1)) < 0)
        return res;
474 475

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

            /* 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
489 490 491 492 493 494 495 496
                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--) {
497 498 499 500 501
                        frame->data[0][pixel_ptr + 0] = 255 - lobyte;
                        frame->data[0][pixel_ptr + 1] = 255 - lobyte;
                        frame->data[0][pixel_ptr + 2] = 255 - lobyte;
                        frame->data[0][pixel_ptr + 3] = 255 - lobyte;
                        pixel_ptr += frame->linesize[0];
Kostya Shishkov's avatar
Kostya Shishkov committed
502 503 504
                    }
                    lines=0;
                }
505 506 507 508 509 510
                break;

            case 2:
                lobyte = s->decode_buffer[lobytes];
                hibyte = s->decode_buffer[hibytes];
                vector_index = (hibyte << 8) | lobyte;
511
                vector_index <<= index_shift;
512
                lines = s->vector_height;
513 514 515 516 517 518 519 520 521
                break;

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

            while (lines--) {
522 523 524 525 526
                frame->data[0][pixel_ptr + 0] = s->codebook[vector_index++];
                frame->data[0][pixel_ptr + 1] = s->codebook[vector_index++];
                frame->data[0][pixel_ptr + 2] = s->codebook[vector_index++];
                frame->data[0][pixel_ptr + 3] = s->codebook[vector_index++];
                pixel_ptr += frame->linesize[0];
527 528 529 530 531 532 533
            }
        }
    }

    /* handle partial codebook */
    if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
        /* 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 539
    }

    if (cbp0_chunk != -1) {

540 541
        bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET);
        chunk_size = bytestream2_get_be32(&s->gb);
542

543
        if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
544 545
            av_log(s->avctx, AV_LOG_ERROR, "cbp0 chunk too large (%u bytes)\n",
                   chunk_size);
546 547 548
            return AVERROR_INVALIDDATA;
        }

549
        /* accumulate partial codebook */
550 551
        bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
                               chunk_size);
552 553 554
        s->next_codebook_buffer_index += chunk_size;

        s->partial_countdown--;
555
        if (s->partial_countdown <= 0) {
556 557

            /* time to replace codebook */
558
            memcpy(s->codebook, s->next_codebook_buffer,
559 560 561 562 563 564 565 566 567 568
                s->next_codebook_buffer_index);

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

    if (cbpz_chunk != -1) {

569 570
        bytestream2_seek(&s->gb, cbpz_chunk, SEEK_SET);
        chunk_size = bytestream2_get_be32(&s->gb);
571

572
        if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) {
573 574
            av_log(s->avctx, AV_LOG_ERROR, "cbpz chunk too large (%u bytes)\n",
                   chunk_size);
575 576 577
            return AVERROR_INVALIDDATA;
        }

578
        /* accumulate partial codebook */
579 580
        bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index],
                               chunk_size);
581 582 583
        s->next_codebook_buffer_index += chunk_size;

        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 589
                                       s->codebook, s->codebook_size, 0)) < 0)
                return res;
590 591 592 593 594

            /* reset accounting */
            s->next_codebook_buffer_index = 0;
            s->partial_countdown = s->partial_count;
        }
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 617
    memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
    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 630 631
    av_freep(&s->codebook);
    av_freep(&s->next_codebook_buffer);
    av_freep(&s->decode_buffer);
632 633 634 635

    return 0;
}

636
AVCodec ff_vqa_decoder = {
637 638
    .name           = "vqavideo",
    .type           = AVMEDIA_TYPE_VIDEO,
639
    .id             = AV_CODEC_ID_WS_VQA,
640 641 642 643 644
    .priv_data_size = sizeof(VqaContext),
    .init           = vqa_decode_init,
    .close          = vqa_decode_end,
    .decode         = vqa_decode_frame,
    .capabilities   = CODEC_CAP_DR1,
645
    .long_name      = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"),
646
};