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