vmd: use the PALETTE_COUNT constant uniformly
[ffmpeg.git] / libavcodec / vmdav.c
1 /*
2  * Sierra VMD Audio & Video Decoders
3  * Copyright (C) 2004 the ffmpeg project
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; 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_get_le32(&gb);
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 + 8 > d_end || 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 + 1 > d_end || bytestream2_get_bytes_left(&gb) < 1)
125                         return;
126                     queue[qpos++] = *d++ = bytestream2_get_byte(&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 + chainlen > d_end)
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
151 static int rle_unpack(const unsigned char *src, unsigned char *dest,
152     int src_count, int src_size, int dest_len)
153 {
154     unsigned char *pd;
155     int i, l;
156     unsigned char *dest_end = dest + dest_len;
157     GetByteContext gb;
158
159     bytestream2_init(&gb, src, src_size);
160     pd = dest;
161     if (src_count & 1) {
162         if (bytestream2_get_bytes_left(&gb) < 1)
163             return 0;
164         *pd++ = bytestream2_get_byteu(&gb);
165     }
166
167     src_count >>= 1;
168     i = 0;
169     do {
170         if (bytestream2_get_bytes_left(&gb) < 1)
171             break;
172         l = bytestream2_get_byteu(&gb);
173         if (l & 0x80) {
174             l = (l & 0x7F) * 2;
175             if (pd + l > dest_end || bytestream2_get_bytes_left(&gb) < l)
176                 return bytestream2_tell(&gb);
177             bytestream2_get_buffer(&gb, pd, l);
178             pd += l;
179         } else {
180             if (pd + i > dest_end || bytestream2_get_bytes_left(&gb) < 2)
181                 return bytestream2_tell(&gb);
182             for (i = 0; i < l; i++) {
183                 *pd++ = bytestream2_get_byteu(&gb);
184                 *pd++ = bytestream2_get_byteu(&gb);
185             }
186             bytestream2_skip(&gb, 2);
187         }
188         i += l;
189     } while (i < src_count);
190
191     return bytestream2_tell(&gb);
192 }
193
194 static void vmd_decode(VmdVideoContext *s, AVFrame *frame)
195 {
196     int i;
197     unsigned int *palette32;
198     unsigned char r, g, b;
199
200     GetByteContext gb;
201
202     unsigned char meth;
203     unsigned char *dp;   /* pointer to current frame */
204     unsigned char *pp;   /* pointer to previous frame */
205     unsigned char len;
206     int ofs;
207
208     int frame_x, frame_y;
209     int frame_width, frame_height;
210
211     frame_x = AV_RL16(&s->buf[6]);
212     frame_y = AV_RL16(&s->buf[8]);
213     frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
214     frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
215     if (frame_x < 0 || frame_width < 0 ||
216         frame_x >= s->avctx->width ||
217         frame_width > s->avctx->width ||
218         frame_x + frame_width > s->avctx->width)
219         return;
220     if (frame_y < 0 || frame_height < 0 ||
221         frame_y >= s->avctx->height ||
222         frame_height > s->avctx->height ||
223         frame_y + frame_height > s->avctx->height)
224         return;
225
226     if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
227         (frame_x || frame_y)) {
228
229         s->x_off = frame_x;
230         s->y_off = frame_y;
231     }
232     frame_x -= s->x_off;
233     frame_y -= s->y_off;
234
235     /* if only a certain region will be updated, copy the entire previous
236      * frame before the decode */
237     if (s->prev_frame.data[0] &&
238         (frame_x || frame_y || (frame_width != s->avctx->width) ||
239         (frame_height != s->avctx->height))) {
240
241         memcpy(frame->data[0], s->prev_frame.data[0],
242             s->avctx->height * frame->linesize[0]);
243     }
244
245     /* check if there is a new palette */
246     bytestream2_init(&gb, s->buf + 16, s->size - 16);
247     if (s->buf[15] & 0x02) {
248         bytestream2_skip(&gb, 2);
249         palette32 = (unsigned int *)s->palette;
250         if (bytestream2_get_bytes_left(&gb) >= PALETTE_COUNT * 3) {
251             for (i = 0; i < PALETTE_COUNT; i++) {
252                 r = bytestream2_get_byteu(&gb) * 4;
253                 g = bytestream2_get_byteu(&gb) * 4;
254                 b = bytestream2_get_byteu(&gb) * 4;
255                 palette32[i] = (r << 16) | (g << 8) | (b);
256             }
257         }
258         s->size -= PALETTE_COUNT * 3 + 2;
259     }
260     if (s->size > 0) {
261         /* originally UnpackFrame in VAG's code */
262         bytestream2_init(&gb, gb.buffer, s->buf + s->size - gb.buffer);
263         if (bytestream2_get_bytes_left(&gb) < 1)
264             return;
265         meth = bytestream2_get_byteu(&gb);
266         if (meth & 0x80) {
267             lz_unpack(gb.buffer, bytestream2_get_bytes_left(&gb),
268                       s->unpack_buffer, s->unpack_buffer_size);
269             meth &= 0x7F;
270             bytestream2_init(&gb, s->unpack_buffer, s->unpack_buffer_size);
271         }
272
273         dp = &frame->data[0][frame_y * frame->linesize[0] + frame_x];
274         pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
275         switch (meth) {
276         case 1:
277             for (i = 0; i < frame_height; i++) {
278                 ofs = 0;
279                 do {
280                     len = bytestream2_get_byte(&gb);
281                     if (len & 0x80) {
282                         len = (len & 0x7F) + 1;
283                         if (ofs + len > frame_width || bytestream2_get_bytes_left(&gb) < len)
284                             return;
285                         bytestream2_get_buffer(&gb, &dp[ofs], len);
286                         ofs += len;
287                     } else {
288                         /* interframe pixel copy */
289                         if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
290                             return;
291                         memcpy(&dp[ofs], &pp[ofs], len + 1);
292                         ofs += len + 1;
293                     }
294                 } while (ofs < frame_width);
295                 if (ofs > frame_width) {
296                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
297                         ofs, frame_width);
298                     break;
299                 }
300                 dp += frame->linesize[0];
301                 pp += s->prev_frame.linesize[0];
302             }
303             break;
304
305         case 2:
306             for (i = 0; i < frame_height; i++) {
307                 bytestream2_get_buffer(&gb, dp, frame_width);
308                 dp += frame->linesize[0];
309                 pp += s->prev_frame.linesize[0];
310             }
311             break;
312
313         case 3:
314             for (i = 0; i < frame_height; i++) {
315                 ofs = 0;
316                 do {
317                     len = bytestream2_get_byte(&gb);
318                     if (len & 0x80) {
319                         len = (len & 0x7F) + 1;
320                         if (bytestream2_get_byte(&gb) == 0xFF)
321                             len = rle_unpack(gb.buffer, &dp[ofs],
322                                              len, bytestream2_get_bytes_left(&gb),
323                                              frame_width - ofs);
324                         else
325                             bytestream2_get_buffer(&gb, &dp[ofs], len);
326                         bytestream2_skip(&gb, len);
327                     } else {
328                         /* interframe pixel copy */
329                         if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
330                             return;
331                         memcpy(&dp[ofs], &pp[ofs], len + 1);
332                         ofs += len + 1;
333                     }
334                 } while (ofs < frame_width);
335                 if (ofs > frame_width) {
336                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
337                         ofs, frame_width);
338                 }
339                 dp += frame->linesize[0];
340                 pp += s->prev_frame.linesize[0];
341             }
342             break;
343         }
344     }
345 }
346
347 static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
348 {
349     VmdVideoContext *s = avctx->priv_data;
350     int i;
351     unsigned int *palette32;
352     int palette_index = 0;
353     unsigned char r, g, b;
354     unsigned char *vmd_header;
355     unsigned char *raw_palette;
356
357     s->avctx = avctx;
358     avctx->pix_fmt = AV_PIX_FMT_PAL8;
359
360     /* make sure the VMD header made it */
361     if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
362         av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
363             VMD_HEADER_SIZE);
364         return -1;
365     }
366     vmd_header = (unsigned char *)avctx->extradata;
367
368     s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
369     s->unpack_buffer = av_malloc(s->unpack_buffer_size);
370     if (!s->unpack_buffer)
371         return -1;
372
373     /* load up the initial palette */
374     raw_palette = &vmd_header[28];
375     palette32 = (unsigned int *)s->palette;
376     for (i = 0; i < PALETTE_COUNT; i++) {
377         r = raw_palette[palette_index++] * 4;
378         g = raw_palette[palette_index++] * 4;
379         b = raw_palette[palette_index++] * 4;
380         palette32[i] = (r << 16) | (g << 8) | (b);
381     }
382
383     return 0;
384 }
385
386 static int vmdvideo_decode_frame(AVCodecContext *avctx,
387                                  void *data, int *got_frame,
388                                  AVPacket *avpkt)
389 {
390     const uint8_t *buf = avpkt->data;
391     int buf_size = avpkt->size;
392     VmdVideoContext *s = avctx->priv_data;
393     AVFrame *frame = data;
394     int ret;
395
396     s->buf = buf;
397     s->size = buf_size;
398
399     if (buf_size < 16)
400         return buf_size;
401
402     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) {
403         av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
404         return ret;
405     }
406
407     vmd_decode(s, frame);
408
409     /* make the palette available on the way out */
410     memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
411
412     /* shuffle frames */
413     av_frame_unref(&s->prev_frame);
414     if ((ret = av_frame_ref(&s->prev_frame, frame)) < 0)
415         return ret;
416
417     *got_frame      = 1;
418
419     /* report that the buffer was completely consumed */
420     return buf_size;
421 }
422
423 static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
424 {
425     VmdVideoContext *s = avctx->priv_data;
426
427     av_frame_unref(&s->prev_frame);
428     av_free(s->unpack_buffer);
429
430     return 0;
431 }
432
433
434 /*
435  * Audio Decoder
436  */
437
438 #define BLOCK_TYPE_AUDIO    1
439 #define BLOCK_TYPE_INITIAL  2
440 #define BLOCK_TYPE_SILENCE  3
441
442 typedef struct VmdAudioContext {
443     int out_bps;
444     int chunk_size;
445 } VmdAudioContext;
446
447 static const uint16_t vmdaudio_table[128] = {
448     0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
449     0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
450     0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
451     0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
452     0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
453     0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
454     0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
455     0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
456     0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
457     0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
458     0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
459     0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
460     0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
461 };
462
463 static av_cold int vmdaudio_decode_init(AVCodecContext *avctx)
464 {
465     VmdAudioContext *s = avctx->priv_data;
466
467     if (avctx->channels < 1 || avctx->channels > 2) {
468         av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
469         return AVERROR(EINVAL);
470     }
471     if (avctx->block_align < 1) {
472         av_log(avctx, AV_LOG_ERROR, "invalid block align\n");
473         return AVERROR(EINVAL);
474     }
475
476     avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO :
477                                                    AV_CH_LAYOUT_STEREO;
478
479     if (avctx->bits_per_coded_sample == 16)
480         avctx->sample_fmt = AV_SAMPLE_FMT_S16;
481     else
482         avctx->sample_fmt = AV_SAMPLE_FMT_U8;
483     s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt);
484
485     s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2);
486
487     av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, "
488            "block align = %d, sample rate = %d\n",
489            avctx->channels, avctx->bits_per_coded_sample, avctx->block_align,
490            avctx->sample_rate);
491
492     return 0;
493 }
494
495 static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size,
496                              int channels)
497 {
498     int ch;
499     const uint8_t *buf_end = buf + buf_size;
500     int predictor[2];
501     int st = channels - 1;
502
503     /* decode initial raw sample */
504     for (ch = 0; ch < channels; ch++) {
505         predictor[ch] = (int16_t)AV_RL16(buf);
506         buf += 2;
507         *out++ = predictor[ch];
508     }
509
510     /* decode DPCM samples */
511     ch = 0;
512     while (buf < buf_end) {
513         uint8_t b = *buf++;
514         if (b & 0x80)
515             predictor[ch] -= vmdaudio_table[b & 0x7F];
516         else
517             predictor[ch] += vmdaudio_table[b];
518         predictor[ch] = av_clip_int16(predictor[ch]);
519         *out++ = predictor[ch];
520         ch ^= st;
521     }
522 }
523
524 static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data,
525                                  int *got_frame_ptr, AVPacket *avpkt)
526 {
527     AVFrame *frame     = data;
528     const uint8_t *buf = avpkt->data;
529     const uint8_t *buf_end;
530     int buf_size = avpkt->size;
531     VmdAudioContext *s = avctx->priv_data;
532     int block_type, silent_chunks, audio_chunks;
533     int ret;
534     uint8_t *output_samples_u8;
535     int16_t *output_samples_s16;
536
537     if (buf_size < 16) {
538         av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n");
539         *got_frame_ptr = 0;
540         return buf_size;
541     }
542
543     block_type = buf[6];
544     if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) {
545         av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type);
546         return AVERROR(EINVAL);
547     }
548     buf      += 16;
549     buf_size -= 16;
550
551     /* get number of silent chunks */
552     silent_chunks = 0;
553     if (block_type == BLOCK_TYPE_INITIAL) {
554         uint32_t flags;
555         if (buf_size < 4) {
556             av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
557             return AVERROR(EINVAL);
558         }
559         flags         = AV_RB32(buf);
560         silent_chunks = av_popcount(flags);
561         buf      += 4;
562         buf_size -= 4;
563     } else if (block_type == BLOCK_TYPE_SILENCE) {
564         silent_chunks = 1;
565         buf_size = 0; // should already be zero but set it just to be sure
566     }
567
568     /* ensure output buffer is large enough */
569     audio_chunks = buf_size / s->chunk_size;
570
571     /* get output buffer */
572     frame->nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) /
573                         avctx->channels;
574     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
575         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
576         return ret;
577     }
578     output_samples_u8  =            frame->data[0];
579     output_samples_s16 = (int16_t *)frame->data[0];
580
581     /* decode silent chunks */
582     if (silent_chunks > 0) {
583         int silent_size = avctx->block_align * silent_chunks;
584         if (s->out_bps == 2) {
585             memset(output_samples_s16, 0x00, silent_size * 2);
586             output_samples_s16 += silent_size;
587         } else {
588             memset(output_samples_u8,  0x80, silent_size);
589             output_samples_u8 += silent_size;
590         }
591     }
592
593     /* decode audio chunks */
594     if (audio_chunks > 0) {
595         buf_end = buf + buf_size;
596         while (buf + s->chunk_size <= buf_end) {
597             if (s->out_bps == 2) {
598                 decode_audio_s16(output_samples_s16, buf, s->chunk_size,
599                                  avctx->channels);
600                 output_samples_s16 += avctx->block_align;
601             } else {
602                 memcpy(output_samples_u8, buf, s->chunk_size);
603                 output_samples_u8  += avctx->block_align;
604             }
605             buf += s->chunk_size;
606         }
607     }
608
609     *got_frame_ptr = 1;
610
611     return avpkt->size;
612 }
613
614
615 /*
616  * Public Data Structures
617  */
618
619 AVCodec ff_vmdvideo_decoder = {
620     .name           = "vmdvideo",
621     .type           = AVMEDIA_TYPE_VIDEO,
622     .id             = AV_CODEC_ID_VMDVIDEO,
623     .priv_data_size = sizeof(VmdVideoContext),
624     .init           = vmdvideo_decode_init,
625     .close          = vmdvideo_decode_end,
626     .decode         = vmdvideo_decode_frame,
627     .capabilities   = CODEC_CAP_DR1,
628     .long_name      = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
629 };
630
631 AVCodec ff_vmdaudio_decoder = {
632     .name           = "vmdaudio",
633     .type           = AVMEDIA_TYPE_AUDIO,
634     .id             = AV_CODEC_ID_VMDAUDIO,
635     .priv_data_size = sizeof(VmdAudioContext),
636     .init           = vmdaudio_decode_init,
637     .decode         = vmdaudio_decode_frame,
638     .capabilities   = CODEC_CAP_DR1,
639     .long_name      = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
640 };