3 * Copyright (c) 2006 Patrick Guimond
5 * This file is part of FFmpeg.
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.
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.
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
24 #include "libavutil/intfloat.h"
25 #include "libavutil/opt.h"
29 #include "avio_internal.h"
39 AVPacketList
*pict_list
;
44 static int put_id3v2_tags(AVFormatContext
*s
, AIFFOutputContext
*aiff
)
47 uint64_t pos
, end
, size
;
48 ID3v2EncContext id3v2
= { 0 };
49 AVIOContext
*pb
= s
->pb
;
50 AVPacketList
*pict_list
= aiff
->pict_list
;
55 if (!s
->metadata
&& !aiff
->pict_list
)
58 avio_wl32(pb
, MKTAG('I', 'D', '3', ' '));
62 ff_id3v2_start(&id3v2
, pb
, aiff
->id3v2_version
, ID3v2_DEFAULT_MAGIC
);
63 ff_id3v2_write_metadata(s
, &id3v2
);
65 if ((ret
= ff_id3v2_write_apic(s
, &id3v2
, &pict_list
->pkt
)) < 0)
67 pict_list
= pict_list
->next
;
69 ff_id3v2_finish(&id3v2
, pb
, s
->metadata_header_padding
);
74 /* Update chunk size */
75 avio_seek(pb
, pos
- 4, SEEK_SET
);
77 avio_seek(pb
, end
, SEEK_SET
);
85 static void put_meta(AVFormatContext
*s
, const char *key
, uint32_t id
)
87 AVDictionaryEntry
*tag
;
88 AVIOContext
*pb
= s
->pb
;
90 if (tag
= av_dict_get(s
->metadata
, key
, NULL
, 0)) {
91 int size
= strlen(tag
->value
);
94 avio_wb32(pb
, FFALIGN(size
, 2));
95 avio_write(pb
, tag
->value
, size
);
101 static int aiff_write_header(AVFormatContext
*s
)
103 AIFFOutputContext
*aiff
= s
->priv_data
;
104 AVIOContext
*pb
= s
->pb
;
106 uint64_t sample_rate
;
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
);
119 if (aiff
->audio_stream_idx
< 0) {
120 av_log(s
, AV_LOG_ERROR
, "No audio stream present.\n");
121 return AVERROR(EINVAL
);
124 enc
= s
->streams
[aiff
->audio_stream_idx
]->codec
;
126 /* First verify if format is ok */
129 if (enc
->codec_tag
!= MKTAG('N','O','N','E'))
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");
138 if (aifc
) { // compressed audio
139 if (!enc
->block_align
) {
140 av_log(s
, AV_LOG_ERROR
, "block align not set\n");
144 ffio_wfourcc(pb
, "FVER");
146 avio_wb32(pb
, 0xA2805140);
149 if (enc
->channels
> 2 && enc
->channel_layout
) {
150 ffio_wfourcc(pb
, "CHAN");
152 ff_mov_write_chan(pb
, enc
->channel_layout
);
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'));
161 ffio_wfourcc(pb
, "COMM");
162 avio_wb32(pb
, aifc
? 24 : 18); /* size */
163 avio_wb16(pb
, enc
->channels
); /* Number of channels */
165 aiff
->frames
= avio_tell(pb
);
166 avio_wb32(pb
, 0); /* Number of frames */
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");
174 if (!enc
->block_align
)
175 enc
->block_align
= (enc
->bits_per_coded_sample
* enc
->channels
) >> 3;
177 avio_wb16(pb
, enc
->bits_per_coded_sample
); /* Sample size */
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);
184 avio_wl32(pb
, enc
->codec_tag
);
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
);
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) */
201 avpriv_set_pts_info(s
->streams
[aiff
->audio_stream_idx
], 64, 1,
202 s
->streams
[aiff
->audio_stream_idx
]->codec
->sample_rate
);
204 /* Data is starting here */
210 static int aiff_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
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
);
218 AVPacketList
*pict_list
, *last
;
220 if (s
->streams
[pkt
->stream_index
]->codec
->codec_type
!= AVMEDIA_TYPE_VIDEO
)
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
);
228 if (s
->streams
[pkt
->stream_index
]->nb_frames
>= 1)
231 pict_list
= av_mallocz(sizeof(AVPacketList
));
233 return AVERROR(ENOMEM
);
235 if ((ret
= av_copy_packet(&pict_list
->pkt
, pkt
)) < 0) {
236 av_freep(&pict_list
);
240 if (!aiff
->pict_list
)
241 aiff
->pict_list
= pict_list
;
243 last
= aiff
->pict_list
;
246 last
->next
= pict_list
;
253 static int aiff_write_trailer(AVFormatContext
*s
)
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
;
261 /* Chunks sizes must be even */
262 int64_t file_size
, end_size
;
263 end_size
= file_size
= avio_tell(pb
);
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
);
274 /* Sound Data chunk size */
275 avio_seek(pb
, aiff
->ssnd
, SEEK_SET
);
276 avio_wb32(pb
, file_size
- aiff
->ssnd
- 4);
278 /* return to the end */
279 avio_seek(pb
, end_size
, SEEK_SET
);
282 if (aiff
->write_id3v2
)
283 if ((ret
= put_id3v2_tags(s
, aiff
)) < 0)
287 file_size
= avio_tell(pb
);
288 avio_seek(pb
, aiff
->form
, SEEK_SET
);
289 avio_wb32(pb
, file_size
- aiff
->form
- 4);
295 AVPacketList
*next
= pict_list
->next
;
296 av_free_packet(&pict_list
->pkt
);
297 av_freep(&pict_list
);
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
},
314 static const AVClass aiff_muxer_class
= {
315 .class_name
= "AIFF muxer",
316 .item_name
= av_default_item_name
,
318 .version
= LIBAVUTIL_VERSION_INT
,
321 AVOutputFormat ff_aiff_muxer
= {
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
,