Statistics
| Branch: | Revision:

ffmpeg / libavcodec / vmdav.c @ f66e4f5f

History | View | Annotate | Download (16.5 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 "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 = AV_RL32(s);
96
    s += 4;
97
    memset(queue, 0x20, QUEUE_SIZE);
98
    if (AV_RL32(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 = AV_RL16(&s->buf[6]);
208
    frame_y = AV_RL16(&s->buf[8]);
209
    frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
210
    frame_height = AV_RL16(&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 = AV_RL32(&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] = av_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++ = buf[i] + 0x80;
491
                    *data++ = buf[i] + 0x80;
492
                }
493
            }
494
        }
495
    } else {
496
        bytes_decoded = s->block_align * 2;
497

    
498
        /* mono handling */
499
        if (silence) {
500
            memset(data, 0, s->block_align * 2);
501
        } else {
502
            if (s->bits == 16) {
503
                vmdaudio_decode_audio(s, data, buf, 0);
504
            } else {
505
                /* copy the data but convert it to signed */
506
                for (i = 0; i < s->block_align; i++){
507
                    *data++ = buf[i] + 0x80;
508
                    *data++ = buf[i] + 0x80;
509
                }
510
            }
511
        }
512
    }
513

    
514
    return s->block_align * 2;
515
}
516

    
517
static int vmdaudio_decode_frame(AVCodecContext *avctx,
518
                                 void *data, int *data_size,
519
                                 uint8_t *buf, int buf_size)
520
{
521
    VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
522
    unsigned char *output_samples = (unsigned char *)data;
523

    
524
    /* point to the start of the encoded data */
525
    unsigned char *p = buf + 16;
526

    
527
    if (buf_size < 16)
528
        return buf_size;
529

    
530
    if (buf[6] == 1) {
531
        /* the chunk contains audio */
532
        *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
533
    } else if (buf[6] == 2) {
534
        /* the chunk may contain audio */
535
        p += 4;
536
        *data_size = vmdaudio_loadsound(s, output_samples, p, (buf_size == 16));
537
        output_samples += (s->block_align * s->bits / 8);
538
    } else if (buf[6] == 3) {
539
        /* silent chunk */
540
        *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
541
    }
542

    
543
    return buf_size;
544
}
545

    
546

    
547
/*
548
 * Public Data Structures
549
 */
550

    
551
AVCodec vmdvideo_decoder = {
552
    "vmdvideo",
553
    CODEC_TYPE_VIDEO,
554
    CODEC_ID_VMDVIDEO,
555
    sizeof(VmdVideoContext),
556
    vmdvideo_decode_init,
557
    NULL,
558
    vmdvideo_decode_end,
559
    vmdvideo_decode_frame,
560
    CODEC_CAP_DR1,
561
};
562

    
563
AVCodec vmdaudio_decoder = {
564
    "vmdaudio",
565
    CODEC_TYPE_AUDIO,
566
    CODEC_ID_VMDAUDIO,
567
    sizeof(VmdAudioContext),
568
    vmdaudio_decode_init,
569
    NULL,
570
    NULL,
571
    vmdaudio_decode_frame,
572
};