OSDN Git Service

Initial caf muxer.
[coroid/ffmpeg_saccubus.git] / libavformat / cafenc.c
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 "riff.h"
25 #include "isom.h"
26 #include "avio_internal.h"
27
28 typedef struct {
29     int64_t data;
30 } CAFContext;
31
32 static uint32_t codec_flags(enum CodecID codec_id) {
33     switch (codec_id) {
34     case CODEC_ID_PCM_F32BE:
35     case CODEC_ID_PCM_F64BE:
36         return 1; //< kCAFLinearPCMFormatFlagIsFloat
37     case CODEC_ID_PCM_S16LE:
38     case CODEC_ID_PCM_S24LE:
39     case CODEC_ID_PCM_S32LE:
40         return 2; //< kCAFLinearPCMFormatFlagIsLittleEndian
41     case CODEC_ID_PCM_F32LE:
42     case CODEC_ID_PCM_F64LE:
43         return 3; //< kCAFLinearPCMFormatFlagIsFloat | kCAFLinearPCMFormatFlagIsLittleEndian
44     default:
45         return 0;
46     }
47 }
48
49 static uint32_t samples_per_packet(enum CodecID codec_id) {
50     switch (codec_id) {
51     case CODEC_ID_PCM_S8:
52     case CODEC_ID_PCM_S16LE:
53     case CODEC_ID_PCM_S16BE:
54     case CODEC_ID_PCM_S24LE:
55     case CODEC_ID_PCM_S24BE:
56     case CODEC_ID_PCM_S32LE:
57     case CODEC_ID_PCM_S32BE:
58     case CODEC_ID_PCM_F32LE:
59     case CODEC_ID_PCM_F32BE:
60     case CODEC_ID_PCM_F64LE:
61     case CODEC_ID_PCM_F64BE:
62     case CODEC_ID_PCM_ALAW:
63     case CODEC_ID_PCM_MULAW:
64         return 1;
65     case CODEC_ID_MACE3:
66     case CODEC_ID_MACE6:
67         return 6;
68     case CODEC_ID_ADPCM_IMA_QT:
69         return 64;
70     case CODEC_ID_AMR_NB:
71     case CODEC_ID_GSM:
72     case CODEC_ID_QCELP:
73         return 160;
74     case CODEC_ID_MP1:
75         return 384;
76     case CODEC_ID_MP2:
77     case CODEC_ID_MP3:
78         return 1152;
79     case CODEC_ID_AC3:
80         return 1536;
81     case CODEC_ID_ALAC:
82     case CODEC_ID_QDM2:
83         return 4096;
84     default:
85         return 0;
86     }
87 }
88
89 static int caf_write_header(AVFormatContext *s)
90 {
91     AVIOContext *pb = s->pb;
92     AVCodecContext *enc = s->streams[0]->codec;
93     CAFContext *caf = s->priv_data;
94     unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, enc->codec_id);
95
96     switch (enc->codec_id) {
97     case CODEC_ID_PCM_S8:
98     case CODEC_ID_PCM_S16LE:
99     case CODEC_ID_PCM_S16BE:
100     case CODEC_ID_PCM_S24LE:
101     case CODEC_ID_PCM_S24BE:
102     case CODEC_ID_PCM_S32LE:
103     case CODEC_ID_PCM_S32BE:
104     case CODEC_ID_PCM_F32LE:
105     case CODEC_ID_PCM_F32BE:
106     case CODEC_ID_PCM_F64LE:
107     case CODEC_ID_PCM_F64BE:
108     case CODEC_ID_PCM_ALAW:
109     case CODEC_ID_PCM_MULAW:
110         codec_tag = MKBETAG('l','p','c','m');
111     }
112
113     if (!codec_tag) {
114         av_log(s, AV_LOG_ERROR, "unsupported codec\n");
115         return AVERROR_INVALIDDATA;
116     }
117
118     if (!enc->block_align) {
119         av_log(s, AV_LOG_ERROR, "muxing with unknown or variable packet size not yet supported\n");
120         return AVERROR_PATCHWELCOME;
121     }
122
123     ffio_wfourcc(pb, "caff"); //< mFileType
124     avio_wb16(pb, 1);         //< mFileVersion
125     avio_wb16(pb, 0);         //< mFileFlags
126
127     ffio_wfourcc(pb, "desc");                         //< Audio Description chunk
128     avio_wb64(pb, 32);                                //< mChunkSize
129     avio_wb64(pb, av_dbl2int(enc->sample_rate));      //< mSampleRate
130     avio_wb32(pb, codec_tag);                         //< mFormatID
131     avio_wb32(pb, codec_flags(enc->codec_id));        //< mFormatFlags
132     avio_wb32(pb, enc->block_align);                  //< mBytesPerPacket
133     avio_wb32(pb, samples_per_packet(enc->codec_id)); //< mFramesPerPacket
134     avio_wb32(pb, enc->channels);                     //< mChannelsPerFrame
135     avio_wb32(pb, enc->bits_per_coded_sample);        //< mBitsPerChannel
136
137     ff_mov_write_chan(s, enc->channel_layout, "chan");
138
139     ffio_wfourcc(pb, "data"); //< Audio Data chunk
140     caf->data = avio_tell(pb);
141     avio_wb64(pb, -1);        //< mChunkSize
142     avio_wb32(pb, 0);         //< mEditCount
143
144     avio_flush(pb);
145     return 0;
146 }
147
148 static int caf_write_packet(AVFormatContext *s, AVPacket *pkt)
149 {
150     avio_write(s->pb, pkt->data, pkt->size);
151     return 0;
152 }
153
154 static int caf_write_trailer(AVFormatContext *s)
155 {
156     AVIOContext *pb = s->pb;
157
158     if (pb->seekable) {
159         CAFContext *caf = s->priv_data;
160         int64_t file_size = avio_tell(pb);
161
162         avio_seek(pb, caf->data, SEEK_SET);
163         avio_wb64(pb, file_size - caf->data - 8);
164         avio_seek(pb, file_size, SEEK_SET);
165         avio_flush(pb);
166     }
167     return 0;
168 }
169
170 AVOutputFormat ff_caf_muxer = {
171     "caf",
172     NULL_IF_CONFIG_SMALL("Apple Core Audio Format"),
173     "audio/x-caf",
174     "caf",
175     sizeof(CAFContext),
176     CODEC_ID_PCM_S16BE,
177     CODEC_ID_NONE,
178     caf_write_header,
179     caf_write_packet,
180     caf_write_trailer,
181     .codec_tag= (const AVCodecTag* const []){ff_codec_caf_tags, 0},
182 };