Revision 23fe14bb

View differences:

libavcodec/vmdav.c
22 22
 * @file vmdvideo.c
23 23
 * Sierra VMD audio & video decoders
24 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/
25 27
 *
26 28
 * The video decoder outputs PAL8 colorspace data. The decoder expects
27 29
 * a 0x330-byte VMD file header to be transmitted via extradata during
......
30 32
 * information record from the VMD file.
31 33
 *
32 34
 * The audio decoder, like the video decoder, expects each encoded data
33
 * chunk to be prepended with the approriate 16-byte frame information
35
 * chunk to be prepended with the appropriate 16-byte frame information
34 36
 * record from the VMD file. It does not require the 0x330-byte VMD file
35 37
 * header, but it does need the audio setup parameters passed in through
36 38
 * normal libavcodec API means.
......
51 53
#define VMD_HEADER_SIZE 0x330
52 54
#define PALETTE_COUNT 256
53 55

  
54
#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
55
#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
56
                   (((uint8_t*)(x))[2] << 16) | \
57
                   (((uint8_t*)(x))[1] << 8) | \
58
                    ((uint8_t*)(x))[0])
59

  
60 56
/*
61 57
 * Video Decoder
62 58
 */
......
275 271
                    if (len & 0x80) {
276 272
                        len = (len & 0x7F) + 1;
277 273
                        if (*pb++ == 0xFF)
278
                            len = rle_unpack(pb, dp, len);
274
                            len = rle_unpack(pb, &dp[ofs], len);
279 275
                        else
280 276
                            memcpy(&dp[ofs], pb, len);
281 277
                        pb += len;
......
349 345
    s->buf = buf;
350 346
    s->size = buf_size;
351 347

  
348
    if (buf_size < 16)
349
        return buf_size;
350

  
352 351
    s->frame.reference = 1;
353 352
    if (avctx->get_buffer(avctx, &s->frame)) {
354 353
        printf ("  VMD Video: get_buffer() failed\n");
......
408 407
    s->bits = avctx->bits_per_sample;
409 408
    s->block_align = avctx->block_align;
410 409

  
411
printf ("  %d channels, %d bits/sample, block align = %d\n",
412
  s->channels, s->bits, s->block_align);
410
printf ("  %d channels, %d bits/sample, block align = %d, sample rate = %d\n",
411
  s->channels, s->bits, s->block_align, avctx->sample_rate);
413 412

  
414 413
    /* set up the steps8 and steps16 tables */
415 414
    for (i = 0; i < 8; i++) {
......
460 459

  
461 460
}
462 461

  
463
static void vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
462
static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
464 463
    uint8_t *buf, int silence)
465 464
{
465
    int bytes_decoded = 0;
466
    int i;
467

  
468
if (silence)
469
  printf (" silent block!\n");
466 470
    if (s->channels == 2) {
471

  
472
        /* stereo handling */
467 473
        if ((s->block_align & 0x01) == 0) {
468 474
            if (silence)
469 475
                memset(data, 0, s->block_align * 2);
......
472 478
        } else {
473 479
            if (silence)
474 480
                memset(data, 0, s->block_align * 2);
475
//            else
476
//                vmdaudio_decode_audio(s, data, buf, 1);
481
            else
482
                vmdaudio_decode_audio(s, data, buf, 1);
477 483
        }
478 484
    } else {
485

  
486
        /* mono handling */
487
        if (silence) {
488
            if (s->bits == 16) {
489
                memset(data, 0, s->block_align * 2);
490
                bytes_decoded = s->block_align * 2;
491
            } else {
492
//                memset(data, 0x00, s->block_align);
493
//                bytes_decoded = s->block_align;
494
memset(data, 0x00, s->block_align * 2);
495
bytes_decoded = s->block_align * 2;
496
            }
497
        } else {
498
            if (s->bits == 16) {
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
                bytes_decoded = s->block_align * 2;
504
            }
505
        }
479 506
    }
507

  
508
    return bytes_decoded;
480 509
}
481 510

  
482 511
static int vmdaudio_decode_frame(AVCodecContext *avctx,
......
491 520
    unsigned char *p = buf + 16;
492 521
    unsigned char *p_end = buf + buf_size;
493 522

  
523
printf ("    processing audio frame with %d bytes\n", buf_size);
524
    if (buf_size < 16)
525
        return buf_size;
526

  
527
    *data_size = 0;
494 528
    if (buf[6] == 1) {
495 529
        /* the chunk contains audio */
496
        vmdaudio_loadsound(s, output_samples, p, 0);
530
        *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
497 531
    } else if (buf[6] == 2) {
532
printf ("  hey! audio case #2\n");
498 533
        /* the chunk contains audio and silence mixed together */
499 534
        sound_flags = LE_32(p);
500 535
        p += 4;
......
503 538

  
504 539
        while (p < p_end) {
505 540
            if (sound_flags & 0x01)
506
                /* audio */
507
                vmdaudio_loadsound(s, output_samples, p, 1);
508
            else
509 541
                /* silence */
510
                vmdaudio_loadsound(s, output_samples, p, 0);
511
            p += s->block_align;
542
                *data_size += vmdaudio_loadsound(s, output_samples, p, 1);
543
            else {
544
                /* audio */
545
                *data_size += vmdaudio_loadsound(s, output_samples, p, 0);
546
                p += s->block_align;
547
            }
512 548
            output_samples += (s->block_align * s->bits / 8);
513 549
            sound_flags >>= 1;
514 550
        }
515 551
    } else if (buf[6] == 3) {
552
printf ("  hey! audio case #3\n");
516 553
        /* silent chunk */
517
        vmdaudio_loadsound(s, output_samples, p, 1);
554
        *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
518 555
    }
519 556

  
520

  
521
//    *datasize = ;
557
printf ("      final sample count = %d, byte count = %d\n", (*data_size) / 2,
558
  *data_size);
522 559
    return buf_size;
523 560
}
524 561

  
libavformat/sierravmd.c
21 21
 * @file sierravmd.c
22 22
 * Sierra VMD file demuxer
23 23
 * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
24
 * for more information on the Sierra VMD file format, visit:
25
 *   http://www.pcisys.net/~melanson/codecs/
24 26
 */
25 27

  
26 28
#include "avformat.h"
27 29

  
28
#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
29
#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
30
                   (((uint8_t*)(x))[2] << 16) | \
31
                   (((uint8_t*)(x))[1] << 8) | \
32
                    ((uint8_t*)(x))[0])
33

  
34 30
#define VMD_HEADER_SIZE 0x0330
35 31
#define BYTES_PER_FRAME_RECORD 16
36 32

  
......
56 52
    vmd_frame_t *frame_table;
57 53
    unsigned int current_frame;
58 54

  
55
    int sample_rate;
56
    int64_t audio_sample_counter;
57
    int audio_frame_divisor;
58
    int audio_block_align;
59

  
59 60
    unsigned char vmd_header[VMD_HEADER_SIZE];
60 61
} VmdDemuxContext;
61 62

  
......
73 74
    return AVPROBE_SCORE_MAX / 2;
74 75
}
75 76

  
77
/* This is a support function to determine the duration, in sample
78
 * frames, of a particular audio chunk, taking into account silent
79
 * encodings. */
80
static int vmd_calculate_audio_duration(unsigned char *audio_chunk,
81
    int audio_chunk_size, int block_align)
82
{
83
    unsigned char *p = audio_chunk + 16;
84
    unsigned char *p_end = audio_chunk + audio_chunk_size;
85
    int total_samples = 0;
86
    unsigned int sound_flags;
87

  
88
    if (audio_chunk_size < 16)
89
        return 0;
90

  
91
    sound_flags = LE_32(p);
92
    p += 4;
93
    while (p < p_end) {
94
        total_samples += block_align;
95
        if ((sound_flags & 0x01) == 0)
96
            p += block_align;
97
        sound_flags >>= 1;
98
    }
99

  
100
    return total_samples;
101
}
102

  
76 103
static int vmd_read_header(AVFormatContext *s,
77 104
                           AVFormatParameters *ap)
78 105
{
......
85 112
    unsigned char *current_frame_record;
86 113
    offset_t current_offset;
87 114
    int i;
88
    int sample_rate;
89 115
    unsigned int total_frames;
90
int video_frame_count = 0;
116
    int64_t video_pts_inc;
117
    int64_t current_video_pts = 0;
91 118

  
92 119
    /* fetch the main header, including the 2 header length bytes */
93 120
    url_fseek(pb, 0, SEEK_SET);
94 121
    if (get_buffer(pb, vmd->vmd_header, VMD_HEADER_SIZE) != VMD_HEADER_SIZE)
95 122
        return -EIO;
96 123

  
124
    vmd->audio_sample_counter = 0;
125
    vmd->audio_frame_divisor = 1;
126
    vmd->audio_block_align = 1;
127

  
97 128
    /* start up the decoders */
98 129
    st = av_new_stream(s, 0);
99 130
    if (!st)
......
109 140
    memcpy(st->codec.extradata, vmd->vmd_header, VMD_HEADER_SIZE);
110 141

  
111 142
    /* if sample rate is 0, assume no audio */
112
    sample_rate = LE_16(&vmd->vmd_header[804]);
113
    if (sample_rate) {
143
    vmd->sample_rate = LE_16(&vmd->vmd_header[804]);
144
    if (vmd->sample_rate) {
114 145
        st = av_new_stream(s, 0);
115 146
        if (!st)
116 147
            return AVERROR_NOMEM;
......
119 150
        st->codec.codec_id = CODEC_ID_VMDAUDIO;
120 151
        st->codec.codec_tag = 0;  /* no codec tag */
121 152
        st->codec.channels = (vmd->vmd_header[811] & 0x80) ? 2 : 1;
122
        st->codec.sample_rate = sample_rate;
123
        st->codec.bit_rate = st->codec.sample_rate * 
124
            st->codec.bits_per_sample * st->codec.channels;
125
        st->codec.block_align = LE_16(&vmd->vmd_header[806]);
153
        st->codec.sample_rate = vmd->sample_rate;
154
        st->codec.block_align = vmd->audio_block_align = 
155
            LE_16(&vmd->vmd_header[806]);
126 156
        if (st->codec.block_align & 0x8000) {
127 157
            st->codec.bits_per_sample = 16;
128 158
            st->codec.block_align = -(st->codec.block_align - 0x10000);
129 159
        } else
130
            st->codec.bits_per_sample = 8;
160
            st->codec.bits_per_sample = 16;
161
//            st->codec.bits_per_sample = 8;
162
        st->codec.bit_rate = st->codec.sample_rate * 
163
            st->codec.bits_per_sample * st->codec.channels;
164

  
165
        /* for calculating pts */
166
        vmd->audio_frame_divisor = st->codec.bits_per_sample / 8 / 
167
            st->codec.channels;
168

  
169
        video_pts_inc = 90000;
170
        video_pts_inc *= st->codec.block_align;
171
        video_pts_inc /= st->codec.sample_rate;
172
    } else {
173
        /* if no audio, assume 10 frames/second */
174
        video_pts_inc = 90000 / 10;
131 175
    }
132 176

  
133 177
    /* skip over the offset table and load the table of contents; don't 
......
184 228
        memcpy(vmd->frame_table[i].frame_record, current_frame_record,
185 229
            BYTES_PER_FRAME_RECORD);
186 230

  
187
if (current_frame_record[0] == 0x02) {
188
  /* assume 15 fps for now */
189
  vmd->frame_table[i].pts = video_frame_count++;
190
  vmd->frame_table[i].pts *= 90000;
191
  vmd->frame_table[i].pts /= 15;
192
}
231
        /* figure out the pts for this frame */
232
        if (current_frame_record[0] == 0x02) {
233
            vmd->frame_table[i].pts = current_video_pts;
234
            current_video_pts += video_pts_inc;
235
        } else if (current_frame_record[0] == 0x01) {
236
            /* figure out the pts during the dispatch phase */
237
            vmd->frame_table[i].pts = 0;
238
        }
193 239

  
194 240
        current_frame_record += BYTES_PER_FRAME_RECORD;
195 241
        i++;
......
227 273
    ret = get_buffer(pb, pkt->data + BYTES_PER_FRAME_RECORD, 
228 274
        frame->frame_size);
229 275

  
230
    if (ret != frame->frame_size)
276
    if (ret != frame->frame_size) {
277
        av_free_packet(pkt);
231 278
        ret = -EIO;
279
    }
232 280
    pkt->stream_index = frame->stream_index;
233
    pkt->pts = frame->pts;
281
    if (frame->frame_record[0] == 0x02)
282
        pkt->pts = frame->pts;
283
    else {
284
        pkt->pts = vmd->audio_sample_counter;
285
        pkt->pts *= 90000;
286
        pkt->pts /= vmd->sample_rate;
287
//        pkt->pts /= vmd->audio_frame_divisor;
288
        vmd->audio_sample_counter += vmd_calculate_audio_duration(
289
            pkt->data, pkt->size, vmd->audio_block_align);
290

  
291
    }
292
printf (" dispatching %s frame with %d bytes and pts %lld (%0.1f sec)\n",
293
  (frame->frame_record[0] == 0x02) ? "video" : "audio",
294
  frame->frame_size + BYTES_PER_FRAME_RECORD,
295
  pkt->pts, (float)(pkt->pts / 90000.0));
234 296

  
235 297
    vmd->current_frame++;
236 298

  

Also available in: Unified diff