Statistics
| Branch: | Revision:

ffmpeg / libavcodec / vmdav.c @ 5509bffa

History | View | Annotate | Download (16.9 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
    unsigned char steps8[16];
418
    unsigned short steps16[16];
419
    unsigned short steps128[256];
420
    short predictors[2];
421
} VmdAudioContext;
422

    
423
static int vmdaudio_decode_init(AVCodecContext *avctx)
424
{
425
    VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
426
    int i;
427

    
428
    s->avctx = avctx;
429
    s->channels = avctx->channels;
430
    s->bits = avctx->bits_per_sample;
431
    s->block_align = avctx->block_align;
432

    
433
    av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
434
            s->channels, s->bits, s->block_align, avctx->sample_rate);
435

    
436
    /* set up the steps8 and steps16 tables */
437
    for (i = 0; i < 8; i++) {
438
        if (i < 4)
439
            s->steps8[i] = i;
440
        else
441
            s->steps8[i] = s->steps8[i - 1] + i - 1;
442

    
443
        if (i == 0)
444
            s->steps16[i] = 0;
445
        else if (i == 1)
446
            s->steps16[i] = 4;
447
        else if (i == 2)
448
            s->steps16[i] = 16;
449
        else
450
            s->steps16[i] = 1 << (i + 4);
451
    }
452

    
453
    /* set up the step128 table */
454
    s->steps128[0] = 0;
455
    s->steps128[1] = 8;
456
    for (i = 0x02; i <= 0x20; i++)
457
        s->steps128[i] = (i - 1) << 4;
458
    for (i = 0x21; i <= 0x60; i++)
459
        s->steps128[i] = (i + 0x1F) << 3;
460
    for (i = 0x61; i <= 0x70; i++)
461
        s->steps128[i] = (i - 0x51) << 6;
462
    for (i = 0x71; i <= 0x78; i++)
463
        s->steps128[i] = (i - 0x69) << 8;
464
    for (i = 0x79; i <= 0x7D; i++)
465
        s->steps128[i] = (i - 0x75) << 10;
466
    s->steps128[0x7E] = 0x3000;
467
    s->steps128[0x7F] = 0x4000;
468

    
469
    /* set up the negative half of each table */
470
    for (i = 0; i < 8; i++) {
471
        s->steps8[i + 8] = -s->steps8[i];
472
        s->steps16[i + 8] = -s->steps16[i];
473
    }
474
    for (i = 0; i < 128; i++)
475
      s->steps128[i + 128] = -s->steps128[i];
476

    
477
    return 0;
478
}
479

    
480
static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
481
    uint8_t *buf, int ratio) {
482

    
483
}
484

    
485
static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
486
    uint8_t *buf, int silence)
487
{
488
    int bytes_decoded = 0;
489
    int i;
490

    
491
    if (silence)
492
        av_log(s->avctx, AV_LOG_INFO, "silent block!\n");
493
    if (s->channels == 2) {
494

    
495
        /* stereo handling */
496
        if ((s->block_align & 0x01) == 0) {
497
            if (silence)
498
                memset(data, 0, s->block_align * 2);
499
            else
500
                vmdaudio_decode_audio(s, data, buf, 1);
501
        } else {
502
            if (silence)
503
                memset(data, 0, s->block_align * 2);
504
            else
505
                vmdaudio_decode_audio(s, data, buf, 1);
506
        }
507
    } else {
508

    
509
        /* mono handling */
510
        if (silence) {
511
            if (s->bits == 16) {
512
                memset(data, 0, s->block_align * 2);
513
                bytes_decoded = s->block_align * 2;
514
            } else {
515
//                memset(data, 0x00, s->block_align);
516
//                bytes_decoded = s->block_align;
517
memset(data, 0x00, s->block_align * 2);
518
bytes_decoded = s->block_align * 2;
519
            }
520
        } else {
521
            /* copy the data but convert it to signed */
522
            for (i = 0; i < s->block_align; i++)
523
                data[i * 2 + 1] = buf[i] + 0x80;
524
            bytes_decoded = s->block_align * 2;
525
        }
526
    }
527

    
528
    return bytes_decoded;
529
}
530

    
531
static int vmdaudio_decode_frame(AVCodecContext *avctx,
532
                                 void *data, int *data_size,
533
                                 uint8_t *buf, int buf_size)
534
{
535
    VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
536
    unsigned int sound_flags;
537
    unsigned char *output_samples = (unsigned char *)data;
538

    
539
    /* point to the start of the encoded data */
540
    unsigned char *p = buf + 16;
541
    unsigned char *p_end = buf + buf_size;
542

    
543
    if (buf_size < 16)
544
        return buf_size;
545

    
546
    if (buf[6] == 1) {
547
        /* the chunk contains audio */
548
        *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
549
    } else if (buf[6] == 2) {
550
        /* the chunk contains audio and silence mixed together */
551
        sound_flags = LE_32(p);
552
        p += 4;
553

    
554
        /* do something with extrabufs here? */
555

    
556
        while (p < p_end) {
557
            if (sound_flags & 0x01)
558
                /* silence */
559
                *data_size += vmdaudio_loadsound(s, output_samples, p, 1);
560
            else {
561
                /* audio */
562
                *data_size += vmdaudio_loadsound(s, output_samples, p, 0);
563
                p += s->block_align;
564
            }
565
            output_samples += (s->block_align * s->bits / 8);
566
            sound_flags >>= 1;
567
        }
568
    } else if (buf[6] == 3) {
569
        /* silent chunk */
570
        *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
571
    }
572

    
573
    return buf_size;
574
}
575

    
576

    
577
/*
578
 * Public Data Structures
579
 */
580

    
581
AVCodec vmdvideo_decoder = {
582
    "vmdvideo",
583
    CODEC_TYPE_VIDEO,
584
    CODEC_ID_VMDVIDEO,
585
    sizeof(VmdVideoContext),
586
    vmdvideo_decode_init,
587
    NULL,
588
    vmdvideo_decode_end,
589
    vmdvideo_decode_frame,
590
    CODEC_CAP_DR1,
591
};
592

    
593
AVCodec vmdaudio_decoder = {
594
    "vmdaudio",
595
    CODEC_TYPE_AUDIO,
596
    CODEC_ID_VMDAUDIO,
597
    sizeof(VmdAudioContext),
598
    vmdaudio_decode_init,
599
    NULL,
600
    NULL,
601
    vmdaudio_decode_frame,
602
};