Statistics
| Branch: | Revision:

ffmpeg / libavcodec / vmdav.c @ 6636b7e8

History | View | Annotate | Download (16.8 KB)

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, QUEUE_SIZE, 0x20);
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
};