1/* 2 * Core Audio Format muxer 3 * Copyright (c) 2011 Carl Eugen Hoyos 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "avformat.h" 23#include "caf.h" 24#include "isom.h" 25#include "avio_internal.h" 26#include "libavutil/intfloat.h" 27#include "libavutil/dict.h" 28 29typedef struct { 30 int64_t data; 31 uint8_t *pkt_sizes; 32 int size_buffer_size; 33 int size_entries_used; 34 int packets; 35} CAFContext; 36 37static uint32_t codec_flags(enum AVCodecID codec_id) { 38 switch (codec_id) { 39 case AV_CODEC_ID_PCM_F32BE: 40 case AV_CODEC_ID_PCM_F64BE: 41 return 1; //< kCAFLinearPCMFormatFlagIsFloat 42 case AV_CODEC_ID_PCM_S16LE: 43 case AV_CODEC_ID_PCM_S24LE: 44 case AV_CODEC_ID_PCM_S32LE: 45 return 2; //< kCAFLinearPCMFormatFlagIsLittleEndian 46 case AV_CODEC_ID_PCM_F32LE: 47 case AV_CODEC_ID_PCM_F64LE: 48 return 3; //< kCAFLinearPCMFormatFlagIsFloat | kCAFLinearPCMFormatFlagIsLittleEndian 49 default: 50 return 0; 51 } 52} 53 54static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int block_align) { 55 switch (codec_id) { 56 case AV_CODEC_ID_PCM_S8: 57 case AV_CODEC_ID_PCM_S16LE: 58 case AV_CODEC_ID_PCM_S16BE: 59 case AV_CODEC_ID_PCM_S24LE: 60 case AV_CODEC_ID_PCM_S24BE: 61 case AV_CODEC_ID_PCM_S32LE: 62 case AV_CODEC_ID_PCM_S32BE: 63 case AV_CODEC_ID_PCM_F32LE: 64 case AV_CODEC_ID_PCM_F32BE: 65 case AV_CODEC_ID_PCM_F64LE: 66 case AV_CODEC_ID_PCM_F64BE: 67 case AV_CODEC_ID_PCM_ALAW: 68 case AV_CODEC_ID_PCM_MULAW: 69 return 1; 70 case AV_CODEC_ID_MACE3: 71 case AV_CODEC_ID_MACE6: 72 return 6; 73 case AV_CODEC_ID_ADPCM_IMA_QT: 74 return 64; 75 case AV_CODEC_ID_AMR_NB: 76 case AV_CODEC_ID_GSM: 77 case AV_CODEC_ID_ILBC: 78 case AV_CODEC_ID_QCELP: 79 return 160; 80 case AV_CODEC_ID_GSM_MS: 81 return 320; 82 case AV_CODEC_ID_MP1: 83 return 384; 84 case AV_CODEC_ID_MP2: 85 case AV_CODEC_ID_MP3: 86 return 1152; 87 case AV_CODEC_ID_AC3: 88 return 1536; 89 case AV_CODEC_ID_QDM2: 90 return 2048 * channels; 91 case AV_CODEC_ID_ALAC: 92 return 4096; 93 case AV_CODEC_ID_ADPCM_IMA_WAV: 94 return (block_align - 4 * channels) * 8 / (4 * channels) + 1; 95 case AV_CODEC_ID_ADPCM_MS: 96 return (block_align - 7 * channels) * 2 / channels + 2; 97 default: 98 return 0; 99 } 100} 101 102static int caf_write_header(AVFormatContext *s) 103{ 104 AVIOContext *pb = s->pb; 105 AVCodecContext *enc = s->streams[0]->codec; 106 CAFContext *caf = s->priv_data; 107 AVDictionaryEntry *t = NULL; 108 unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, enc->codec_id); 109 int64_t chunk_size = 0; 110 int frame_size = enc->frame_size; 111 112 if (s->nb_streams != 1) { 113 av_log(s, AV_LOG_ERROR, "CAF files have exactly one stream\n"); 114 return AVERROR(EINVAL); 115 } 116 117 switch (enc->codec_id) { 118 case AV_CODEC_ID_AAC: 119 av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n"); 120 return AVERROR_PATCHWELCOME; 121 } 122 123 switch (enc->codec_id) { 124 case AV_CODEC_ID_PCM_S8: 125 case AV_CODEC_ID_PCM_S16LE: 126 case AV_CODEC_ID_PCM_S16BE: 127 case AV_CODEC_ID_PCM_S24LE: 128 case AV_CODEC_ID_PCM_S24BE: 129 case AV_CODEC_ID_PCM_S32LE: 130 case AV_CODEC_ID_PCM_S32BE: 131 case AV_CODEC_ID_PCM_F32LE: 132 case AV_CODEC_ID_PCM_F32BE: 133 case AV_CODEC_ID_PCM_F64LE: 134 case AV_CODEC_ID_PCM_F64BE: 135 codec_tag = MKTAG('l','p','c','m'); 136 } 137 138 if (!codec_tag) { 139 av_log(s, AV_LOG_ERROR, "unsupported codec\n"); 140 return AVERROR_INVALIDDATA; 141 } 142 143 if (!enc->block_align && !pb->seekable) { 144 av_log(s, AV_LOG_ERROR, "Muxing variable packet size not supported on non seekable output\n"); 145 return AVERROR_INVALIDDATA; 146 } 147 148 if (enc->codec_id != AV_CODEC_ID_MP3 || frame_size != 576) 149 frame_size = samples_per_packet(enc->codec_id, enc->channels, enc->block_align); 150 151 ffio_wfourcc(pb, "caff"); //< mFileType 152 avio_wb16(pb, 1); //< mFileVersion 153 avio_wb16(pb, 0); //< mFileFlags 154 155 ffio_wfourcc(pb, "desc"); //< Audio Description chunk 156 avio_wb64(pb, 32); //< mChunkSize 157 avio_wb64(pb, av_double2int(enc->sample_rate)); //< mSampleRate 158 avio_wl32(pb, codec_tag); //< mFormatID 159 avio_wb32(pb, codec_flags(enc->codec_id)); //< mFormatFlags 160 avio_wb32(pb, enc->block_align); //< mBytesPerPacket 161 avio_wb32(pb, frame_size); //< mFramesPerPacket 162 avio_wb32(pb, enc->channels); //< mChannelsPerFrame 163 avio_wb32(pb, av_get_bits_per_sample(enc->codec_id)); //< mBitsPerChannel 164 165 if (enc->channel_layout) { 166 ffio_wfourcc(pb, "chan"); 167 avio_wb64(pb, 12); 168 ff_mov_write_chan(pb, enc->channel_layout); 169 } 170 171 if (enc->codec_id == AV_CODEC_ID_ALAC) { 172 ffio_wfourcc(pb, "kuki"); 173 avio_wb64(pb, 12 + enc->extradata_size); 174 avio_write(pb, "\0\0\0\14frmaalac", 12); 175 avio_write(pb, enc->extradata, enc->extradata_size); 176 } else if (enc->codec_id == AV_CODEC_ID_AMR_NB) { 177 ffio_wfourcc(pb, "kuki"); 178 avio_wb64(pb, 29); 179 avio_write(pb, "\0\0\0\14frmasamr", 12); 180 avio_wb32(pb, 0x11); /* size */ 181 avio_write(pb, "samrFFMP", 8); 182 avio_w8(pb, 0); /* decoder version */ 183 184 avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */ 185 avio_w8(pb, 0x00); /* Mode change period (no restriction) */ 186 avio_w8(pb, 0x01); /* Frames per sample */ 187 } else if (enc->codec_id == AV_CODEC_ID_QDM2) { 188 ffio_wfourcc(pb, "kuki"); 189 avio_wb64(pb, enc->extradata_size); 190 avio_write(pb, enc->extradata, enc->extradata_size); 191 } 192 193 if (av_dict_count(s->metadata)) { 194 ffio_wfourcc(pb, "info"); //< Information chunk 195 while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) { 196 chunk_size += strlen(t->key) + strlen(t->value) + 2; 197 } 198 avio_wb64(pb, chunk_size + 4); 199 avio_wb32(pb, av_dict_count(s->metadata)); 200 t = NULL; 201 while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) { 202 avio_put_str(pb, t->key); 203 avio_put_str(pb, t->value); 204 } 205 } 206 207 ffio_wfourcc(pb, "data"); //< Audio Data chunk 208 caf->data = avio_tell(pb); 209 avio_wb64(pb, -1); //< mChunkSize 210 avio_wb32(pb, 0); //< mEditCount 211 212 avio_flush(pb); 213 return 0; 214} 215 216static int caf_write_packet(AVFormatContext *s, AVPacket *pkt) 217{ 218 CAFContext *caf = s->priv_data; 219 220 avio_write(s->pb, pkt->data, pkt->size); 221 if (!s->streams[0]->codec->block_align) { 222 void *pkt_sizes = caf->pkt_sizes; 223 int i, alloc_size = caf->size_entries_used + 5; 224 if (alloc_size < 0) { 225 caf->pkt_sizes = NULL; 226 } else { 227 caf->pkt_sizes = av_fast_realloc(caf->pkt_sizes, 228 &caf->size_buffer_size, 229 alloc_size); 230 } 231 if (!caf->pkt_sizes) { 232 av_free(pkt_sizes); 233 return AVERROR(ENOMEM); 234 } 235 for (i = 4; i > 0; i--) { 236 unsigned top = pkt->size >> i * 7; 237 if (top) 238 caf->pkt_sizes[caf->size_entries_used++] = 128 | top; 239 } 240 caf->pkt_sizes[caf->size_entries_used++] = pkt->size & 127; 241 caf->packets++; 242 } 243 return 0; 244} 245 246static int caf_write_trailer(AVFormatContext *s) 247{ 248 CAFContext *caf = s->priv_data; 249 AVIOContext *pb = s->pb; 250 AVCodecContext *enc = s->streams[0]->codec; 251 252 if (pb->seekable) { 253 int64_t file_size = avio_tell(pb); 254 255 avio_seek(pb, caf->data, SEEK_SET); 256 avio_wb64(pb, file_size - caf->data - 8); 257 avio_seek(pb, file_size, SEEK_SET); 258 if (!enc->block_align) { 259 ffio_wfourcc(pb, "pakt"); 260 avio_wb64(pb, caf->size_entries_used + 24); 261 avio_wb64(pb, caf->packets); ///< mNumberPackets 262 avio_wb64(pb, caf->packets * samples_per_packet(enc->codec_id, enc->channels, enc->block_align)); ///< mNumberValidFrames 263 avio_wb32(pb, 0); ///< mPrimingFrames 264 avio_wb32(pb, 0); ///< mRemainderFrames 265 avio_write(pb, caf->pkt_sizes, caf->size_entries_used); 266 caf->size_buffer_size = 0; 267 } 268 avio_flush(pb); 269 } 270 av_freep(&caf->pkt_sizes); 271 return 0; 272} 273 274AVOutputFormat ff_caf_muxer = { 275 .name = "caf", 276 .long_name = NULL_IF_CONFIG_SMALL("Apple CAF (Core Audio Format)"), 277 .mime_type = "audio/x-caf", 278 .extensions = "caf", 279 .priv_data_size = sizeof(CAFContext), 280 .audio_codec = AV_CODEC_ID_PCM_S16BE, 281 .video_codec = AV_CODEC_ID_NONE, 282 .write_header = caf_write_header, 283 .write_packet = caf_write_packet, 284 .write_trailer = caf_write_trailer, 285 .codec_tag = (const AVCodecTag* const []){ff_codec_caf_tags, 0}, 286}; 287