FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
westwood_vqa.c
Go to the documentation of this file.
1
/*
2
* Westwood Studios VQA Format Demuxer
3
* Copyright (c) 2003 The ffmpeg Project
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
24
* Westwood Studios VQA file demuxer
25
* by Mike Melanson (melanson@pcisys.net)
26
* for more information on the Westwood file formats, visit:
27
* http://www.pcisys.net/~melanson/codecs/
28
* http://www.geocities.com/SiliconValley/8682/aud3.txt
29
*/
30
31
#include "
libavutil/intreadwrite.h
"
32
#include "
avformat.h
"
33
#include "
internal.h
"
34
35
#define FORM_TAG MKBETAG('F', 'O', 'R', 'M')
36
#define WVQA_TAG MKBETAG('W', 'V', 'Q', 'A')
37
#define VQHD_TAG MKBETAG('V', 'Q', 'H', 'D')
38
#define FINF_TAG MKBETAG('F', 'I', 'N', 'F')
39
#define SND0_TAG MKBETAG('S', 'N', 'D', '0')
40
#define SND1_TAG MKBETAG('S', 'N', 'D', '1')
41
#define SND2_TAG MKBETAG('S', 'N', 'D', '2')
42
#define VQFR_TAG MKBETAG('V', 'Q', 'F', 'R')
43
44
/* don't know what these tags are for, but acknowledge their existence */
45
#define CINF_TAG MKBETAG('C', 'I', 'N', 'F')
46
#define CINH_TAG MKBETAG('C', 'I', 'N', 'H')
47
#define CIND_TAG MKBETAG('C', 'I', 'N', 'D')
48
#define PINF_TAG MKBETAG('P', 'I', 'N', 'F')
49
#define PINH_TAG MKBETAG('P', 'I', 'N', 'H')
50
#define PIND_TAG MKBETAG('P', 'I', 'N', 'D')
51
#define CMDS_TAG MKBETAG('C', 'M', 'D', 'S')
52
53
#define VQA_HEADER_SIZE 0x2A
54
#define VQA_PREAMBLE_SIZE 8
55
56
typedef
struct
WsVqaDemuxContext
{
57
int
version
;
58
int
bps
;
59
int
channels
;
60
int
sample_rate
;
61
int
audio_stream_index
;
62
int
video_stream_index
;
63
}
WsVqaDemuxContext
;
64
65
static
int
wsvqa_probe
(
AVProbeData
*p)
66
{
67
/* need 12 bytes to qualify */
68
if
(p->
buf_size
< 12)
69
return
0;
70
71
/* check for the VQA signatures */
72
if
((
AV_RB32
(&p->
buf
[0]) !=
FORM_TAG
) ||
73
(
AV_RB32
(&p->
buf
[8]) !=
WVQA_TAG
))
74
return
0;
75
76
return
AVPROBE_SCORE_MAX
;
77
}
78
79
static
int
wsvqa_read_header
(
AVFormatContext
*
s
)
80
{
81
WsVqaDemuxContext
*wsvqa = s->
priv_data
;
82
AVIOContext
*pb = s->
pb
;
83
AVStream
*st;
84
unsigned
char
*header;
85
unsigned
char
scratch[
VQA_PREAMBLE_SIZE
];
86
unsigned
int
chunk_tag;
87
unsigned
int
chunk_size;
88
int
fps;
89
90
/* initialize the video decoder stream */
91
st =
avformat_new_stream
(s, NULL);
92
if
(!st)
93
return
AVERROR
(ENOMEM);
94
st->
start_time
= 0;
95
wsvqa->
video_stream_index
= st->
index
;
96
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
97
st->
codec
->
codec_id
=
AV_CODEC_ID_WS_VQA
;
98
st->
codec
->
codec_tag
= 0;
/* no fourcc */
99
100
/* skip to the start of the VQA header */
101
avio_seek
(pb, 20, SEEK_SET);
102
103
/* the VQA header needs to go to the decoder */
104
st->
codec
->
extradata
=
av_mallocz
(
VQA_HEADER_SIZE
+
FF_INPUT_BUFFER_PADDING_SIZE
);
105
if
(!st->
codec
->
extradata
)
106
return
AVERROR
(ENOMEM);
107
st->
codec
->
extradata_size
=
VQA_HEADER_SIZE
;
108
header = (
unsigned
char
*)st->
codec
->
extradata
;
109
if
(
avio_read
(pb, st->
codec
->
extradata
,
VQA_HEADER_SIZE
) !=
110
VQA_HEADER_SIZE
) {
111
return
AVERROR
(EIO);
112
}
113
st->
codec
->
width
=
AV_RL16
(&header[6]);
114
st->
codec
->
height
=
AV_RL16
(&header[8]);
115
fps = header[12];
116
st->
nb_frames
=
117
st->
duration
=
AV_RL16
(&header[4]);
118
if
(fps < 1 || fps > 30) {
119
av_log
(s,
AV_LOG_ERROR
,
"invalid fps: %d\n"
, fps);
120
return
AVERROR_INVALIDDATA
;
121
}
122
avpriv_set_pts_info
(st, 64, 1, fps);
123
124
wsvqa->
version
=
AV_RL16
(&header[ 0]);
125
wsvqa->
sample_rate
=
AV_RL16
(&header[24]);
126
wsvqa->
channels
= header[26];
127
wsvqa->
bps
= header[27];
128
wsvqa->
audio_stream_index
= -1;
129
130
s->
ctx_flags
|=
AVFMTCTX_NOHEADER
;
131
132
/* there are 0 or more chunks before the FINF chunk; iterate until
133
* FINF has been skipped and the file will be ready to be demuxed */
134
do
{
135
if
(
avio_read
(pb, scratch,
VQA_PREAMBLE_SIZE
) !=
VQA_PREAMBLE_SIZE
)
136
return
AVERROR
(EIO);
137
chunk_tag =
AV_RB32
(&scratch[0]);
138
chunk_size =
AV_RB32
(&scratch[4]);
139
140
/* catch any unknown header tags, for curiousity */
141
switch
(chunk_tag) {
142
case
CINF_TAG
:
143
case
CINH_TAG
:
144
case
CIND_TAG
:
145
case
PINF_TAG
:
146
case
PINH_TAG
:
147
case
PIND_TAG
:
148
case
FINF_TAG
:
149
case
CMDS_TAG
:
150
break
;
151
152
default
:
153
av_log
(s,
AV_LOG_ERROR
,
" note: unknown chunk seen (%c%c%c%c)\n"
,
154
scratch[0], scratch[1],
155
scratch[2], scratch[3]);
156
break
;
157
}
158
159
avio_skip
(pb, chunk_size);
160
}
while
(chunk_tag !=
FINF_TAG
);
161
162
return
0;
163
}
164
165
static
int
wsvqa_read_packet
(
AVFormatContext
*
s
,
166
AVPacket
*
pkt
)
167
{
168
WsVqaDemuxContext
*wsvqa = s->
priv_data
;
169
AVIOContext
*pb = s->
pb
;
170
int
ret
= -1;
171
unsigned
char
preamble[
VQA_PREAMBLE_SIZE
];
172
unsigned
int
chunk_type;
173
unsigned
int
chunk_size;
174
int
skip_byte;
175
176
while
(
avio_read
(pb, preamble,
VQA_PREAMBLE_SIZE
) ==
VQA_PREAMBLE_SIZE
) {
177
chunk_type =
AV_RB32
(&preamble[0]);
178
chunk_size =
AV_RB32
(&preamble[4]);
179
180
skip_byte = chunk_size & 0x01;
181
182
if
((chunk_type ==
SND0_TAG
) || (chunk_type ==
SND1_TAG
) ||
183
(chunk_type ==
SND2_TAG
) || (chunk_type ==
VQFR_TAG
)) {
184
185
ret=
av_get_packet
(pb, pkt, chunk_size);
186
if
(ret<0)
187
return
AVERROR
(EIO);
188
189
switch
(chunk_type) {
190
case
SND0_TAG
:
191
case
SND1_TAG
:
192
case
SND2_TAG
:
193
if
(wsvqa->
audio_stream_index
== -1) {
194
AVStream
*st =
avformat_new_stream
(s, NULL);
195
if
(!st)
196
return
AVERROR
(ENOMEM);
197
198
wsvqa->
audio_stream_index
= st->
index
;
199
if
(!wsvqa->
sample_rate
)
200
wsvqa->
sample_rate
= 22050;
201
if
(!wsvqa->
channels
)
202
wsvqa->
channels
= 1;
203
if
(!wsvqa->
bps
)
204
wsvqa->
bps
= 8;
205
st->
codec
->
sample_rate
= wsvqa->
sample_rate
;
206
st->
codec
->
bits_per_coded_sample
= wsvqa->
bps
;
207
st->
codec
->
channels
= wsvqa->
channels
;
208
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
209
210
avpriv_set_pts_info
(st, 64, 1, st->
codec
->
sample_rate
);
211
212
switch
(chunk_type) {
213
case
SND0_TAG
:
214
if
(wsvqa->
bps
== 16)
215
st->
codec
->
codec_id
=
AV_CODEC_ID_PCM_S16LE
;
216
else
217
st->
codec
->
codec_id
=
AV_CODEC_ID_PCM_U8
;
218
break
;
219
case
SND1_TAG
:
220
st->
codec
->
codec_id
=
AV_CODEC_ID_WESTWOOD_SND1
;
221
break
;
222
case
SND2_TAG
:
223
st->
codec
->
codec_id
=
AV_CODEC_ID_ADPCM_IMA_WS
;
224
st->
codec
->
extradata_size
= 2;
225
st->
codec
->
extradata
=
av_mallocz
(2 +
FF_INPUT_BUFFER_PADDING_SIZE
);
226
if
(!st->
codec
->
extradata
)
227
return
AVERROR
(ENOMEM);
228
AV_WL16
(st->
codec
->
extradata
, wsvqa->
version
);
229
break
;
230
}
231
}
232
233
pkt->
stream_index
= wsvqa->
audio_stream_index
;
234
switch
(chunk_type) {
235
case
SND1_TAG
:
236
/* unpacked size is stored in header */
237
if
(pkt->
data
)
238
pkt->
duration
=
AV_RL16
(pkt->
data
) / wsvqa->
channels
;
239
break
;
240
case
SND2_TAG
:
241
/* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
242
pkt->
duration
= (chunk_size * 2) / wsvqa->
channels
;
243
break
;
244
}
245
break
;
246
case
VQFR_TAG
:
247
pkt->
stream_index
= wsvqa->
video_stream_index
;
248
pkt->
duration
= 1;
249
break
;
250
}
251
252
/* stay on 16-bit alignment */
253
if
(skip_byte)
254
avio_skip
(pb, 1);
255
256
return
ret
;
257
}
else
{
258
switch
(chunk_type){
259
case
CMDS_TAG
:
260
break
;
261
default
:
262
av_log
(s,
AV_LOG_INFO
,
"Skipping unknown chunk 0x%08X\n"
, chunk_type);
263
}
264
avio_skip
(pb, chunk_size + skip_byte);
265
}
266
}
267
268
return
ret
;
269
}
270
271
AVInputFormat
ff_wsvqa_demuxer
= {
272
.
name
=
"wsvqa"
,
273
.long_name =
NULL_IF_CONFIG_SMALL
(
"Westwood Studios VQA"
),
274
.priv_data_size =
sizeof
(
WsVqaDemuxContext
),
275
.
read_probe
=
wsvqa_probe
,
276
.
read_header
=
wsvqa_read_header
,
277
.
read_packet
=
wsvqa_read_packet
,
278
};
Generated on Wed Jul 10 2013 23:48:15 for FFmpeg by
1.8.2