Statistics
| Branch: | Revision:

ffmpeg / libavformat / electronicarts.c @ f4097430

History | View | Annotate | Download (8.89 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 PT00_TAG MKTAG('P', 'T', 0x0, 0x0)
31
#define GSTR_TAG MKTAG('G', 'S', 'T', 'R')
32
#define SCDl_TAG MKTAG('S', 'C', 'D', 'l')
33
#define SCEl_TAG MKTAG('S', 'C', 'E', 'l')
34
#define MVhd_TAG MKTAG('M', 'V', 'h', 'd')
35
#define MV0K_TAG MKTAG('M', 'V', '0', 'K')
36
#define MV0F_TAG MKTAG('M', 'V', '0', 'F')
37

    
38
#define EA_SAMPLE_RATE 22050
39
#define EA_BITS_PER_SAMPLE 16
40
#define EA_PREAMBLE_SIZE 8
41

    
42
typedef struct EaDemuxContext {
43
    AVRational time_base;
44
    int video_stream_index;
45

    
46
    int audio_stream_index;
47
    int audio_frame_counter;
48

    
49
    int64_t audio_pts;
50

    
51
    int num_channels;
52
    int num_samples;
53
    int compression_type;
54
} EaDemuxContext;
55

    
56
static uint32_t read_arbitary(ByteIOContext *pb) {
57
    uint8_t size, byte;
58
    int i;
59
    uint32_t word;
60

    
61
    size = get_byte(pb);
62

    
63
    word = 0;
64
    for (i = 0; i < size; i++) {
65
        byte = get_byte(pb);
66
        word <<= 8;
67
        word |= byte;
68
    }
69

    
70
    return word;
71
}
72

    
73
/*
74
 * Process PT/GSTR sound header
75
 * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
76
 */
77
static int process_audio_header_elements(AVFormatContext *s)
78
{
79
    int inHeader = 1;
80
    EaDemuxContext *ea = s->priv_data;
81
    ByteIOContext *pb = &s->pb;
82

    
83
    ea->num_channels = 1;
84

    
85
    while (inHeader) {
86
        int inSubheader;
87
        uint8_t byte;
88
        byte = get_byte(pb);
89

    
90
        switch (byte) {
91
        case 0xFD:
92
            av_log (s, AV_LOG_INFO, "entered audio subheader\n");
93
            inSubheader = 1;
94
            while (inSubheader) {
95
                uint8_t subbyte;
96
                subbyte = get_byte(pb);
97

    
98
                switch (subbyte) {
99
                case 0x82:
100
                    ea->num_channels = read_arbitary(pb);
101
                    av_log (s, AV_LOG_INFO, "num_channels (element 0x82) set to 0x%08x\n", ea->num_channels);
102
                    break;
103
                case 0x83:
104
                    ea->compression_type = read_arbitary(pb);
105
                    av_log (s, AV_LOG_INFO, "compression_type (element 0x83) set to 0x%08x\n", ea->compression_type);
106
                    break;
107
                case 0x85:
108
                    ea->num_samples = read_arbitary(pb);
109
                    av_log (s, AV_LOG_INFO, "num_samples (element 0x85) set to 0x%08x\n", ea->num_samples);
110
                    break;
111
                case 0x8A:
112
                    av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
113
                    av_log (s, AV_LOG_INFO, "exited audio subheader\n");
114
                    inSubheader = 0;
115
                    break;
116
                case 0xFF:
117
                    av_log (s, AV_LOG_INFO, "end of header block reached (within audio subheader)\n");
118
                    inSubheader = 0;
119
                    inHeader = 0;
120
                    break;
121
                default:
122
                    av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
123
                    break;
124
                }
125
            }
126
            break;
127
        case 0xFF:
128
            av_log (s, AV_LOG_INFO, "end of header block reached\n");
129
            inHeader = 0;
130
            break;
131
        default:
132
            av_log (s, AV_LOG_INFO, "header element 0x%02x set to 0x%08x\n", byte, read_arbitary(pb));
133
            break;
134
        }
135
    }
136

    
137
    return 1;
138
}
139

    
140
static int process_video_header_vp6(AVFormatContext *s)
141
{
142
    EaDemuxContext *ea = s->priv_data;
143
    ByteIOContext *pb = &s->pb;
144

    
145
    url_fskip(pb, 16);
146
    ea->time_base.den = get_le32(pb);
147
    ea->time_base.num = get_le32(pb);
148

    
149
    return 1;
150
}
151

    
152
/*
153
 * Process EA file header
154
 * Returns 1 if the EA file is valid and successfully opened, 0 otherwise
155
 */
156
static int process_ea_header(AVFormatContext *s) {
157
    uint32_t blockid, size = 0;
158
    EaDemuxContext *ea = s->priv_data;
159
    ByteIOContext *pb = &s->pb;
160

    
161
    blockid = get_le32(pb);
162
    if (blockid == MVhd_TAG) {
163
        size = get_le32(pb);
164
        process_video_header_vp6(s);
165
        url_fskip(pb, size-32);
166
        blockid = get_le32(pb);
167
    }
168
    if (blockid != SCHl_TAG)
169
        return 0;
170
    size += get_le32(pb);
171
    blockid = get_le32(pb);
172
    if (blockid == GSTR_TAG) {
173
        url_fskip(pb, 4);
174
    } else if (blockid != PT00_TAG) {
175
        av_log (s, AV_LOG_ERROR, "PT header missing\n");
176
        return 0;
177
    }
178

    
179
    process_audio_header_elements(s);
180

    
181
    /* skip to the start of the data */
182
    url_fseek(pb, size, SEEK_SET);
183

    
184
    return 1;
185
}
186

    
187

    
188
static int ea_probe(AVProbeData *p)
189
{
190
    uint32_t tag;
191

    
192
    tag = AV_RL32(&p->buf[0]);
193
    if (tag == SCHl_TAG || tag == MVhd_TAG)
194
        return AVPROBE_SCORE_MAX;
195

    
196
    return 0;
197
}
198

    
199
static int ea_read_header(AVFormatContext *s,
200
                          AVFormatParameters *ap)
201
{
202
    EaDemuxContext *ea = s->priv_data;
203
    AVStream *st;
204

    
205
    if (!process_ea_header(s))
206
        return AVERROR(EIO);
207

    
208
    if (ea->time_base.num && ea->time_base.den) {
209
        /* initialize the video decoder stream */
210
        st = av_new_stream(s, 0);
211
        if (!st)
212
            return AVERROR(ENOMEM);
213
        ea->video_stream_index = st->index;
214
        st->codec->codec_type = CODEC_TYPE_VIDEO;
215
        st->codec->codec_id = CODEC_ID_VP6;
216
        st->codec->codec_tag = 0;  /* no fourcc */
217
        st->codec->time_base = ea->time_base;
218
    }
219

    
220
    /* initialize the audio decoder stream */
221
    st = av_new_stream(s, 0);
222
    if (!st)
223
        return AVERROR(ENOMEM);
224
    av_set_pts_info(st, 33, 1, EA_SAMPLE_RATE);
225
    st->codec->codec_type = CODEC_TYPE_AUDIO;
226
    st->codec->codec_id = CODEC_ID_ADPCM_EA;
227
    st->codec->codec_tag = 0;  /* no tag */
228
    st->codec->channels = ea->num_channels;
229
    st->codec->sample_rate = EA_SAMPLE_RATE;
230
    st->codec->bits_per_sample = EA_BITS_PER_SAMPLE;
231
    st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
232
        st->codec->bits_per_sample / 4;
233
    st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
234

    
235
    ea->audio_stream_index = st->index;
236
    ea->audio_frame_counter = 0;
237

    
238
    return 1;
239
}
240

    
241
static int ea_read_packet(AVFormatContext *s,
242
                          AVPacket *pkt)
243
{
244
    EaDemuxContext *ea = s->priv_data;
245
    ByteIOContext *pb = &s->pb;
246
    int ret = 0;
247
    int packet_read = 0;
248
    unsigned char preamble[EA_PREAMBLE_SIZE];
249
    unsigned int chunk_type, chunk_size;
250
    int key = 0;
251

    
252
    while (!packet_read) {
253

    
254
        if (get_buffer(pb, preamble, EA_PREAMBLE_SIZE) != EA_PREAMBLE_SIZE)
255
            return AVERROR(EIO);
256
        chunk_type = AV_RL32(&preamble[0]);
257
        chunk_size = AV_RL32(&preamble[4]) - EA_PREAMBLE_SIZE;
258

    
259
        switch (chunk_type) {
260
        /* audio data */
261
        case SCDl_TAG:
262
            ret = av_get_packet(pb, pkt, chunk_size);
263
            if (ret != chunk_size)
264
                ret = AVERROR(EIO);
265
            else {
266
                    pkt->stream_index = ea->audio_stream_index;
267
                    pkt->pts = 90000;
268
                    pkt->pts *= ea->audio_frame_counter;
269
                    pkt->pts /= EA_SAMPLE_RATE;
270

    
271
                    /* 2 samples/byte, 1 or 2 samples per frame depending
272
                     * on stereo; chunk also has 12-byte header */
273
                    ea->audio_frame_counter += ((chunk_size - 12) * 2) /
274
                        ea->num_channels;
275
            }
276

    
277
            packet_read = 1;
278
            break;
279

    
280
        /* ending tag */
281
        case SCEl_TAG:
282
            ret = AVERROR(EIO);
283
            packet_read = 1;
284
            break;
285

    
286
        case MV0K_TAG:
287
            key = PKT_FLAG_KEY;
288
        case MV0F_TAG:
289
            ret = av_get_packet(pb, pkt, chunk_size);
290
            if (ret != chunk_size)
291
                ret = AVERROR_IO;
292
            else {
293
                pkt->stream_index = ea->video_stream_index;
294
                pkt->flags |= key;
295
            }
296
            packet_read = 1;
297
            break;
298

    
299
        default:
300
            url_fseek(pb, chunk_size, SEEK_CUR);
301
            break;
302
        }
303
    }
304

    
305
    return ret;
306
}
307

    
308
AVInputFormat ea_demuxer = {
309
    "ea",
310
    "Electronic Arts Multimedia Format",
311
    sizeof(EaDemuxContext),
312
    ea_probe,
313
    ea_read_header,
314
    ea_read_packet,
315
};