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