]> git.sesse.net Git - ffmpeg/blob - libavcodec/vmdav.c
Change some leftover __attribute__((unused)) and __attribute__((used)) to
[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 "avcodec.h"
49 #include "dsputil.h"
50
51 #define VMD_HEADER_SIZE 0x330
52 #define PALETTE_COUNT 256
53
54 /*
55  * Video Decoder
56  */
57
58 typedef struct VmdVideoContext {
59
60     AVCodecContext *avctx;
61     DSPContext dsp;
62     AVFrame frame;
63     AVFrame prev_frame;
64
65     unsigned char *buf;
66     int size;
67
68     unsigned char palette[PALETTE_COUNT * 4];
69     unsigned char *unpack_buffer;
70     int unpack_buffer_size;
71
72 } VmdVideoContext;
73
74 #define QUEUE_SIZE 0x1000
75 #define QUEUE_MASK 0x0FFF
76
77 static void lz_unpack(unsigned char *src, unsigned char *dest, int dest_len)
78 {
79     unsigned char *s;
80     unsigned char *d;
81     unsigned char *d_end;
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     d_end = d + dest_len;
94     dataleft = AV_RL32(s);
95     s += 4;
96     memset(queue, 0x20, QUEUE_SIZE);
97     if (AV_RL32(s) == 0x56781234) {
98         s += 4;
99         qpos = 0x111;
100         speclen = 0xF + 3;
101     } else {
102         qpos = 0xFEE;
103         speclen = 100;  /* no speclen */
104     }
105
106     while (dataleft > 0) {
107         tag = *s++;
108         if ((tag == 0xFF) && (dataleft > 8)) {
109             if (d + 8 > d_end)
110                 return;
111             for (i = 0; i < 8; i++) {
112                 queue[qpos++] = *d++ = *s++;
113                 qpos &= QUEUE_MASK;
114             }
115             dataleft -= 8;
116         } else {
117             for (i = 0; i < 8; i++) {
118                 if (dataleft == 0)
119                     break;
120                 if (tag & 0x01) {
121                     if (d + 1 > d_end)
122                         return;
123                     queue[qpos++] = *d++ = *s++;
124                     qpos &= QUEUE_MASK;
125                     dataleft--;
126                 } else {
127                     chainofs = *s++;
128                     chainofs |= ((*s & 0xF0) << 4);
129                     chainlen = (*s++ & 0x0F) + 3;
130                     if (chainlen == speclen)
131                         chainlen = *s++ + 0xF + 3;
132                     if (d + chainlen > d_end)
133                         return;
134                     for (j = 0; j < chainlen; j++) {
135                         *d = queue[chainofs++ & QUEUE_MASK];
136                         queue[qpos++] = *d++;
137                         qpos &= QUEUE_MASK;
138                     }
139                     dataleft -= chainlen;
140                 }
141                 tag >>= 1;
142             }
143         }
144     }
145 }
146
147 static int rle_unpack(unsigned char *src, unsigned char *dest,
148     int src_len, int dest_len)
149 {
150     unsigned char *ps;
151     unsigned char *pd;
152     int i, l;
153     unsigned char *dest_end = dest + dest_len;
154
155     ps = src;
156     pd = dest;
157     if (src_len & 1)
158         *pd++ = *ps++;
159
160     src_len >>= 1;
161     i = 0;
162     do {
163         l = *ps++;
164         if (l & 0x80) {
165             l = (l & 0x7F) * 2;
166             if (pd + l > dest_end)
167                 return (ps - src);
168             memcpy(pd, ps, l);
169             ps += l;
170             pd += l;
171         } else {
172             if (pd + i > dest_end)
173                 return (ps - src);
174             for (i = 0; i < l; i++) {
175                 *pd++ = ps[0];
176                 *pd++ = ps[1];
177             }
178             ps += 2;
179         }
180         i += l;
181     } while (i < src_len);
182
183     return (ps - src);
184 }
185
186 static void vmd_decode(VmdVideoContext *s)
187 {
188     int i;
189     unsigned int *palette32;
190     unsigned char r, g, b;
191
192     /* point to the start of the encoded data */
193     unsigned char *p = s->buf + 16;
194
195     unsigned char *pb;
196     unsigned char meth;
197     unsigned char *dp;   /* pointer to current frame */
198     unsigned char *pp;   /* pointer to previous frame */
199     unsigned char len;
200     int ofs;
201
202     int frame_x, frame_y;
203     int frame_width, frame_height;
204     int dp_size;
205
206     frame_x = AV_RL16(&s->buf[6]);
207     frame_y = AV_RL16(&s->buf[8]);
208     frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
209     frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
210
211     /* if only a certain region will be updated, copy the entire previous
212      * frame before the decode */
213     if (frame_x || frame_y || (frame_width != s->avctx->width) ||
214         (frame_height != s->avctx->height)) {
215
216         memcpy(s->frame.data[0], s->prev_frame.data[0],
217             s->avctx->height * s->frame.linesize[0]);
218     }
219
220     /* check if there is a new palette */
221     if (s->buf[15] & 0x02) {
222         p += 2;
223         palette32 = (unsigned int *)s->palette;
224         for (i = 0; i < PALETTE_COUNT; i++) {
225             r = *p++ * 4;
226             g = *p++ * 4;
227             b = *p++ * 4;
228             palette32[i] = (r << 16) | (g << 8) | (b);
229         }
230         s->size -= (256 * 3 + 2);
231     }
232     if (s->size >= 0) {
233         /* originally UnpackFrame in VAG's code */
234         pb = p;
235         meth = *pb++;
236         if (meth & 0x80) {
237             lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
238             meth &= 0x7F;
239             pb = s->unpack_buffer;
240         }
241
242         dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
243         dp_size = s->frame.linesize[0] * s->avctx->height;
244         pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
245         switch (meth) {
246         case 1:
247             for (i = 0; i < frame_height; i++) {
248                 ofs = 0;
249                 do {
250                     len = *pb++;
251                     if (len & 0x80) {
252                         len = (len & 0x7F) + 1;
253                         if (ofs + len > frame_width)
254                             return;
255                         memcpy(&dp[ofs], pb, len);
256                         pb += len;
257                         ofs += len;
258                     } else {
259                         /* interframe pixel copy */
260                         if (ofs + len + 1 > frame_width)
261                             return;
262                         memcpy(&dp[ofs], &pp[ofs], len + 1);
263                         ofs += len + 1;
264                     }
265                 } while (ofs < frame_width);
266                 if (ofs > frame_width) {
267                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
268                         ofs, frame_width);
269                     break;
270                 }
271                 dp += s->frame.linesize[0];
272                 pp += s->prev_frame.linesize[0];
273             }
274             break;
275
276         case 2:
277             for (i = 0; i < frame_height; i++) {
278                 memcpy(dp, pb, frame_width);
279                 pb += frame_width;
280                 dp += s->frame.linesize[0];
281                 pp += s->prev_frame.linesize[0];
282             }
283             break;
284
285         case 3:
286             for (i = 0; i < frame_height; i++) {
287                 ofs = 0;
288                 do {
289                     len = *pb++;
290                     if (len & 0x80) {
291                         len = (len & 0x7F) + 1;
292                         if (*pb++ == 0xFF)
293                             len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
294                         else
295                             memcpy(&dp[ofs], pb, len);
296                         pb += len;
297                         ofs += len;
298                     } else {
299                         /* interframe pixel copy */
300                         if (ofs + len + 1 > frame_width)
301                             return;
302                         memcpy(&dp[ofs], &pp[ofs], len + 1);
303                         ofs += len + 1;
304                     }
305                 } while (ofs < frame_width);
306                 if (ofs > frame_width) {
307                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
308                         ofs, frame_width);
309                 }
310                 dp += s->frame.linesize[0];
311                 pp += s->prev_frame.linesize[0];
312             }
313             break;
314         }
315     }
316 }
317
318 static int vmdvideo_decode_init(AVCodecContext *avctx)
319 {
320     VmdVideoContext *s = avctx->priv_data;
321     int i;
322     unsigned int *palette32;
323     int palette_index = 0;
324     unsigned char r, g, b;
325     unsigned char *vmd_header;
326     unsigned char *raw_palette;
327
328     s->avctx = avctx;
329     avctx->pix_fmt = PIX_FMT_PAL8;
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 = AV_RL32(&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 = 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 = 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 = 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] = av_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++ = buf[i] + 0x80;
489                     *data++ = buf[i] + 0x80;
490                 }
491             }
492         }
493     } else {
494         bytes_decoded = s->block_align * 2;
495
496         /* mono handling */
497         if (silence) {
498             memset(data, 0, s->block_align * 2);
499         } else {
500             if (s->bits == 16) {
501                 vmdaudio_decode_audio(s, data, buf, 0);
502             } else {
503                 /* copy the data but convert it to signed */
504                 for (i = 0; i < s->block_align; i++){
505                     *data++ = buf[i] + 0x80;
506                     *data++ = buf[i] + 0x80;
507                 }
508             }
509         }
510     }
511
512     return s->block_align * 2;
513 }
514
515 static int vmdaudio_decode_frame(AVCodecContext *avctx,
516                                  void *data, int *data_size,
517                                  uint8_t *buf, int buf_size)
518 {
519     VmdAudioContext *s = avctx->priv_data;
520     unsigned char *output_samples = (unsigned char *)data;
521
522     /* point to the start of the encoded data */
523     unsigned char *p = buf + 16;
524
525     if (buf_size < 16)
526         return buf_size;
527
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         /* the chunk may contain audio */
533         p += 4;
534         *data_size = vmdaudio_loadsound(s, output_samples, p, (buf_size == 16));
535         output_samples += (s->block_align * s->bits / 8);
536     } else if (buf[6] == 3) {
537         /* silent chunk */
538         *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
539     }
540
541     return buf_size;
542 }
543
544
545 /*
546  * Public Data Structures
547  */
548
549 AVCodec vmdvideo_decoder = {
550     "vmdvideo",
551     CODEC_TYPE_VIDEO,
552     CODEC_ID_VMDVIDEO,
553     sizeof(VmdVideoContext),
554     vmdvideo_decode_init,
555     NULL,
556     vmdvideo_decode_end,
557     vmdvideo_decode_frame,
558     CODEC_CAP_DR1,
559 };
560
561 AVCodec vmdaudio_decoder = {
562     "vmdaudio",
563     CODEC_TYPE_AUDIO,
564     CODEC_ID_VMDAUDIO,
565     sizeof(VmdAudioContext),
566     vmdaudio_decode_init,
567     NULL,
568     NULL,
569     vmdaudio_decode_frame,
570 };