OSDN Git Service

072a5a502b3814215c3835f704f6a45649c6603a
[coroid/libav_saccubus.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 VMD_HEADER_SIZE 0x330
51 #define PALETTE_COUNT 256
52
53 /*
54  * Video Decoder
55  */
56
57 typedef struct VmdVideoContext {
58
59     AVCodecContext *avctx;
60     DSPContext dsp;
61     AVFrame frame;
62     AVFrame prev_frame;
63
64     unsigned char *buf;
65     int size;
66
67     unsigned char palette[PALETTE_COUNT * 4];
68     unsigned char *unpack_buffer;
69     int unpack_buffer_size;
70
71 } VmdVideoContext;
72
73 #define QUEUE_SIZE 0x1000
74 #define QUEUE_MASK 0x0FFF
75
76 static void lz_unpack(unsigned char *src, unsigned char *dest, int dest_len)
77 {
78     unsigned char *s;
79     unsigned char *d;
80     unsigned char *d_end;
81     unsigned char queue[QUEUE_SIZE];
82     unsigned int qpos;
83     unsigned int dataleft;
84     unsigned int chainofs;
85     unsigned int chainlen;
86     unsigned int speclen;
87     unsigned char tag;
88     unsigned int i, j;
89
90     s = src;
91     d = dest;
92     d_end = d + dest_len;
93     dataleft = LE_32(s);
94     s += 4;
95     memset(queue, 0x20, QUEUE_SIZE);
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             if (d + 8 > d_end)
109                 return;
110             for (i = 0; i < 8; i++) {
111                 queue[qpos++] = *d++ = *s++;
112                 qpos &= QUEUE_MASK;
113             }
114             dataleft -= 8;
115         } else {
116             for (i = 0; i < 8; i++) {
117                 if (dataleft == 0)
118                     break;
119                 if (tag & 0x01) {
120                     if (d + 1 > d_end)
121                         return;
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                     if (d + chainlen > d_end)
132                         return;
133                     for (j = 0; j < chainlen; j++) {
134                         *d = queue[chainofs++ & QUEUE_MASK];
135                         queue[qpos++] = *d++;
136                         qpos &= QUEUE_MASK;
137                     }
138                     dataleft -= chainlen;
139                 }
140                 tag >>= 1;
141             }
142         }
143     }
144 }
145
146 static int rle_unpack(unsigned char *src, unsigned char *dest,
147     int src_len, int dest_len)
148 {
149     unsigned char *ps;
150     unsigned char *pd;
151     int i, l;
152     unsigned char *dest_end = dest + dest_len;
153
154     ps = src;
155     pd = dest;
156     if (src_len & 1)
157         *pd++ = *ps++;
158
159     src_len >>= 1;
160     i = 0;
161     do {
162         l = *ps++;
163         if (l & 0x80) {
164             l = (l & 0x7F) * 2;
165             if (pd + l > dest_end)
166                 return (ps - src);
167             memcpy(pd, ps, l);
168             ps += l;
169             pd += l;
170         } else {
171             if (pd + i > dest_end)
172                 return (ps - src);
173             for (i = 0; i < l; i++) {
174                 *pd++ = ps[0];
175                 *pd++ = ps[1];
176             }
177             ps += 2;
178         }
179         i += l;
180     } while (i < src_len);
181
182     return (ps - src);
183 }
184
185 static void vmd_decode(VmdVideoContext *s)
186 {
187     int i;
188     unsigned int *palette32;
189     unsigned char r, g, b;
190
191     /* point to the start of the encoded data */
192     unsigned char *p = s->buf + 16;
193
194     unsigned char *pb;
195     unsigned char meth;
196     unsigned char *dp;   /* pointer to current frame */
197     unsigned char *pp;   /* pointer to previous frame */
198     unsigned char len;
199     int ofs;
200
201     int frame_x, frame_y;
202     int frame_width, frame_height;
203     int dp_size;
204
205     frame_x = LE_16(&s->buf[6]);
206     frame_y = LE_16(&s->buf[8]);
207     frame_width = LE_16(&s->buf[10]) - frame_x + 1;
208     frame_height = LE_16(&s->buf[12]) - frame_y + 1;
209
210     /* if only a certain region will be updated, copy the entire previous
211      * frame before the decode */
212     if (frame_x || frame_y || (frame_width != s->avctx->width) ||
213         (frame_height != s->avctx->height)) {
214
215         memcpy(s->frame.data[0], s->prev_frame.data[0],
216             s->avctx->height * s->frame.linesize[0]);
217     }
218
219     /* check if there is a new palette */
220     if (s->buf[15] & 0x02) {
221         p += 2;
222         palette32 = (unsigned int *)s->palette;
223         for (i = 0; i < PALETTE_COUNT; i++) {
224             r = *p++ * 4;
225             g = *p++ * 4;
226             b = *p++ * 4;
227             palette32[i] = (r << 16) | (g << 8) | (b);
228         }
229         s->size -= (256 * 3 + 2);
230     }
231     if (s->size >= 0) {
232         /* originally UnpackFrame in VAG's code */
233         pb = p;
234         meth = *pb++;
235         if (meth & 0x80) {
236             lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
237             meth &= 0x7F;
238             pb = s->unpack_buffer;
239         }
240
241         dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
242         dp_size = s->frame.linesize[0] * s->avctx->height;
243         pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
244         switch (meth) {
245         case 1:
246             for (i = 0; i < frame_height; i++) {
247                 ofs = 0;
248                 do {
249                     len = *pb++;
250                     if (len & 0x80) {
251                         len = (len & 0x7F) + 1;
252                         if (ofs + len > frame_width)
253                             return;
254                         memcpy(&dp[ofs], pb, len);
255                         pb += len;
256                         ofs += len;
257                     } else {
258                         /* interframe pixel copy */
259                         if (ofs + len + 1 > frame_width)
260                             return;
261                         memcpy(&dp[ofs], &pp[ofs], len + 1);
262                         ofs += len + 1;
263                     }
264                 } while (ofs < frame_width);
265                 if (ofs > frame_width) {
266                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
267                         ofs, frame_width);
268                     break;
269                 }
270                 dp += s->frame.linesize[0];
271                 pp += s->prev_frame.linesize[0];
272             }
273             break;
274
275         case 2:
276             for (i = 0; i < frame_height; i++) {
277                 memcpy(dp, pb, frame_width);
278                 pb += frame_width;
279                 dp += s->frame.linesize[0];
280                 pp += s->prev_frame.linesize[0];
281             }
282             break;
283
284         case 3:
285             for (i = 0; i < frame_height; i++) {
286                 ofs = 0;
287                 do {
288                     len = *pb++;
289                     if (len & 0x80) {
290                         len = (len & 0x7F) + 1;
291                         if (*pb++ == 0xFF)
292                             len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
293                         else
294                             memcpy(&dp[ofs], pb, len);
295                         pb += len;
296                         ofs += len;
297                     } else {
298                         /* interframe pixel copy */
299                         if (ofs + len + 1 > frame_width)
300                             return;
301                         memcpy(&dp[ofs], &pp[ofs], len + 1);
302                         ofs += len + 1;
303                     }
304                 } while (ofs < frame_width);
305                 if (ofs > frame_width) {
306                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
307                         ofs, frame_width);
308                 }
309                 dp += s->frame.linesize[0];
310                 pp += s->prev_frame.linesize[0];
311             }
312             break;
313         }
314     }
315 }
316
317 static int vmdvideo_decode_init(AVCodecContext *avctx)
318 {
319     VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
320     int i;
321     unsigned int *palette32;
322     int palette_index = 0;
323     unsigned char r, g, b;
324     unsigned char *vmd_header;
325     unsigned char *raw_palette;
326
327     s->avctx = avctx;
328     avctx->pix_fmt = PIX_FMT_PAL8;
329     avctx->has_b_frames = 0;
330     dsputil_init(&s->dsp, avctx);
331
332     /* make sure the VMD header made it */
333     if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
334         av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
335             VMD_HEADER_SIZE);
336         return -1;
337     }
338     vmd_header = (unsigned char *)avctx->extradata;
339
340     s->unpack_buffer_size = LE_32(&vmd_header[800]);
341     s->unpack_buffer = av_malloc(s->unpack_buffer_size);
342     if (!s->unpack_buffer)
343         return -1;
344
345     /* load up the initial palette */
346     raw_palette = &vmd_header[28];
347     palette32 = (unsigned int *)s->palette;
348     for (i = 0; i < PALETTE_COUNT; i++) {
349         r = raw_palette[palette_index++] * 4;
350         g = raw_palette[palette_index++] * 4;
351         b = raw_palette[palette_index++] * 4;
352         palette32[i] = (r << 16) | (g << 8) | (b);
353     }
354
355     s->frame.data[0] = s->prev_frame.data[0] = NULL;
356
357     return 0;
358 }
359
360 static int vmdvideo_decode_frame(AVCodecContext *avctx,
361                                  void *data, int *data_size,
362                                  uint8_t *buf, int buf_size)
363 {
364     VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
365
366     s->buf = buf;
367     s->size = buf_size;
368
369     if (buf_size < 16)
370         return buf_size;
371
372     s->frame.reference = 1;
373     if (avctx->get_buffer(avctx, &s->frame)) {
374         av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
375         return -1;
376     }
377
378     vmd_decode(s);
379
380     /* make the palette available on the way out */
381     memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
382
383     if (s->prev_frame.data[0])
384         avctx->release_buffer(avctx, &s->prev_frame);
385
386     /* shuffle frames */
387     s->prev_frame = s->frame;
388
389     *data_size = sizeof(AVFrame);
390     *(AVFrame*)data = s->frame;
391
392     /* report that the buffer was completely consumed */
393     return buf_size;
394 }
395
396 static int vmdvideo_decode_end(AVCodecContext *avctx)
397 {
398     VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
399
400     if (s->prev_frame.data[0])
401         avctx->release_buffer(avctx, &s->prev_frame);
402     av_free(s->unpack_buffer);
403
404     return 0;
405 }
406
407
408 /*
409  * Audio Decoder
410  */
411
412 typedef struct VmdAudioContext {
413     AVCodecContext *avctx;
414     int channels;
415     int bits;
416     int block_align;
417     int predictors[2];
418 } VmdAudioContext;
419
420 static uint16_t vmdaudio_table[128] = {
421     0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
422     0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
423     0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
424     0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
425     0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
426     0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
427     0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
428     0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
429     0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
430     0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
431     0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
432     0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
433     0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
434 };
435
436 static int vmdaudio_decode_init(AVCodecContext *avctx)
437 {
438     VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
439
440     s->avctx = avctx;
441     s->channels = avctx->channels;
442     s->bits = avctx->bits_per_sample;
443     s->block_align = avctx->block_align;
444
445     av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
446             s->channels, s->bits, s->block_align, avctx->sample_rate);
447
448     return 0;
449 }
450
451 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
452     uint8_t *buf, int stereo)
453 {
454     int i;
455     int chan = 0;
456     int16_t *out = (int16_t*)data;
457
458     for(i = 0; i < s->block_align; i++) {
459         if(buf[i] & 0x80)
460             s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
461         else
462             s->predictors[chan] += vmdaudio_table[buf[i]];
463         s->predictors[chan] = clip(s->predictors[chan], -32768, 32767);
464         out[i] = s->predictors[chan];
465         chan ^= stereo;
466     }
467 }
468
469 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
470     uint8_t *buf, int silence)
471 {
472     int bytes_decoded = 0;
473     int i;
474
475 //    if (silence)
476 //        av_log(s->avctx, AV_LOG_INFO, "silent block!\n");
477     if (s->channels == 2) {
478
479         /* stereo handling */
480         if (silence) {
481             memset(data, 0, s->block_align * 2);
482         } else {
483             if (s->bits == 16)
484                 vmdaudio_decode_audio(s, data, buf, 1);
485             else
486                 /* copy the data but convert it to signed */
487                 for (i = 0; i < s->block_align; i++)
488                     data[i * 2 + 1] = buf[i] + 0x80;
489         }
490     } else {
491         bytes_decoded = s->block_align * 2;
492
493         /* mono handling */
494         if (silence) {
495             memset(data, 0, s->block_align * 2);
496         } else {
497             if (s->bits == 16) {
498                 vmdaudio_decode_audio(s, data, buf, 0);
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             }
504         }
505     }
506
507     return s->block_align * 2;
508 }
509
510 static int vmdaudio_decode_frame(AVCodecContext *avctx,
511                                  void *data, int *data_size,
512                                  uint8_t *buf, int buf_size)
513 {
514     VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
515     unsigned int sound_flags;
516     unsigned char *output_samples = (unsigned char *)data;
517
518     /* point to the start of the encoded data */
519     unsigned char *p = buf + 16;
520     unsigned char *p_end = buf + buf_size;
521
522     if (buf_size < 16)
523         return buf_size;
524
525     if (buf[6] == 1) {
526         /* the chunk contains audio */
527         *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
528     } else if (buf[6] == 2) {
529         /* the chunk contains audio and silence mixed together */
530         sound_flags = LE_32(p);
531         p += 4;
532
533         /* do something with extrabufs here? */
534
535         while (p < p_end) {
536             if (sound_flags & 0x01)
537                 /* silence */
538                 *data_size += vmdaudio_loadsound(s, output_samples, p, 1);
539             else {
540                 /* audio */
541                 *data_size += vmdaudio_loadsound(s, output_samples, p, 0);
542                 p += s->block_align;
543             }
544             output_samples += (s->block_align * s->bits / 8);
545             sound_flags >>= 1;
546         }
547     } else if (buf[6] == 3) {
548         /* silent chunk */
549         *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
550     }
551
552     return buf_size;
553 }
554
555
556 /*
557  * Public Data Structures
558  */
559
560 AVCodec vmdvideo_decoder = {
561     "vmdvideo",
562     CODEC_TYPE_VIDEO,
563     CODEC_ID_VMDVIDEO,
564     sizeof(VmdVideoContext),
565     vmdvideo_decode_init,
566     NULL,
567     vmdvideo_decode_end,
568     vmdvideo_decode_frame,
569     CODEC_CAP_DR1,
570 };
571
572 AVCodec vmdaudio_decoder = {
573     "vmdaudio",
574     CODEC_TYPE_AUDIO,
575     CODEC_ID_VMDAUDIO,
576     sizeof(VmdAudioContext),
577     vmdaudio_decode_init,
578     NULL,
579     NULL,
580     vmdaudio_decode_frame,
581 };