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