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