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