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