Libav
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
aiffdec.c
Go to the documentation of this file.
1
/*
2
* AIFF/AIFF-C demuxer
3
* Copyright (c) 2006 Patrick Guimond
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/mathematics.h
"
23
#include "
libavutil/dict.h
"
24
#include "
avformat.h
"
25
#include "
internal.h
"
26
#include "
pcm.h
"
27
#include "
aiff.h
"
28
29
#define AIFF 0
30
#define AIFF_C_VERSION1 0xA2805140
31
32
typedef
struct
{
33
int64_t
data_end
;
34
int
block_duration
;
35
}
AIFFInputContext
;
36
37
static
enum
AVCodecID
aiff_codec_get_id
(
int
bps
)
38
{
39
if
(bps <= 8)
40
return
AV_CODEC_ID_PCM_S8
;
41
if
(bps <= 16)
42
return
AV_CODEC_ID_PCM_S16BE
;
43
if
(bps <= 24)
44
return
AV_CODEC_ID_PCM_S24BE
;
45
if
(bps <= 32)
46
return
AV_CODEC_ID_PCM_S32BE
;
47
48
/* bigger than 32 isn't allowed */
49
return
AV_CODEC_ID_NONE
;
50
}
51
52
/* returns the size of the found tag */
53
static
int
get_tag
(
AVIOContext
*pb, uint32_t *
tag
)
54
{
55
int
size
;
56
57
if
(pb->
eof_reached
)
58
return
AVERROR
(EIO);
59
60
*tag =
avio_rl32
(pb);
61
size =
avio_rb32
(pb);
62
63
if
(size < 0)
64
size = 0x7fffffff;
65
66
return
size
;
67
}
68
69
/* Metadata string read */
70
static
void
get_meta
(
AVFormatContext
*s,
const
char
*key,
int
size
)
71
{
72
uint8_t
*str =
av_malloc
(size+1);
73
int
res;
74
75
if
(!str) {
76
avio_skip
(s->
pb
, size);
77
return
;
78
}
79
80
res =
avio_read
(s->
pb
, str, size);
81
if
(res < 0)
82
return
;
83
84
str[res] = 0;
85
av_dict_set
(&s->
metadata
, key, str,
AV_DICT_DONT_STRDUP_VAL
);
86
}
87
88
/* Returns the number of sound data frames or negative on error */
89
static
unsigned
int
get_aiff_header
(
AVFormatContext
*s,
int
size
,
90
unsigned
version
)
91
{
92
AVIOContext
*pb = s->
pb
;
93
AVCodecContext
*codec = s->
streams
[0]->
codec
;
94
AIFFInputContext
*aiff = s->
priv_data
;
95
int
exp;
96
uint64_t val;
97
double
sample_rate;
98
unsigned
int
num_frames;
99
100
if
(size & 1)
101
size++;
102
codec->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
103
codec->
channels
=
avio_rb16
(pb);
104
num_frames =
avio_rb32
(pb);
105
codec->
bits_per_coded_sample
=
avio_rb16
(pb);
106
107
exp =
avio_rb16
(pb);
108
val =
avio_rb64
(pb);
109
sample_rate = ldexp(val, exp - 16383 - 63);
110
codec->
sample_rate
= sample_rate;
111
size -= 18;
112
113
/* get codec id for AIFF-C */
114
if
(version ==
AIFF_C_VERSION1
) {
115
codec->
codec_tag
=
avio_rl32
(pb);
116
codec->
codec_id
=
ff_codec_get_id
(
ff_codec_aiff_tags
, codec->
codec_tag
);
117
size -= 4;
118
}
119
120
if
(version !=
AIFF_C_VERSION1
|| codec->
codec_id
==
AV_CODEC_ID_PCM_S16BE
) {
121
codec->
codec_id
=
aiff_codec_get_id
(codec->
bits_per_coded_sample
);
122
codec->
bits_per_coded_sample
=
av_get_bits_per_sample
(codec->
codec_id
);
123
aiff->
block_duration
= 1;
124
}
else
{
125
switch
(codec->
codec_id
) {
126
case
AV_CODEC_ID_PCM_F32BE
:
127
case
AV_CODEC_ID_PCM_F64BE
:
128
case
AV_CODEC_ID_PCM_S16LE
:
129
case
AV_CODEC_ID_PCM_ALAW
:
130
case
AV_CODEC_ID_PCM_MULAW
:
131
aiff->
block_duration
= 1;
132
break
;
133
case
AV_CODEC_ID_ADPCM_IMA_QT
:
134
codec->
block_align
= 34*codec->
channels
;
135
break
;
136
case
AV_CODEC_ID_MACE3
:
137
codec->
block_align
= 2*codec->
channels
;
138
break
;
139
case
AV_CODEC_ID_MACE6
:
140
codec->
block_align
= 1*codec->
channels
;
141
break
;
142
case
AV_CODEC_ID_GSM
:
143
codec->
block_align
= 33;
144
break
;
145
case
AV_CODEC_ID_QCELP
:
146
codec->
block_align
= 35;
147
break
;
148
default
:
149
break
;
150
}
151
if
(codec->
block_align
> 0)
152
aiff->
block_duration
=
av_get_audio_frame_duration
(codec,
153
codec->
block_align
);
154
}
155
156
/* Block align needs to be computed in all cases, as the definition
157
* is specific to applications -> here we use the WAVE format definition */
158
if
(!codec->
block_align
)
159
codec->
block_align
= (codec->
bits_per_coded_sample
* codec->
channels
) >> 3;
160
161
if
(aiff->
block_duration
) {
162
codec->
bit_rate
= codec->
sample_rate
* (codec->
block_align
<< 3) /
163
aiff->
block_duration
;
164
}
165
166
/* Chunk is over */
167
if
(size)
168
avio_skip
(pb, size);
169
170
return
num_frames;
171
}
172
173
static
int
aiff_probe
(
AVProbeData
*p)
174
{
175
/* check file header */
176
if
(p->
buf
[0] ==
'F'
&& p->
buf
[1] ==
'O'
&&
177
p->
buf
[2] ==
'R'
&& p->
buf
[3] ==
'M'
&&
178
p->
buf
[8] ==
'A'
&& p->
buf
[9] ==
'I'
&&
179
p->
buf
[10] ==
'F'
&& (p->
buf
[11] ==
'F'
|| p->
buf
[11] ==
'C'
))
180
return
AVPROBE_SCORE_MAX
;
181
else
182
return
0;
183
}
184
185
/* aiff input */
186
static
int
aiff_read_header
(
AVFormatContext
*s)
187
{
188
int
size
, filesize;
189
int64_t offset = 0;
190
uint32_t
tag
;
191
unsigned
version
=
AIFF_C_VERSION1
;
192
AVIOContext
*pb = s->
pb
;
193
AVStream
* st;
194
AIFFInputContext
*aiff = s->
priv_data
;
195
196
/* check FORM header */
197
filesize =
get_tag
(pb, &tag);
198
if
(filesize < 0 || tag !=
MKTAG
(
'F'
,
'O'
,
'R'
,
'M'
))
199
return
AVERROR_INVALIDDATA
;
200
201
/* AIFF data type */
202
tag =
avio_rl32
(pb);
203
if
(tag ==
MKTAG
(
'A'
,
'I'
,
'F'
,
'F'
))
/* Got an AIFF file */
204
version =
AIFF
;
205
else
if
(tag !=
MKTAG
(
'A'
,
'I'
,
'F'
,
'C'
))
/* An AIFF-C file then */
206
return
AVERROR_INVALIDDATA
;
207
208
filesize -= 4;
209
210
st =
avformat_new_stream
(s,
NULL
);
211
if
(!st)
212
return
AVERROR
(ENOMEM);
213
214
while
(filesize > 0) {
215
/* parse different chunks */
216
size =
get_tag
(pb, &tag);
217
if
(size < 0)
218
return
size
;
219
220
filesize -= size + 8;
221
222
switch
(tag) {
223
case
MKTAG
(
'C'
,
'O'
,
'M'
,
'M'
):
/* Common chunk */
224
/* Then for the complete header info */
225
st->
nb_frames
=
get_aiff_header
(s, size, version);
226
if
(st->
nb_frames
< 0)
227
return
st->
nb_frames
;
228
if
(offset > 0)
// COMM is after SSND
229
goto
got_sound;
230
break
;
231
case
MKTAG
(
'F'
,
'V'
,
'E'
,
'R'
):
/* Version chunk */
232
version =
avio_rb32
(pb);
233
break
;
234
case
MKTAG
(
'N'
,
'A'
,
'M'
,
'E'
):
/* Sample name chunk */
235
get_meta
(s,
"title"
, size);
236
break
;
237
case
MKTAG
(
'A'
,
'U'
,
'T'
,
'H'
):
/* Author chunk */
238
get_meta
(s,
"author"
, size);
239
break
;
240
case
MKTAG
(
'('
,
'c'
,
')'
,
' '
):
/* Copyright chunk */
241
get_meta
(s,
"copyright"
, size);
242
break
;
243
case
MKTAG
(
'A'
,
'N'
,
'N'
,
'O'
):
/* Annotation chunk */
244
get_meta
(s,
"comment"
, size);
245
break
;
246
case
MKTAG
(
'S'
,
'S'
,
'N'
,
'D'
):
/* Sampled sound chunk */
247
aiff->
data_end
=
avio_tell
(pb) +
size
;
248
offset =
avio_rb32
(pb);
/* Offset of sound data */
249
avio_rb32
(pb);
/* BlockSize... don't care */
250
offset +=
avio_tell
(pb);
/* Compute absolute data offset */
251
if
(st->
codec
->
block_align
)
/* Assume COMM already parsed */
252
goto
got_sound;
253
if
(!pb->
seekable
) {
254
av_log
(s,
AV_LOG_ERROR
,
"file is not seekable\n"
);
255
return
-1;
256
}
257
avio_skip
(pb, size - 8);
258
break
;
259
case
MKTAG
(
'w'
,
'a'
,
'v'
,
'e'
):
260
if
((uint64_t)size > (1<<30))
261
return
-1;
262
st->
codec
->
extradata
=
av_mallocz
(size +
FF_INPUT_BUFFER_PADDING_SIZE
);
263
if
(!st->
codec
->
extradata
)
264
return
AVERROR
(ENOMEM);
265
st->
codec
->
extradata_size
=
size
;
266
avio_read
(pb, st->
codec
->
extradata
, size);
267
break
;
268
default
:
/* Jump */
269
if
(size & 1)
/* Always even aligned */
270
size++;
271
avio_skip
(pb, size);
272
}
273
}
274
275
got_sound:
276
if
(!st->
codec
->
block_align
) {
277
av_log
(s,
AV_LOG_ERROR
,
"could not find COMM tag or invalid block_align value\n"
);
278
return
-1;
279
}
280
281
/* Now positioned, get the sound data start and end */
282
avpriv_set_pts_info
(st, 64, 1, st->
codec
->
sample_rate
);
283
st->
start_time
= 0;
284
st->
duration
= st->
nb_frames
* aiff->
block_duration
;
285
286
/* Position the stream at the first block */
287
avio_seek
(pb, offset, SEEK_SET);
288
289
return
0;
290
}
291
292
#define MAX_SIZE 4096
293
294
static
int
aiff_read_packet
(
AVFormatContext
*s,
295
AVPacket
*pkt)
296
{
297
AVStream
*st = s->
streams
[0];
298
AIFFInputContext
*aiff = s->
priv_data
;
299
int64_t max_size;
300
int
res,
size
;
301
302
/* calculate size of remaining data */
303
max_size = aiff->
data_end
-
avio_tell
(s->
pb
);
304
if
(max_size <= 0)
305
return
AVERROR_EOF
;
306
307
/* Now for that packet */
308
if
(st->
codec
->
block_align
>= 33)
// GSM, QCLP, IMA4
309
size = st->
codec
->
block_align
;
310
else
311
size = (
MAX_SIZE
/ st->
codec
->
block_align
) * st->
codec
->
block_align
;
312
size =
FFMIN
(max_size, size);
313
res =
av_get_packet
(s->
pb
, pkt, size);
314
if
(res < 0)
315
return
res;
316
317
/* Only one stream in an AIFF file */
318
pkt->
stream_index
= 0;
319
pkt->
duration
= (res / st->
codec
->
block_align
) * aiff->
block_duration
;
320
return
0;
321
}
322
323
AVInputFormat
ff_aiff_demuxer
= {
324
.
name
=
"aiff"
,
325
.long_name =
NULL_IF_CONFIG_SMALL
(
"Audio IFF"
),
326
.priv_data_size =
sizeof
(
AIFFInputContext
),
327
.
read_probe
=
aiff_probe
,
328
.
read_header
=
aiff_read_header
,
329
.
read_packet
=
aiff_read_packet
,
330
.
read_seek
=
ff_pcm_read_seek
,
331
.codec_tag = (
const
AVCodecTag
*
const
[]){
ff_codec_aiff_tags
, 0 },
332
};
Generated on Sun Jun 1 2014 17:55:35 for Libav by
1.8.1.2