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