VirtualBox

source: vbox/trunk/src/libs/ffmpeg-20060710/libavformat/westwood.c@ 9713

Last change on this file since 9713 was 5776, checked in by vboxsync, 17 years ago

ffmpeg: exported to OSE

File size: 11.8 KB
Line 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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#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
48/* don't know what these tags are for, but acknowledge their existence */
49#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
56#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
61typedef 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
70typedef 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
82static 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
113static 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 return AVERROR_IO;
123 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 av_set_pts_info(st, 33, 1, wsaud->audio_samplerate);
139 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
155static 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 return AVERROR_IO;
167
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 ret= av_get_packet(pb, pkt, chunk_size);
174 if (ret != chunk_size)
175 return AVERROR_IO;
176 pkt->stream_index = wsaud->audio_stream_index;
177 pkt->pts = wsaud->audio_frame_counter;
178 pkt->pts /= wsaud->audio_samplerate;
179
180 /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
181 wsaud->audio_frame_counter += (chunk_size * 2) / wsaud->audio_channels;
182
183 return ret;
184}
185
186static int wsaud_read_close(AVFormatContext *s)
187{
188// WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
189
190 return 0;
191}
192
193
194static int wsvqa_probe(AVProbeData *p)
195{
196 /* need 12 bytes to qualify */
197 if (p->buf_size < 12)
198 return 0;
199
200 /* check for the VQA signatures */
201 if ((BE_32(&p->buf[0]) != FORM_TAG) ||
202 (BE_32(&p->buf[8]) != WVQA_TAG))
203 return 0;
204
205 return AVPROBE_SCORE_MAX;
206}
207
208static int wsvqa_read_header(AVFormatContext *s,
209 AVFormatParameters *ap)
210{
211 WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
212 ByteIOContext *pb = &s->pb;
213 AVStream *st;
214 unsigned char *header;
215 unsigned char scratch[VQA_PREAMBLE_SIZE];
216 unsigned int chunk_tag;
217 unsigned int chunk_size;
218
219 /* initialize the video decoder stream */
220 st = av_new_stream(s, 0);
221 if (!st)
222 return AVERROR_NOMEM;
223 av_set_pts_info(st, 33, 1, 90000);
224 wsvqa->video_stream_index = st->index;
225 st->codec->codec_type = CODEC_TYPE_VIDEO;
226 st->codec->codec_id = CODEC_ID_WS_VQA;
227 st->codec->codec_tag = 0; /* no fourcc */
228
229 /* skip to the start of the VQA header */
230 url_fseek(pb, 20, SEEK_SET);
231
232 /* the VQA header needs to go to the decoder */
233 st->codec->extradata_size = VQA_HEADER_SIZE;
234 st->codec->extradata = av_mallocz(VQA_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
235 header = (unsigned char *)st->codec->extradata;
236 if (get_buffer(pb, st->codec->extradata, VQA_HEADER_SIZE) !=
237 VQA_HEADER_SIZE) {
238 av_free(st->codec->extradata);
239 return AVERROR_IO;
240 }
241 st->codec->width = LE_16(&header[6]);
242 st->codec->height = LE_16(&header[8]);
243
244 /* initialize the audio decoder stream is sample rate is non-zero */
245 if (LE_16(&header[24])) {
246 st = av_new_stream(s, 0);
247 if (!st)
248 return AVERROR_NOMEM;
249 av_set_pts_info(st, 33, 1, 90000);
250 st->codec->codec_type = CODEC_TYPE_AUDIO;
251 st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS;
252 st->codec->codec_tag = 0; /* no tag */
253 st->codec->sample_rate = LE_16(&header[24]);
254 st->codec->channels = header[26];
255 st->codec->bits_per_sample = 16;
256 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
257 st->codec->bits_per_sample / 4;
258 st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
259
260 wsvqa->audio_stream_index = st->index;
261 wsvqa->audio_samplerate = st->codec->sample_rate;
262 wsvqa->audio_channels = st->codec->channels;
263 wsvqa->audio_frame_counter = 0;
264 }
265
266 /* there are 0 or more chunks before the FINF chunk; iterate until
267 * FINF has been skipped and the file will be ready to be demuxed */
268 do {
269 if (get_buffer(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE) {
270 av_free(st->codec->extradata);
271 return AVERROR_IO;
272 }
273 chunk_tag = BE_32(&scratch[0]);
274 chunk_size = BE_32(&scratch[4]);
275
276 /* catch any unknown header tags, for curiousity */
277 switch (chunk_tag) {
278 case CINF_TAG:
279 case CINH_TAG:
280 case CIND_TAG:
281 case PINF_TAG:
282 case PINH_TAG:
283 case PIND_TAG:
284 case FINF_TAG:
285 break;
286
287 default:
288 av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n",
289 scratch[0], scratch[1],
290 scratch[2], scratch[3]);
291 break;
292 }
293
294 url_fseek(pb, chunk_size, SEEK_CUR);
295 } while (chunk_tag != FINF_TAG);
296
297 wsvqa->video_pts = wsvqa->audio_frame_counter = 0;
298
299 return 0;
300}
301
302static int wsvqa_read_packet(AVFormatContext *s,
303 AVPacket *pkt)
304{
305 WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
306 ByteIOContext *pb = &s->pb;
307 int ret = 0;
308 unsigned char preamble[VQA_PREAMBLE_SIZE];
309 unsigned int chunk_type;
310 unsigned int chunk_size;
311 int skip_byte;
312
313 if (get_buffer(pb, preamble, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE)
314 return AVERROR_IO;
315
316 chunk_type = BE_32(&preamble[0]);
317 chunk_size = BE_32(&preamble[4]);
318 skip_byte = chunk_size & 0x01;
319
320 if ((chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) {
321
322 av_get_packet(pb, pkt, chunk_size);
323 if (ret != chunk_size) {
324 ret = AVERROR_IO;
325 }
326
327 if (chunk_type == SND2_TAG) {
328 pkt->stream_index = wsvqa->audio_stream_index;
329
330 pkt->pts = 90000;
331 pkt->pts *= wsvqa->audio_frame_counter;
332 pkt->pts /= wsvqa->audio_samplerate;
333
334 /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
335 wsvqa->audio_frame_counter += (chunk_size * 2) /
336 wsvqa->audio_channels;
337 } else {
338 pkt->stream_index = wsvqa->video_stream_index;
339 pkt->pts = wsvqa->video_pts;
340 wsvqa->video_pts += VQA_VIDEO_PTS_INC;
341 }
342
343 } else
344 return AVERROR_INVALIDDATA;
345
346 /* stay on 16-bit alignment */
347 if (skip_byte)
348 url_fseek(pb, 1, SEEK_CUR);
349
350 return ret;
351}
352
353static int wsvqa_read_close(AVFormatContext *s)
354{
355// WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
356
357 return 0;
358}
359
360static AVInputFormat wsaud_demuxer = {
361 "wsaud",
362 "Westwood Studios audio format",
363 sizeof(WsAudDemuxContext),
364 wsaud_probe,
365 wsaud_read_header,
366 wsaud_read_packet,
367 wsaud_read_close,
368};
369
370static AVInputFormat wsvqa_demuxer = {
371 "wsvqa",
372 "Westwood Studios VQA format",
373 sizeof(WsVqaDemuxContext),
374 wsvqa_probe,
375 wsvqa_read_header,
376 wsvqa_read_packet,
377 wsvqa_read_close,
378};
379
380int westwood_init(void)
381{
382 av_register_input_format(&wsaud_demuxer);
383 av_register_input_format(&wsvqa_demuxer);
384 return 0;
385}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette