]> git.sesse.net Git - ffmpeg/blob - libavcodec/vmdav.c
tiffdec: remove an unneeded variable
[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_end(AVCodecContext *avctx)
376 {
377     VmdVideoContext *s = avctx->priv_data;
378
379     av_frame_free(&s->prev_frame);
380     av_free(s->unpack_buffer);
381
382     return 0;
383 }
384
385 static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
386 {
387     VmdVideoContext *s = avctx->priv_data;
388     int i;
389     unsigned int *palette32;
390     int palette_index = 0;
391     unsigned char r, g, b;
392     unsigned char *vmd_header;
393     unsigned char *raw_palette;
394
395     s->avctx = avctx;
396     avctx->pix_fmt = AV_PIX_FMT_PAL8;
397
398     /* make sure the VMD header made it */
399     if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
400         av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
401             VMD_HEADER_SIZE);
402         return -1;
403     }
404     vmd_header = (unsigned char *)avctx->extradata;
405
406     s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
407     if (s->unpack_buffer_size) {
408         s->unpack_buffer = av_malloc(s->unpack_buffer_size);
409         if (!s->unpack_buffer)
410             return AVERROR(ENOMEM);
411     }
412
413     /* load up the initial palette */
414     raw_palette = &vmd_header[28];
415     palette32 = (unsigned int *)s->palette;
416     for (i = 0; i < PALETTE_COUNT; i++) {
417         r = raw_palette[palette_index++] * 4;
418         g = raw_palette[palette_index++] * 4;
419         b = raw_palette[palette_index++] * 4;
420         palette32[i] = (r << 16) | (g << 8) | (b);
421     }
422
423     s->prev_frame = av_frame_alloc();
424     if (!s->prev_frame) {
425         vmdvideo_decode_end(avctx);
426         return AVERROR(ENOMEM);
427     }
428
429     return 0;
430 }
431
432 static int vmdvideo_decode_frame(AVCodecContext *avctx,
433                                  void *data, int *got_frame,
434                                  AVPacket *avpkt)
435 {
436     const uint8_t *buf = avpkt->data;
437     int buf_size = avpkt->size;
438     VmdVideoContext *s = avctx->priv_data;
439     AVFrame *frame = data;
440     int ret;
441
442     s->buf = buf;
443     s->size = buf_size;
444
445     if (buf_size < 16)
446         return AVERROR_INVALIDDATA;
447
448     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) {
449         av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
450         return ret;
451     }
452
453     if ((ret = vmd_decode(s, frame)) < 0)
454         return ret;
455
456     /* make the palette available on the way out */
457     memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
458
459     /* shuffle frames */
460     av_frame_unref(s->prev_frame);
461     if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
462         return ret;
463
464     *got_frame      = 1;
465
466     /* report that the buffer was completely consumed */
467     return buf_size;
468 }
469
470
471 /*
472  * Audio Decoder
473  */
474
475 #define BLOCK_TYPE_AUDIO    1
476 #define BLOCK_TYPE_INITIAL  2
477 #define BLOCK_TYPE_SILENCE  3
478
479 typedef struct VmdAudioContext {
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     av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, "
525            "block align = %d, sample rate = %d\n",
526            avctx->channels, avctx->bits_per_coded_sample, avctx->block_align,
527            avctx->sample_rate);
528
529     return 0;
530 }
531
532 static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size,
533                              int channels)
534 {
535     int ch;
536     const uint8_t *buf_end = buf + buf_size;
537     int predictor[2];
538     int st = channels - 1;
539
540     /* decode initial raw sample */
541     for (ch = 0; ch < channels; ch++) {
542         predictor[ch] = (int16_t)AV_RL16(buf);
543         buf += 2;
544         *out++ = predictor[ch];
545     }
546
547     /* decode DPCM samples */
548     ch = 0;
549     while (buf < buf_end) {
550         uint8_t b = *buf++;
551         if (b & 0x80)
552             predictor[ch] -= vmdaudio_table[b & 0x7F];
553         else
554             predictor[ch] += vmdaudio_table[b];
555         predictor[ch] = av_clip_int16(predictor[ch]);
556         *out++ = predictor[ch];
557         ch ^= st;
558     }
559 }
560
561 static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data,
562                                  int *got_frame_ptr, AVPacket *avpkt)
563 {
564     AVFrame *frame     = data;
565     const uint8_t *buf = avpkt->data;
566     const uint8_t *buf_end;
567     int buf_size = avpkt->size;
568     VmdAudioContext *s = avctx->priv_data;
569     int block_type, silent_chunks, audio_chunks;
570     int ret;
571     uint8_t *output_samples_u8;
572     int16_t *output_samples_s16;
573
574     if (buf_size < 16) {
575         av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n");
576         *got_frame_ptr = 0;
577         return buf_size;
578     }
579
580     block_type = buf[6];
581     if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) {
582         av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type);
583         return AVERROR(EINVAL);
584     }
585     buf      += 16;
586     buf_size -= 16;
587
588     /* get number of silent chunks */
589     silent_chunks = 0;
590     if (block_type == BLOCK_TYPE_INITIAL) {
591         uint32_t flags;
592         if (buf_size < 4) {
593             av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
594             return AVERROR(EINVAL);
595         }
596         flags         = AV_RB32(buf);
597         silent_chunks = av_popcount(flags);
598         buf      += 4;
599         buf_size -= 4;
600     } else if (block_type == BLOCK_TYPE_SILENCE) {
601         silent_chunks = 1;
602         buf_size = 0; // should already be zero but set it just to be sure
603     }
604
605     /* ensure output buffer is large enough */
606     audio_chunks = buf_size / s->chunk_size;
607
608     /* drop incomplete chunks */
609     buf_size     = audio_chunks * s->chunk_size;
610
611     /* get output buffer */
612     frame->nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) /
613                         avctx->channels;
614     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
615         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
616         return ret;
617     }
618     output_samples_u8  =            frame->data[0];
619     output_samples_s16 = (int16_t *)frame->data[0];
620
621     /* decode silent chunks */
622     if (silent_chunks > 0) {
623         int silent_size = FFMIN(avctx->block_align * silent_chunks,
624                                 frame->nb_samples * avctx->channels);
625         if (s->out_bps == 2) {
626             memset(output_samples_s16, 0x00, silent_size * 2);
627             output_samples_s16 += silent_size;
628         } else {
629             memset(output_samples_u8,  0x80, silent_size);
630             output_samples_u8 += silent_size;
631         }
632     }
633
634     /* decode audio chunks */
635     if (audio_chunks > 0) {
636         buf_end = buf + (buf_size & ~(avctx->channels > 1));
637         while (buf + s->chunk_size <= buf_end) {
638             if (s->out_bps == 2) {
639                 decode_audio_s16(output_samples_s16, buf, s->chunk_size,
640                                  avctx->channels);
641                 output_samples_s16 += avctx->block_align;
642             } else {
643                 memcpy(output_samples_u8, buf, s->chunk_size);
644                 output_samples_u8  += avctx->block_align;
645             }
646             buf += s->chunk_size;
647         }
648     }
649
650     *got_frame_ptr = 1;
651
652     return avpkt->size;
653 }
654
655
656 /*
657  * Public Data Structures
658  */
659
660 AVCodec ff_vmdvideo_decoder = {
661     .name           = "vmdvideo",
662     .long_name      = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
663     .type           = AVMEDIA_TYPE_VIDEO,
664     .id             = AV_CODEC_ID_VMDVIDEO,
665     .priv_data_size = sizeof(VmdVideoContext),
666     .init           = vmdvideo_decode_init,
667     .close          = vmdvideo_decode_end,
668     .decode         = vmdvideo_decode_frame,
669     .capabilities   = CODEC_CAP_DR1,
670 };
671
672 AVCodec ff_vmdaudio_decoder = {
673     .name           = "vmdaudio",
674     .long_name      = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
675     .type           = AVMEDIA_TYPE_AUDIO,
676     .id             = AV_CODEC_ID_VMDAUDIO,
677     .priv_data_size = sizeof(VmdAudioContext),
678     .init           = vmdaudio_decode_init,
679     .decode         = vmdaudio_decode_frame,
680     .capabilities   = CODEC_CAP_DR1,
681 };