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