vmdav.c 21.8 KB
Newer Older
1 2 3 4
/*
 * Sierra VMD Audio & Video Decoders
 * Copyright (C) 2004 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
 * Sierra VMD audio & video decoders
 * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
26 27
 * for more information on the Sierra VMD format, visit:
 *   http://www.pcisys.net/~melanson/codecs/
28 29 30 31
 *
 * The video decoder outputs PAL8 colorspace data. The decoder expects
 * a 0x330-byte VMD file header to be transmitted via extradata during
 * codec initialization. Each encoded frame that is sent to this decoder
32
 * is expected to be prepended with the appropriate 16-byte frame
33 34 35
 * information record from the VMD file.
 *
 * The audio decoder, like the video decoder, expects each encoded data
36
 * chunk to be prepended with the appropriate 16-byte frame information
37 38 39 40 41 42 43 44 45
 * record from the VMD file. It does not require the 0x330-byte VMD file
 * header, but it does need the audio setup parameters passed in through
 * normal libavcodec API means.
 */

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

46
#include "libavutil/avassert.h"
47
#include "libavutil/channel_layout.h"
48
#include "libavutil/common.h"
49
#include "libavutil/intreadwrite.h"
50
#include "avcodec.h"
51
#include "internal.h"
52
#include "bytestream.h"
53 54 55 56 57 58 59 60 61 62 63

#define VMD_HEADER_SIZE 0x330
#define PALETTE_COUNT 256

/*
 * Video Decoder
 */

typedef struct VmdVideoContext {

    AVCodecContext *avctx;
64
    AVFrame *prev_frame;
65

Michael Niedermayer's avatar
Michael Niedermayer committed
66
    const unsigned char *buf;
67 68 69 70
    int size;

    unsigned char palette[PALETTE_COUNT * 4];
    unsigned char *unpack_buffer;
71
    int unpack_buffer_size;
72

73
    int x_off, y_off;
74 75 76 77 78
} VmdVideoContext;

#define QUEUE_SIZE 0x1000
#define QUEUE_MASK 0x0FFF

79
static int lz_unpack(const unsigned char *src, int src_len,
80
                      unsigned char *dest, int dest_len)
81 82
{
    unsigned char *d;
83
    unsigned char *d_end;
84 85 86 87 88 89 90 91
    unsigned char queue[QUEUE_SIZE];
    unsigned int qpos;
    unsigned int dataleft;
    unsigned int chainofs;
    unsigned int chainlen;
    unsigned int speclen;
    unsigned char tag;
    unsigned int i, j;
92
    GetByteContext gb;
93

94
    bytestream2_init(&gb, src, src_len);
95
    d = dest;
96
    d_end = d + dest_len;
97
    dataleft = bytestream2_get_le32(&gb);
98
    memset(queue, 0x20, QUEUE_SIZE);
99
    if (bytestream2_get_bytes_left(&gb) < 4)
100
        return AVERROR_INVALIDDATA;
101
    if (bytestream2_peek_le32(&gb) == 0x56781234) {
102
        bytestream2_skipu(&gb, 4);
103 104 105 106 107 108 109
        qpos = 0x111;
        speclen = 0xF + 3;
    } else {
        qpos = 0xFEE;
        speclen = 100;  /* no speclen */
    }

110 111
    while (dataleft > 0 && bytestream2_get_bytes_left(&gb) > 0) {
        tag = bytestream2_get_byteu(&gb);
112
        if ((tag == 0xFF) && (dataleft > 8)) {
113
            if (d_end - d < 8 || bytestream2_get_bytes_left(&gb) < 8)
114
                return AVERROR_INVALIDDATA;
115
            for (i = 0; i < 8; i++) {
116
                queue[qpos++] = *d++ = bytestream2_get_byteu(&gb);
117 118 119 120 121 122 123 124
                qpos &= QUEUE_MASK;
            }
            dataleft -= 8;
        } else {
            for (i = 0; i < 8; i++) {
                if (dataleft == 0)
                    break;
                if (tag & 0x01) {
125
                    if (d_end - d < 1 || bytestream2_get_bytes_left(&gb) < 1)
126
                        return AVERROR_INVALIDDATA;
127
                    queue[qpos++] = *d++ = bytestream2_get_byteu(&gb);
128 129 130
                    qpos &= QUEUE_MASK;
                    dataleft--;
                } else {
131 132 133
                    chainofs = bytestream2_get_byte(&gb);
                    chainofs |= ((bytestream2_peek_byte(&gb) & 0xF0) << 4);
                    chainlen = (bytestream2_get_byte(&gb) & 0x0F) + 3;
134
                    if (chainlen == speclen) {
135
                        chainlen = bytestream2_get_byte(&gb) + 0xF + 3;
136
                    }
137
                    if (d_end - d < chainlen)
138
                        return AVERROR_INVALIDDATA;
139 140 141 142 143 144 145 146 147 148 149
                    for (j = 0; j < chainlen; j++) {
                        *d = queue[chainofs++ & QUEUE_MASK];
                        queue[qpos++] = *d++;
                        qpos &= QUEUE_MASK;
                    }
                    dataleft -= chainlen;
                }
                tag >>= 1;
            }
        }
    }
150
    return d - dest;
151
}
Michael Niedermayer's avatar
Michael Niedermayer committed
152
static int rle_unpack(const unsigned char *src, unsigned char *dest,
153
                      int src_count, int src_size, int dest_len)
154 155
{
    unsigned char *pd;
156
    int i, l, used = 0;
157
    unsigned char *dest_end = dest + dest_len;
158
    GetByteContext gb;
159
    uint16_t run_val;
160

161
    bytestream2_init(&gb, src, src_size);
162
    pd = dest;
163
    if (src_count & 1) {
164
        if (bytestream2_get_bytes_left(&gb) < 1)
165
            return 0;
166
        *pd++ = bytestream2_get_byteu(&gb);
167
        used++;
168
    }
169 170

    do {
171
        if (bytestream2_get_bytes_left(&gb) < 1)
172
            break;
173
        l = bytestream2_get_byteu(&gb);
174 175
        if (l & 0x80) {
            l = (l & 0x7F) * 2;
176
            if (dest_end - pd < l || bytestream2_get_bytes_left(&gb) < l)
177
                return bytestream2_tell(&gb);
178
            bytestream2_get_bufferu(&gb, pd, l);
179 180
            pd += l;
        } else {
181
            if (dest_end - pd < 2*l || bytestream2_get_bytes_left(&gb) < 2)
182
                return bytestream2_tell(&gb);
183
            run_val = bytestream2_get_ne16(&gb);
184
            for (i = 0; i < l; i++) {
185 186
                AV_WN16(pd, run_val);
                pd += 2;
187
            }
188
            l *= 2;
189
        }
190 191
        used += l;
    } while (used < src_count);
192

193
    return bytestream2_tell(&gb);
194 195
}

196
static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
197 198 199 200 201
{
    int i;
    unsigned int *palette32;
    unsigned char r, g, b;

202
    GetByteContext gb;
203 204 205 206 207 208 209 210 211 212

    unsigned char meth;
    unsigned char *dp;   /* pointer to current frame */
    unsigned char *pp;   /* pointer to previous frame */
    unsigned char len;
    int ofs;

    int frame_x, frame_y;
    int frame_width, frame_height;

213 214 215 216
    frame_x = AV_RL16(&s->buf[6]);
    frame_y = AV_RL16(&s->buf[8]);
    frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
    frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
217

218 219 220 221 222 223 224 225 226
    if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
        (frame_x || frame_y)) {

        s->x_off = frame_x;
        s->y_off = frame_y;
    }
    frame_x -= s->x_off;
    frame_y -= s->y_off;

227 228 229 230
    if (frame_x < 0 || frame_width < 0 ||
        frame_x >= s->avctx->width ||
        frame_width > s->avctx->width ||
        frame_x + frame_width > s->avctx->width) {
231 232 233
        av_log(s->avctx, AV_LOG_ERROR,
               "Invalid horizontal range %d-%d\n",
               frame_x, frame_width);
234 235 236 237 238 239
        return AVERROR_INVALIDDATA;
    }
    if (frame_y < 0 || frame_height < 0 ||
        frame_y >= s->avctx->height ||
        frame_height > s->avctx->height ||
        frame_y + frame_height > s->avctx->height) {
240 241 242
        av_log(s->avctx, AV_LOG_ERROR,
               "Invalid vertical range %d-%d\n",
               frame_x, frame_width);
243 244 245
        return AVERROR_INVALIDDATA;
    }

246 247
    /* if only a certain region will be updated, copy the entire previous
     * frame before the decode */
248
    if (s->prev_frame->data[0] &&
249 250
        (frame_x || frame_y || (frame_width != s->avctx->width) ||
        (frame_height != s->avctx->height))) {
251

252
        memcpy(frame->data[0], s->prev_frame->data[0],
253
            s->avctx->height * frame->linesize[0]);
254 255 256
    }

    /* check if there is a new palette */
257
    bytestream2_init(&gb, s->buf + 16, s->size - 16);
258
    if (s->buf[15] & 0x02) {
259
        bytestream2_skip(&gb, 2);
260
        palette32 = (unsigned int *)s->palette;
261 262 263 264 265
        if (bytestream2_get_bytes_left(&gb) >= PALETTE_COUNT * 3) {
            for (i = 0; i < PALETTE_COUNT; i++) {
                r = bytestream2_get_byteu(&gb) * 4;
                g = bytestream2_get_byteu(&gb) * 4;
                b = bytestream2_get_byteu(&gb) * 4;
266 267
                palette32[i] = 0xFFU << 24 | (r << 16) | (g << 8) | (b);
                palette32[i] |= palette32[i] >> 6 & 0x30303;
268
            }
269 270 271
        } else {
            av_log(s->avctx, AV_LOG_ERROR, "Incomplete palette\n");
            return AVERROR_INVALIDDATA;
272 273 274
        }
    }

275 276 277 278 279 280 281 282
    if (!s->size)
        return 0;

    /* originally UnpackFrame in VAG's code */
    if (bytestream2_get_bytes_left(&gb) < 1)
        return AVERROR_INVALIDDATA;
    meth = bytestream2_get_byteu(&gb);
    if (meth & 0x80) {
283
        int size;
284 285 286 287 288
        if (!s->unpack_buffer_size) {
            av_log(s->avctx, AV_LOG_ERROR,
                   "Trying to unpack LZ-compressed frame with no LZ buffer\n");
            return AVERROR_INVALIDDATA;
        }
289 290 291 292
        size = lz_unpack(gb.buffer, bytestream2_get_bytes_left(&gb),
                         s->unpack_buffer, s->unpack_buffer_size);
        if (size < 0)
            return size;
293
        meth &= 0x7F;
294
        bytestream2_init(&gb, s->unpack_buffer, size);
295
    }
296

297
    dp = &frame->data[0][frame_y * frame->linesize[0] + frame_x];
298
    pp = &s->prev_frame->data[0][frame_y * s->prev_frame->linesize[0] + frame_x];
299 300 301 302 303 304 305 306 307 308 309
    switch (meth) {
    case 1:
        for (i = 0; i < frame_height; i++) {
            ofs = 0;
            do {
                len = bytestream2_get_byte(&gb);
                if (len & 0x80) {
                    len = (len & 0x7F) + 1;
                    if (ofs + len > frame_width ||
                        bytestream2_get_bytes_left(&gb) < len)
                        return AVERROR_INVALIDDATA;
310
                    bytestream2_get_bufferu(&gb, &dp[ofs], len);
311 312 313
                    ofs += len;
                } else {
                    /* interframe pixel copy */
314
                    if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
315 316 317
                        return AVERROR_INVALIDDATA;
                    memcpy(&dp[ofs], &pp[ofs], len + 1);
                    ofs += len + 1;
318
                }
319 320 321
            } while (ofs < frame_width);
            if (ofs > frame_width) {
                av_log(s->avctx, AV_LOG_ERROR,
322
                       "offset > width (%d > %d)\n",
323 324
                       ofs, frame_width);
                return AVERROR_INVALIDDATA;
325
            }
326
            dp += frame->linesize[0];
327
            pp += s->prev_frame->linesize[0];
328 329
        }
        break;
330

331 332 333 334
    case 2:
        for (i = 0; i < frame_height; i++) {
            bytestream2_get_buffer(&gb, dp, frame_width);
            dp += frame->linesize[0];
335
            pp += s->prev_frame->linesize[0];
336 337
        }
        break;
338

339 340 341 342 343 344 345
    case 3:
        for (i = 0; i < frame_height; i++) {
            ofs = 0;
            do {
                len = bytestream2_get_byte(&gb);
                if (len & 0x80) {
                    len = (len & 0x7F) + 1;
346 347 348
                    if (bytestream2_peek_byte(&gb) == 0xFF) {
                        int slen = len;
                        bytestream2_get_byte(&gb);
349 350 351
                        len = rle_unpack(gb.buffer, &dp[ofs],
                                         len, bytestream2_get_bytes_left(&gb),
                                         frame_width - ofs);
352 353 354
                        ofs += slen;
                        bytestream2_skip(&gb, len);
                    } else {
355
                        bytestream2_get_buffer(&gb, &dp[ofs], len);
356 357
                        ofs += len;
                    }
358 359
                } else {
                    /* interframe pixel copy */
360
                    if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
361 362 363
                        return AVERROR_INVALIDDATA;
                    memcpy(&dp[ofs], &pp[ofs], len + 1);
                    ofs += len + 1;
364
                }
365 366 367
            } while (ofs < frame_width);
            if (ofs > frame_width) {
                av_log(s->avctx, AV_LOG_ERROR,
368
                       "offset > width (%d > %d)\n",
369 370
                       ofs, frame_width);
                return AVERROR_INVALIDDATA;
371
            }
372
            dp += frame->linesize[0];
373
            pp += s->prev_frame->linesize[0];
374
        }
375
        break;
376
    }
377
    return 0;
378 379
}

380 381 382 383 384
static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
{
    VmdVideoContext *s = avctx->priv_data;

    av_frame_free(&s->prev_frame);
385 386
    av_freep(&s->unpack_buffer);
    s->unpack_buffer_size = 0;
387 388 389 390

    return 0;
}

391
static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
392
{
393
    VmdVideoContext *s = avctx->priv_data;
394 395 396 397 398 399 400 401
    int i;
    unsigned int *palette32;
    int palette_index = 0;
    unsigned char r, g, b;
    unsigned char *vmd_header;
    unsigned char *raw_palette;

    s->avctx = avctx;
402
    avctx->pix_fmt = AV_PIX_FMT_PAL8;
403 404 405

    /* make sure the VMD header made it */
    if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
406
        av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n",
407
            VMD_HEADER_SIZE);
408
        return AVERROR_INVALIDDATA;
409 410 411
    }
    vmd_header = (unsigned char *)avctx->extradata;

412
    s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
413 414 415 416 417
    if (s->unpack_buffer_size) {
        s->unpack_buffer = av_malloc(s->unpack_buffer_size);
        if (!s->unpack_buffer)
            return AVERROR(ENOMEM);
    }
418 419 420 421 422 423 424 425

    /* load up the initial palette */
    raw_palette = &vmd_header[28];
    palette32 = (unsigned int *)s->palette;
    for (i = 0; i < PALETTE_COUNT; i++) {
        r = raw_palette[palette_index++] * 4;
        g = raw_palette[palette_index++] * 4;
        b = raw_palette[palette_index++] * 4;
426 427
        palette32[i] = 0xFFU << 24 | (r << 16) | (g << 8) | (b);
        palette32[i] |= palette32[i] >> 6 & 0x30303;
428 429
    }

430 431 432 433 434
    s->prev_frame = av_frame_alloc();
    if (!s->prev_frame) {
        vmdvideo_decode_end(avctx);
        return AVERROR(ENOMEM);
    }
435

436 437 438 439
    return 0;
}

static int vmdvideo_decode_frame(AVCodecContext *avctx,
440
                                 void *data, int *got_frame,
441
                                 AVPacket *avpkt)
442
{
443 444
    const uint8_t *buf = avpkt->data;
    int buf_size = avpkt->size;
445
    VmdVideoContext *s = avctx->priv_data;
446 447
    AVFrame *frame = data;
    int ret;
448 449 450 451

    s->buf = buf;
    s->size = buf_size;

452
    if (buf_size < 16)
453
        return AVERROR_INVALIDDATA;
454

455
    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
456
        return ret;
457

458 459
    if ((ret = vmd_decode(s, frame)) < 0)
        return ret;
460 461

    /* make the palette available on the way out */
462
    memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
463 464

    /* shuffle frames */
465 466
    av_frame_unref(s->prev_frame);
    if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
467
        return ret;
468

469
    *got_frame      = 1;
470 471 472 473 474 475 476 477 478

    /* report that the buffer was completely consumed */
    return buf_size;
}

/*
 * Audio Decoder
 */

479 480 481 482
#define BLOCK_TYPE_AUDIO    1
#define BLOCK_TYPE_INITIAL  2
#define BLOCK_TYPE_SILENCE  3

483
typedef struct VmdAudioContext {
484
    int out_bps;
485
    int chunk_size;
486 487
} VmdAudioContext;

488
static const uint16_t vmdaudio_table[128] = {
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
    0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
    0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
    0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
    0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
    0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
    0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
    0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
    0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
    0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
    0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
    0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
    0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
    0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
};

504
static av_cold int vmdaudio_decode_init(AVCodecContext *avctx)
505
{
506
    VmdAudioContext *s = avctx->priv_data;
507

508 509 510 511
    if (avctx->channels < 1 || avctx->channels > 2) {
        av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
        return AVERROR(EINVAL);
    }
512
    if (avctx->block_align < 1 || avctx->block_align % avctx->channels) {
513 514 515 516
        av_log(avctx, AV_LOG_ERROR, "invalid block align\n");
        return AVERROR(EINVAL);
    }

517 518 519
    avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO :
                                                   AV_CH_LAYOUT_STEREO;

520 521 522 523
    if (avctx->bits_per_coded_sample == 16)
        avctx->sample_fmt = AV_SAMPLE_FMT_S16;
    else
        avctx->sample_fmt = AV_SAMPLE_FMT_U8;
524
    s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt);
525

526 527
    s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2);

528 529 530 531
    av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, "
           "block align = %d, sample rate = %d\n",
           avctx->channels, avctx->bits_per_coded_sample, avctx->block_align,
           avctx->sample_rate);
532 533 534 535

    return 0;
}

536 537
static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size,
                             int channels)
538
{
539 540 541 542 543 544 545 546 547 548
    int ch;
    const uint8_t *buf_end = buf + buf_size;
    int predictor[2];
    int st = channels - 1;

    /* decode initial raw sample */
    for (ch = 0; ch < channels; ch++) {
        predictor[ch] = (int16_t)AV_RL16(buf);
        buf += 2;
        *out++ = predictor[ch];
549
    }
550

551 552 553 554 555 556 557 558 559 560 561
    /* decode DPCM samples */
    ch = 0;
    while (buf < buf_end) {
        uint8_t b = *buf++;
        if (b & 0x80)
            predictor[ch] -= vmdaudio_table[b & 0x7F];
        else
            predictor[ch] += vmdaudio_table[b];
        predictor[ch] = av_clip_int16(predictor[ch]);
        *out++ = predictor[ch];
        ch ^= st;
562
    }
563 564
}

565 566
static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data,
                                 int *got_frame_ptr, AVPacket *avpkt)
567
{
568
    AVFrame *frame     = data;
569
    const uint8_t *buf = avpkt->data;
570
    const uint8_t *buf_end;
571
    int buf_size = avpkt->size;
572
    VmdAudioContext *s = avctx->priv_data;
573
    int block_type, silent_chunks, audio_chunks;
574 575 576
    int ret;
    uint8_t *output_samples_u8;
    int16_t *output_samples_s16;
577

578 579
    if (buf_size < 16) {
        av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n");
580
        *got_frame_ptr = 0;
581
        return buf_size;
582
    }
583

584
    block_type = buf[6];
585 586 587 588
    if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) {
        av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type);
        return AVERROR(EINVAL);
    }
589 590
    buf      += 16;
    buf_size -= 16;
591

592
    /* get number of silent chunks */
593 594
    silent_chunks = 0;
    if (block_type == BLOCK_TYPE_INITIAL) {
595
        uint32_t flags;
596 597 598 599 600 601
        if (buf_size < 4) {
            av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
            return AVERROR(EINVAL);
        }
        flags         = AV_RB32(buf);
        silent_chunks = av_popcount(flags);
602 603
        buf      += 4;
        buf_size -= 4;
604
    } else if (block_type == BLOCK_TYPE_SILENCE) {
605 606
        silent_chunks = 1;
        buf_size = 0; // should already be zero but set it just to be sure
607 608
    }

609
    /* ensure output buffer is large enough */
610
    audio_chunks = buf_size / s->chunk_size;
611

612 613 614
    /* drop incomplete chunks */
    buf_size     = audio_chunks * s->chunk_size;

615
    /* get output buffer */
616 617
    frame->nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) /
                        avctx->channels;
618
    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
619
        return ret;
620 621
    output_samples_u8  =            frame->data[0];
    output_samples_s16 = (int16_t *)frame->data[0];
622

623 624 625
    /* decode silent chunks */
    if (silent_chunks > 0) {
        int silent_size = avctx->block_align * silent_chunks;
626 627
        av_assert0(avctx->block_align * silent_chunks <= frame->nb_samples * avctx->channels);

628 629 630 631 632 633 634 635 636 637 638 639
        if (s->out_bps == 2) {
            memset(output_samples_s16, 0x00, silent_size * 2);
            output_samples_s16 += silent_size;
        } else {
            memset(output_samples_u8,  0x80, silent_size);
            output_samples_u8 += silent_size;
        }
    }

    /* decode audio chunks */
    if (audio_chunks > 0) {
        buf_end = buf + buf_size;
640
        av_assert0((buf_size & (avctx->channels > 1)) == 0);
641
        while (buf_end - buf >= s->chunk_size) {
642 643 644 645 646 647 648 649 650 651 652
            if (s->out_bps == 2) {
                decode_audio_s16(output_samples_s16, buf, s->chunk_size,
                                 avctx->channels);
                output_samples_s16 += avctx->block_align;
            } else {
                memcpy(output_samples_u8, buf, s->chunk_size);
                output_samples_u8  += avctx->block_align;
            }
            buf += s->chunk_size;
        }
    }
653

654
    *got_frame_ptr = 1;
655

656
    return avpkt->size;
657 658 659 660 661 662 663
}


/*
 * Public Data Structures
 */

664
AVCodec ff_vmdvideo_decoder = {
665
    .name           = "vmdvideo",
666
    .long_name      = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
667
    .type           = AVMEDIA_TYPE_VIDEO,
668
    .id             = AV_CODEC_ID_VMDVIDEO,
669 670 671 672 673
    .priv_data_size = sizeof(VmdVideoContext),
    .init           = vmdvideo_decode_init,
    .close          = vmdvideo_decode_end,
    .decode         = vmdvideo_decode_frame,
    .capabilities   = CODEC_CAP_DR1,
674 675
};

676
AVCodec ff_vmdaudio_decoder = {
677
    .name           = "vmdaudio",
678
    .long_name      = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
679
    .type           = AVMEDIA_TYPE_AUDIO,
680
    .id             = AV_CODEC_ID_VMDAUDIO,
681 682 683
    .priv_data_size = sizeof(VmdAudioContext),
    .init           = vmdaudio_decode_init,
    .decode         = vmdaudio_decode_frame,
684
    .capabilities   = CODEC_CAP_DR1,
685
};