Statistics
| Branch: | Revision:

ffmpeg / libavformat / westwood.c @ 7be806f3

History | View | Annotate | Download (11.9 KB)

1 2fdf638b Mike Melanson
/*
2
 * Westwood Studios Multimedia Formats Demuxer (VQA, AUD)
3
 * Copyright (c) 2003 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19
20
/**
21
 * @file westwood.c
22
 * Westwood Studios VQA & AUD file demuxers
23
 * by Mike Melanson (melanson@pcisys.net)
24
 * for more information on the Westwood file formats, visit:
25
 *   http://www.pcisys.net/~melanson/codecs/
26
 *   http://www.geocities.com/SiliconValley/8682/aud3.txt
27
 *
28
 * Implementation note: There is no definite file signature for AUD files.
29
 * The demuxer uses a probabilistic strategy for content detection. This
30
 * entails performing sanity checks on certain header values in order to
31
 * qualify a file. Refer to wsaud_probe() for the precise parameters.
32
 */
33
34
#include "avformat.h"
35
36
#define AUD_HEADER_SIZE 12
37
#define AUD_CHUNK_PREAMBLE_SIZE 8
38
#define AUD_CHUNK_SIGNATURE 0x0000DEAF
39
40 3a278992 Mike Melanson
#define FORM_TAG MKBETAG('F', 'O', 'R', 'M')
41
#define WVQA_TAG MKBETAG('W', 'V', 'Q', 'A')
42
#define VQHD_TAG MKBETAG('V', 'Q', 'H', 'D')
43
#define FINF_TAG MKBETAG('F', 'I', 'N', 'F')
44
#define SND0_TAG MKBETAG('S', 'N', 'D', '0')
45
#define SND2_TAG MKBETAG('S', 'N', 'D', '2')
46
#define VQFR_TAG MKBETAG('V', 'Q', 'F', 'R')
47 2fdf638b Mike Melanson
48 20f269dc Mike Melanson
/* don't know what these tags are for, but acknowledge their existence */
49 3a278992 Mike Melanson
#define CINF_TAG MKBETAG('C', 'I', 'N', 'F')
50
#define CINH_TAG MKBETAG('C', 'I', 'N', 'H')
51
#define CIND_TAG MKBETAG('C', 'I', 'N', 'D')
52
#define PINF_TAG MKBETAG('P', 'I', 'N', 'F')
53
#define PINH_TAG MKBETAG('P', 'I', 'N', 'H')
54
#define PIND_TAG MKBETAG('P', 'I', 'N', 'D')
55 20f269dc Mike Melanson
56 2fdf638b Mike Melanson
#define VQA_HEADER_SIZE 0x2A
57
#define VQA_FRAMERATE 15
58
#define VQA_VIDEO_PTS_INC (90000 / VQA_FRAMERATE)
59
#define VQA_PREAMBLE_SIZE 8
60
61
typedef struct WsAudDemuxContext {
62
    int audio_samplerate;
63
    int audio_channels;
64
    int audio_bits;
65
    int audio_type;
66
    int audio_stream_index;
67
    int64_t audio_frame_counter;
68
} WsAudDemuxContext;
69
70
typedef struct WsVqaDemuxContext {
71
    int audio_samplerate;
72
    int audio_channels;
73
    int audio_bits;
74
75
    int audio_stream_index;
76
    int video_stream_index;
77
78
    int64_t audio_frame_counter;
79
    int64_t video_pts;
80
} WsVqaDemuxContext;
81
82
static int wsaud_probe(AVProbeData *p)
83
{
84
    int field;
85
86
    /* Probabilistic content detection strategy: There is no file signature
87
     * so perform sanity checks on various header parameters:
88
     *   8000 <= sample rate (16 bits) <= 48000  ==> 40001 acceptable numbers
89
     *   compression type (8 bits) = 1 or 99     ==> 2 acceptable numbers
90
     * There is a total of 24 bits. The number space contains 2^24 =
91
     * 16777216 numbers. There are 40001 * 2 = 80002 acceptable combinations
92
     * of numbers. There is a 80002/16777216 = 0.48% chance of a false
93
     * positive.
94
     */
95
96
    if (p->buf_size < AUD_HEADER_SIZE)
97
        return 0;
98
99
    /* check sample rate */
100
    field = LE_16(&p->buf[0]);
101
    if ((field < 8000) || (field > 48000))
102
        return 0;
103
104
    /* note: only check for WS IMA (type 99) right now since there is no 
105
     * support for type 1 */
106
    if (p->buf[11] != 99)
107
        return 0;
108
109
    /* return 1/2 certainty since this file check is a little sketchy */
110
    return AVPROBE_SCORE_MAX / 2;
111
}
112
113
static int wsaud_read_header(AVFormatContext *s,
114
                             AVFormatParameters *ap)
115
{
116
    WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
117
    ByteIOContext *pb = &s->pb;
118
    AVStream *st;
119
    unsigned char header[AUD_HEADER_SIZE];
120
121
    if (get_buffer(pb, header, AUD_HEADER_SIZE) != AUD_HEADER_SIZE)
122 0bd586c5 Mike Melanson
        return AVERROR_IO;
123 2fdf638b Mike Melanson
    wsaud->audio_samplerate = LE_16(&header[0]);
124
    if (header[11] == 99)
125
        wsaud->audio_type = CODEC_ID_ADPCM_IMA_WS;
126
    else
127
        return AVERROR_INVALIDDATA;
128
129
    /* flag 0 indicates stereo */
130
    wsaud->audio_channels = (header[10] & 0x1) + 1;
131
    /* flag 1 indicates 16 bit audio */
132
    wsaud->audio_bits = (((header[10] & 0x2) >> 1) + 1) * 8;
133
134
    /* initialize the audio decoder stream */
135
    st = av_new_stream(s, 0);
136
    if (!st)
137
        return AVERROR_NOMEM;
138 9ee91c2f Michael Niedermayer
    av_set_pts_info(st, 33, 1, wsaud->audio_samplerate);
139 2fdf638b Mike Melanson
    st->codec.codec_type = CODEC_TYPE_AUDIO;
140
    st->codec.codec_id = wsaud->audio_type;
141
    st->codec.codec_tag = 0;  /* no tag */
142
    st->codec.channels = wsaud->audio_channels;
143
    st->codec.sample_rate = wsaud->audio_samplerate;
144
    st->codec.bits_per_sample = wsaud->audio_bits;
145
    st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
146
        st->codec.bits_per_sample / 4;
147
    st->codec.block_align = st->codec.channels * st->codec.bits_per_sample;
148
149
    wsaud->audio_stream_index = st->index;
150
    wsaud->audio_frame_counter = 0;
151
152
    return 0;
153
}
154
155
static int wsaud_read_packet(AVFormatContext *s,
156
                             AVPacket *pkt)
157
{
158
    WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
159
    ByteIOContext *pb = &s->pb;
160
    unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE];
161
    unsigned int chunk_size;
162
    int ret = 0;
163
164
    if (get_buffer(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) !=
165
        AUD_CHUNK_PREAMBLE_SIZE)
166 0bd586c5 Mike Melanson
        return AVERROR_IO;
167 2fdf638b Mike Melanson
168
    /* validate the chunk */
169
    if (LE_32(&preamble[4]) != AUD_CHUNK_SIGNATURE)
170
        return AVERROR_INVALIDDATA;
171
172
    chunk_size = LE_16(&preamble[0]);
173
    if (av_new_packet(pkt, chunk_size))
174 0bd586c5 Mike Melanson
        return AVERROR_IO;
175 2fdf638b Mike Melanson
    pkt->stream_index = wsaud->audio_stream_index;
176
    pkt->pts = wsaud->audio_frame_counter;
177
    pkt->pts /= wsaud->audio_samplerate;
178
    if ((ret = get_buffer(pb, pkt->data, chunk_size)) != chunk_size) {
179
        av_free_packet(pkt);
180 0bd586c5 Mike Melanson
        ret = AVERROR_IO;
181 2fdf638b Mike Melanson
    }
182
183
    /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
184
    wsaud->audio_frame_counter += (chunk_size * 2) / wsaud->audio_channels;
185
186
    return ret;
187
}
188
189
static int wsaud_read_close(AVFormatContext *s)
190
{
191
//    WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
192
193
    return 0;
194
}
195
196
197
static int wsvqa_probe(AVProbeData *p)
198
{
199
    /* need 12 bytes to qualify */
200
    if (p->buf_size < 12)
201
        return 0;
202
203
    /* check for the VQA signatures */
204
    if ((BE_32(&p->buf[0]) != FORM_TAG) ||
205
        (BE_32(&p->buf[8]) != WVQA_TAG))
206
        return 0;
207
208
    return AVPROBE_SCORE_MAX;
209
}
210
211
static int wsvqa_read_header(AVFormatContext *s,
212
                             AVFormatParameters *ap)
213
{
214
    WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
215
    ByteIOContext *pb = &s->pb;
216
    AVStream *st;
217
    unsigned char *header;
218
    unsigned char scratch[VQA_PREAMBLE_SIZE];
219 20f269dc Mike Melanson
    unsigned int chunk_tag;
220
    unsigned int chunk_size;
221 2fdf638b Mike Melanson
222
    /* initialize the video decoder stream */
223
    st = av_new_stream(s, 0);
224
    if (!st)
225
        return AVERROR_NOMEM;
226 9ee91c2f Michael Niedermayer
    av_set_pts_info(st, 33, 1, 90000);
227 2fdf638b Mike Melanson
    wsvqa->video_stream_index = st->index;
228
    st->codec.codec_type = CODEC_TYPE_VIDEO;
229
    st->codec.codec_id = CODEC_ID_WS_VQA;
230
    st->codec.codec_tag = 0;  /* no fourcc */
231
232
    /* skip to the start of the VQA header */
233
    url_fseek(pb, 20, SEEK_SET);
234
235
    /* the VQA header needs to go to the decoder */
236
    st->codec.extradata_size = VQA_HEADER_SIZE;
237
    st->codec.extradata = av_malloc(VQA_HEADER_SIZE);
238
    header = (unsigned char *)st->codec.extradata;
239
    if (get_buffer(pb, st->codec.extradata, VQA_HEADER_SIZE) !=
240
        VQA_HEADER_SIZE) {
241
        av_free(st->codec.extradata);
242 0bd586c5 Mike Melanson
        return AVERROR_IO;
243 2fdf638b Mike Melanson
    }
244
    st->codec.width = LE_16(&header[6]);
245
    st->codec.height = LE_16(&header[8]);
246
247 20f269dc Mike Melanson
    /* initialize the audio decoder stream is sample rate is non-zero */
248
    if (LE_16(&header[24])) {
249
        st = av_new_stream(s, 0);
250
        if (!st)
251
            return AVERROR_NOMEM;
252 9ee91c2f Michael Niedermayer
        av_set_pts_info(st, 33, 1, 90000);
253 20f269dc Mike Melanson
        st->codec.codec_type = CODEC_TYPE_AUDIO;
254
        st->codec.codec_id = CODEC_ID_ADPCM_IMA_WS;
255
        st->codec.codec_tag = 0;  /* no tag */
256
        st->codec.sample_rate = LE_16(&header[24]);
257
        st->codec.channels = header[26];
258
        st->codec.bits_per_sample = 16;
259
        st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
260
            st->codec.bits_per_sample / 4;
261
        st->codec.block_align = st->codec.channels * st->codec.bits_per_sample;
262
263
        wsvqa->audio_stream_index = st->index;
264
        wsvqa->audio_samplerate = st->codec.sample_rate;
265
        wsvqa->audio_channels = st->codec.channels;
266
        wsvqa->audio_frame_counter = 0;
267
    }
268 2fdf638b Mike Melanson
269 20f269dc Mike Melanson
    /* there are 0 or more chunks before the FINF chunk; iterate until
270
     * FINF has been skipped and the file will be ready to be demuxed */
271
    do {
272
        if (get_buffer(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE) {
273
            av_free(st->codec.extradata);
274 0bd586c5 Mike Melanson
            return AVERROR_IO;
275 20f269dc Mike Melanson
        }
276
        chunk_tag = BE_32(&scratch[0]);
277
        chunk_size = BE_32(&scratch[4]);
278
279
        /* catch any unknown header tags, for curiousity */
280
        switch (chunk_tag) {
281
        case CINF_TAG:
282
        case CINH_TAG:
283
        case CIND_TAG:
284
        case PINF_TAG:
285
        case PINH_TAG:
286
        case PIND_TAG:
287
        case FINF_TAG:
288
            break;
289
290
        default:
291 bc874dae Michel Bardiaux
            av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n",
292 20f269dc Mike Melanson
                scratch[0], scratch[1],
293
                scratch[2], scratch[3]);
294
            break;
295
        }
296
297
        url_fseek(pb, chunk_size, SEEK_CUR);
298
    } while (chunk_tag != FINF_TAG);
299 2fdf638b Mike Melanson
300
    wsvqa->video_pts = wsvqa->audio_frame_counter = 0;
301
302
    return 0;
303
}
304
305
static int wsvqa_read_packet(AVFormatContext *s,
306
                             AVPacket *pkt)
307
{
308
    WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
309
    ByteIOContext *pb = &s->pb;
310
    int ret = 0;
311
    unsigned char preamble[VQA_PREAMBLE_SIZE];
312
    unsigned int chunk_type;
313
    unsigned int chunk_size;
314
    int skip_byte;
315
316
    if (get_buffer(pb, preamble, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE)
317 0bd586c5 Mike Melanson
        return AVERROR_IO;
318 2fdf638b Mike Melanson
319
    chunk_type = BE_32(&preamble[0]);
320
    chunk_size = BE_32(&preamble[4]);
321
    skip_byte = chunk_size & 0x01;
322
323
    if ((chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) {
324
325
        if (av_new_packet(pkt, chunk_size))
326 0bd586c5 Mike Melanson
            return AVERROR_IO;
327 2fdf638b Mike Melanson
        ret = get_buffer(pb, pkt->data, chunk_size);
328
        if (ret != chunk_size) {
329
            av_free_packet(pkt);
330 0bd586c5 Mike Melanson
            ret = AVERROR_IO;
331 2fdf638b Mike Melanson
        }
332
333
        if (chunk_type == SND2_TAG) {
334
            pkt->stream_index = wsvqa->audio_stream_index;
335
336
            pkt->pts = 90000;
337
            pkt->pts *= wsvqa->audio_frame_counter;
338
            pkt->pts /= wsvqa->audio_samplerate;
339
340
            /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
341
            wsvqa->audio_frame_counter += (chunk_size * 2) / 
342
                wsvqa->audio_channels;
343
        } else {
344
            pkt->stream_index = wsvqa->video_stream_index;
345
            pkt->pts = wsvqa->video_pts;
346
            wsvqa->video_pts += VQA_VIDEO_PTS_INC;
347
        }
348
349
    } else
350
        return AVERROR_INVALIDDATA;
351
352
    /* stay on 16-bit alignment */
353
    if (skip_byte)
354
        url_fseek(pb, 1, SEEK_CUR);
355
356
    return ret;
357
}
358
359
static int wsvqa_read_close(AVFormatContext *s)
360
{
361
//    WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
362
363
    return 0;
364
}
365
366
static AVInputFormat wsaud_iformat = {
367
    "wsaud",
368
    "Westwood Studios audio format",
369
    sizeof(WsAudDemuxContext),
370
    wsaud_probe,
371
    wsaud_read_header,
372
    wsaud_read_packet,
373
    wsaud_read_close,
374
};
375
376
static AVInputFormat wsvqa_iformat = {
377
    "wsvqa",
378
    "Westwood Studios VQA format",
379
    sizeof(WsVqaDemuxContext),
380
    wsvqa_probe,
381
    wsvqa_read_header,
382
    wsvqa_read_packet,
383
    wsvqa_read_close,
384
};
385
386
int westwood_init(void)
387
{
388
    av_register_input_format(&wsaud_iformat);
389
    av_register_input_format(&wsvqa_iformat);
390
    return 0;
391
}