]> git.sesse.net Git - ffmpeg/blob - libavcodec/vmdav.c
remove unused context var
[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  * @file vmdvideo.c
24  * Sierra VMD audio & video decoders
25  * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
26  * for more information on the Sierra VMD format, visit:
27  *   http://www.pcisys.net/~melanson/codecs/
28  *
29  * The video decoder outputs PAL8 colorspace data. The decoder expects
30  * a 0x330-byte VMD file header to be transmitted via extradata during
31  * codec initialization. Each encoded frame that is sent to this decoder
32  * is expected to be prepended with the appropriate 16-byte frame
33  * information record from the VMD file.
34  *
35  * The audio decoder, like the video decoder, expects each encoded data
36  * chunk to be prepended with the appropriate 16-byte frame information
37  * record from the VMD file. It does not require the 0x330-byte VMD file
38  * header, but it does need the audio setup parameters passed in through
39  * normal libavcodec API means.
40  */
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46
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     int x_off, y_off;
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 ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
212         (frame_x || frame_y)) {
213
214         s->x_off = frame_x;
215         s->y_off = frame_y;
216     }
217     frame_x -= s->x_off;
218     frame_y -= s->y_off;
219
220     /* if only a certain region will be updated, copy the entire previous
221      * frame before the decode */
222     if (frame_x || frame_y || (frame_width != s->avctx->width) ||
223         (frame_height != s->avctx->height)) {
224
225         memcpy(s->frame.data[0], s->prev_frame.data[0],
226             s->avctx->height * s->frame.linesize[0]);
227     }
228
229     /* check if there is a new palette */
230     if (s->buf[15] & 0x02) {
231         p += 2;
232         palette32 = (unsigned int *)s->palette;
233         for (i = 0; i < PALETTE_COUNT; i++) {
234             r = *p++ * 4;
235             g = *p++ * 4;
236             b = *p++ * 4;
237             palette32[i] = (r << 16) | (g << 8) | (b);
238         }
239         s->size -= (256 * 3 + 2);
240     }
241     if (s->size >= 0) {
242         /* originally UnpackFrame in VAG's code */
243         pb = p;
244         meth = *pb++;
245         if (meth & 0x80) {
246             lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
247             meth &= 0x7F;
248             pb = s->unpack_buffer;
249         }
250
251         dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
252         dp_size = s->frame.linesize[0] * s->avctx->height;
253         pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
254         switch (meth) {
255         case 1:
256             for (i = 0; i < frame_height; i++) {
257                 ofs = 0;
258                 do {
259                     len = *pb++;
260                     if (len & 0x80) {
261                         len = (len & 0x7F) + 1;
262                         if (ofs + len > frame_width)
263                             return;
264                         memcpy(&dp[ofs], pb, len);
265                         pb += len;
266                         ofs += len;
267                     } else {
268                         /* interframe pixel copy */
269                         if (ofs + len + 1 > frame_width)
270                             return;
271                         memcpy(&dp[ofs], &pp[ofs], len + 1);
272                         ofs += len + 1;
273                     }
274                 } while (ofs < frame_width);
275                 if (ofs > frame_width) {
276                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
277                         ofs, frame_width);
278                     break;
279                 }
280                 dp += s->frame.linesize[0];
281                 pp += s->prev_frame.linesize[0];
282             }
283             break;
284
285         case 2:
286             for (i = 0; i < frame_height; i++) {
287                 memcpy(dp, pb, frame_width);
288                 pb += frame_width;
289                 dp += s->frame.linesize[0];
290                 pp += s->prev_frame.linesize[0];
291             }
292             break;
293
294         case 3:
295             for (i = 0; i < frame_height; i++) {
296                 ofs = 0;
297                 do {
298                     len = *pb++;
299                     if (len & 0x80) {
300                         len = (len & 0x7F) + 1;
301                         if (*pb++ == 0xFF)
302                             len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
303                         else
304                             memcpy(&dp[ofs], pb, len);
305                         pb += len;
306                         ofs += len;
307                     } else {
308                         /* interframe pixel copy */
309                         if (ofs + len + 1 > frame_width)
310                             return;
311                         memcpy(&dp[ofs], &pp[ofs], len + 1);
312                         ofs += len + 1;
313                     }
314                 } while (ofs < frame_width);
315                 if (ofs > frame_width) {
316                     av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
317                         ofs, frame_width);
318                 }
319                 dp += s->frame.linesize[0];
320                 pp += s->prev_frame.linesize[0];
321             }
322             break;
323         }
324     }
325 }
326
327 static int vmdvideo_decode_init(AVCodecContext *avctx)
328 {
329     VmdVideoContext *s = avctx->priv_data;
330     int i;
331     unsigned int *palette32;
332     int palette_index = 0;
333     unsigned char r, g, b;
334     unsigned char *vmd_header;
335     unsigned char *raw_palette;
336
337     s->avctx = avctx;
338     avctx->pix_fmt = PIX_FMT_PAL8;
339     dsputil_init(&s->dsp, avctx);
340
341     /* make sure the VMD header made it */
342     if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
343         av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
344             VMD_HEADER_SIZE);
345         return -1;
346     }
347     vmd_header = (unsigned char *)avctx->extradata;
348
349     s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
350     s->unpack_buffer = av_malloc(s->unpack_buffer_size);
351     if (!s->unpack_buffer)
352         return -1;
353
354     /* load up the initial palette */
355     raw_palette = &vmd_header[28];
356     palette32 = (unsigned int *)s->palette;
357     for (i = 0; i < PALETTE_COUNT; i++) {
358         r = raw_palette[palette_index++] * 4;
359         g = raw_palette[palette_index++] * 4;
360         b = raw_palette[palette_index++] * 4;
361         palette32[i] = (r << 16) | (g << 8) | (b);
362     }
363
364     s->frame.data[0] = s->prev_frame.data[0] = NULL;
365
366     return 0;
367 }
368
369 static int vmdvideo_decode_frame(AVCodecContext *avctx,
370                                  void *data, int *data_size,
371                                  uint8_t *buf, int buf_size)
372 {
373     VmdVideoContext *s = avctx->priv_data;
374
375     s->buf = buf;
376     s->size = buf_size;
377
378     if (buf_size < 16)
379         return buf_size;
380
381     s->frame.reference = 1;
382     if (avctx->get_buffer(avctx, &s->frame)) {
383         av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
384         return -1;
385     }
386
387     vmd_decode(s);
388
389     /* make the palette available on the way out */
390     memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
391
392     /* shuffle frames */
393     FFSWAP(AVFrame, s->frame, s->prev_frame);
394     if (s->frame.data[0])
395         avctx->release_buffer(avctx, &s->frame);
396
397     *data_size = sizeof(AVFrame);
398     *(AVFrame*)data = s->prev_frame;
399
400     /* report that the buffer was completely consumed */
401     return buf_size;
402 }
403
404 static int vmdvideo_decode_end(AVCodecContext *avctx)
405 {
406     VmdVideoContext *s = avctx->priv_data;
407
408     if (s->prev_frame.data[0])
409         avctx->release_buffer(avctx, &s->prev_frame);
410     av_free(s->unpack_buffer);
411
412     return 0;
413 }
414
415
416 /*
417  * Audio Decoder
418  */
419
420 typedef struct VmdAudioContext {
421     AVCodecContext *avctx;
422     int channels;
423     int bits;
424     int block_align;
425     int predictors[2];
426 } VmdAudioContext;
427
428 static uint16_t vmdaudio_table[128] = {
429     0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
430     0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
431     0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
432     0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
433     0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
434     0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
435     0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
436     0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
437     0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
438     0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
439     0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
440     0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
441     0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
442 };
443
444 static int vmdaudio_decode_init(AVCodecContext *avctx)
445 {
446     VmdAudioContext *s = avctx->priv_data;
447
448     s->avctx = avctx;
449     s->channels = avctx->channels;
450     s->bits = avctx->bits_per_sample;
451     s->block_align = avctx->block_align;
452
453     av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
454             s->channels, s->bits, s->block_align, avctx->sample_rate);
455
456     return 0;
457 }
458
459 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
460     uint8_t *buf, int stereo)
461 {
462     int i;
463     int chan = 0;
464     int16_t *out = (int16_t*)data;
465
466     for(i = 0; i < s->block_align; i++) {
467         if(buf[i] & 0x80)
468             s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
469         else
470             s->predictors[chan] += vmdaudio_table[buf[i]];
471         s->predictors[chan] = av_clip_int16(s->predictors[chan]);
472         out[i] = s->predictors[chan];
473         chan ^= stereo;
474     }
475 }
476
477 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
478     uint8_t *buf, int silence)
479 {
480     int bytes_decoded = 0;
481     int i;
482
483 //    if (silence)
484 //        av_log(s->avctx, AV_LOG_INFO, "silent block!\n");
485     if (s->channels == 2) {
486
487         /* stereo handling */
488         if (silence) {
489             memset(data, 0, s->block_align * 2);
490         } else {
491             if (s->bits == 16)
492                 vmdaudio_decode_audio(s, data, buf, 1);
493             else {
494                 /* copy the data but convert it to signed */
495                 for (i = 0; i < s->block_align; i++){
496                     *data++ = buf[i] + 0x80;
497                     *data++ = buf[i] + 0x80;
498                 }
499             }
500         }
501     } else {
502         bytes_decoded = s->block_align * 2;
503
504         /* mono handling */
505         if (silence) {
506             memset(data, 0, s->block_align * 2);
507         } else {
508             if (s->bits == 16) {
509                 vmdaudio_decode_audio(s, data, buf, 0);
510             } else {
511                 /* copy the data but convert it to signed */
512                 for (i = 0; i < s->block_align; i++){
513                     *data++ = buf[i] + 0x80;
514                     *data++ = buf[i] + 0x80;
515                 }
516             }
517         }
518     }
519
520     return s->block_align * 2;
521 }
522
523 static int vmdaudio_decode_frame(AVCodecContext *avctx,
524                                  void *data, int *data_size,
525                                  uint8_t *buf, int buf_size)
526 {
527     VmdAudioContext *s = avctx->priv_data;
528     unsigned char *output_samples = (unsigned char *)data;
529
530     /* point to the start of the encoded data */
531     unsigned char *p = buf + 16;
532
533     if (buf_size < 16)
534         return buf_size;
535
536     if (buf[6] == 1) {
537         /* the chunk contains audio */
538         *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
539     } else if (buf[6] == 2) {
540         /* the chunk may contain audio */
541         p += 4;
542         *data_size = vmdaudio_loadsound(s, output_samples, p, (buf_size == 16));
543         output_samples += (s->block_align * s->bits / 8);
544     } else if (buf[6] == 3) {
545         /* silent chunk */
546         *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
547     }
548
549     return buf_size;
550 }
551
552
553 /*
554  * Public Data Structures
555  */
556
557 AVCodec vmdvideo_decoder = {
558     "vmdvideo",
559     CODEC_TYPE_VIDEO,
560     CODEC_ID_VMDVIDEO,
561     sizeof(VmdVideoContext),
562     vmdvideo_decode_init,
563     NULL,
564     vmdvideo_decode_end,
565     vmdvideo_decode_frame,
566     CODEC_CAP_DR1,
567 };
568
569 AVCodec vmdaudio_decoder = {
570     "vmdaudio",
571     CODEC_TYPE_AUDIO,
572     CODEC_ID_VMDAUDIO,
573     sizeof(VmdAudioContext),
574     vmdaudio_decode_init,
575     NULL,
576     NULL,
577     vmdaudio_decode_frame,
578 };