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