Statistics
| Branch: | Revision:

ffmpeg / libavcodec / vmdav.c @ 2029f312

History | View | Annotate | Download (16.4 KB)

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
};