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