2 * Sierra VMD Audio & Video Decoders
3 * Copyright (C) 2004 the ffmpeg project
5 * This file is part of FFmpeg.
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.
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.
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
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/
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.
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.
46 #include "libavutil/channel_layout.h"
47 #include "libavutil/common.h"
48 #include "libavutil/intreadwrite.h"
51 #define VMD_HEADER_SIZE 0x330
52 #define PALETTE_COUNT 256
58 typedef struct VmdVideoContext {
60 AVCodecContext *avctx;
64 const unsigned char *buf;
67 unsigned char palette[PALETTE_COUNT * 4];
68 unsigned char *unpack_buffer;
69 int unpack_buffer_size;
74 #define QUEUE_SIZE 0x1000
75 #define QUEUE_MASK 0x0FFF
77 static void lz_unpack(const unsigned char *src, int src_len,
78 unsigned char *dest, int dest_len)
80 const unsigned char *s;
81 const unsigned char *s_end;
84 unsigned char queue[QUEUE_SIZE];
86 unsigned int dataleft;
87 unsigned int chainofs;
88 unsigned int chainlen;
94 s_end = src + src_len;
100 dataleft = AV_RL32(s);
102 memset(queue, 0x20, QUEUE_SIZE);
103 if (AV_RL32(s) == 0x56781234) {
109 speclen = 100; /* no speclen */
112 while (s_end - s > 0 && dataleft > 0) {
114 if ((tag == 0xFF) && (dataleft > 8)) {
115 if (d_end - d < 8 || s_end - s < 8)
117 for (i = 0; i < 8; i++) {
118 queue[qpos++] = *d++ = *s++;
123 for (i = 0; i < 8; i++) {
127 if (d_end - d < 1 || s_end - s < 1)
129 queue[qpos++] = *d++ = *s++;
136 chainofs |= ((*s & 0xF0) << 4);
137 chainlen = (*s++ & 0x0F) + 3;
138 if (chainlen == speclen) {
141 chainlen = *s++ + 0xF + 3;
143 if (d_end - d < chainlen)
145 for (j = 0; j < chainlen; j++) {
146 *d = queue[chainofs++ & QUEUE_MASK];
147 queue[qpos++] = *d++;
150 dataleft -= chainlen;
158 static int rle_unpack(const unsigned char *src, int src_len, int src_count,
159 unsigned char *dest, int dest_len)
161 const unsigned char *ps;
162 const unsigned char *ps_end;
165 unsigned char *dest_end = dest + dest_len;
168 ps_end = src + src_len;
184 if (dest_end - pd < l || ps_end - ps < l)
190 if (dest_end - pd < i || ps_end - ps < 2)
192 for (i = 0; i < l; i++) {
199 } while (i < src_count);
204 static void vmd_decode(VmdVideoContext *s)
207 unsigned int *palette32;
208 unsigned char r, g, b;
210 /* point to the start of the encoded data */
211 const unsigned char *p = s->buf + 16;
212 const unsigned char *p_end = s->buf + s->size;
214 const unsigned char *pb;
215 const unsigned char *pb_end;
217 unsigned char *dp; /* pointer to current frame */
218 unsigned char *pp; /* pointer to previous frame */
222 int frame_x, frame_y;
223 int frame_width, frame_height;
225 frame_x = AV_RL16(&s->buf[6]);
226 frame_y = AV_RL16(&s->buf[8]);
227 frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
228 frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
229 if (frame_x < 0 || frame_width < 0 ||
230 frame_x >= s->avctx->width ||
231 frame_width > s->avctx->width ||
232 frame_x + frame_width > s->avctx->width)
234 if (frame_y < 0 || frame_height < 0 ||
235 frame_y >= s->avctx->height ||
236 frame_height > s->avctx->height ||
237 frame_y + frame_height > s->avctx->height)
240 if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
241 (frame_x || frame_y)) {
249 /* if only a certain region will be updated, copy the entire previous
250 * frame before the decode */
251 if (s->prev_frame.data[0] &&
252 (frame_x || frame_y || (frame_width != s->avctx->width) ||
253 (frame_height != s->avctx->height))) {
255 memcpy(s->frame.data[0], s->prev_frame.data[0],
256 s->avctx->height * s->frame.linesize[0]);
259 /* check if there is a new palette */
260 if (s->buf[15] & 0x02) {
261 if (p_end - p < 2 + 3 * PALETTE_COUNT)
264 palette32 = (unsigned int *)s->palette;
265 for (i = 0; i < PALETTE_COUNT; i++) {
269 palette32[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
270 palette32[i] |= palette32[i] >> 6 & 0x30303;
274 /* originally UnpackFrame in VAG's code */
279 lz_unpack(pb, p_end - pb, s->unpack_buffer, s->unpack_buffer_size);
281 pb = s->unpack_buffer;
282 pb_end = s->unpack_buffer + s->unpack_buffer_size;
285 dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
286 pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
289 for (i = 0; i < frame_height; i++) {
296 len = (len & 0x7F) + 1;
297 if (ofs + len > frame_width || pb_end - pb < len)
299 memcpy(&dp[ofs], pb, len);
303 /* interframe pixel copy */
304 if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
306 memcpy(&dp[ofs], &pp[ofs], len + 1);
309 } while (ofs < frame_width);
310 if (ofs > frame_width) {
311 av_log(s->avctx, AV_LOG_ERROR, "offset > width (%d > %d)\n",
315 dp += s->frame.linesize[0];
316 pp += s->prev_frame.linesize[0];
321 for (i = 0; i < frame_height; i++) {
322 if (pb_end -pb < frame_width)
324 memcpy(dp, pb, frame_width);
326 dp += s->frame.linesize[0];
327 pp += s->prev_frame.linesize[0];
332 for (i = 0; i < frame_height; i++) {
339 len = (len & 0x7F) + 1;
343 len = rle_unpack(pb, pb_end - pb, len, &dp[ofs], frame_width - ofs);
345 if (pb_end - pb < len)
347 memcpy(&dp[ofs], pb, len);
352 /* interframe pixel copy */
353 if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
355 memcpy(&dp[ofs], &pp[ofs], len + 1);
358 } while (ofs < frame_width);
359 if (ofs > frame_width) {
360 av_log(s->avctx, AV_LOG_ERROR, "offset > width (%d > %d)\n",
363 dp += s->frame.linesize[0];
364 pp += s->prev_frame.linesize[0];
371 static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
373 VmdVideoContext *s = avctx->priv_data;
375 unsigned int *palette32;
376 int palette_index = 0;
377 unsigned char r, g, b;
378 unsigned char *vmd_header;
379 unsigned char *raw_palette;
382 avctx->pix_fmt = AV_PIX_FMT_PAL8;
384 /* make sure the VMD header made it */
385 if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
386 av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n",
390 vmd_header = (unsigned char *)avctx->extradata;
392 s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
393 s->unpack_buffer = av_malloc(s->unpack_buffer_size);
394 if (!s->unpack_buffer)
397 /* load up the initial palette */
398 raw_palette = &vmd_header[28];
399 palette32 = (unsigned int *)s->palette;
400 for (i = 0; i < PALETTE_COUNT; i++) {
401 r = raw_palette[palette_index++] * 4;
402 g = raw_palette[palette_index++] * 4;
403 b = raw_palette[palette_index++] * 4;
404 palette32[i] = (r << 16) | (g << 8) | (b);
407 avcodec_get_frame_defaults(&s->frame);
408 avcodec_get_frame_defaults(&s->prev_frame);
413 static int vmdvideo_decode_frame(AVCodecContext *avctx,
414 void *data, int *data_size,
417 const uint8_t *buf = avpkt->data;
418 int buf_size = avpkt->size;
419 VmdVideoContext *s = avctx->priv_data;
427 s->frame.reference = 3;
428 if (avctx->get_buffer(avctx, &s->frame)) {
429 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
435 /* make the palette available on the way out */
436 memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
439 FFSWAP(AVFrame, s->frame, s->prev_frame);
440 if (s->frame.data[0])
441 avctx->release_buffer(avctx, &s->frame);
443 *data_size = sizeof(AVFrame);
444 *(AVFrame*)data = s->prev_frame;
446 /* report that the buffer was completely consumed */
450 static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
452 VmdVideoContext *s = avctx->priv_data;
454 if (s->prev_frame.data[0])
455 avctx->release_buffer(avctx, &s->prev_frame);
456 av_free(s->unpack_buffer);
466 #define BLOCK_TYPE_AUDIO 1
467 #define BLOCK_TYPE_INITIAL 2
468 #define BLOCK_TYPE_SILENCE 3
470 typedef struct VmdAudioContext {
476 static const uint16_t vmdaudio_table[128] = {
477 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
478 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
479 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
480 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
481 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
482 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
483 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
484 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
485 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
486 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
487 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
488 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
489 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
492 static av_cold int vmdaudio_decode_init(AVCodecContext *avctx)
494 VmdAudioContext *s = avctx->priv_data;
496 if (avctx->channels < 1 || avctx->channels > 2) {
497 av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
498 return AVERROR(EINVAL);
500 if (avctx->block_align < 1 || avctx->block_align % avctx->channels) {
501 av_log(avctx, AV_LOG_ERROR, "invalid block align\n");
502 return AVERROR(EINVAL);
505 avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO :
508 if (avctx->bits_per_coded_sample == 16)
509 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
511 avctx->sample_fmt = AV_SAMPLE_FMT_U8;
512 s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt);
514 s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2);
516 avcodec_get_frame_defaults(&s->frame);
517 avctx->coded_frame = &s->frame;
519 av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, "
520 "block align = %d, sample rate = %d\n",
521 avctx->channels, avctx->bits_per_coded_sample, avctx->block_align,
527 static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size,
531 const uint8_t *buf_end = buf + buf_size;
533 int st = channels - 1;
535 /* decode initial raw sample */
536 for (ch = 0; ch < channels; ch++) {
537 predictor[ch] = (int16_t)AV_RL16(buf);
539 *out++ = predictor[ch];
542 /* decode DPCM samples */
544 while (buf < buf_end) {
547 predictor[ch] -= vmdaudio_table[b & 0x7F];
549 predictor[ch] += vmdaudio_table[b];
550 predictor[ch] = av_clip_int16(predictor[ch]);
551 *out++ = predictor[ch];
556 static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data,
557 int *got_frame_ptr, AVPacket *avpkt)
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;
565 uint8_t *output_samples_u8;
566 int16_t *output_samples_s16;
569 av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n");
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);
582 /* get number of silent chunks */
584 if (block_type == BLOCK_TYPE_INITIAL) {
587 av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
588 return AVERROR(EINVAL);
590 flags = AV_RB32(buf);
591 silent_chunks = av_popcount(flags);
594 } else if (block_type == BLOCK_TYPE_SILENCE) {
596 buf_size = 0; // should already be zero but set it just to be sure
599 /* ensure output buffer is large enough */
600 audio_chunks = buf_size / s->chunk_size;
602 /* get output buffer */
603 s->frame.nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / avctx->channels;
604 if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
605 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
608 output_samples_u8 = s->frame.data[0];
609 output_samples_s16 = (int16_t *)s->frame.data[0];
611 /* decode silent chunks */
612 if (silent_chunks > 0) {
613 int silent_size = avctx->block_align * silent_chunks;
614 if (s->out_bps == 2) {
615 memset(output_samples_s16, 0x00, silent_size * 2);
616 output_samples_s16 += silent_size;
618 memset(output_samples_u8, 0x80, silent_size);
619 output_samples_u8 += silent_size;
623 /* decode audio chunks */
624 if (audio_chunks > 0) {
625 buf_end = buf + buf_size;
626 while ( buf_end - buf >= s->chunk_size) {
627 if (s->out_bps == 2) {
628 decode_audio_s16(output_samples_s16, buf, s->chunk_size,
630 output_samples_s16 += avctx->block_align;
632 memcpy(output_samples_u8, buf, s->chunk_size);
633 output_samples_u8 += avctx->block_align;
635 buf += s->chunk_size;
640 *(AVFrame *)data = s->frame;
647 * Public Data Structures
650 AVCodec ff_vmdvideo_decoder = {
652 .type = AVMEDIA_TYPE_VIDEO,
653 .id = AV_CODEC_ID_VMDVIDEO,
654 .priv_data_size = sizeof(VmdVideoContext),
655 .init = vmdvideo_decode_init,
656 .close = vmdvideo_decode_end,
657 .decode = vmdvideo_decode_frame,
658 .capabilities = CODEC_CAP_DR1,
659 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
662 AVCodec ff_vmdaudio_decoder = {
664 .type = AVMEDIA_TYPE_AUDIO,
665 .id = AV_CODEC_ID_VMDAUDIO,
666 .priv_data_size = sizeof(VmdAudioContext),
667 .init = vmdaudio_decode_init,
668 .decode = vmdaudio_decode_frame,
669 .capabilities = CODEC_CAP_DR1,
670 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),