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_readwrite.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 AVExtFloat 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_dbl2ext((double)enc->sample_rate);
00093 avio_write(pb, (uint8_t*)&sample_rate, sizeof(sample_rate));
00094
00095 if (aifc) {
00096 avio_wl32(pb, enc->codec_tag);
00097 avio_wb16(pb, 0);
00098 }
00099
00100
00101 ffio_wfourcc(pb, "SSND");
00102 aiff->ssnd = avio_tell(pb);
00103 avio_wb32(pb, 0);
00104 avio_wb32(pb, 0);
00105 avio_wb32(pb, 0);
00106
00107 avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
00108
00109
00110 avio_flush(pb);
00111
00112 return 0;
00113 }
00114
00115 static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt)
00116 {
00117 AVIOContext *pb = s->pb;
00118 avio_write(pb, pkt->data, pkt->size);
00119 return 0;
00120 }
00121
00122 static int aiff_write_trailer(AVFormatContext *s)
00123 {
00124 AVIOContext *pb = s->pb;
00125 AIFFOutputContext *aiff = s->priv_data;
00126 AVCodecContext *enc = s->streams[0]->codec;
00127
00128
00129 int64_t file_size, end_size;
00130 end_size = file_size = avio_tell(pb);
00131 if (file_size & 1) {
00132 avio_w8(pb, 0);
00133 end_size++;
00134 }
00135
00136 if (s->pb->seekable) {
00137
00138 avio_seek(pb, aiff->form, SEEK_SET);
00139 avio_wb32(pb, file_size - aiff->form - 4);
00140
00141
00142 avio_seek(pb, aiff->frames, SEEK_SET);
00143 avio_wb32(pb, (file_size-aiff->ssnd-12)/enc->block_align);
00144
00145
00146 avio_seek(pb, aiff->ssnd, SEEK_SET);
00147 avio_wb32(pb, file_size - aiff->ssnd - 4);
00148
00149
00150 avio_seek(pb, end_size, SEEK_SET);
00151
00152 avio_flush(pb);
00153 }
00154
00155 return 0;
00156 }
00157
00158 AVOutputFormat ff_aiff_muxer = {
00159 .name = "aiff",
00160 .long_name = NULL_IF_CONFIG_SMALL("Audio IFF"),
00161 .mime_type = "audio/aiff",
00162 .extensions = "aif,aiff,afc,aifc",
00163 .priv_data_size = sizeof(AIFFOutputContext),
00164 .audio_codec = CODEC_ID_PCM_S16BE,
00165 .video_codec = CODEC_ID_NONE,
00166 .write_header = aiff_write_header,
00167 .write_packet = aiff_write_packet,
00168 .write_trailer = aiff_write_trailer,
00169 .codec_tag= (const AVCodecTag* const []){ff_codec_aiff_tags, 0},
00170 };