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