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