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