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