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
aiffenc.c
Go to the documentation of this file.
1
/*
2
* AIFF/AIFF-C muxer
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/intfloat.h
"
23
#include "
libavutil/opt.h
"
24
#include "
avformat.h
"
25
#include "
internal.h
"
26
#include "
aiff.h
"
27
#include "
avio_internal.h
"
28
#include "
isom.h
"
29
#include "
id3v2.h
"
30
31
typedef
struct
{
32
const
AVClass
*
class
;
33
int64_t
form
;
34
int64_t
frames
;
35
int64_t
ssnd
;
36
int
audio_stream_idx
;
37
AVPacketList
*
pict_list
;
38
int
write_id3v2
;
39
int
id3v2_version
;
40
}
AIFFOutputContext
;
41
42
static
int
put_id3v2_tags
(
AVFormatContext
*s,
AIFFOutputContext
*aiff)
43
{
44
int
ret;
45
uint64_t pos,
end
,
size
;
46
ID3v2EncContext
id3v2 = { 0 };
47
AVIOContext
*pb = s->
pb
;
48
AVPacketList
*pict_list = aiff->
pict_list
;
49
50
if
(!pb->
seekable
)
51
return
0;
52
53
if
(!s->
metadata
&& !aiff->
pict_list
)
54
return
0;
55
56
avio_wl32
(pb,
MKTAG
(
'I'
,
'D'
,
'3'
,
' '
));
57
avio_wb32
(pb, 0);
58
pos =
avio_tell
(pb);
59
60
ff_id3v2_start
(&id3v2, pb, aiff->
id3v2_version
,
ID3v2_DEFAULT_MAGIC
);
61
ff_id3v2_write_metadata
(s, &id3v2);
62
while
(pict_list) {
63
if
((ret =
ff_id3v2_write_apic
(s, &id3v2, &pict_list->
pkt
)) < 0)
64
return
ret;
65
pict_list = pict_list->
next
;
66
}
67
ff_id3v2_finish
(&id3v2, pb);
68
69
end =
avio_tell
(pb);
70
size = end - pos;
71
72
/* Update chunk size */
73
avio_seek
(pb, pos - 4, SEEK_SET);
74
avio_wb32
(pb, size);
75
avio_seek
(pb, end, SEEK_SET);
76
77
if
(size & 1)
78
avio_w8
(pb, 0);
79
80
return
0;
81
}
82
83
static
void
put_meta
(
AVFormatContext
*s,
const
char
*key, uint32_t
id
)
84
{
85
AVDictionaryEntry
*
tag
;
86
AVIOContext
*pb = s->
pb
;
87
88
if
(tag =
av_dict_get
(s->
metadata
, key,
NULL
, 0)) {
89
int
size
= strlen(tag->
value
);
90
91
avio_wl32
(pb,
id
);
92
avio_wb32
(pb,
FFALIGN
(size, 2));
93
avio_write
(pb, tag->
value
, size);
94
if
(size & 1)
95
avio_w8
(pb, 0);
96
}
97
}
98
99
static
int
aiff_write_header
(
AVFormatContext
*s)
100
{
101
AIFFOutputContext
*aiff = s->
priv_data
;
102
AVIOContext
*pb = s->
pb
;
103
AVCodecContext
*enc;
104
uint64_t
sample_rate
;
105
int
i, aifc = 0;
106
107
aiff->
audio_stream_idx
= -1;
108
for
(i = 0; i < s->
nb_streams
; i++) {
109
AVStream
*st = s->
streams
[i];
110
if
(aiff->
audio_stream_idx
< 0 && st->
codec
->
codec_type
==
AVMEDIA_TYPE_AUDIO
) {
111
aiff->
audio_stream_idx
= i;
112
}
else
if
(st->
codec
->
codec_type
!=
AVMEDIA_TYPE_VIDEO
) {
113
av_log
(s,
AV_LOG_ERROR
,
"Only audio streams and pictures are allowed in AIFF.\n"
);
114
return
AVERROR
(EINVAL);
115
}
116
}
117
if
(aiff->
audio_stream_idx
< 0) {
118
av_log
(s,
AV_LOG_ERROR
,
"No audio stream present.\n"
);
119
return
AVERROR
(EINVAL);
120
}
121
122
enc = s->
streams
[aiff->
audio_stream_idx
]->
codec
;
123
124
/* First verify if format is ok */
125
if
(!enc->
codec_tag
)
126
return
-1;
127
if
(enc->
codec_tag
!=
MKTAG
(
'N'
,
'O'
,
'N'
,
'E'
))
128
aifc = 1;
129
130
/* FORM AIFF header */
131
ffio_wfourcc
(pb,
"FORM"
);
132
aiff->
form
=
avio_tell
(pb);
133
avio_wb32
(pb, 0);
/* file length */
134
ffio_wfourcc
(pb, aifc ?
"AIFC"
:
"AIFF"
);
135
136
if
(aifc) {
// compressed audio
137
if
(!enc->
block_align
) {
138
av_log
(s,
AV_LOG_ERROR
,
"block align not set\n"
);
139
return
-1;
140
}
141
/* Version chunk */
142
ffio_wfourcc
(pb,
"FVER"
);
143
avio_wb32
(pb, 4);
144
avio_wb32
(pb, 0xA2805140);
145
}
146
147
if
(enc->
channels
> 2 && enc->
channel_layout
) {
148
ffio_wfourcc
(pb,
"CHAN"
);
149
avio_wb32
(pb, 12);
150
ff_mov_write_chan
(pb, enc->
channel_layout
);
151
}
152
153
put_meta
(s,
"title"
,
MKTAG
(
'N'
,
'A'
,
'M'
,
'E'
));
154
put_meta
(s,
"author"
,
MKTAG
(
'A'
,
'U'
,
'T'
,
'H'
));
155
put_meta
(s,
"copyright"
,
MKTAG
(
'('
,
'c'
,
')'
,
' '
));
156
put_meta
(s,
"comment"
,
MKTAG
(
'A'
,
'N'
,
'N'
,
'O'
));
157
158
/* Common chunk */
159
ffio_wfourcc
(pb,
"COMM"
);
160
avio_wb32
(pb, aifc ? 24 : 18);
/* size */
161
avio_wb16
(pb, enc->
channels
);
/* Number of channels */
162
163
aiff->
frames
=
avio_tell
(pb);
164
avio_wb32
(pb, 0);
/* Number of frames */
165
166
if
(!enc->
bits_per_coded_sample
)
167
enc->
bits_per_coded_sample
=
av_get_bits_per_sample
(enc->
codec_id
);
168
if
(!enc->
bits_per_coded_sample
) {
169
av_log
(s,
AV_LOG_ERROR
,
"could not compute bits per sample\n"
);
170
return
-1;
171
}
172
if
(!enc->
block_align
)
173
enc->
block_align
= (enc->
bits_per_coded_sample
* enc->
channels
) >> 3;
174
175
avio_wb16
(pb, enc->
bits_per_coded_sample
);
/* Sample size */
176
177
sample_rate =
av_double2int
(enc->
sample_rate
);
178
avio_wb16
(pb, (sample_rate >> 52) + (16383 - 1023));
179
avio_wb64
(pb, UINT64_C(1) << 63 | sample_rate << 11);
180
181
if
(aifc) {
182
avio_wl32
(pb, enc->
codec_tag
);
183
avio_wb16
(pb, 0);
184
}
185
186
if
(enc->
codec_tag
==
MKTAG
(
'Q'
,
'D'
,
'M'
,
'2'
) && enc->
extradata_size
) {
187
ffio_wfourcc
(pb,
"wave"
);
188
avio_wb32
(pb, enc->
extradata_size
);
189
avio_write
(pb, enc->
extradata
, enc->
extradata_size
);
190
}
191
192
/* Sound data chunk */
193
ffio_wfourcc
(pb,
"SSND"
);
194
aiff->
ssnd
=
avio_tell
(pb);
/* Sound chunk size */
195
avio_wb32
(pb, 0);
/* Sound samples data size */
196
avio_wb32
(pb, 0);
/* Data offset */
197
avio_wb32
(pb, 0);
/* Block-size (block align) */
198
199
avpriv_set_pts_info
(s->
streams
[aiff->
audio_stream_idx
], 64, 1,
200
s->
streams
[aiff->
audio_stream_idx
]->
codec
->
sample_rate
);
201
202
/* Data is starting here */
203
avio_flush
(pb);
204
205
return
0;
206
}
207
208
static
int
aiff_write_packet
(
AVFormatContext
*s,
AVPacket
*
pkt
)
209
{
210
AIFFOutputContext
*aiff = s->
priv_data
;
211
AVIOContext
*pb = s->
pb
;
212
if
(pkt->
stream_index
== aiff->
audio_stream_idx
)
213
avio_write
(pb, pkt->
data
, pkt->
size
);
214
else
{
215
int
ret;
216
AVPacketList
*pict_list, *last;
217
218
if
(s->
streams
[pkt->
stream_index
]->
codec
->
codec_type
!=
AVMEDIA_TYPE_VIDEO
)
219
return
0;
220
221
/* warn only once for each stream */
222
if
(s->
streams
[pkt->
stream_index
]->
nb_frames
== 1) {
223
av_log
(s,
AV_LOG_WARNING
,
"Got more than one picture in stream %d,"
224
" ignoring.\n"
, pkt->
stream_index
);
225
}
226
if
(s->
streams
[pkt->
stream_index
]->
nb_frames
>= 1)
227
return
0;
228
229
pict_list =
av_mallocz
(
sizeof
(
AVPacketList
));
230
if
(!pict_list)
231
return
AVERROR
(ENOMEM);
232
233
if
((ret =
av_copy_packet
(&pict_list->
pkt
, pkt)) < 0) {
234
av_freep
(&pict_list);
235
return
ret;
236
}
237
238
if
(!aiff->
pict_list
)
239
aiff->
pict_list
= pict_list;
240
else
{
241
last = aiff->
pict_list
;
242
while
(last->
next
)
243
last = last->
next
;
244
last->
next
= pict_list;
245
}
246
}
247
248
return
0;
249
}
250
251
static
int
aiff_write_trailer
(
AVFormatContext
*s)
252
{
253
int
ret;
254
AVIOContext
*pb = s->
pb
;
255
AIFFOutputContext
*aiff = s->
priv_data
;
256
AVPacketList
*pict_list = aiff->
pict_list
;
257
AVCodecContext
*enc = s->
streams
[aiff->
audio_stream_idx
]->
codec
;
258
259
/* Chunks sizes must be even */
260
int64_t file_size, end_size;
261
end_size = file_size =
avio_tell
(pb);
262
if
(file_size & 1) {
263
avio_w8
(pb, 0);
264
end_size++;
265
}
266
267
if
(s->
pb
->
seekable
) {
268
/* Number of sample frames */
269
avio_seek
(pb, aiff->
frames
, SEEK_SET);
270
avio_wb32
(pb, (file_size-aiff->
ssnd
-12)/enc->
block_align
);
271
272
/* Sound Data chunk size */
273
avio_seek
(pb, aiff->
ssnd
, SEEK_SET);
274
avio_wb32
(pb, file_size - aiff->
ssnd
- 4);
275
276
/* return to the end */
277
avio_seek
(pb, end_size, SEEK_SET);
278
279
/* Write ID3 tags */
280
if
(aiff->
write_id3v2
)
281
if
((ret =
put_id3v2_tags
(s, aiff)) < 0)
282
return
ret;
283
284
/* File length */
285
file_size =
avio_tell
(pb);
286
avio_seek
(pb, aiff->
form
, SEEK_SET);
287
avio_wb32
(pb, file_size - aiff->
form
- 4);
288
289
avio_flush
(pb);
290
}
291
292
while
(pict_list) {
293
AVPacketList
*next = pict_list->
next
;
294
av_free_packet
(&pict_list->
pkt
);
295
av_freep
(&pict_list);
296
pict_list = next;
297
}
298
299
return
0;
300
}
301
302
#define OFFSET(x) offsetof(AIFFOutputContext, x)
303
#define ENC AV_OPT_FLAG_ENCODING_PARAM
304
static
const
AVOption
options
[] = {
305
{
"write_id3v2"
,
"Enable ID3 tags writing."
,
306
OFFSET
(write_id3v2),
AV_OPT_TYPE_INT
, {.i64 = 0}, 0, 1,
ENC
},
307
{
"id3v2_version"
,
"Select ID3v2 version to write. Currently 3 and 4 are supported."
,
308
OFFSET
(id3v2_version),
AV_OPT_TYPE_INT
, {.i64 = 4}, 3, 4,
ENC
},
309
{
NULL
},
310
};
311
312
static
const
AVClass
aiff_muxer_class
= {
313
.
class_name
=
"AIFF muxer"
,
314
.item_name =
av_default_item_name
,
315
.option =
options
,
316
.version =
LIBAVUTIL_VERSION_INT
,
317
};
318
319
AVOutputFormat
ff_aiff_muxer
= {
320
.
name
=
"aiff"
,
321
.long_name =
NULL_IF_CONFIG_SMALL
(
"Audio IFF"
),
322
.mime_type =
"audio/aiff"
,
323
.extensions =
"aif,aiff,afc,aifc"
,
324
.priv_data_size =
sizeof
(
AIFFOutputContext
),
325
.audio_codec =
AV_CODEC_ID_PCM_S16BE
,
326
.video_codec =
AV_CODEC_ID_PNG
,
327
.
write_header
=
aiff_write_header
,
328
.
write_packet
=
aiff_write_packet
,
329
.
write_trailer
=
aiff_write_trailer
,
330
.codec_tag = (
const
AVCodecTag
*
const
[]){
ff_codec_aiff_tags
, 0 },
331
.priv_class = &
aiff_muxer_class
,
332
};
Generated on Sat May 25 2013 04:01:16 for FFmpeg by
1.8.2