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