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
AIFFOutputContext
{
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 Mar 8 2015 02:35:08 for FFmpeg by
1.8.2