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