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