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
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
case
AV_CODEC_ID_QCELP
:
151
codec->
block_align
= 35;
152
break
;
153
default
:
154
aiff->
block_duration
= 1;
155
break
;
156
}
157
if
(codec->
block_align
> 0)
158
aiff->
block_duration
=
av_get_audio_frame_duration
(codec,
159
codec->
block_align
);
160
}
161
162
/* Block align needs to be computed in all cases, as the definition
163
* is specific to applications -> here we use the WAVE format definition */
164
if
(!codec->
block_align
)
165
codec->
block_align
= (
av_get_bits_per_sample
(codec->
codec_id
) * codec->
channels
) >> 3;
166
167
if
(aiff->
block_duration
) {
168
codec->
bit_rate
= codec->
sample_rate
* (codec->
block_align
<< 3) /
169
aiff->
block_duration
;
170
}
171
172
/* Chunk is over */
173
if
(size)
174
avio_skip
(pb, size);
175
176
return
num_frames;
177
}
178
179
static
int
aiff_probe
(
AVProbeData
*p)
180
{
181
/* check file header */
182
if
(p->
buf
[0] ==
'F'
&& p->
buf
[1] ==
'O'
&&
183
p->
buf
[2] ==
'R'
&& p->
buf
[3] ==
'M'
&&
184
p->
buf
[8] ==
'A'
&& p->
buf
[9] ==
'I'
&&
185
p->
buf
[10] ==
'F'
&& (p->
buf
[11] ==
'F'
|| p->
buf
[11] ==
'C'
))
186
return
AVPROBE_SCORE_MAX
;
187
else
188
return
0;
189
}
190
191
/* aiff input */
192
static
int
aiff_read_header
(
AVFormatContext
*s)
193
{
194
int
ret,
size
, filesize;
195
int64_t
offset
= 0, position;
196
uint32_t
tag
;
197
unsigned
version
=
AIFF_C_VERSION1
;
198
AVIOContext
*pb = s->
pb
;
199
AVStream
* st;
200
AIFFInputContext
*aiff = s->
priv_data
;
201
ID3v2ExtraMeta
*id3v2_extra_meta =
NULL
;
202
203
/* check FORM header */
204
filesize =
get_tag
(pb, &tag);
205
if
(filesize < 0 || tag !=
MKTAG
(
'F'
,
'O'
,
'R'
,
'M'
))
206
return
AVERROR_INVALIDDATA
;
207
208
/* AIFF data type */
209
tag =
avio_rl32
(pb);
210
if
(tag ==
MKTAG
(
'A'
,
'I'
,
'F'
,
'F'
))
/* Got an AIFF file */
211
version =
AIFF
;
212
else
if
(tag !=
MKTAG
(
'A'
,
'I'
,
'F'
,
'C'
))
/* An AIFF-C file then */
213
return
AVERROR_INVALIDDATA
;
214
215
filesize -= 4;
216
217
st =
avformat_new_stream
(s,
NULL
);
218
if
(!st)
219
return
AVERROR
(ENOMEM);
220
221
while
(filesize > 0) {
222
/* parse different chunks */
223
size =
get_tag
(pb, &tag);
224
if
(size < 0)
225
return
size
;
226
227
filesize -= size + 8;
228
229
switch
(tag) {
230
case
MKTAG
(
'C'
,
'O'
,
'M'
,
'M'
):
/* Common chunk */
231
/* Then for the complete header info */
232
st->
nb_frames
=
get_aiff_header
(s, size, version);
233
if
(st->
nb_frames
< 0)
234
return
st->
nb_frames
;
235
if
(offset > 0)
// COMM is after SSND
236
goto
got_sound;
237
break
;
238
case
MKTAG
(
'I'
,
'D'
,
'3'
,
' '
):
239
position =
avio_tell
(pb);
240
ff_id3v2_read
(s,
ID3v2_DEFAULT_MAGIC
, &id3v2_extra_meta);
241
if
(id3v2_extra_meta)
242
if
((ret =
ff_id3v2_parse_apic
(s, &id3v2_extra_meta)) < 0) {
243
ff_id3v2_free_extra_meta
(&id3v2_extra_meta);
244
return
ret;
245
}
246
ff_id3v2_free_extra_meta
(&id3v2_extra_meta);
247
if
(position + size >
avio_tell
(pb))
248
avio_skip
(pb, position + size -
avio_tell
(pb));
249
break
;
250
case
MKTAG
(
'F'
,
'V'
,
'E'
,
'R'
):
/* Version chunk */
251
version =
avio_rb32
(pb);
252
break
;
253
case
MKTAG
(
'N'
,
'A'
,
'M'
,
'E'
):
/* Sample name chunk */
254
get_meta
(s,
"title"
, size);
255
break
;
256
case
MKTAG
(
'A'
,
'U'
,
'T'
,
'H'
):
/* Author chunk */
257
get_meta
(s,
"author"
, size);
258
break
;
259
case
MKTAG
(
'('
,
'c'
,
')'
,
' '
):
/* Copyright chunk */
260
get_meta
(s,
"copyright"
, size);
261
break
;
262
case
MKTAG
(
'A'
,
'N'
,
'N'
,
'O'
):
/* Annotation chunk */
263
get_meta
(s,
"comment"
, size);
264
break
;
265
case
MKTAG
(
'S'
,
'S'
,
'N'
,
'D'
):
/* Sampled sound chunk */
266
aiff->
data_end
=
avio_tell
(pb) +
size
;
267
offset =
avio_rb32
(pb);
/* Offset of sound data */
268
avio_rb32
(pb);
/* BlockSize... don't care */
269
offset +=
avio_tell
(pb);
/* Compute absolute data offset */
270
if
(st->
codec
->
block_align
&& !pb->
seekable
)
/* Assume COMM already parsed */
271
goto
got_sound;
272
if
(!pb->
seekable
) {
273
av_log
(s,
AV_LOG_ERROR
,
"file is not seekable\n"
);
274
return
-1;
275
}
276
avio_skip
(pb, size - 8);
277
break
;
278
case
MKTAG
(
'w'
,
'a'
,
'v'
,
'e'
):
279
if
((uint64_t)size > (1<<30))
280
return
-1;
281
st->
codec
->
extradata
=
av_mallocz
(size +
FF_INPUT_BUFFER_PADDING_SIZE
);
282
if
(!st->
codec
->
extradata
)
283
return
AVERROR
(ENOMEM);
284
st->
codec
->
extradata_size
=
size
;
285
avio_read
(pb, st->
codec
->
extradata
, size);
286
if
(st->
codec
->
codec_id
==
AV_CODEC_ID_QDM2
&& size>=12*4 && !st->
codec
->
block_align
) {
287
st->
codec
->
block_align
=
AV_RB32
(st->
codec
->
extradata
+11*4);
288
aiff->
block_duration
=
AV_RB32
(st->
codec
->
extradata
+9*4);
289
}
290
break
;
291
case
MKTAG
(
'C'
,
'H'
,
'A'
,
'N'
):
292
if
(
ff_mov_read_chan
(s, pb, st, size) < 0)
293
return
AVERROR_INVALIDDATA
;
294
break
;
295
default
:
/* Jump */
296
if
(size & 1)
/* Always even aligned */
297
size++;
298
avio_skip
(pb, size);
299
}
300
}
301
302
got_sound:
303
if
(!st->
codec
->
block_align
) {
304
av_log
(s,
AV_LOG_ERROR
,
"could not find COMM tag or invalid block_align value\n"
);
305
return
-1;
306
}
307
308
/* Now positioned, get the sound data start and end */
309
avpriv_set_pts_info
(st, 64, 1, st->
codec
->
sample_rate
);
310
st->
start_time
= 0;
311
st->
duration
= st->
nb_frames
* aiff->
block_duration
;
312
313
/* Position the stream at the first block */
314
avio_seek
(pb, offset, SEEK_SET);
315
316
return
0;
317
}
318
319
#define MAX_SIZE 4096
320
321
static
int
aiff_read_packet
(
AVFormatContext
*s,
322
AVPacket
*
pkt
)
323
{
324
AVStream
*st = s->
streams
[0];
325
AIFFInputContext
*aiff = s->
priv_data
;
326
int64_t max_size;
327
int
res,
size
;
328
329
/* calculate size of remaining data */
330
max_size = aiff->
data_end
-
avio_tell
(s->
pb
);
331
if
(max_size <= 0)
332
return
AVERROR_EOF
;
333
334
/* Now for that packet */
335
if
(st->
codec
->
block_align
>= 33)
// GSM, QCLP, IMA4
336
size = st->
codec
->
block_align
;
337
else
338
size = (
MAX_SIZE
/ st->
codec
->
block_align
) * st->
codec
->
block_align
;
339
size =
FFMIN
(max_size, size);
340
res =
av_get_packet
(s->
pb
, pkt, size);
341
if
(res < 0)
342
return
res;
343
344
if
(size >= st->
codec
->
block_align
)
345
pkt->
flags
&= ~
AV_PKT_FLAG_CORRUPT
;
346
/* Only one stream in an AIFF file */
347
pkt->
stream_index
= 0;
348
pkt->
duration
= (res / st->
codec
->
block_align
) * aiff->
block_duration
;
349
return
0;
350
}
351
352
AVInputFormat
ff_aiff_demuxer
= {
353
.
name
=
"aiff"
,
354
.long_name =
NULL_IF_CONFIG_SMALL
(
"Audio IFF"
),
355
.priv_data_size =
sizeof
(
AIFFInputContext
),
356
.
read_probe
=
aiff_probe
,
357
.
read_header
=
aiff_read_header
,
358
.
read_packet
=
aiff_read_packet
,
359
.
read_seek
=
ff_pcm_read_seek
,
360
.codec_tag = (
const
AVCodecTag
*
const
[]){
ff_codec_aiff_tags
, 0 },
361
};
Generated on Sat May 25 2013 04:01:16 for FFmpeg by
1.8.2