FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
wv.c
Go to the documentation of this file.
1
/*
2
* WavPack demuxer
3
* Copyright (c) 2006,2011 Konstantin Shishkov
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
#include "
libavutil/channel_layout.h
"
23
#include "
libavutil/intreadwrite.h
"
24
#include "
libavutil/dict.h
"
25
#include "
avformat.h
"
26
#include "
internal.h
"
27
#include "
apetag.h
"
28
#include "
id3v1.h
"
29
30
// specs say that maximum block size is 1Mb
31
#define WV_BLOCK_LIMIT 1047576
32
33
#define WV_EXTRA_SIZE 12
34
35
#define WV_START_BLOCK 0x0800
36
#define WV_END_BLOCK 0x1000
37
#define WV_SINGLE_BLOCK (WV_START_BLOCK | WV_END_BLOCK)
38
39
enum
WV_FLAGS
{
40
WV_MONO
= 0x0004,
41
WV_HYBRID
= 0x0008,
42
WV_JOINT
= 0x0010,
43
WV_CROSSD
= 0x0020,
44
WV_HSHAPE
= 0x0040,
45
WV_FLOAT
= 0x0080,
46
WV_INT32
= 0x0100,
47
WV_HBR
= 0x0200,
48
WV_HBAL
= 0x0400,
49
WV_MCINIT
= 0x0800,
50
WV_MCEND
= 0x1000,
51
};
52
53
static
const
int
wv_rates
[16] = {
54
6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000,
55
32000, 44100, 48000, 64000, 88200, 96000, 192000, -1
56
};
57
58
typedef
struct
{
59
uint32_t blksize,
flags
;
60
int
rate
, chan, bpp;
61
uint32_t
chmask
;
62
uint32_t
samples
,
soff
;
63
int
multichannel
;
64
int
block_parsed
;
65
uint8_t
extra[
WV_EXTRA_SIZE
];
66
int64_t
pos
;
67
68
int64_t
apetag_start
;
69
}
WVContext
;
70
71
static
int
wv_probe
(
AVProbeData
*p)
72
{
73
/* check file header */
74
if
(p->
buf_size
<= 32)
75
return
0;
76
if
(p->
buf
[0] ==
'w'
&& p->
buf
[1] ==
'v'
&&
77
p->
buf
[2] ==
'p'
&& p->
buf
[3] ==
'k'
)
78
return
AVPROBE_SCORE_MAX
;
79
else
80
return
0;
81
}
82
83
static
int
wv_read_block_header
(
AVFormatContext
*ctx,
AVIOContext
*pb,
84
int
append
)
85
{
86
WVContext
*wc = ctx->
priv_data
;
87
uint32_t
tag
, ver;
88
int
size
;
89
int
rate, bpp, chan;
90
uint32_t chmask;
91
92
wc->
pos
=
avio_tell
(pb);
93
94
/* don't return bogus packets with the ape tag data */
95
if
(wc->
apetag_start
&& wc->
pos
>= wc->
apetag_start
)
96
return
AVERROR_EOF
;
97
98
if
(!append) {
99
tag =
avio_rl32
(pb);
100
if
(tag !=
MKTAG
(
'w'
,
'v'
,
'p'
,
'k'
))
101
return
AVERROR_INVALIDDATA
;
102
size =
avio_rl32
(pb);
103
if
(size < 24 || size >
WV_BLOCK_LIMIT
) {
104
av_log
(ctx,
AV_LOG_ERROR
,
"Incorrect block size %i\n"
, size);
105
return
AVERROR_INVALIDDATA
;
106
}
107
wc->
blksize
=
size
;
108
ver =
avio_rl16
(pb);
109
if
(ver < 0x402 || ver > 0x410) {
110
av_log
(ctx,
AV_LOG_ERROR
,
"Unsupported version %03X\n"
, ver);
111
return
AVERROR_PATCHWELCOME
;
112
}
113
avio_r8
(pb);
// track no
114
avio_r8
(pb);
// track sub index
115
wc->
samples
=
avio_rl32
(pb);
// total samples in file
116
wc->
soff
=
avio_rl32
(pb);
// offset in samples of current block
117
avio_read
(pb, wc->
extra
,
WV_EXTRA_SIZE
);
118
}
else
{
119
size = wc->
blksize
;
120
}
121
wc->
flags
=
AV_RL32
(wc->
extra
+ 4);
122
/* Blocks with zero samples don't contain actual audio information
123
* and should be ignored */
124
if
(!
AV_RN32
(wc->
extra
))
125
return
0;
126
// parse flags
127
bpp = ((wc->
flags
& 3) + 1) << 3;
128
chan = 1 + !(wc->
flags
&
WV_MONO
);
129
chmask = wc->
flags
&
WV_MONO
?
AV_CH_LAYOUT_MONO
:
AV_CH_LAYOUT_STEREO
;
130
rate =
wv_rates
[(wc->
flags
>> 23) & 0xF];
131
wc->
multichannel
= !!((wc->
flags
&
WV_SINGLE_BLOCK
) !=
WV_SINGLE_BLOCK
);
132
if
(wc->
multichannel
) {
133
chan = wc->
chan
;
134
chmask = wc->
chmask
;
135
}
136
if
((rate == -1 || !chan) && !wc->
block_parsed
) {
137
int64_t block_end =
avio_tell
(pb) + wc->
blksize
- 24;
138
if
(!pb->
seekable
) {
139
av_log
(ctx,
AV_LOG_ERROR
,
140
"Cannot determine additional parameters\n"
);
141
return
AVERROR_INVALIDDATA
;
142
}
143
while
(
avio_tell
(pb) < block_end) {
144
int
id
,
size
;
145
id
=
avio_r8
(pb);
146
size = (
id
& 0x80) ?
avio_rl24
(pb) :
avio_r8
(pb);
147
size <<= 1;
148
if
(
id
& 0x40)
149
size--;
150
switch
(
id
& 0x3F) {
151
case
0xD:
152
if
(size <= 1) {
153
av_log
(ctx,
AV_LOG_ERROR
,
154
"Insufficient channel information\n"
);
155
return
AVERROR_INVALIDDATA
;
156
}
157
chan =
avio_r8
(pb);
158
switch
(size - 2) {
159
case
0:
160
chmask =
avio_r8
(pb);
161
break
;
162
case
1:
163
chmask =
avio_rl16
(pb);
164
break
;
165
case
2:
166
chmask =
avio_rl24
(pb);
167
break
;
168
case
3:
169
chmask =
avio_rl32
(pb);
170
break
;
171
case
5:
172
avio_skip
(pb, 1);
173
chan |= (
avio_r8
(pb) & 0xF) << 8;
174
chmask =
avio_rl24
(pb);
175
break
;
176
default
:
177
av_log
(ctx,
AV_LOG_ERROR
,
178
"Invalid channel info size %d\n"
, size);
179
return
AVERROR_INVALIDDATA
;
180
}
181
break
;
182
case
0x27:
183
rate =
avio_rl24
(pb);
184
break
;
185
default
:
186
avio_skip
(pb, size);
187
}
188
if
(
id
& 0x40)
189
avio_skip
(pb, 1);
190
}
191
if
(rate == -1) {
192
av_log
(ctx,
AV_LOG_ERROR
,
193
"Cannot determine custom sampling rate\n"
);
194
return
AVERROR_INVALIDDATA
;
195
}
196
avio_seek
(pb, block_end - wc->
blksize
+ 24, SEEK_SET);
197
}
198
if
(!wc->
bpp
)
199
wc->
bpp
= bpp;
200
if
(!wc->
chan
)
201
wc->
chan
= chan;
202
if
(!wc->
chmask
)
203
wc->
chmask
= chmask;
204
if
(!wc->
rate
)
205
wc->
rate
= rate;
206
207
if
(wc->
flags
&& bpp != wc->
bpp
) {
208
av_log
(ctx,
AV_LOG_ERROR
,
209
"Bits per sample differ, this block: %i, header block: %i\n"
,
210
bpp, wc->
bpp
);
211
return
AVERROR_INVALIDDATA
;
212
}
213
if
(wc->
flags
&& !wc->
multichannel
&& chan != wc->
chan
) {
214
av_log
(ctx,
AV_LOG_ERROR
,
215
"Channels differ, this block: %i, header block: %i\n"
,
216
chan, wc->
chan
);
217
return
AVERROR_INVALIDDATA
;
218
}
219
if
(wc->
flags
&& rate != -1 && rate != wc->
rate
) {
220
av_log
(ctx,
AV_LOG_ERROR
,
221
"Sampling rate differ, this block: %i, header block: %i\n"
,
222
rate, wc->
rate
);
223
return
AVERROR_INVALIDDATA
;
224
}
225
wc->
blksize
= size - 24;
226
return
0;
227
}
228
229
static
int
wv_read_header
(
AVFormatContext
*s)
230
{
231
AVIOContext
*pb = s->
pb
;
232
WVContext
*wc = s->
priv_data
;
233
AVStream
*st;
234
int
ret;
235
236
wc->
block_parsed
= 0;
237
for
(;;) {
238
if
((ret =
wv_read_block_header
(s, pb, 0)) < 0)
239
return
ret;
240
if
(!
AV_RN32
(wc->
extra
))
241
avio_skip
(pb, wc->
blksize
- 24);
242
else
243
break
;
244
}
245
246
/* now we are ready: build format streams */
247
st =
avformat_new_stream
(s,
NULL
);
248
if
(!st)
249
return
AVERROR
(ENOMEM);
250
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
251
st->
codec
->
codec_id
=
AV_CODEC_ID_WAVPACK
;
252
st->
codec
->
channels
= wc->
chan
;
253
st->
codec
->
channel_layout
= wc->
chmask
;
254
st->
codec
->
sample_rate
= wc->
rate
;
255
st->
codec
->
bits_per_coded_sample
= wc->
bpp
;
256
avpriv_set_pts_info
(st, 64, 1, wc->
rate
);
257
st->
start_time
= 0;
258
if
(wc->
samples
!= 0xFFFFFFFFu)
259
st->
duration
= wc->
samples
;
260
261
if
(s->
pb
->
seekable
) {
262
int64_t cur =
avio_tell
(s->
pb
);
263
wc->
apetag_start
=
ff_ape_parse_tag
(s);
264
if
(!
av_dict_get
(s->
metadata
,
""
,
NULL
,
AV_DICT_IGNORE_SUFFIX
))
265
ff_id3v1_read
(s);
266
avio_seek
(s->
pb
, cur, SEEK_SET);
267
}
268
269
return
0;
270
}
271
272
static
int
wv_read_packet
(
AVFormatContext
*s,
AVPacket
*
pkt
)
273
{
274
WVContext
*wc = s->
priv_data
;
275
int
ret;
276
int
size
, ver,
off
;
277
int64_t pos;
278
uint32_t block_samples;
279
280
if
(
url_feof
(s->
pb
))
281
return
AVERROR_EOF
;
282
if
(wc->
block_parsed
) {
283
if
((ret =
wv_read_block_header
(s, s->
pb
, 0)) < 0)
284
return
ret;
285
}
286
287
pos = wc->
pos
;
288
off = wc->
multichannel
? 4 : 0;
289
if
(
av_new_packet
(pkt, wc->
blksize
+
WV_EXTRA_SIZE
+ off) < 0)
290
return
AVERROR
(ENOMEM);
291
if
(wc->
multichannel
)
292
AV_WL32
(pkt->
data
, wc->
blksize
+
WV_EXTRA_SIZE
+ 12);
293
memcpy(pkt->
data
+ off, wc->
extra
,
WV_EXTRA_SIZE
);
294
ret =
avio_read
(s->
pb
, pkt->
data
+
WV_EXTRA_SIZE
+ off, wc->
blksize
);
295
if
(ret != wc->
blksize
) {
296
av_free_packet
(pkt);
297
return
AVERROR
(EIO);
298
}
299
while
(!(wc->
flags
&
WV_END_BLOCK
)) {
300
if
(
avio_rl32
(s->
pb
) !=
MKTAG
(
'w'
,
'v'
,
'p'
,
'k'
)) {
301
av_free_packet
(pkt);
302
return
AVERROR_INVALIDDATA
;
303
}
304
if
((ret =
av_append_packet
(s->
pb
, pkt, 4)) < 0) {
305
av_free_packet
(pkt);
306
return
ret;
307
}
308
size =
AV_RL32
(pkt->
data
+ pkt->
size
- 4);
309
if
(size < 24 || size >
WV_BLOCK_LIMIT
) {
310
av_free_packet
(pkt);
311
av_log
(s,
AV_LOG_ERROR
,
"Incorrect block size %d\n"
, size);
312
return
AVERROR_INVALIDDATA
;
313
}
314
wc->
blksize
=
size
;
315
ver =
avio_rl16
(s->
pb
);
316
if
(ver < 0x402 || ver > 0x410) {
317
av_free_packet
(pkt);
318
av_log
(s,
AV_LOG_ERROR
,
"Unsupported version %03X\n"
, ver);
319
return
AVERROR_PATCHWELCOME
;
320
}
321
avio_r8
(s->
pb
);
// track no
322
avio_r8
(s->
pb
);
// track sub index
323
wc->
samples
=
avio_rl32
(s->
pb
);
// total samples in file
324
wc->
soff
=
avio_rl32
(s->
pb
);
// offset in samples of current block
325
if
((ret =
av_append_packet
(s->
pb
, pkt,
WV_EXTRA_SIZE
)) < 0) {
326
av_free_packet
(pkt);
327
return
ret;
328
}
329
memcpy(wc->
extra
, pkt->
data
+ pkt->
size
-
WV_EXTRA_SIZE
,
WV_EXTRA_SIZE
);
330
331
if
((ret =
wv_read_block_header
(s, s->
pb
, 1)) < 0) {
332
av_free_packet
(pkt);
333
return
ret;
334
}
335
ret =
av_append_packet
(s->
pb
, pkt, wc->
blksize
);
336
if
(ret < 0) {
337
av_free_packet
(pkt);
338
return
ret;
339
}
340
}
341
pkt->
stream_index
= 0;
342
wc->
block_parsed
= 1;
343
pkt->
pts
= wc->
soff
;
344
block_samples =
AV_RL32
(wc->
extra
);
345
if
(block_samples > INT32_MAX)
346
av_log
(s,
AV_LOG_WARNING
,
347
"Too many samples in block: %"
PRIu32
"\n"
, block_samples);
348
else
349
pkt->
duration
= block_samples;
350
351
av_add_index_entry
(s->
streams
[0], pos, pkt->
pts
, 0, 0,
AVINDEX_KEYFRAME
);
352
return
0;
353
}
354
355
static
int
wv_read_seek
(
AVFormatContext
*s,
int
stream_index,
356
int64_t timestamp,
int
flags
)
357
{
358
AVStream
*st = s->
streams
[stream_index];
359
WVContext
*wc = s->
priv_data
;
360
AVPacket
pkt1, *
pkt
= &pkt1;
361
int
ret;
362
int
index
=
av_index_search_timestamp
(st, timestamp, flags);
363
int64_t pos, pts;
364
365
/* if found, seek there */
366
if
(index >= 0 &&
367
timestamp <= st->index_entries[st->
nb_index_entries
- 1].timestamp) {
368
wc->
block_parsed
= 1;
369
avio_seek
(s->
pb
, st->
index_entries
[index].
pos
, SEEK_SET);
370
return
0;
371
}
372
/* if timestamp is out of bounds, return error */
373
if
(timestamp < 0 || timestamp >= s->
duration
)
374
return
AVERROR
(EINVAL);
375
376
pos =
avio_tell
(s->
pb
);
377
do
{
378
ret =
av_read_frame
(s, pkt);
379
if
(ret < 0) {
380
avio_seek
(s->
pb
, pos, SEEK_SET);
381
return
ret;
382
}
383
pts = pkt->
pts
;
384
av_free_packet
(pkt);
385
}
while
(pts < timestamp);
386
return
0;
387
}
388
389
AVInputFormat
ff_wv_demuxer
= {
390
.
name
=
"wv"
,
391
.long_name =
NULL_IF_CONFIG_SMALL
(
"WavPack"
),
392
.priv_data_size =
sizeof
(
WVContext
),
393
.
read_probe
=
wv_probe
,
394
.
read_header
=
wv_read_header
,
395
.
read_packet
=
wv_read_packet
,
396
.
read_seek
=
wv_read_seek
,
397
};
Generated on Sat May 25 2013 03:58:49 for FFmpeg by
1.8.2