2 * Sierra VMD Audio & Video Decoders
3 * Copyright (C) 2004 the ffmpeg project
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Sierra VMD audio & video decoders
24 * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
26 * The video decoder outputs PAL8 colorspace data. The decoder expects
27 * a 0x330-byte VMD file header to be transmitted via extradata during
28 * codec initialization. Each encoded frame that is sent to this decoder
29 * is expected to be prepended with the appropriate 16-byte frame
30 * information record from the VMD file.
32 * The audio decoder, like the video decoder, expects each encoded data
33 * chunk to be prepended with the approriate 16-byte frame information
34 * record from the VMD file. It does not require the 0x330-byte VMD file
35 * header, but it does need the audio setup parameters passed in through
36 * normal libavcodec API means.
48 #define VMD_HEADER_SIZE 0x330
49 #define PALETTE_COUNT 256
51 #define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
52 #define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \
53 (((uint8_t*)(x))[2] << 16) | \
54 (((uint8_t*)(x))[1] << 8) | \
61 typedef struct VmdVideoContext {
63 AVCodecContext *avctx;
71 unsigned char palette[PALETTE_COUNT * 4];
72 unsigned char *unpack_buffer;
76 #define QUEUE_SIZE 0x1000
77 #define QUEUE_MASK 0x0FFF
79 static void lz_unpack(unsigned char *src, unsigned char *dest)
83 unsigned char queue[QUEUE_SIZE];
85 unsigned int dataleft;
86 unsigned int chainofs;
87 unsigned int chainlen;
96 memset(queue, QUEUE_SIZE, 0x20);
97 if (LE_32(s) == 0x56781234) {
103 speclen = 100; /* no speclen */
106 while (dataleft > 0) {
108 if ((tag == 0xFF) && (dataleft > 8)) {
109 for (i = 0; i < 8; i++) {
110 queue[qpos++] = *d++ = *s++;
115 for (i = 0; i < 8; i++) {
119 queue[qpos++] = *d++ = *s++;
124 chainofs |= ((*s & 0xF0) << 4);
125 chainlen = (*s++ & 0x0F) + 3;
126 if (chainlen == speclen)
127 chainlen = *s++ + 0xF + 3;
128 for (j = 0; j < chainlen; j++) {
129 *d = queue[chainofs++ & QUEUE_MASK];
130 queue[qpos++] = *d++;
133 dataleft -= chainlen;
141 static int rle_unpack(unsigned char *src, unsigned char *dest, int len)
162 for (i = 0; i < l; i++) {
174 static void vmd_decode(VmdVideoContext *s)
177 unsigned int *palette32;
178 unsigned char r, g, b;
180 /* point to the start of the encoded data */
181 unsigned char *p = s->buf + 16;
185 unsigned char *dp; /* pointer to current frame */
186 unsigned char *pp; /* pointer to previous frame */
190 int frame_x, frame_y;
191 int frame_width, frame_height;
193 frame_x = LE_16(&s->buf[6]);
194 frame_y = LE_16(&s->buf[8]);
195 frame_width = LE_16(&s->buf[10]) - frame_x + 1;
196 frame_height = LE_16(&s->buf[12]) - frame_y + 1;
198 /* if only a certain region will be updated, copy the entire previous
199 * frame before the decode */
200 if (frame_x || frame_y || (frame_width != s->avctx->width) ||
201 (frame_height != s->avctx->height)) {
203 memcpy(s->frame.data[0], s->prev_frame.data[0],
204 s->avctx->height * s->frame.linesize[0]);
207 /* check if there is a new palette */
208 if (s->buf[15] & 0x02) {
210 palette32 = (unsigned int *)s->palette;
211 for (i = 0; i < PALETTE_COUNT; i++) {
215 palette32[i] = (r << 16) | (g << 8) | (b);
217 s->size -= (256 * 3 + 2);
220 /* originally UnpackFrame in VAG's code */
224 lz_unpack(pb, s->unpack_buffer);
226 pb = s->unpack_buffer;
229 dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
230 pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
233 for (i = 0; i < frame_height; i++) {
238 len = (len & 0x7F) + 1;
239 memcpy(&dp[ofs], pb, len);
243 /* interframe pixel copy */
244 memcpy(&dp[ofs], &pp[ofs], len + 1);
247 } while (ofs < frame_width);
248 if (ofs > frame_width) {
249 printf (" VMD video: offset > width (%d > %d)\n",
253 dp += s->frame.linesize[0];
254 pp += s->prev_frame.linesize[0];
259 for (i = 0; i < frame_height; i++) {
260 memcpy(dp, pb, frame_width);
262 dp += s->frame.linesize[0];
263 pp += s->prev_frame.linesize[0];
268 for (i = 0; i < frame_height; i++) {
273 len = (len & 0x7F) + 1;
275 len = rle_unpack(pb, dp, len);
277 memcpy(&dp[ofs], pb, len);
281 /* interframe pixel copy */
282 memcpy(&dp[ofs], &pp[ofs], len + 1);
285 } while (ofs < frame_width);
286 if (ofs > frame_width) {
287 printf (" VMD video: offset > width (%d > %d)\n",
290 dp += s->frame.linesize[0];
291 pp += s->prev_frame.linesize[0];
298 static int vmdvideo_decode_init(AVCodecContext *avctx)
300 VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
302 unsigned int *palette32;
303 int palette_index = 0;
304 unsigned char r, g, b;
305 unsigned char *vmd_header;
306 unsigned char *raw_palette;
309 avctx->pix_fmt = PIX_FMT_PAL8;
310 avctx->has_b_frames = 0;
311 dsputil_init(&s->dsp, avctx);
313 /* make sure the VMD header made it */
314 if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
315 printf(" VMD video: expected extradata size of %d\n",
319 vmd_header = (unsigned char *)avctx->extradata;
321 s->unpack_buffer = av_malloc(LE_32(&vmd_header[800]));
322 if (!s->unpack_buffer)
325 /* load up the initial palette */
326 raw_palette = &vmd_header[28];
327 palette32 = (unsigned int *)s->palette;
328 for (i = 0; i < PALETTE_COUNT; i++) {
329 r = raw_palette[palette_index++] * 4;
330 g = raw_palette[palette_index++] * 4;
331 b = raw_palette[palette_index++] * 4;
332 palette32[i] = (r << 16) | (g << 8) | (b);
335 s->frame.data[0] = s->prev_frame.data[0] = NULL;
340 static int vmdvideo_decode_frame(AVCodecContext *avctx,
341 void *data, int *data_size,
342 uint8_t *buf, int buf_size)
344 VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
349 s->frame.reference = 1;
350 if (avctx->get_buffer(avctx, &s->frame)) {
351 printf (" VMD Video: get_buffer() failed\n");
357 /* make the palette available on the way out */
358 memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
360 if (s->prev_frame.data[0])
361 avctx->release_buffer(avctx, &s->prev_frame);
364 s->prev_frame = s->frame;
366 *data_size = sizeof(AVFrame);
367 *(AVFrame*)data = s->frame;
369 /* report that the buffer was completely consumed */
373 static int vmdvideo_decode_end(AVCodecContext *avctx)
375 VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
377 if (s->prev_frame.data[0])
378 avctx->release_buffer(avctx, &s->prev_frame);
379 av_free(s->unpack_buffer);
389 typedef struct VmdAudioContext {
393 unsigned char steps8[16];
394 unsigned short steps16[16];
395 unsigned short steps128[256];
399 static int vmdaudio_decode_init(AVCodecContext *avctx)
401 VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
404 s->channels = avctx->channels;
405 s->bits = avctx->bits_per_sample;
406 s->block_align = avctx->block_align;
408 printf (" %d channels, %d bits/sample, block align = %d\n",
409 s->channels, s->bits, s->block_align);
411 /* set up the steps8 and steps16 tables */
412 for (i = 0; i < 8; i++) {
416 s->steps8[i] = s->steps8[i - 1] + i - 1;
425 s->steps16[i] = 1 << (i + 4);
428 /* set up the step128 table */
431 for (i = 0x02; i <= 0x20; i++)
432 s->steps128[i] = (i - 1) << 4;
433 for (i = 0x21; i <= 0x60; i++)
434 s->steps128[i] = (i + 0x1F) << 3;
435 for (i = 0x61; i <= 0x70; i++)
436 s->steps128[i] = (i - 0x51) << 6;
437 for (i = 0x71; i <= 0x78; i++)
438 s->steps128[i] = (i - 0x69) << 8;
439 for (i = 0x79; i <= 0x7D; i++)
440 s->steps128[i] = (i - 0x75) << 10;
441 s->steps128[0x7E] = 0x3000;
442 s->steps128[0x7F] = 0x4000;
444 /* set up the negative half of each table */
445 for (i = 0; i < 8; i++) {
446 s->steps8[i + 8] = -s->steps8[i];
447 s->steps16[i + 8] = -s->steps16[i];
449 for (i = 0; i < 128; i++)
450 s->steps128[i + 128] = -s->steps128[i];
455 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
456 uint8_t *buf, int ratio) {
460 static void vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
461 uint8_t *buf, int silence)
463 if (s->channels == 2) {
464 if ((s->block_align & 0x01) == 0) {
466 memset(data, 0, s->block_align * 2);
468 vmdaudio_decode_audio(s, data, buf, 1);
471 memset(data, 0, s->block_align * 2);
473 // vmdaudio_decode_audio(s, data, buf, 1);
479 static int vmdaudio_decode_frame(AVCodecContext *avctx,
480 void *data, int *data_size,
481 uint8_t *buf, int buf_size)
483 VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
484 unsigned int sound_flags;
485 unsigned char *output_samples = (unsigned char *)data;
487 /* point to the start of the encoded data */
488 unsigned char *p = buf + 16;
489 unsigned char *p_end = buf + buf_size;
492 /* the chunk contains audio */
493 vmdaudio_loadsound(s, output_samples, p, 0);
494 } else if (buf[6] == 2) {
495 /* the chunk contains audio and silence mixed together */
496 sound_flags = LE_32(p);
499 /* do something with extrabufs here? */
502 if (sound_flags & 0x01)
504 vmdaudio_loadsound(s, output_samples, p, 1);
507 vmdaudio_loadsound(s, output_samples, p, 0);
509 output_samples += (s->block_align * s->bits / 8);
512 } else if (buf[6] == 3) {
514 vmdaudio_loadsound(s, output_samples, p, 1);
524 * Public Data Structures
527 AVCodec vmdvideo_decoder = {
531 sizeof(VmdVideoContext),
532 vmdvideo_decode_init,
535 vmdvideo_decode_frame,
539 AVCodec vmdaudio_decoder = {
543 sizeof(VmdAudioContext),
544 vmdaudio_decode_init,
547 vmdaudio_decode_frame,