Statistics
| Branch: | Revision:

ffmpeg / libavformat / electronicarts.c @ d9d9a8c0

History | View | Annotate | Download (15.9 KB)

1
/* Electronic Arts Multimedia File Demuxer
2
 * Copyright (c) 2004  The ffmpeg Project
3
 * Copyright (c) 2006-2008 Peter Ross
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
 * @file electronicarts.c
24
 * Electronic Arts Multimedia file demuxer (WVE/UV2/etc.)
25
 * by Robin Kay (komadori at gekkou.co.uk)
26
 */
27

    
28
#include "avformat.h"
29

    
30
#define SCHl_TAG MKTAG('S', 'C', 'H', 'l')
31
#define SEAD_TAG MKTAG('S', 'E', 'A', 'D')    /* Sxxx header */
32
#define SNDC_TAG MKTAG('S', 'N', 'D', 'C')    /* Sxxx data */
33
#define SEND_TAG MKTAG('S', 'E', 'N', 'D')    /* Sxxx end */
34
#define ISNh_TAG MKTAG('1', 'S', 'N', 'h')    /* 1SNx header */
35
#define EACS_TAG MKTAG('E', 'A', 'C', 'S')
36
#define ISNd_TAG MKTAG('1', 'S', 'N', 'd')    /* 1SNx data */
37
#define ISNe_TAG MKTAG('1', 'S', 'N', 'e')    /* 1SNx end */
38
#define PT00_TAG MKTAG('P', 'T', 0x0, 0x0)
39
#define GSTR_TAG MKTAG('G', 'S', 'T', 'R')
40
#define SCDl_TAG MKTAG('S', 'C', 'D', 'l')
41
#define SCEl_TAG MKTAG('S', 'C', 'E', 'l')
42
#define kVGT_TAG MKTAG('k', 'V', 'G', 'T')    /* TGV i-frame */
43
#define fVGT_TAG MKTAG('f', 'V', 'G', 'T')    /* TGV p-frame */
44
#define mTCD_TAG MKTAG('m', 'T', 'C', 'D')    /* MDEC */
45
#define MADk_TAG MKTAG('M', 'A', 'D', 'k')    /* MAD i-frame */
46
#define MPCh_TAG MKTAG('M', 'P', 'C', 'h')    /* MPEG2 */
47
#define MVhd_TAG MKTAG('M', 'V', 'h', 'd')
48
#define MV0K_TAG MKTAG('M', 'V', '0', 'K')
49
#define MV0F_TAG MKTAG('M', 'V', '0', 'F')
50
#define MVIh_TAG MKTAG('M', 'V', 'I', 'h')    /* CMV header */
51
#define MVIf_TAG MKTAG('M', 'V', 'I', 'f')    /* CMV i-frame */
52

    
53
typedef struct EaDemuxContext {
54
    int big_endian;
55

    
56
    enum CodecID video_codec;
57
    AVRational time_base;
58
    int width, height;
59
    int video_stream_index;
60

    
61
    enum CodecID audio_codec;
62
    int audio_stream_index;
63
    int audio_frame_counter;
64

    
65
    int64_t audio_pts;
66

    
67
    int bytes;
68
    int sample_rate;
69
    int num_channels;
70
    int num_samples;
71
} EaDemuxContext;
72

    
73
static uint32_t read_arbitary(ByteIOContext *pb) {
74
    uint8_t size, byte;
75
    int i;
76
    uint32_t word;
77

    
78
    size = get_byte(pb);
79

    
80
    word = 0;
81
    for (i = 0; i < size; i++) {
82
        byte = get_byte(pb);
83
        word <<= 8;
84
        word |= byte;
85
    }
86

    
87
    return word;
88
}
89

    
90
/*
91
 * Process PT/GSTR sound header
92
 * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
93
 */
94
static int process_audio_header_elements(AVFormatContext *s)
95
{
96
    int inHeader = 1;
97
    EaDemuxContext *ea = s->priv_data;
98
    ByteIOContext *pb = s->pb;
99
    int compression_type = -1, revision = -1, revision2 = -1;
100

    
101
    ea->bytes = 2;
102
    ea->sample_rate = -1;
103
    ea->num_channels = 1;
104

    
105
    while (inHeader) {
106
        int inSubheader;
107
        uint8_t byte;
108
        byte = get_byte(pb);
109

    
110
        switch (byte) {
111
        case 0xFD:
112
            av_log (s, AV_LOG_INFO, "entered audio subheader\n");
113
            inSubheader = 1;
114
            while (inSubheader) {
115
                uint8_t subbyte;
116
                subbyte = get_byte(pb);
117

    
118
                switch (subbyte) {
119
                case 0x80:
120
                    revision = read_arbitary(pb);
121
                    av_log (s, AV_LOG_INFO, "revision (element 0x80) set to 0x%08x\n", revision);
122
                    break;
123
                case 0x82:
124
                    ea->num_channels = read_arbitary(pb);
125
                    av_log (s, AV_LOG_INFO, "num_channels (element 0x82) set to 0x%08x\n", ea->num_channels);
126
                    break;
127
                case 0x83:
128
                    compression_type = read_arbitary(pb);
129
                    av_log (s, AV_LOG_INFO, "compression_type (element 0x83) set to 0x%08x\n", compression_type);
130
                    break;
131
                case 0x84:
132
                    ea->sample_rate = read_arbitary(pb);
133
                    av_log (s, AV_LOG_INFO, "sample_rate (element 0x84) set to %i\n", ea->sample_rate);
134
                    break;
135
                case 0x85:
136
                    ea->num_samples = read_arbitary(pb);
137
                    av_log (s, AV_LOG_INFO, "num_samples (element 0x85) set to 0x%08x\n", ea->num_samples);
138
                    break;
139
                case 0x8A:
140
                    av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
141
                    av_log (s, AV_LOG_INFO, "exited audio subheader\n");
142
                    inSubheader = 0;
143
                    break;
144
                case 0xA0:
145
                    revision2 = read_arbitary(pb);
146
                    av_log (s, AV_LOG_INFO, "revision2 (element 0xA0) set to 0x%08x\n", revision2);
147
                    break;
148
                case 0xFF:
149
                    av_log (s, AV_LOG_INFO, "end of header block reached (within audio subheader)\n");
150
                    inSubheader = 0;
151
                    inHeader = 0;
152
                    break;
153
                default:
154
                    av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
155
                    break;
156
                }
157
            }
158
            break;
159
        case 0xFF:
160
            av_log (s, AV_LOG_INFO, "end of header block reached\n");
161
            inHeader = 0;
162
            break;
163
        default:
164
            av_log (s, AV_LOG_INFO, "header element 0x%02x set to 0x%08x\n", byte, read_arbitary(pb));
165
            break;
166
        }
167
    }
168

    
169
    switch (compression_type) {
170
    case  0: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
171
    case  7: ea->audio_codec = CODEC_ID_ADPCM_EA; break;
172
    case -1:
173
        switch (revision) {
174
        case  1: ea->audio_codec = CODEC_ID_ADPCM_EA_R1; break;
175
        case  2: ea->audio_codec = CODEC_ID_ADPCM_EA_R2; break;
176
        case  3: ea->audio_codec = CODEC_ID_ADPCM_EA_R3; break;
177
        case -1: break;
178
        default:
179
            av_log(s, AV_LOG_ERROR, "unsupported stream type; revision=%i\n", revision);
180
            return 0;
181
        }
182
        switch (revision2) {
183
        case  8: ea->audio_codec = CODEC_ID_PCM_S16LE_PLANAR; break;
184
        case -1: break;
185
        default:
186
            av_log(s, AV_LOG_ERROR, "unsupported stream type; revision2=%i\n", revision2);
187
            return 0;
188
        }
189
        break;
190
    default:
191
        av_log(s, AV_LOG_ERROR, "unsupported stream type; compression_type=%i\n", compression_type);
192
        return 0;
193
    }
194

    
195
    if (ea->sample_rate == -1)
196
        ea->sample_rate = revision==3 ? 48000 : 22050;
197

    
198
    return 1;
199
}
200

    
201
/*
202
 * Process EACS sound header
203
 * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
204
 */
205
static int process_audio_header_eacs(AVFormatContext *s)
206
{
207
    EaDemuxContext *ea = s->priv_data;
208
    ByteIOContext *pb = s->pb;
209
    int compression_type;
210

    
211
    ea->sample_rate  = ea->big_endian ? get_be32(pb) : get_le32(pb);
212
    ea->bytes        = get_byte(pb);   /* 1=8-bit, 2=16-bit */
213
    ea->num_channels = get_byte(pb);
214
    compression_type = get_byte(pb);
215
    url_fskip(pb, 13);
216

    
217
    switch (compression_type) {
218
    case 0:
219
        switch (ea->bytes) {
220
        case 1: ea->audio_codec = CODEC_ID_PCM_S8;    break;
221
        case 2: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
222
        }
223
        break;
224
    case 1: ea->audio_codec = CODEC_ID_PCM_MULAW; ea->bytes = 1; break;
225
    case 2: ea->audio_codec = CODEC_ID_ADPCM_IMA_EA_EACS; break;
226
    default:
227
        av_log (s, AV_LOG_ERROR, "unsupported stream type; audio compression_type=%i\n", compression_type);
228
    }
229

    
230
    return 1;
231
}
232

    
233
/*
234
 * Process SEAD sound header
235
 * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
236
 */
237
static int process_audio_header_sead(AVFormatContext *s)
238
{
239
    EaDemuxContext *ea = s->priv_data;
240
    ByteIOContext *pb = s->pb;
241

    
242
    ea->sample_rate  = get_le32(pb);
243
    ea->bytes        = get_le32(pb);  /* 1=8-bit, 2=16-bit */
244
    ea->num_channels = get_le32(pb);
245
    ea->audio_codec  = CODEC_ID_ADPCM_IMA_EA_SEAD;
246

    
247
    return 1;
248
}
249

    
250
static int process_video_header_mdec(AVFormatContext *s)
251
{
252
    EaDemuxContext *ea = s->priv_data;
253
    ByteIOContext *pb = s->pb;
254
    url_fskip(pb, 4);
255
    ea->width  = get_le16(pb);
256
    ea->height = get_le16(pb);
257
    ea->time_base = (AVRational){1,15};
258
    ea->video_codec = CODEC_ID_MDEC;
259
    return 1;
260
}
261

    
262
static int process_video_header_vp6(AVFormatContext *s)
263
{
264
    EaDemuxContext *ea = s->priv_data;
265
    ByteIOContext *pb = s->pb;
266

    
267
    url_fskip(pb, 16);
268
    ea->time_base.den = get_le32(pb);
269
    ea->time_base.num = get_le32(pb);
270
    ea->video_codec = CODEC_ID_VP6;
271

    
272
    return 1;
273
}
274

    
275
/*
276
 * Process EA file header
277
 * Returns 1 if the EA file is valid and successfully opened, 0 otherwise
278
 */
279
static int process_ea_header(AVFormatContext *s) {
280
    uint32_t blockid, size = 0;
281
    EaDemuxContext *ea = s->priv_data;
282
    ByteIOContext *pb = s->pb;
283
    int i;
284

    
285
    for (i=0; i<5 && (!ea->audio_codec || !ea->video_codec); i++) {
286
        unsigned int startpos = url_ftell(pb);
287
        int err = 0;
288

    
289
        blockid = get_le32(pb);
290
        size = get_le32(pb);
291
        if (i == 0)
292
            ea->big_endian = size > 0x000FFFFF;
293
        if (ea->big_endian)
294
            size = bswap_32(size);
295

    
296
        switch (blockid) {
297
            case ISNh_TAG:
298
                if (get_le32(pb) != EACS_TAG) {
299
                    av_log (s, AV_LOG_ERROR, "unknown 1SNh headerid\n");
300
                    return 0;
301
                }
302
                err = process_audio_header_eacs(s);
303
                break;
304

    
305
            case SCHl_TAG :
306
                blockid = get_le32(pb);
307
                if (blockid == GSTR_TAG) {
308
                    url_fskip(pb, 4);
309
                } else if (blockid != PT00_TAG) {
310
                    av_log (s, AV_LOG_ERROR, "unknown SCHl headerid\n");
311
                    return 0;
312
                }
313
                err = process_audio_header_elements(s);
314
                break;
315

    
316
            case SEAD_TAG:
317
                err = process_audio_header_sead(s);
318
                break;
319

    
320
            case MVIh_TAG :
321
                ea->video_codec = CODEC_ID_CMV;
322
                ea->time_base = (AVRational){0,0};
323
                break;
324

    
325
            case kVGT_TAG:
326
                ea->video_codec = CODEC_ID_TGV;
327
                ea->time_base = (AVRational){0,0};
328
                break;
329

    
330
            case mTCD_TAG :
331
                err = process_video_header_mdec(s);
332
                break;
333

    
334
            case MVhd_TAG :
335
                err = process_video_header_vp6(s);
336
                break;
337
        }
338

    
339
        if (err < 0) {
340
            av_log(s, AV_LOG_ERROR, "error parsing header: %i\n", err);
341
            return err;
342
        }
343

    
344
        url_fseek(pb, startpos + size, SEEK_SET);
345
    }
346

    
347
    url_fseek(pb, 0, SEEK_SET);
348

    
349
    return 1;
350
}
351

    
352

    
353
static int ea_probe(AVProbeData *p)
354
{
355
    switch (AV_RL32(&p->buf[0])) {
356
    case ISNh_TAG:
357
    case SCHl_TAG:
358
    case SEAD_TAG:
359
    case kVGT_TAG:
360
    case MADk_TAG:
361
    case MPCh_TAG:
362
    case MVhd_TAG:
363
    case MVIh_TAG:
364
        return AVPROBE_SCORE_MAX;
365
    }
366
    return 0;
367
}
368

    
369
static int ea_read_header(AVFormatContext *s,
370
                          AVFormatParameters *ap)
371
{
372
    EaDemuxContext *ea = s->priv_data;
373
    AVStream *st;
374

    
375
    if (!process_ea_header(s))
376
        return AVERROR(EIO);
377

    
378
    if (ea->video_codec) {
379
        /* initialize the video decoder stream */
380
        st = av_new_stream(s, 0);
381
        if (!st)
382
            return AVERROR(ENOMEM);
383
        ea->video_stream_index = st->index;
384
        st->codec->codec_type = CODEC_TYPE_VIDEO;
385
        st->codec->codec_id = ea->video_codec;
386
        st->codec->codec_tag = 0;  /* no fourcc */
387
        st->codec->time_base = ea->time_base;
388
        st->codec->width = ea->width;
389
        st->codec->height = ea->height;
390
    }
391

    
392
    if (ea->audio_codec) {
393
        /* initialize the audio decoder stream */
394
        st = av_new_stream(s, 0);
395
        if (!st)
396
            return AVERROR(ENOMEM);
397
        av_set_pts_info(st, 33, 1, ea->sample_rate);
398
        st->codec->codec_type = CODEC_TYPE_AUDIO;
399
        st->codec->codec_id = ea->audio_codec;
400
        st->codec->codec_tag = 0;  /* no tag */
401
        st->codec->channels = ea->num_channels;
402
        st->codec->sample_rate = ea->sample_rate;
403
        st->codec->bits_per_sample = ea->bytes * 8;
404
        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
405
            st->codec->bits_per_sample / 4;
406
        st->codec->block_align = st->codec->channels*st->codec->bits_per_sample;
407
        ea->audio_stream_index = st->index;
408
        ea->audio_frame_counter = 0;
409
    }
410

    
411
    return 1;
412
}
413

    
414
static int ea_read_packet(AVFormatContext *s,
415
                          AVPacket *pkt)
416
{
417
    EaDemuxContext *ea = s->priv_data;
418
    ByteIOContext *pb = s->pb;
419
    int ret = 0;
420
    int packet_read = 0;
421
    unsigned int chunk_type, chunk_size;
422
    int key = 0;
423

    
424
    while (!packet_read) {
425
        chunk_type = get_le32(pb);
426
        chunk_size = (ea->big_endian ? get_be32(pb) : get_le32(pb)) - 8;
427

    
428
        switch (chunk_type) {
429
        /* audio data */
430
        case ISNh_TAG:
431
            /* header chunk also contains data; skip over the header portion*/
432
            url_fskip(pb, 32);
433
            chunk_size -= 32;
434
        case ISNd_TAG:
435
        case SCDl_TAG:
436
        case SNDC_TAG:
437
            if (!ea->audio_codec) {
438
                url_fskip(pb, chunk_size);
439
                break;
440
            } else if (ea->audio_codec == CODEC_ID_PCM_S16LE_PLANAR) {
441
                url_fskip(pb, 12);  /* planar header */
442
                chunk_size -= 12;
443
            }
444
            ret = av_get_packet(pb, pkt, chunk_size);
445
            if (ret != chunk_size)
446
                ret = AVERROR(EIO);
447
            else {
448
                    pkt->stream_index = ea->audio_stream_index;
449
                    pkt->pts = 90000;
450
                    pkt->pts *= ea->audio_frame_counter;
451
                    pkt->pts /= ea->sample_rate;
452

    
453
                    switch (ea->audio_codec) {
454
                    case CODEC_ID_ADPCM_EA:
455
                    /* 2 samples/byte, 1 or 2 samples per frame depending
456
                     * on stereo; chunk also has 12-byte header */
457
                    ea->audio_frame_counter += ((chunk_size - 12) * 2) /
458
                        ea->num_channels;
459
                        break;
460
                    default:
461
                        ea->audio_frame_counter += chunk_size /
462
                            (ea->bytes * ea->num_channels);
463
                    }
464
            }
465

    
466
            packet_read = 1;
467
            break;
468

    
469
        /* ending tag */
470
        case 0:
471
        case ISNe_TAG:
472
        case SCEl_TAG:
473
        case SEND_TAG:
474
            ret = AVERROR(EIO);
475
            packet_read = 1;
476
            break;
477

    
478
        case MVIh_TAG:
479
        case kVGT_TAG:
480
            key = PKT_FLAG_KEY;
481
        case MVIf_TAG:
482
        case fVGT_TAG:
483
            url_fseek(pb, -8, SEEK_CUR);     // include chunk preamble
484
            chunk_size += 8;
485
            goto get_video_packet;
486

    
487
        case mTCD_TAG:
488
            url_fseek(pb, 8, SEEK_CUR);  // skip ea dct header
489
            chunk_size -= 8;
490
            goto get_video_packet;
491

    
492
        case MV0K_TAG:
493
            key = PKT_FLAG_KEY;
494
        case MV0F_TAG:
495
get_video_packet:
496
            ret = av_get_packet(pb, pkt, chunk_size);
497
            if (ret != chunk_size)
498
                ret = AVERROR_IO;
499
            else {
500
                pkt->stream_index = ea->video_stream_index;
501
                pkt->flags |= key;
502
            }
503
            packet_read = 1;
504
            break;
505

    
506
        default:
507
            url_fseek(pb, chunk_size, SEEK_CUR);
508
            break;
509
        }
510
    }
511

    
512
    return ret;
513
}
514

    
515
AVInputFormat ea_demuxer = {
516
    "ea",
517
    NULL_IF_CONFIG_SMALL("Electronic Arts Multimedia Format"),
518
    sizeof(EaDemuxContext),
519
    ea_probe,
520
    ea_read_header,
521
    ea_read_packet,
522
};