Statistics
| Branch: | Revision:

ffmpeg / libavformat / electronicarts.c @ 98168220

History | View | Annotate | Download (12.6 KB)

1
/* Electronic Arts Multimedia File Demuxer
2
 * Copyright (c) 2004  The ffmpeg Project
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20

    
21
/**
22
 * @file electronicarts.c
23
 * Electronic Arts Multimedia file demuxer (WVE/UV2/etc.)
24
 * by Robin Kay (komadori at gekkou.co.uk)
25
 */
26

    
27
#include "avformat.h"
28

    
29
#define SCHl_TAG MKTAG('S', 'C', 'H', 'l')
30
#define _SNh_TAG MKTAG('1', 'S', 'N', 'h')    /* 1SNx header */
31
#define EACS_TAG MKTAG('E', 'A', 'C', 'S')
32
#define _SNd_TAG MKTAG('1', 'S', 'N', 'd')    /* 1SNx data */
33
#define _SNe_TAG MKTAG('1', 'S', 'N', 'e')    /* 1SNx end */
34
#define PT00_TAG MKTAG('P', 'T', 0x0, 0x0)
35
#define GSTR_TAG MKTAG('G', 'S', 'T', 'R')
36
#define SCDl_TAG MKTAG('S', 'C', 'D', 'l')
37
#define SCEl_TAG MKTAG('S', 'C', 'E', 'l')
38
#define MVhd_TAG MKTAG('M', 'V', 'h', 'd')
39
#define MV0K_TAG MKTAG('M', 'V', '0', 'K')
40
#define MV0F_TAG MKTAG('M', 'V', '0', 'F')
41

    
42
typedef struct EaDemuxContext {
43
    int big_endian;
44

    
45
    int video_codec;
46
    AVRational time_base;
47
    int video_stream_index;
48

    
49
    int audio_codec;
50
    int audio_stream_index;
51
    int audio_frame_counter;
52

    
53
    int64_t audio_pts;
54

    
55
    int bytes;
56
    int sample_rate;
57
    int num_channels;
58
    int num_samples;
59
} EaDemuxContext;
60

    
61
static uint32_t read_arbitary(ByteIOContext *pb) {
62
    uint8_t size, byte;
63
    int i;
64
    uint32_t word;
65

    
66
    size = get_byte(pb);
67

    
68
    word = 0;
69
    for (i = 0; i < size; i++) {
70
        byte = get_byte(pb);
71
        word <<= 8;
72
        word |= byte;
73
    }
74

    
75
    return word;
76
}
77

    
78
/*
79
 * Process PT/GSTR sound header
80
 * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
81
 */
82
static int process_audio_header_elements(AVFormatContext *s)
83
{
84
    int inHeader = 1;
85
    EaDemuxContext *ea = s->priv_data;
86
    ByteIOContext *pb = &s->pb;
87
    int compression_type = -1, revision = -1;
88

    
89
    ea->bytes = 2;
90
    ea->sample_rate = -1;
91
    ea->num_channels = 1;
92

    
93
    while (inHeader) {
94
        int inSubheader;
95
        uint8_t byte;
96
        byte = get_byte(pb);
97

    
98
        switch (byte) {
99
        case 0xFD:
100
            av_log (s, AV_LOG_INFO, "entered audio subheader\n");
101
            inSubheader = 1;
102
            while (inSubheader) {
103
                uint8_t subbyte;
104
                subbyte = get_byte(pb);
105

    
106
                switch (subbyte) {
107
                case 0x80:
108
                    revision = read_arbitary(pb);
109
                    av_log (s, AV_LOG_INFO, "revision (element 0x80) set to 0x%08x\n", revision);
110
                    break;
111
                case 0x82:
112
                    ea->num_channels = read_arbitary(pb);
113
                    av_log (s, AV_LOG_INFO, "num_channels (element 0x82) set to 0x%08x\n", ea->num_channels);
114
                    break;
115
                case 0x83:
116
                    compression_type = read_arbitary(pb);
117
                    av_log (s, AV_LOG_INFO, "compression_type (element 0x83) set to 0x%08x\n", compression_type);
118
                    break;
119
                case 0x84:
120
                    ea->sample_rate = read_arbitary(pb);
121
                    av_log (s, AV_LOG_INFO, "sample_rate (element 0x84) set to %i\n", ea->sample_rate);
122
                    break;
123
                case 0x85:
124
                    ea->num_samples = read_arbitary(pb);
125
                    av_log (s, AV_LOG_INFO, "num_samples (element 0x85) set to 0x%08x\n", ea->num_samples);
126
                    break;
127
                case 0x8A:
128
                    av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
129
                    av_log (s, AV_LOG_INFO, "exited audio subheader\n");
130
                    inSubheader = 0;
131
                    break;
132
                case 0xFF:
133
                    av_log (s, AV_LOG_INFO, "end of header block reached (within audio subheader)\n");
134
                    inSubheader = 0;
135
                    inHeader = 0;
136
                    break;
137
                default:
138
                    av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
139
                    break;
140
                }
141
            }
142
            break;
143
        case 0xFF:
144
            av_log (s, AV_LOG_INFO, "end of header block reached\n");
145
            inHeader = 0;
146
            break;
147
        default:
148
            av_log (s, AV_LOG_INFO, "header element 0x%02x set to 0x%08x\n", byte, read_arbitary(pb));
149
            break;
150
        }
151
    }
152

    
153
    switch (compression_type) {
154
    case  0: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
155
    case  7: ea->audio_codec = CODEC_ID_ADPCM_EA; break;
156
    case -1:
157
        switch (revision) {
158
        case  1: ea->audio_codec = CODEC_ID_ADPCM_EA_R1; break;
159
        case  2: ea->audio_codec = CODEC_ID_ADPCM_EA_R2; break;
160
        case  3: ea->audio_codec = CODEC_ID_ADPCM_EA_R3; break;
161
        default:
162
            av_log(s, AV_LOG_ERROR, "unsupported stream type; revision=%i\n", revision);
163
            return 0;
164
        }
165
        break;
166
    default:
167
        av_log(s, AV_LOG_ERROR, "unsupported stream type; compression_type=%i\n", compression_type);
168
        return 0;
169
    }
170

    
171
    if (ea->sample_rate == -1)
172
        ea->sample_rate = revision==3 ? 48000 : 22050;
173

    
174
    return 1;
175
}
176

    
177
/*
178
 * Process EACS sound header
179
 * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
180
 */
181
static int process_audio_header_eacs(AVFormatContext *s)
182
{
183
    EaDemuxContext *ea = s->priv_data;
184
    ByteIOContext *pb = &s->pb;
185
    int compression_type;
186

    
187
    ea->sample_rate  = ea->big_endian ? get_be32(pb) : get_le32(pb);
188
    ea->bytes        = get_byte(pb);   /* 1=8-bit, 2=16-bit */
189
    ea->num_channels = get_byte(pb);
190
    compression_type = get_byte(pb);
191
    url_fskip(pb, 13);
192

    
193
    switch (compression_type) {
194
    case 0:
195
        switch (ea->bytes) {
196
        case 1: ea->audio_codec = CODEC_ID_PCM_S8;    break;
197
        case 2: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
198
        }
199
        break;
200
    case 1: ea->audio_codec = CODEC_ID_PCM_MULAW; ea->bytes = 1; break;
201
    default:
202
        av_log (s, AV_LOG_ERROR, "unsupported stream type; audio compression_type=%i\n", compression_type);
203
    }
204

    
205
    return 1;
206
}
207

    
208
static int process_video_header_vp6(AVFormatContext *s)
209
{
210
    EaDemuxContext *ea = s->priv_data;
211
    ByteIOContext *pb = &s->pb;
212

    
213
    url_fskip(pb, 16);
214
    ea->time_base.den = get_le32(pb);
215
    ea->time_base.num = get_le32(pb);
216
    ea->video_codec = CODEC_ID_VP6;
217

    
218
    return 1;
219
}
220

    
221
/*
222
 * Process EA file header
223
 * Returns 1 if the EA file is valid and successfully opened, 0 otherwise
224
 */
225
static int process_ea_header(AVFormatContext *s) {
226
    uint32_t blockid, size = 0;
227
    EaDemuxContext *ea = s->priv_data;
228
    ByteIOContext *pb = &s->pb;
229
    int i;
230

    
231
    for (i=0; i<5 && (!ea->audio_codec || !ea->video_codec); i++) {
232
        unsigned int startpos = url_ftell(pb);
233
        int err = 0;
234

    
235
        blockid = get_le32(pb);
236
        size = get_le32(pb);
237
        if (i == 0)
238
            ea->big_endian = size > 0x000FFFFF;
239
        if (ea->big_endian)
240
            size = bswap_32(size);
241

    
242
        switch (blockid) {
243
            case _SNh_TAG:
244
                if (get_le32(pb) != EACS_TAG) {
245
                    av_log (s, AV_LOG_ERROR, "unknown 1SNh headerid\n");
246
                    return 0;
247
                }
248
                err = process_audio_header_eacs(s);
249
                break;
250

    
251
            case SCHl_TAG :
252
                blockid = get_le32(pb);
253
                if (blockid == GSTR_TAG) {
254
                    url_fskip(pb, 4);
255
                } else if (blockid != PT00_TAG) {
256
                    av_log (s, AV_LOG_ERROR, "unknown SCHl headerid\n");
257
                    return 0;
258
                }
259
                err = process_audio_header_elements(s);
260
                break;
261

    
262
            case MVhd_TAG :
263
                err = process_video_header_vp6(s);
264
                break;
265
        }
266

    
267
        if (err < 0) {
268
            av_log(s, AV_LOG_ERROR, "error parsing header: %i\n", err);
269
            return err;
270
        }
271

    
272
        url_fseek(pb, startpos + size, SEEK_SET);
273
    }
274

    
275
    url_fseek(pb, 0, SEEK_SET);
276

    
277
    return 1;
278
}
279

    
280

    
281
static int ea_probe(AVProbeData *p)
282
{
283
    switch (AV_RL32(&p->buf[0])) {
284
    case SCHl_TAG:
285
    case MVhd_TAG:
286
        return AVPROBE_SCORE_MAX;
287
    }
288
    return 0;
289
}
290

    
291
static int ea_read_header(AVFormatContext *s,
292
                          AVFormatParameters *ap)
293
{
294
    EaDemuxContext *ea = s->priv_data;
295
    AVStream *st;
296

    
297
    if (!process_ea_header(s))
298
        return AVERROR(EIO);
299

    
300
    if (ea->video_codec) {
301
        /* initialize the video decoder stream */
302
        st = av_new_stream(s, 0);
303
        if (!st)
304
            return AVERROR(ENOMEM);
305
        ea->video_stream_index = st->index;
306
        st->codec->codec_type = CODEC_TYPE_VIDEO;
307
        st->codec->codec_id = ea->video_codec;
308
        st->codec->codec_tag = 0;  /* no fourcc */
309
        st->codec->time_base = ea->time_base;
310
    }
311

    
312
    if (ea->audio_codec) {
313
        /* initialize the audio decoder stream */
314
        st = av_new_stream(s, 0);
315
        if (!st)
316
            return AVERROR(ENOMEM);
317
        av_set_pts_info(st, 33, 1, ea->sample_rate);
318
        st->codec->codec_type = CODEC_TYPE_AUDIO;
319
        st->codec->codec_id = ea->audio_codec;
320
        st->codec->codec_tag = 0;  /* no tag */
321
        st->codec->channels = ea->num_channels;
322
        st->codec->sample_rate = ea->sample_rate;
323
        st->codec->bits_per_sample = ea->bytes * 8;
324
        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
325
            st->codec->bits_per_sample / 4;
326
        st->codec->block_align = st->codec->channels*st->codec->bits_per_sample;
327
        ea->audio_stream_index = st->index;
328
        ea->audio_frame_counter = 0;
329
    }
330

    
331
    return 1;
332
}
333

    
334
static int ea_read_packet(AVFormatContext *s,
335
                          AVPacket *pkt)
336
{
337
    EaDemuxContext *ea = s->priv_data;
338
    ByteIOContext *pb = &s->pb;
339
    int ret = 0;
340
    int packet_read = 0;
341
    unsigned int chunk_type, chunk_size;
342
    int key = 0;
343

    
344
    while (!packet_read) {
345
        chunk_type = get_le32(pb);
346
        chunk_size = (ea->big_endian ? get_be32(pb) : get_le32(pb)) - 8;
347

    
348
        switch (chunk_type) {
349
        /* audio data */
350
        case _SNh_TAG:
351
            /* header chunk also contains data; skip over the header portion*/
352
            url_fskip(pb, 32);
353
            chunk_size -= 32;
354
        case _SNd_TAG:
355
        case SCDl_TAG:
356
            if (!ea->audio_codec) {
357
                url_fskip(pb, chunk_size);
358
                break;
359
            }
360
            ret = av_get_packet(pb, pkt, chunk_size);
361
            if (ret != chunk_size)
362
                ret = AVERROR(EIO);
363
            else {
364
                    pkt->stream_index = ea->audio_stream_index;
365
                    pkt->pts = 90000;
366
                    pkt->pts *= ea->audio_frame_counter;
367
                    pkt->pts /= ea->sample_rate;
368

    
369
                    switch (ea->audio_codec) {
370
                    case CODEC_ID_ADPCM_EA:
371
                    /* 2 samples/byte, 1 or 2 samples per frame depending
372
                     * on stereo; chunk also has 12-byte header */
373
                    ea->audio_frame_counter += ((chunk_size - 12) * 2) /
374
                        ea->num_channels;
375
                        break;
376
                    default:
377
                        ea->audio_frame_counter += chunk_size /
378
                            (ea->bytes * ea->num_channels);
379
                    }
380
            }
381

    
382
            packet_read = 1;
383
            break;
384

    
385
        /* ending tag */
386
        case 0:
387
        case _SNe_TAG:
388
        case SCEl_TAG:
389
            ret = AVERROR(EIO);
390
            packet_read = 1;
391
            break;
392

    
393
        case MV0K_TAG:
394
            key = PKT_FLAG_KEY;
395
        case MV0F_TAG:
396
            ret = av_get_packet(pb, pkt, chunk_size);
397
            if (ret != chunk_size)
398
                ret = AVERROR_IO;
399
            else {
400
                pkt->stream_index = ea->video_stream_index;
401
                pkt->flags |= key;
402
            }
403
            packet_read = 1;
404
            break;
405

    
406
        default:
407
            url_fseek(pb, chunk_size, SEEK_CUR);
408
            break;
409
        }
410
    }
411

    
412
    return ret;
413
}
414

    
415
AVInputFormat ea_demuxer = {
416
    "ea",
417
    "Electronic Arts Multimedia Format",
418
    sizeof(EaDemuxContext),
419
    ea_probe,
420
    ea_read_header,
421
    ea_read_packet,
422
};