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