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
23 * @file libavcodec/vmdav.c
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.
47 #include "libavutil/intreadwrite.h"
50 #define VMD_HEADER_SIZE 0x330
51 #define PALETTE_COUNT 256
57 typedef struct VmdVideoContext
{
59 AVCodecContext
*avctx
;
63 const unsigned char *buf
;
66 unsigned char palette
[PALETTE_COUNT
* 4];
67 unsigned char *unpack_buffer
;
68 int unpack_buffer_size
;
73 #define QUEUE_SIZE 0x1000
74 #define QUEUE_MASK 0x0FFF
76 static void lz_unpack(const unsigned char *src
, unsigned char *dest
, int dest_len
)
78 const unsigned char *s
;
81 unsigned char queue
[QUEUE_SIZE
];
83 unsigned int dataleft
;
84 unsigned int chainofs
;
85 unsigned int chainlen
;
93 dataleft
= AV_RL32(s
);
95 memset(queue
, 0x20, QUEUE_SIZE
);
96 if (AV_RL32(s
) == 0x56781234) {
102 speclen
= 100; /* no speclen */
105 while (dataleft
> 0) {
107 if ((tag
== 0xFF) && (dataleft
> 8)) {
110 for (i
= 0; i
< 8; i
++) {
111 queue
[qpos
++] = *d
++ = *s
++;
116 for (i
= 0; i
< 8; i
++) {
122 queue
[qpos
++] = *d
++ = *s
++;
127 chainofs
|= ((*s
& 0xF0) << 4);
128 chainlen
= (*s
++ & 0x0F) + 3;
129 if (chainlen
== speclen
)
130 chainlen
= *s
++ + 0xF + 3;
131 if (d
+ chainlen
> d_end
)
133 for (j
= 0; j
< chainlen
; j
++) {
134 *d
= queue
[chainofs
++ & QUEUE_MASK
];
135 queue
[qpos
++] = *d
++;
138 dataleft
-= chainlen
;
146 static int rle_unpack(const unsigned char *src
, unsigned char *dest
,
147 int src_len
, int dest_len
)
149 const unsigned char *ps
;
152 unsigned char *dest_end
= dest
+ dest_len
;
165 if (pd
+ l
> dest_end
)
171 if (pd
+ i
> dest_end
)
173 for (i
= 0; i
< l
; i
++) {
180 } while (i
< src_len
);
185 static void vmd_decode(VmdVideoContext
*s
)
188 unsigned int *palette32
;
189 unsigned char r
, g
, b
;
191 /* point to the start of the encoded data */
192 const unsigned char *p
= s
->buf
+ 16;
194 const unsigned char *pb
;
196 unsigned char *dp
; /* pointer to current frame */
197 unsigned char *pp
; /* pointer to previous frame */
201 int frame_x
, frame_y
;
202 int frame_width
, frame_height
;
205 frame_x
= AV_RL16(&s
->buf
[6]);
206 frame_y
= AV_RL16(&s
->buf
[8]);
207 frame_width
= AV_RL16(&s
->buf
[10]) - frame_x
+ 1;
208 frame_height
= AV_RL16(&s
->buf
[12]) - frame_y
+ 1;
210 if ((frame_width
== s
->avctx
->width
&& frame_height
== s
->avctx
->height
) &&
211 (frame_x
|| frame_y
)) {
219 /* if only a certain region will be updated, copy the entire previous
220 * frame before the decode */
221 if (frame_x
|| frame_y
|| (frame_width
!= s
->avctx
->width
) ||
222 (frame_height
!= s
->avctx
->height
)) {
224 memcpy(s
->frame
.data
[0], s
->prev_frame
.data
[0],
225 s
->avctx
->height
* s
->frame
.linesize
[0]);
228 /* check if there is a new palette */
229 if (s
->buf
[15] & 0x02) {
231 palette32
= (unsigned int *)s
->palette
;
232 for (i
= 0; i
< PALETTE_COUNT
; i
++) {
236 palette32
[i
] = (r
<< 16) | (g
<< 8) | (b
);
238 s
->size
-= (256 * 3 + 2);
241 /* originally UnpackFrame in VAG's code */
245 lz_unpack(pb
, s
->unpack_buffer
, s
->unpack_buffer_size
);
247 pb
= s
->unpack_buffer
;
250 dp
= &s
->frame
.data
[0][frame_y
* s
->frame
.linesize
[0] + frame_x
];
251 dp_size
= s
->frame
.linesize
[0] * s
->avctx
->height
;
252 pp
= &s
->prev_frame
.data
[0][frame_y
* s
->prev_frame
.linesize
[0] + frame_x
];
255 for (i
= 0; i
< frame_height
; i
++) {
260 len
= (len
& 0x7F) + 1;
261 if (ofs
+ len
> frame_width
)
263 memcpy(&dp
[ofs
], pb
, len
);
267 /* interframe pixel copy */
268 if (ofs
+ len
+ 1 > frame_width
)
270 memcpy(&dp
[ofs
], &pp
[ofs
], len
+ 1);
273 } while (ofs
< frame_width
);
274 if (ofs
> frame_width
) {
275 av_log(s
->avctx
, AV_LOG_ERROR
, "VMD video: offset > width (%d > %d)\n",
279 dp
+= s
->frame
.linesize
[0];
280 pp
+= s
->prev_frame
.linesize
[0];
285 for (i
= 0; i
< frame_height
; i
++) {
286 memcpy(dp
, pb
, frame_width
);
288 dp
+= s
->frame
.linesize
[0];
289 pp
+= s
->prev_frame
.linesize
[0];
294 for (i
= 0; i
< frame_height
; i
++) {
299 len
= (len
& 0x7F) + 1;
301 len
= rle_unpack(pb
, &dp
[ofs
], len
, frame_width
- ofs
);
303 memcpy(&dp
[ofs
], pb
, len
);
307 /* interframe pixel copy */
308 if (ofs
+ len
+ 1 > frame_width
)
310 memcpy(&dp
[ofs
], &pp
[ofs
], len
+ 1);
313 } while (ofs
< frame_width
);
314 if (ofs
> frame_width
) {
315 av_log(s
->avctx
, AV_LOG_ERROR
, "VMD video: offset > width (%d > %d)\n",
318 dp
+= s
->frame
.linesize
[0];
319 pp
+= s
->prev_frame
.linesize
[0];
326 static av_cold
int vmdvideo_decode_init(AVCodecContext
*avctx
)
328 VmdVideoContext
*s
= avctx
->priv_data
;
330 unsigned int *palette32
;
331 int palette_index
= 0;
332 unsigned char r
, g
, b
;
333 unsigned char *vmd_header
;
334 unsigned char *raw_palette
;
337 avctx
->pix_fmt
= PIX_FMT_PAL8
;
339 /* make sure the VMD header made it */
340 if (s
->avctx
->extradata_size
!= VMD_HEADER_SIZE
) {
341 av_log(s
->avctx
, AV_LOG_ERROR
, "VMD video: expected extradata size of %d\n",
345 vmd_header
= (unsigned char *)avctx
->extradata
;
347 s
->unpack_buffer_size
= AV_RL32(&vmd_header
[800]);
348 s
->unpack_buffer
= av_malloc(s
->unpack_buffer_size
);
349 if (!s
->unpack_buffer
)
352 /* load up the initial palette */
353 raw_palette
= &vmd_header
[28];
354 palette32
= (unsigned int *)s
->palette
;
355 for (i
= 0; i
< PALETTE_COUNT
; i
++) {
356 r
= raw_palette
[palette_index
++] * 4;
357 g
= raw_palette
[palette_index
++] * 4;
358 b
= raw_palette
[palette_index
++] * 4;
359 palette32
[i
] = (r
<< 16) | (g
<< 8) | (b
);
365 static int vmdvideo_decode_frame(AVCodecContext
*avctx
,
366 void *data
, int *data_size
,
369 const uint8_t *buf
= avpkt
->data
;
370 int buf_size
= avpkt
->size
;
371 VmdVideoContext
*s
= avctx
->priv_data
;
379 s
->frame
.reference
= 1;
380 if (avctx
->get_buffer(avctx
, &s
->frame
)) {
381 av_log(s
->avctx
, AV_LOG_ERROR
, "VMD Video: get_buffer() failed\n");
387 /* make the palette available on the way out */
388 memcpy(s
->frame
.data
[1], s
->palette
, PALETTE_COUNT
* 4);
391 FFSWAP(AVFrame
, s
->frame
, s
->prev_frame
);
392 if (s
->frame
.data
[0])
393 avctx
->release_buffer(avctx
, &s
->frame
);
395 *data_size
= sizeof(AVFrame
);
396 *(AVFrame
*)data
= s
->prev_frame
;
398 /* report that the buffer was completely consumed */
402 static av_cold
int vmdvideo_decode_end(AVCodecContext
*avctx
)
404 VmdVideoContext
*s
= avctx
->priv_data
;
406 if (s
->prev_frame
.data
[0])
407 avctx
->release_buffer(avctx
, &s
->prev_frame
);
408 av_free(s
->unpack_buffer
);
418 typedef struct VmdAudioContext
{
419 AVCodecContext
*avctx
;
426 static const uint16_t vmdaudio_table
[128] = {
427 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
428 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
429 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
430 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
431 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
432 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
433 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
434 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
435 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
436 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
437 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
438 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
439 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
442 static av_cold
int vmdaudio_decode_init(AVCodecContext
*avctx
)
444 VmdAudioContext
*s
= avctx
->priv_data
;
447 s
->channels
= avctx
->channels
;
448 s
->bits
= avctx
->bits_per_coded_sample
;
449 s
->block_align
= avctx
->block_align
;
450 avctx
->sample_fmt
= SAMPLE_FMT_S16
;
452 av_log(s
->avctx
, AV_LOG_DEBUG
, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
453 s
->channels
, s
->bits
, s
->block_align
, avctx
->sample_rate
);
458 static void vmdaudio_decode_audio(VmdAudioContext
*s
, unsigned char *data
,
459 const uint8_t *buf
, int buf_size
, int stereo
)
463 int16_t *out
= (int16_t*)data
;
465 for(i
= 0; i
< buf_size
; i
++) {
467 s
->predictors
[chan
] -= vmdaudio_table
[buf
[i
] & 0x7F];
469 s
->predictors
[chan
] += vmdaudio_table
[buf
[i
]];
470 s
->predictors
[chan
] = av_clip_int16(s
->predictors
[chan
]);
471 out
[i
] = s
->predictors
[chan
];
476 static int vmdaudio_loadsound(VmdAudioContext
*s
, unsigned char *data
,
477 const uint8_t *buf
, int silence
, int data_size
)
479 int bytes_decoded
= 0;
483 // av_log(s->avctx, AV_LOG_INFO, "silent block!\n");
484 if (s
->channels
== 2) {
486 /* stereo handling */
488 memset(data
, 0, data_size
* 2);
491 vmdaudio_decode_audio(s
, data
, buf
, data_size
, 1);
493 /* copy the data but convert it to signed */
494 for (i
= 0; i
< data_size
; i
++){
495 *data
++ = buf
[i
] + 0x80;
496 *data
++ = buf
[i
] + 0x80;
501 bytes_decoded
= data_size
* 2;
505 memset(data
, 0, data_size
* 2);
508 vmdaudio_decode_audio(s
, data
, buf
, data_size
, 0);
510 /* copy the data but convert it to signed */
511 for (i
= 0; i
< data_size
; i
++){
512 *data
++ = buf
[i
] + 0x80;
513 *data
++ = buf
[i
] + 0x80;
519 return data_size
* 2;
522 static int vmdaudio_decode_frame(AVCodecContext
*avctx
,
523 void *data
, int *data_size
,
526 const uint8_t *buf
= avpkt
->data
;
527 int buf_size
= avpkt
->size
;
528 VmdAudioContext
*s
= avctx
->priv_data
;
529 unsigned char *output_samples
= (unsigned char *)data
;
531 /* point to the start of the encoded data */
532 const unsigned char *p
= buf
+ 16;
538 /* the chunk contains audio */
539 *data_size
= vmdaudio_loadsound(s
, output_samples
, p
, 0, buf_size
- 16);
540 } else if (buf
[6] == 2) {
541 /* initial chunk, may contain audio and silence */
542 uint32_t flags
= AV_RB32(p
);
543 int raw_block_size
= s
->block_align
* s
->bits
/ 8;
545 if(flags
== 0xFFFFFFFF)
548 silent_chunks
= av_log2(flags
+ 1);
549 if(*data_size
< (s
->block_align
*silent_chunks
+ buf_size
- 20) * 2)
552 memset(output_samples
, 0, raw_block_size
* silent_chunks
);
553 output_samples
+= raw_block_size
* silent_chunks
;
554 *data_size
= raw_block_size
* silent_chunks
;
555 *data_size
+= vmdaudio_loadsound(s
, output_samples
, p
+ 4, 0, buf_size
- 20);
556 } else if (buf
[6] == 3) {
558 *data_size
= vmdaudio_loadsound(s
, output_samples
, p
, 1, 0);
566 * Public Data Structures
569 AVCodec vmdvideo_decoder
= {
573 sizeof(VmdVideoContext
),
574 vmdvideo_decode_init
,
577 vmdvideo_decode_frame
,
579 .long_name
= NULL_IF_CONFIG_SMALL("Sierra VMD video"),
582 AVCodec vmdaudio_decoder
= {
586 sizeof(VmdAudioContext
),
587 vmdaudio_decode_init
,
590 vmdaudio_decode_frame
,
591 .long_name
= NULL_IF_CONFIG_SMALL("Sierra VMD audio"),