minor VMD system update; still not perfect, but should not crash either
[ffmpeg.git] / libavcodec / vmdav.c
1 /*
2  * Sierra VMD Audio & Video Decoders
3  * Copyright (C) 2004 the ffmpeg project
4  *
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.
9  *
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.
14  *
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
18  *
19  */
20
21 /**
22  * @file vmdvideo.c
23  * Sierra VMD audio & video decoders
24  * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
25  * for more information on the Sierra VMD format, visit:
26  *   http://www.pcisys.net/~melanson/codecs/
27  *
28  * The video decoder outputs PAL8 colorspace data. The decoder expects
29  * a 0x330-byte VMD file header to be transmitted via extradata during
30  * codec initialization. Each encoded frame that is sent to this decoder
31  * is expected to be prepended with the appropriate 16-byte frame 
32  * information record from the VMD file.
33  *
34  * The audio decoder, like the video decoder, expects each encoded data
35  * chunk to be prepended with the appropriate 16-byte frame information
36  * record from the VMD file. It does not require the 0x330-byte VMD file
37  * header, but it does need the audio setup parameters passed in through
38  * normal libavcodec API means.
39  */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45
46 #include "common.h"
47 #include "avcodec.h"
48 #include "dsputil.h"
49
50 #define printf(...) {} //(f)printf() usage is forbidden in libavcodec, use av_log
51 #define fprintf(...) {} 
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     DSPContext dsp;
64     AVFrame frame;
65     AVFrame prev_frame;
66
67     unsigned char *buf;
68     int size;
69
70     unsigned char palette[PALETTE_COUNT * 4];
71     unsigned char *unpack_buffer;
72
73 } VmdVideoContext;
74
75 #define QUEUE_SIZE 0x1000
76 #define QUEUE_MASK 0x0FFF
77
78 static void lz_unpack(unsigned char *src, unsigned char *dest)
79 {
80     unsigned char *s;
81     unsigned char *d;
82     unsigned char queue[QUEUE_SIZE];
83     unsigned int qpos;
84     unsigned int dataleft;
85     unsigned int chainofs;
86     unsigned int chainlen;
87     unsigned int speclen;
88     unsigned char tag;
89     unsigned int i, j;
90
91     s = src;
92     d = dest;
93     dataleft = LE_32(s);
94     s += 4;
95     memset(queue, QUEUE_SIZE, 0x20);
96     if (LE_32(s) == 0x56781234) {
97         s += 4;
98         qpos = 0x111;
99         speclen = 0xF + 3;
100     } else {
101         qpos = 0xFEE;
102         speclen = 100;  /* no speclen */
103     }
104
105     while (dataleft > 0) {
106         tag = *s++;
107         if ((tag == 0xFF) && (dataleft > 8)) {
108             for (i = 0; i < 8; i++) {
109                 queue[qpos++] = *d++ = *s++;
110                 qpos &= QUEUE_MASK;
111             }
112             dataleft -= 8;
113         } else {
114             for (i = 0; i < 8; i++) {
115                 if (dataleft == 0)
116                     break;
117                 if (tag & 0x01) {
118                     queue[qpos++] = *d++ = *s++;
119                     qpos &= QUEUE_MASK;
120                     dataleft--;
121                 } else {
122                     chainofs = *s++;
123                     chainofs |= ((*s & 0xF0) << 4);
124                     chainlen = (*s++ & 0x0F) + 3;
125                     if (chainlen == speclen)
126                         chainlen = *s++ + 0xF + 3;
127                     for (j = 0; j < chainlen; j++) {
128                         *d = queue[chainofs++ & QUEUE_MASK];
129                         queue[qpos++] = *d++;
130                         qpos &= QUEUE_MASK;
131                     }
132                     dataleft -= chainlen;
133                 }
134                 tag >>= 1;
135             }
136         }
137     }
138 }
139
140 static int rle_unpack(unsigned char *src, unsigned char *dest, int len)
141 {
142     unsigned char *ps;
143     unsigned char *pd;
144     int i, l;
145
146     ps = src;
147     pd = dest;
148     if (len & 1)
149         *pd++ = *ps++;
150
151     len >>= 1;
152     i = 0;
153     do {
154         l = *ps++;
155         if (l & 0x80) {
156             l = (l & 0x7F) * 2;
157             memcpy(pd, ps, l);
158             ps += l;
159             pd += l;
160         } else {
161             for (i = 0; i < l; i++) {
162                 *pd++ = ps[0];
163                 *pd++ = ps[1];
164             }
165             ps += 2;
166         }
167         i += l;
168     } while (i < len);
169
170     return (ps - src);
171 }
172
173 static void vmd_decode(VmdVideoContext *s)
174 {
175     int i;
176     unsigned int *palette32;
177     unsigned char r, g, b;
178
179     /* point to the start of the encoded data */
180     unsigned char *p = s->buf + 16;
181
182     unsigned char *pb;
183     unsigned char meth;
184     unsigned char *dp;   /* pointer to current frame */
185     unsigned char *pp;   /* pointer to previous frame */
186     unsigned char len;
187     int ofs;
188
189     int frame_x, frame_y;
190     int frame_width, frame_height;
191
192     frame_x = LE_16(&s->buf[6]);
193     frame_y = LE_16(&s->buf[8]);
194     frame_width = LE_16(&s->buf[10]) - frame_x + 1;
195     frame_height = LE_16(&s->buf[12]) - frame_y + 1;
196
197     /* if only a certain region will be updated, copy the entire previous
198      * frame before the decode */
199     if (frame_x || frame_y || (frame_width != s->avctx->width) ||
200         (frame_height != s->avctx->height)) {
201
202         memcpy(s->frame.data[0], s->prev_frame.data[0], 
203             s->avctx->height * s->frame.linesize[0]);
204     }
205
206     /* check if there is a new palette */
207     if (s->buf[15] & 0x02) {
208         p += 2;
209         palette32 = (unsigned int *)s->palette;
210         for (i = 0; i < PALETTE_COUNT; i++) {
211             r = *p++ * 4;
212             g = *p++ * 4;
213             b = *p++ * 4;
214             palette32[i] = (r << 16) | (g << 8) | (b);
215         }
216         s->size -= (256 * 3 + 2);
217     }
218     if (s->size >= 0) {
219         /* originally UnpackFrame in VAG's code */
220         pb = p;
221         meth = *pb++;
222         if (meth & 0x80) {
223             lz_unpack(pb, s->unpack_buffer);
224             meth &= 0x7F;
225             pb = s->unpack_buffer;
226         }
227
228         dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
229         pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
230         switch (meth) {
231         case 1:
232             for (i = 0; i < frame_height; i++) {
233                 ofs = 0;
234                 do {
235                     len = *pb++;
236                     if (len & 0x80) {
237                         len = (len & 0x7F) + 1;
238                         memcpy(&dp[ofs], pb, len);
239                         pb += len;
240                         ofs += len;
241                     } else {
242                         /* interframe pixel copy */
243                         memcpy(&dp[ofs], &pp[ofs], len + 1);
244                         ofs += len + 1;
245                     }
246                 } while (ofs < frame_width);
247                 if (ofs > frame_width) {
248                     printf (" VMD video: offset > width (%d > %d)\n",
249                         ofs, frame_width);
250                     break;
251                 }
252                 dp += s->frame.linesize[0];
253                 pp += s->prev_frame.linesize[0];
254             }
255             break;
256
257         case 2:
258             for (i = 0; i < frame_height; i++) {
259                 memcpy(dp, pb, frame_width);
260                 pb += frame_width;
261                 dp += s->frame.linesize[0];
262                 pp += s->prev_frame.linesize[0];
263             }
264             break;
265
266         case 3:
267             for (i = 0; i < frame_height; i++) {
268                 ofs = 0;
269                 do {
270                     len = *pb++;
271                     if (len & 0x80) {
272                         len = (len & 0x7F) + 1;
273                         if (*pb++ == 0xFF)
274                             len = rle_unpack(pb, &dp[ofs], len);
275                         else
276                             memcpy(&dp[ofs], pb, len);
277                         pb += len;
278                         ofs += len;
279                     } else {
280                         /* interframe pixel copy */
281                         memcpy(&dp[ofs], &pp[ofs], len + 1);
282                         ofs += len + 1;
283                     }
284                 } while (ofs < frame_width);
285                 if (ofs > frame_width) {
286                     printf (" VMD video: offset > width (%d > %d)\n",
287                         ofs, frame_width);
288                 }
289                 dp += s->frame.linesize[0];
290                 pp += s->prev_frame.linesize[0];
291             }
292             break;
293         }
294     }
295 }
296
297 static int vmdvideo_decode_init(AVCodecContext *avctx)
298 {
299     VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
300     int i;
301     unsigned int *palette32;
302     int palette_index = 0;
303     unsigned char r, g, b;
304     unsigned char *vmd_header;
305     unsigned char *raw_palette;
306
307     s->avctx = avctx;
308     avctx->pix_fmt = PIX_FMT_PAL8;
309     avctx->has_b_frames = 0;
310     dsputil_init(&s->dsp, avctx);
311
312     /* make sure the VMD header made it */
313     if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
314         printf("  VMD video: expected extradata size of %d\n", 
315             VMD_HEADER_SIZE);
316         return -1;
317     }
318     vmd_header = (unsigned char *)avctx->extradata;
319
320     s->unpack_buffer = av_malloc(LE_32(&vmd_header[800]));
321     if (!s->unpack_buffer)
322         return -1;
323
324     /* load up the initial palette */
325     raw_palette = &vmd_header[28];
326     palette32 = (unsigned int *)s->palette;
327     for (i = 0; i < PALETTE_COUNT; i++) {
328         r = raw_palette[palette_index++] * 4;
329         g = raw_palette[palette_index++] * 4;
330         b = raw_palette[palette_index++] * 4;
331         palette32[i] = (r << 16) | (g << 8) | (b);
332     }
333
334     s->frame.data[0] = s->prev_frame.data[0] = NULL;
335
336     return 0;
337 }
338
339 static int vmdvideo_decode_frame(AVCodecContext *avctx,
340                                  void *data, int *data_size,
341                                  uint8_t *buf, int buf_size)
342 {
343     VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
344
345     s->buf = buf;
346     s->size = buf_size;
347
348     if (buf_size < 16)
349         return buf_size;
350
351     s->frame.reference = 1;
352     if (avctx->get_buffer(avctx, &s->frame)) {
353         printf ("  VMD Video: get_buffer() failed\n");
354         return -1;
355     }
356
357     vmd_decode(s);
358
359     /* make the palette available on the way out */
360     memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
361
362     if (s->prev_frame.data[0])
363         avctx->release_buffer(avctx, &s->prev_frame);
364
365     /* shuffle frames */
366     s->prev_frame = s->frame;
367
368     *data_size = sizeof(AVFrame);
369     *(AVFrame*)data = s->frame;
370
371     /* report that the buffer was completely consumed */
372     return buf_size;
373 }
374
375 static int vmdvideo_decode_end(AVCodecContext *avctx)
376 {
377     VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
378
379     if (s->prev_frame.data[0])
380         avctx->release_buffer(avctx, &s->prev_frame);
381     av_free(s->unpack_buffer);
382
383     return 0;
384 }
385
386
387 /*
388  * Audio Decoder
389  */
390
391 typedef struct VmdAudioContext {
392     int channels;
393     int bits;
394     int block_align;
395     unsigned char steps8[16];
396     unsigned short steps16[16];
397     unsigned short steps128[256];
398     short predictors[2];
399 } VmdAudioContext;
400
401 static int vmdaudio_decode_init(AVCodecContext *avctx)
402 {
403     VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
404     int i;
405
406     s->channels = avctx->channels;
407     s->bits = avctx->bits_per_sample;
408     s->block_align = avctx->block_align;
409
410 printf ("  %d channels, %d bits/sample, block align = %d, sample rate = %d\n",
411   s->channels, s->bits, s->block_align, avctx->sample_rate);
412
413     /* set up the steps8 and steps16 tables */
414     for (i = 0; i < 8; i++) {
415         if (i < 4)
416             s->steps8[i] = i;
417         else
418             s->steps8[i] = s->steps8[i - 1] + i - 1;
419
420         if (i == 0)
421             s->steps16[i] = 0;
422         else if (i == 1)
423             s->steps16[i] = 4;
424         else if (i == 2)
425             s->steps16[i] = 16;
426         else
427             s->steps16[i] = 1 << (i + 4);
428     }
429
430     /* set up the step128 table */
431     s->steps128[0] = 0;
432     s->steps128[1] = 8;
433     for (i = 0x02; i <= 0x20; i++)
434         s->steps128[i] = (i - 1) << 4;
435     for (i = 0x21; i <= 0x60; i++)
436         s->steps128[i] = (i + 0x1F) << 3;
437     for (i = 0x61; i <= 0x70; i++)
438         s->steps128[i] = (i - 0x51) << 6;
439     for (i = 0x71; i <= 0x78; i++)
440         s->steps128[i] = (i - 0x69) << 8;
441     for (i = 0x79; i <= 0x7D; i++)
442         s->steps128[i] = (i - 0x75) << 10;
443     s->steps128[0x7E] = 0x3000;
444     s->steps128[0x7F] = 0x4000;
445
446     /* set up the negative half of each table */
447     for (i = 0; i < 8; i++) {
448         s->steps8[i + 8] = -s->steps8[i];
449         s->steps16[i + 8] = -s->steps16[i];
450     }
451     for (i = 0; i < 128; i++)
452       s->steps128[i + 128] = -s->steps128[i];
453
454     return 0;
455 }
456
457 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
458     uint8_t *buf, int ratio) {
459
460 }
461
462 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
463     uint8_t *buf, int silence)
464 {
465     int bytes_decoded = 0;
466     int i;
467
468 if (silence)
469   printf (" silent block!\n");
470     if (s->channels == 2) {
471
472         /* stereo handling */
473         if ((s->block_align & 0x01) == 0) {
474             if (silence)
475                 memset(data, 0, s->block_align * 2);
476             else
477                 vmdaudio_decode_audio(s, data, buf, 1);
478         } else {
479             if (silence)
480                 memset(data, 0, s->block_align * 2);
481             else
482                 vmdaudio_decode_audio(s, data, buf, 1);
483         }
484     } else {
485
486         /* mono handling */
487         if (silence) {
488             if (s->bits == 16) {
489                 memset(data, 0, s->block_align * 2);
490                 bytes_decoded = s->block_align * 2;
491             } else {
492 //                memset(data, 0x00, s->block_align);
493 //                bytes_decoded = s->block_align;
494 memset(data, 0x00, s->block_align * 2);
495 bytes_decoded = s->block_align * 2;
496             }
497         } else {
498             if (s->bits == 16) {
499             } else {
500                 /* copy the data but convert it to signed */
501                 for (i = 0; i < s->block_align; i++)
502                     data[i * 2 + 1] = buf[i] + 0x80;
503                 bytes_decoded = s->block_align * 2;
504             }
505         }
506     }
507
508     return bytes_decoded;
509 }
510
511 static int vmdaudio_decode_frame(AVCodecContext *avctx,
512                                  void *data, int *data_size,
513                                  uint8_t *buf, int buf_size)
514 {
515     VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
516     unsigned int sound_flags;
517     unsigned char *output_samples = (unsigned char *)data;
518
519     /* point to the start of the encoded data */
520     unsigned char *p = buf + 16;
521     unsigned char *p_end = buf + buf_size;
522
523 printf ("    processing audio frame with %d bytes\n", buf_size);
524     if (buf_size < 16)
525         return buf_size;
526
527     *data_size = 0;
528     if (buf[6] == 1) {
529         /* the chunk contains audio */
530         *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
531     } else if (buf[6] == 2) {
532 printf ("  hey! audio case #2\n");
533         /* the chunk contains audio and silence mixed together */
534         sound_flags = LE_32(p);
535         p += 4;
536
537         /* do something with extrabufs here? */
538
539         while (p < p_end) {
540             if (sound_flags & 0x01)
541                 /* silence */
542                 *data_size += vmdaudio_loadsound(s, output_samples, p, 1);
543             else {
544                 /* audio */
545                 *data_size += vmdaudio_loadsound(s, output_samples, p, 0);
546                 p += s->block_align;
547             }
548             output_samples += (s->block_align * s->bits / 8);
549             sound_flags >>= 1;
550         }
551     } else if (buf[6] == 3) {
552 printf ("  hey! audio case #3\n");
553         /* silent chunk */
554         *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
555     }
556
557 printf ("      final sample count = %d, byte count = %d\n", (*data_size) / 2,
558   *data_size);
559     return buf_size;
560 }
561
562
563 /*
564  * Public Data Structures
565  */
566
567 AVCodec vmdvideo_decoder = {
568     "vmdvideo",
569     CODEC_TYPE_VIDEO,
570     CODEC_ID_VMDVIDEO,
571     sizeof(VmdVideoContext),
572     vmdvideo_decode_init,
573     NULL,
574     vmdvideo_decode_end,
575     vmdvideo_decode_frame,
576     CODEC_CAP_DR1,
577 };
578
579 AVCodec vmdaudio_decoder = {
580     "vmdaudio",
581     CODEC_TYPE_AUDIO,
582     CODEC_ID_VMDAUDIO,
583     sizeof(VmdAudioContext),
584     vmdaudio_decode_init,
585     NULL,
586     NULL,
587     vmdaudio_decode_frame,
588 };