Statistics
| Branch: | Revision:

ffmpeg / libavcodec / vmdav.c @ 6636b7e8

History | View | Annotate | Download (16.8 KB)

1 fafa0b75 Mike Melanson
/*
2
 * Sierra VMD Audio & Video Decoders
3
 * Copyright (C) 2004 the ffmpeg project
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 fafa0b75 Mike Melanson
 *
19
 */
20
21
/**
22
 * @file vmdvideo.c
23
 * Sierra VMD audio & video decoders
24
 * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
25 23fe14bb Mike Melanson
 * for more information on the Sierra VMD format, visit:
26
 *   http://www.pcisys.net/~melanson/codecs/
27 fafa0b75 Mike Melanson
 *
28
 * The video decoder outputs PAL8 colorspace data. The decoder expects
29
 * a 0x330-byte VMD file header to be transmitted via extradata during
30
 * codec initialization. Each encoded frame that is sent to this decoder
31 115329f1 Diego Biurrun
 * is expected to be prepended with the appropriate 16-byte frame
32 fafa0b75 Mike Melanson
 * information record from the VMD file.
33
 *
34
 * The audio decoder, like the video decoder, expects each encoded data
35 23fe14bb Mike Melanson
 * chunk to be prepended with the appropriate 16-byte frame information
36 fafa0b75 Mike Melanson
 * record from the VMD file. It does not require the 0x330-byte VMD file
37
 * header, but it does need the audio setup parameters passed in through
38
 * normal libavcodec API means.
39
 */
40
41
#include <stdio.h>
42
#include <stdlib.h>
43
#include <string.h>
44
#include <unistd.h>
45
46
#include "common.h"
47
#include "avcodec.h"
48
#include "dsputil.h"
49
50
#define VMD_HEADER_SIZE 0x330
51
#define PALETTE_COUNT 256
52
53
/*
54
 * Video Decoder
55
 */
56
57
typedef struct VmdVideoContext {
58
59
    AVCodecContext *avctx;
60
    DSPContext dsp;
61
    AVFrame frame;
62
    AVFrame prev_frame;
63
64
    unsigned char *buf;
65
    int size;
66
67
    unsigned char palette[PALETTE_COUNT * 4];
68
    unsigned char *unpack_buffer;
69 8458dab1 Mike Melanson
    int unpack_buffer_size;
70 fafa0b75 Mike Melanson
71
} VmdVideoContext;
72
73
#define QUEUE_SIZE 0x1000
74
#define QUEUE_MASK 0x0FFF
75
76 8458dab1 Mike Melanson
static void lz_unpack(unsigned char *src, unsigned char *dest, int dest_len)
77 fafa0b75 Mike Melanson
{
78
    unsigned char *s;
79
    unsigned char *d;
80 8458dab1 Mike Melanson
    unsigned char *d_end;
81 fafa0b75 Mike Melanson
    unsigned char queue[QUEUE_SIZE];
82
    unsigned int qpos;
83
    unsigned int dataleft;
84
    unsigned int chainofs;
85
    unsigned int chainlen;
86
    unsigned int speclen;
87
    unsigned char tag;
88
    unsigned int i, j;
89
90
    s = src;
91
    d = dest;
92 8458dab1 Mike Melanson
    d_end = d + dest_len;
93 fafa0b75 Mike Melanson
    dataleft = LE_32(s);
94
    s += 4;
95
    memset(queue, QUEUE_SIZE, 0x20);
96
    if (LE_32(s) == 0x56781234) {
97
        s += 4;
98
        qpos = 0x111;
99
        speclen = 0xF + 3;
100
    } else {
101
        qpos = 0xFEE;
102
        speclen = 100;  /* no speclen */
103
    }
104
105
    while (dataleft > 0) {
106
        tag = *s++;
107
        if ((tag == 0xFF) && (dataleft > 8)) {
108 8458dab1 Mike Melanson
            if (d + 8 > d_end)
109
                return;
110 fafa0b75 Mike Melanson
            for (i = 0; i < 8; i++) {
111
                queue[qpos++] = *d++ = *s++;
112
                qpos &= QUEUE_MASK;
113
            }
114
            dataleft -= 8;
115
        } else {
116
            for (i = 0; i < 8; i++) {
117
                if (dataleft == 0)
118
                    break;
119
                if (tag & 0x01) {
120 8458dab1 Mike Melanson
                    if (d + 1 > d_end)
121
                        return;
122 fafa0b75 Mike Melanson
                    queue[qpos++] = *d++ = *s++;
123
                    qpos &= QUEUE_MASK;
124
                    dataleft--;
125
                } else {
126
                    chainofs = *s++;
127
                    chainofs |= ((*s & 0xF0) << 4);
128
                    chainlen = (*s++ & 0x0F) + 3;
129
                    if (chainlen == speclen)
130
                        chainlen = *s++ + 0xF + 3;
131 8458dab1 Mike Melanson
                    if (d + chainlen > d_end)
132
                        return;
133 fafa0b75 Mike Melanson
                    for (j = 0; j < chainlen; j++) {
134
                        *d = queue[chainofs++ & QUEUE_MASK];
135
                        queue[qpos++] = *d++;
136
                        qpos &= QUEUE_MASK;
137
                    }
138
                    dataleft -= chainlen;
139
                }
140
                tag >>= 1;
141
            }
142
        }
143
    }
144
}
145
146 115329f1 Diego Biurrun
static int rle_unpack(unsigned char *src, unsigned char *dest,
147 8458dab1 Mike Melanson
    int src_len, int dest_len)
148 fafa0b75 Mike Melanson
{
149
    unsigned char *ps;
150
    unsigned char *pd;
151
    int i, l;
152 8458dab1 Mike Melanson
    unsigned char *dest_end = dest + dest_len;
153 fafa0b75 Mike Melanson
154
    ps = src;
155
    pd = dest;
156 8458dab1 Mike Melanson
    if (src_len & 1)
157 fafa0b75 Mike Melanson
        *pd++ = *ps++;
158
159 8458dab1 Mike Melanson
    src_len >>= 1;
160 fafa0b75 Mike Melanson
    i = 0;
161
    do {
162
        l = *ps++;
163
        if (l & 0x80) {
164
            l = (l & 0x7F) * 2;
165 8458dab1 Mike Melanson
            if (pd + l > dest_end)
166
                return (ps - src);
167 fafa0b75 Mike Melanson
            memcpy(pd, ps, l);
168
            ps += l;
169
            pd += l;
170
        } else {
171 8458dab1 Mike Melanson
            if (pd + i > dest_end)
172
                return (ps - src);
173 fafa0b75 Mike Melanson
            for (i = 0; i < l; i++) {
174
                *pd++ = ps[0];
175
                *pd++ = ps[1];
176
            }
177
            ps += 2;
178
        }
179
        i += l;
180 8458dab1 Mike Melanson
    } while (i < src_len);
181 fafa0b75 Mike Melanson
182
    return (ps - src);
183
}
184
185
static void vmd_decode(VmdVideoContext *s)
186
{
187
    int i;
188
    unsigned int *palette32;
189
    unsigned char r, g, b;
190
191
    /* point to the start of the encoded data */
192
    unsigned char *p = s->buf + 16;
193
194
    unsigned char *pb;
195
    unsigned char meth;
196
    unsigned char *dp;   /* pointer to current frame */
197
    unsigned char *pp;   /* pointer to previous frame */
198
    unsigned char len;
199
    int ofs;
200
201
    int frame_x, frame_y;
202
    int frame_width, frame_height;
203 8458dab1 Mike Melanson
    int dp_size;
204 fafa0b75 Mike Melanson
205
    frame_x = LE_16(&s->buf[6]);
206
    frame_y = LE_16(&s->buf[8]);
207
    frame_width = LE_16(&s->buf[10]) - frame_x + 1;
208
    frame_height = LE_16(&s->buf[12]) - frame_y + 1;
209
210
    /* if only a certain region will be updated, copy the entire previous
211
     * frame before the decode */
212
    if (frame_x || frame_y || (frame_width != s->avctx->width) ||
213
        (frame_height != s->avctx->height)) {
214
215 115329f1 Diego Biurrun
        memcpy(s->frame.data[0], s->prev_frame.data[0],
216 fafa0b75 Mike Melanson
            s->avctx->height * s->frame.linesize[0]);
217
    }
218
219
    /* check if there is a new palette */
220
    if (s->buf[15] & 0x02) {
221
        p += 2;
222
        palette32 = (unsigned int *)s->palette;
223
        for (i = 0; i < PALETTE_COUNT; i++) {
224
            r = *p++ * 4;
225
            g = *p++ * 4;
226
            b = *p++ * 4;
227
            palette32[i] = (r << 16) | (g << 8) | (b);
228
        }
229
        s->size -= (256 * 3 + 2);
230
    }
231
    if (s->size >= 0) {
232
        /* originally UnpackFrame in VAG's code */
233
        pb = p;
234
        meth = *pb++;
235
        if (meth & 0x80) {
236 8458dab1 Mike Melanson
            lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
237 fafa0b75 Mike Melanson
            meth &= 0x7F;
238
            pb = s->unpack_buffer;
239
        }
240
241
        dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
242 8458dab1 Mike Melanson
        dp_size = s->frame.linesize[0] * s->avctx->height;
243 fafa0b75 Mike Melanson
        pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
244
        switch (meth) {
245
        case 1:
246
            for (i = 0; i < frame_height; i++) {
247
                ofs = 0;
248
                do {
249
                    len = *pb++;
250
                    if (len & 0x80) {
251
                        len = (len & 0x7F) + 1;
252 8458dab1 Mike Melanson
                        if (ofs + len > frame_width)
253
                            return;
254 fafa0b75 Mike Melanson
                        memcpy(&dp[ofs], pb, len);
255
                        pb += len;
256
                        ofs += len;
257
                    } else {
258
                        /* interframe pixel copy */
259 8458dab1 Mike Melanson
                        if (ofs + len + 1 > frame_width)
260
                            return;
261 fafa0b75 Mike Melanson
                        memcpy(&dp[ofs], &pp[ofs], len + 1);
262
                        ofs += len + 1;
263
                    }
264
                } while (ofs < frame_width);
265
                if (ofs > frame_width) {
266 fd146758 Alex Beregszaszi
                    av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
267 fafa0b75 Mike Melanson
                        ofs, frame_width);
268
                    break;
269
                }
270
                dp += s->frame.linesize[0];
271
                pp += s->prev_frame.linesize[0];
272
            }
273
            break;
274
275
        case 2:
276
            for (i = 0; i < frame_height; i++) {
277
                memcpy(dp, pb, frame_width);
278
                pb += frame_width;
279
                dp += s->frame.linesize[0];
280
                pp += s->prev_frame.linesize[0];
281
            }
282
            break;
283
284
        case 3:
285
            for (i = 0; i < frame_height; i++) {
286
                ofs = 0;
287
                do {
288
                    len = *pb++;
289
                    if (len & 0x80) {
290
                        len = (len & 0x7F) + 1;
291
                        if (*pb++ == 0xFF)
292 8458dab1 Mike Melanson
                            len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
293 fafa0b75 Mike Melanson
                        else
294
                            memcpy(&dp[ofs], pb, len);
295
                        pb += len;
296
                        ofs += len;
297
                    } else {
298
                        /* interframe pixel copy */
299 8458dab1 Mike Melanson
                        if (ofs + len + 1 > frame_width)
300
                            return;
301 fafa0b75 Mike Melanson
                        memcpy(&dp[ofs], &pp[ofs], len + 1);
302
                        ofs += len + 1;
303
                    }
304
                } while (ofs < frame_width);
305
                if (ofs > frame_width) {
306 fd146758 Alex Beregszaszi
                    av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
307 fafa0b75 Mike Melanson
                        ofs, frame_width);
308
                }
309
                dp += s->frame.linesize[0];
310
                pp += s->prev_frame.linesize[0];
311
            }
312
            break;
313
        }
314
    }
315
}
316
317
static int vmdvideo_decode_init(AVCodecContext *avctx)
318
{
319
    VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
320
    int i;
321
    unsigned int *palette32;
322
    int palette_index = 0;
323
    unsigned char r, g, b;
324
    unsigned char *vmd_header;
325
    unsigned char *raw_palette;
326
327
    s->avctx = avctx;
328
    avctx->pix_fmt = PIX_FMT_PAL8;
329
    avctx->has_b_frames = 0;
330
    dsputil_init(&s->dsp, avctx);
331
332
    /* make sure the VMD header made it */
333
    if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
334 115329f1 Diego Biurrun
        av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
335 fafa0b75 Mike Melanson
            VMD_HEADER_SIZE);
336
        return -1;
337
    }
338
    vmd_header = (unsigned char *)avctx->extradata;
339
340 8458dab1 Mike Melanson
    s->unpack_buffer_size = LE_32(&vmd_header[800]);
341
    s->unpack_buffer = av_malloc(s->unpack_buffer_size);
342 fafa0b75 Mike Melanson
    if (!s->unpack_buffer)
343
        return -1;
344
345
    /* load up the initial palette */
346
    raw_palette = &vmd_header[28];
347
    palette32 = (unsigned int *)s->palette;
348
    for (i = 0; i < PALETTE_COUNT; i++) {
349
        r = raw_palette[palette_index++] * 4;
350
        g = raw_palette[palette_index++] * 4;
351
        b = raw_palette[palette_index++] * 4;
352
        palette32[i] = (r << 16) | (g << 8) | (b);
353
    }
354
355
    s->frame.data[0] = s->prev_frame.data[0] = NULL;
356
357
    return 0;
358
}
359
360
static int vmdvideo_decode_frame(AVCodecContext *avctx,
361
                                 void *data, int *data_size,
362
                                 uint8_t *buf, int buf_size)
363
{
364
    VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
365
366
    s->buf = buf;
367
    s->size = buf_size;
368
369 23fe14bb Mike Melanson
    if (buf_size < 16)
370
        return buf_size;
371
372 fafa0b75 Mike Melanson
    s->frame.reference = 1;
373
    if (avctx->get_buffer(avctx, &s->frame)) {
374 fd146758 Alex Beregszaszi
        av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
375 fafa0b75 Mike Melanson
        return -1;
376
    }
377
378
    vmd_decode(s);
379
380
    /* make the palette available on the way out */
381
    memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
382
383
    if (s->prev_frame.data[0])
384
        avctx->release_buffer(avctx, &s->prev_frame);
385
386
    /* shuffle frames */
387
    s->prev_frame = s->frame;
388
389
    *data_size = sizeof(AVFrame);
390
    *(AVFrame*)data = s->frame;
391
392
    /* report that the buffer was completely consumed */
393
    return buf_size;
394
}
395
396
static int vmdvideo_decode_end(AVCodecContext *avctx)
397
{
398
    VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
399
400
    if (s->prev_frame.data[0])
401
        avctx->release_buffer(avctx, &s->prev_frame);
402
    av_free(s->unpack_buffer);
403
404
    return 0;
405
}
406
407
408
/*
409
 * Audio Decoder
410
 */
411
412
typedef struct VmdAudioContext {
413 fd146758 Alex Beregszaszi
    AVCodecContext *avctx;
414 fafa0b75 Mike Melanson
    int channels;
415
    int bits;
416
    int block_align;
417 79d15fd4 Kostya Shishkov
    int predictors[2];
418 fafa0b75 Mike Melanson
} VmdAudioContext;
419
420 79d15fd4 Kostya Shishkov
static uint16_t vmdaudio_table[128] = {
421
    0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
422
    0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
423
    0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
424
    0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
425
    0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
426
    0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
427
    0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
428
    0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
429
    0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
430
    0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
431
    0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
432
    0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
433
    0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
434
};
435
436 fafa0b75 Mike Melanson
static int vmdaudio_decode_init(AVCodecContext *avctx)
437
{
438
    VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
439
440 fd146758 Alex Beregszaszi
    s->avctx = avctx;
441 fafa0b75 Mike Melanson
    s->channels = avctx->channels;
442
    s->bits = avctx->bits_per_sample;
443
    s->block_align = avctx->block_align;
444
445 fd146758 Alex Beregszaszi
    av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
446 bb270c08 Diego Biurrun
            s->channels, s->bits, s->block_align, avctx->sample_rate);
447 fafa0b75 Mike Melanson
448
    return 0;
449
}
450
451
static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
452 79d15fd4 Kostya Shishkov
    uint8_t *buf, int stereo)
453
{
454
    int i;
455
    int chan = 0;
456
    int16_t *out = (int16_t*)data;
457 fafa0b75 Mike Melanson
458 79d15fd4 Kostya Shishkov
    for(i = 0; i < s->block_align; i++) {
459
        if(buf[i] & 0x80)
460
            s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
461
        else
462
            s->predictors[chan] += vmdaudio_table[buf[i]];
463
        s->predictors[chan] = clip(s->predictors[chan], -32768, 32767);
464
        out[i] = s->predictors[chan];
465
        chan ^= stereo;
466
    }
467 fafa0b75 Mike Melanson
}
468
469 23fe14bb Mike Melanson
static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
470 fafa0b75 Mike Melanson
    uint8_t *buf, int silence)
471
{
472 23fe14bb Mike Melanson
    int bytes_decoded = 0;
473
    int i;
474
475 79d15fd4 Kostya Shishkov
//    if (silence)
476
//        av_log(s->avctx, AV_LOG_INFO, "silent block!\n");
477 fafa0b75 Mike Melanson
    if (s->channels == 2) {
478 23fe14bb Mike Melanson
479
        /* stereo handling */
480 79d15fd4 Kostya Shishkov
        if (silence) {
481
            memset(data, 0, s->block_align * 2);
482 fafa0b75 Mike Melanson
        } else {
483 79d15fd4 Kostya Shishkov
            if (s->bits == 16)
484 23fe14bb Mike Melanson
                vmdaudio_decode_audio(s, data, buf, 1);
485 79d15fd4 Kostya Shishkov
            else
486
                /* copy the data but convert it to signed */
487
                for (i = 0; i < s->block_align; i++)
488
                    data[i * 2 + 1] = buf[i] + 0x80;
489 fafa0b75 Mike Melanson
        }
490
    } else {
491 79d15fd4 Kostya Shishkov
        bytes_decoded = s->block_align * 2;
492 23fe14bb Mike Melanson
493
        /* mono handling */
494
        if (silence) {
495 79d15fd4 Kostya Shishkov
            memset(data, 0, s->block_align * 2);
496
        } else {
497 23fe14bb Mike Melanson
            if (s->bits == 16) {
498 79d15fd4 Kostya Shishkov
                vmdaudio_decode_audio(s, data, buf, 0);
499 23fe14bb Mike Melanson
            } else {
500 79d15fd4 Kostya Shishkov
                /* copy the data but convert it to signed */
501
                for (i = 0; i < s->block_align; i++)
502
                    data[i * 2 + 1] = buf[i] + 0x80;
503 23fe14bb Mike Melanson
            }
504
        }
505 fafa0b75 Mike Melanson
    }
506 23fe14bb Mike Melanson
507 79d15fd4 Kostya Shishkov
    return s->block_align * 2;
508 fafa0b75 Mike Melanson
}
509
510
static int vmdaudio_decode_frame(AVCodecContext *avctx,
511
                                 void *data, int *data_size,
512
                                 uint8_t *buf, int buf_size)
513
{
514
    VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
515
    unsigned int sound_flags;
516
    unsigned char *output_samples = (unsigned char *)data;
517
518
    /* point to the start of the encoded data */
519
    unsigned char *p = buf + 16;
520
    unsigned char *p_end = buf + buf_size;
521
522 23fe14bb Mike Melanson
    if (buf_size < 16)
523
        return buf_size;
524
525 fafa0b75 Mike Melanson
    if (buf[6] == 1) {
526
        /* the chunk contains audio */
527 23fe14bb Mike Melanson
        *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
528 fafa0b75 Mike Melanson
    } else if (buf[6] == 2) {
529
        /* the chunk contains audio and silence mixed together */
530
        sound_flags = LE_32(p);
531
        p += 4;
532
533
        /* do something with extrabufs here? */
534
535
        while (p < p_end) {
536
            if (sound_flags & 0x01)
537
                /* silence */
538 23fe14bb Mike Melanson
                *data_size += vmdaudio_loadsound(s, output_samples, p, 1);
539
            else {
540
                /* audio */
541
                *data_size += vmdaudio_loadsound(s, output_samples, p, 0);
542
                p += s->block_align;
543
            }
544 fafa0b75 Mike Melanson
            output_samples += (s->block_align * s->bits / 8);
545
            sound_flags >>= 1;
546
        }
547
    } else if (buf[6] == 3) {
548
        /* silent chunk */
549 23fe14bb Mike Melanson
        *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
550 fafa0b75 Mike Melanson
    }
551
552
    return buf_size;
553
}
554
555
556
/*
557
 * Public Data Structures
558
 */
559
560
AVCodec vmdvideo_decoder = {
561
    "vmdvideo",
562
    CODEC_TYPE_VIDEO,
563
    CODEC_ID_VMDVIDEO,
564
    sizeof(VmdVideoContext),
565
    vmdvideo_decode_init,
566
    NULL,
567
    vmdvideo_decode_end,
568
    vmdvideo_decode_frame,
569
    CODEC_CAP_DR1,
570
};
571
572
AVCodec vmdaudio_decoder = {
573
    "vmdaudio",
574
    CODEC_TYPE_AUDIO,
575
    CODEC_ID_VMDAUDIO,
576
    sizeof(VmdAudioContext),
577
    vmdaudio_decode_init,
578
    NULL,
579
    NULL,
580
    vmdaudio_decode_frame,
581
};