annotate ffmpeg/libavformat/aiffenc.c @ 13:844d341cf643 tip

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