00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/intfloat.h"
00023 #include "avformat.h"
00024 #include "internal.h"
00025 #include "aiff.h"
00026 #include "avio_internal.h"
00027 #include "isom.h"
00028
00029 typedef struct {
00030 int64_t form;
00031 int64_t frames;
00032 int64_t ssnd;
00033 } AIFFOutputContext;
00034
00035 static int aiff_write_header(AVFormatContext *s)
00036 {
00037 AIFFOutputContext *aiff = s->priv_data;
00038 AVIOContext *pb = s->pb;
00039 AVCodecContext *enc = s->streams[0]->codec;
00040 uint64_t sample_rate;
00041 int aifc = 0;
00042
00043
00044 if (!enc->codec_tag)
00045 return -1;
00046 if (enc->codec_tag != MKTAG('N','O','N','E'))
00047 aifc = 1;
00048
00049
00050 ffio_wfourcc(pb, "FORM");
00051 aiff->form = avio_tell(pb);
00052 avio_wb32(pb, 0);
00053 ffio_wfourcc(pb, aifc ? "AIFC" : "AIFF");
00054
00055 if (aifc) {
00056 enc->bits_per_coded_sample = 16;
00057 if (!enc->block_align) {
00058 av_log(s, AV_LOG_ERROR, "block align not set\n");
00059 return -1;
00060 }
00061
00062 ffio_wfourcc(pb, "FVER");
00063 avio_wb32(pb, 4);
00064 avio_wb32(pb, 0xA2805140);
00065 }
00066
00067 if (enc->channels > 2 && enc->channel_layout) {
00068 ffio_wfourcc(pb, "CHAN");
00069 avio_wb32(pb, 12);
00070 ff_mov_write_chan(pb, enc->channel_layout);
00071 }
00072
00073
00074 ffio_wfourcc(pb, "COMM");
00075 avio_wb32(pb, aifc ? 24 : 18);
00076 avio_wb16(pb, enc->channels);
00077
00078 aiff->frames = avio_tell(pb);
00079 avio_wb32(pb, 0);
00080
00081 if (!enc->bits_per_coded_sample)
00082 enc->bits_per_coded_sample = av_get_bits_per_sample(enc->codec_id);
00083 if (!enc->bits_per_coded_sample) {
00084 av_log(s, AV_LOG_ERROR, "could not compute bits per sample\n");
00085 return -1;
00086 }
00087 if (!enc->block_align)
00088 enc->block_align = (enc->bits_per_coded_sample * enc->channels) >> 3;
00089
00090 avio_wb16(pb, enc->bits_per_coded_sample);
00091
00092 sample_rate = av_double2int(enc->sample_rate);
00093 avio_wb16(pb, (sample_rate >> 52) + (16383 - 1023));
00094 avio_wb64(pb, UINT64_C(1) << 63 | sample_rate << 11);
00095
00096 if (aifc) {
00097 avio_wl32(pb, enc->codec_tag);
00098 avio_wb16(pb, 0);
00099 }
00100
00101 if (enc->codec_tag == MKTAG('Q','D','M','2') && enc->extradata_size) {
00102 ffio_wfourcc(pb, "wave");
00103 avio_wb32(pb, enc->extradata_size);
00104 avio_write(pb, enc->extradata, enc->extradata_size);
00105 }
00106
00107
00108 ffio_wfourcc(pb, "SSND");
00109 aiff->ssnd = avio_tell(pb);
00110 avio_wb32(pb, 0);
00111 avio_wb32(pb, 0);
00112 avio_wb32(pb, 0);
00113
00114 avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
00115
00116
00117 avio_flush(pb);
00118
00119 return 0;
00120 }
00121
00122 static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt)
00123 {
00124 AVIOContext *pb = s->pb;
00125 avio_write(pb, pkt->data, pkt->size);
00126 return 0;
00127 }
00128
00129 static int aiff_write_trailer(AVFormatContext *s)
00130 {
00131 AVIOContext *pb = s->pb;
00132 AIFFOutputContext *aiff = s->priv_data;
00133 AVCodecContext *enc = s->streams[0]->codec;
00134
00135
00136 int64_t file_size, end_size;
00137 end_size = file_size = avio_tell(pb);
00138 if (file_size & 1) {
00139 avio_w8(pb, 0);
00140 end_size++;
00141 }
00142
00143 if (s->pb->seekable) {
00144
00145 avio_seek(pb, aiff->form, SEEK_SET);
00146 avio_wb32(pb, file_size - aiff->form - 4);
00147
00148
00149 avio_seek(pb, aiff->frames, SEEK_SET);
00150 avio_wb32(pb, (file_size-aiff->ssnd-12)/enc->block_align);
00151
00152
00153 avio_seek(pb, aiff->ssnd, SEEK_SET);
00154 avio_wb32(pb, file_size - aiff->ssnd - 4);
00155
00156
00157 avio_seek(pb, end_size, SEEK_SET);
00158
00159 avio_flush(pb);
00160 }
00161
00162 return 0;
00163 }
00164
00165 AVOutputFormat ff_aiff_muxer = {
00166 .name = "aiff",
00167 .long_name = NULL_IF_CONFIG_SMALL("Audio IFF"),
00168 .mime_type = "audio/aiff",
00169 .extensions = "aif,aiff,afc,aifc",
00170 .priv_data_size = sizeof(AIFFOutputContext),
00171 .audio_codec = AV_CODEC_ID_PCM_S16BE,
00172 .video_codec = AV_CODEC_ID_NONE,
00173 .write_header = aiff_write_header,
00174 .write_packet = aiff_write_packet,
00175 .write_trailer = aiff_write_trailer,
00176 .codec_tag = (const AVCodecTag* const []){ ff_codec_aiff_tags, 0 },
00177 };