FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
cafenc.c
Go to the documentation of this file.
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
29
typedef
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
37
static
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
54
static
uint32_t
samples_per_packet
(
enum
AVCodecID
codec_id
,
int
channels) {
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
(1024 - 4 * channels) * 8 / (4 * channels) + 1;
95
case
AV_CODEC_ID_ADPCM_MS
:
96
return
(1024 - 7 * channels) * 2 / channels + 2;
97
default
:
98
return
0;
99
}
100
}
101
102
static
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
111
if
(s->
nb_streams
!= 1) {
112
av_log
(s,
AV_LOG_ERROR
,
"CAF files have exactly one stream\n"
);
113
return
AVERROR
(EINVAL);
114
}
115
116
switch
(enc->
codec_id
) {
117
case
AV_CODEC_ID_AAC
:
118
case
AV_CODEC_ID_AC3
:
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
case
AV_CODEC_ID_PCM_ALAW
:
136
case
AV_CODEC_ID_PCM_MULAW
:
137
codec_tag =
MKTAG
(
'l'
,
'p'
,
'c'
,
'm'
);
138
}
139
140
if
(!codec_tag) {
141
av_log
(s,
AV_LOG_ERROR
,
"unsupported codec\n"
);
142
return
AVERROR_INVALIDDATA
;
143
}
144
145
if
(!enc->
block_align
&& !pb->
seekable
) {
146
av_log
(s,
AV_LOG_ERROR
,
"Muxing variable packet size not supported on non seekable output\n"
);
147
return
AVERROR_INVALIDDATA
;
148
}
149
150
ffio_wfourcc
(pb,
"caff"
);
//< mFileType
151
avio_wb16
(pb, 1);
//< mFileVersion
152
avio_wb16
(pb, 0);
//< mFileFlags
153
154
ffio_wfourcc
(pb,
"desc"
);
//< Audio Description chunk
155
avio_wb64
(pb, 32);
//< mChunkSize
156
avio_wb64
(pb,
av_double2int
(enc->
sample_rate
));
//< mSampleRate
157
avio_wl32
(pb, codec_tag);
//< mFormatID
158
avio_wb32
(pb,
codec_flags
(enc->
codec_id
));
//< mFormatFlags
159
avio_wb32
(pb, enc->
block_align
);
//< mBytesPerPacket
160
avio_wb32
(pb,
samples_per_packet
(enc->
codec_id
, enc->
channels
));
//< mFramesPerPacket
161
avio_wb32
(pb, enc->
channels
);
//< mChannelsPerFrame
162
avio_wb32
(pb,
av_get_bits_per_sample
(enc->
codec_id
));
//< mBitsPerChannel
163
164
if
(enc->
channel_layout
) {
165
ffio_wfourcc
(pb,
"chan"
);
166
avio_wb64
(pb, 12);
167
ff_mov_write_chan
(pb, enc->
channel_layout
);
168
}
169
170
if
(enc->
codec_id
==
AV_CODEC_ID_ALAC
) {
171
ffio_wfourcc
(pb,
"kuki"
);
172
avio_wb64
(pb, 12 + enc->
extradata_size
);
173
avio_write
(pb,
"\0\0\0\14frmaalac"
, 12);
174
avio_write
(pb, enc->
extradata
, enc->
extradata_size
);
175
}
else
if
(enc->
codec_id
==
AV_CODEC_ID_AMR_NB
) {
176
ffio_wfourcc
(pb,
"kuki"
);
177
avio_wb64
(pb, 29);
178
avio_write
(pb,
"\0\0\0\14frmasamr"
, 12);
179
avio_wb32
(pb, 0x11);
/* size */
180
avio_write
(pb,
"samrFFMP"
, 8);
181
avio_w8
(pb, 0);
/* decoder version */
182
183
avio_wb16
(pb, 0x81FF);
/* Mode set (all modes for AMR_NB) */
184
avio_w8
(pb, 0x00);
/* Mode change period (no restriction) */
185
avio_w8
(pb, 0x01);
/* Frames per sample */
186
}
else
if
(enc->
codec_id
==
AV_CODEC_ID_QDM2
) {
187
ffio_wfourcc
(pb,
"kuki"
);
188
avio_wb64
(pb, enc->
extradata_size
);
189
avio_write
(pb, enc->
extradata
, enc->
extradata_size
);
190
}
191
192
if
(
av_dict_count
(s->
metadata
)) {
193
ffio_wfourcc
(pb,
"info"
);
//< Information chunk
194
while
((t =
av_dict_get
(s->
metadata
,
""
, t,
AV_DICT_IGNORE_SUFFIX
))) {
195
chunk_size += strlen(t->
key
) + strlen(t->
value
) + 2;
196
}
197
avio_wb64
(pb, chunk_size + 4);
198
avio_wb32
(pb,
av_dict_count
(s->
metadata
));
199
t = NULL;
200
while
((t =
av_dict_get
(s->
metadata
,
""
, t,
AV_DICT_IGNORE_SUFFIX
))) {
201
avio_put_str
(pb, t->
key
);
202
avio_put_str
(pb, t->
value
);
203
}
204
}
205
206
ffio_wfourcc
(pb,
"data"
);
//< Audio Data chunk
207
caf->
data
=
avio_tell
(pb);
208
avio_wb64
(pb, -1);
//< mChunkSize
209
avio_wb32
(pb, 0);
//< mEditCount
210
211
avio_flush
(pb);
212
return
0;
213
}
214
215
static
int
caf_write_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
216
{
217
CAFContext
*caf = s->
priv_data
;
218
219
avio_write
(s->
pb
, pkt->
data
, pkt->
size
);
220
if
(!s->
streams
[0]->
codec
->
block_align
) {
221
void
*pkt_sizes = caf->
pkt_sizes
;
222
int
i, alloc_size = caf->
size_entries_used
+ 5;
223
if
(alloc_size < 0) {
224
caf->
pkt_sizes
= NULL;
225
}
else
{
226
caf->
pkt_sizes
=
av_fast_realloc
(caf->
pkt_sizes
,
227
&caf->
size_buffer_size
,
228
alloc_size);
229
}
230
if
(!caf->
pkt_sizes
) {
231
av_free
(pkt_sizes);
232
return
AVERROR
(ENOMEM);
233
}
234
for
(i = 4; i > 0; i--) {
235
unsigned
top = pkt->
size
>> i * 7;
236
if
(top)
237
caf->
pkt_sizes
[caf->
size_entries_used
++] = 128 | top;
238
}
239
caf->
pkt_sizes
[caf->
size_entries_used
++] = pkt->
size
& 127;
240
caf->
packets
++;
241
}
242
return
0;
243
}
244
245
static
int
caf_write_trailer
(
AVFormatContext
*
s
)
246
{
247
CAFContext
*caf = s->
priv_data
;
248
AVIOContext
*pb = s->
pb
;
249
AVCodecContext
*enc = s->
streams
[0]->
codec
;
250
251
if
(pb->
seekable
) {
252
int64_t file_size =
avio_tell
(pb);
253
254
avio_seek
(pb, caf->
data
, SEEK_SET);
255
avio_wb64
(pb, file_size - caf->
data
- 8);
256
avio_seek
(pb, file_size, SEEK_SET);
257
if
(!enc->
block_align
) {
258
ffio_wfourcc
(pb,
"pakt"
);
259
avio_wb64
(pb, caf->
size_entries_used
+ 24);
260
avio_wb64
(pb, caf->
packets
);
///< mNumberPackets
261
avio_wb64
(pb, caf->
packets
*
samples_per_packet
(enc->
codec_id
, enc->
channels
));
///< mNumberValidFrames
262
avio_wb32
(pb, 0);
///< mPrimingFrames
263
avio_wb32
(pb, 0);
///< mRemainderFrames
264
avio_write
(pb, caf->
pkt_sizes
, caf->
size_entries_used
);
265
caf->
size_buffer_size
= 0;
266
}
267
avio_flush
(pb);
268
}
269
av_freep
(&caf->
pkt_sizes
);
270
return
0;
271
}
272
273
AVOutputFormat
ff_caf_muxer
= {
274
.
name
=
"caf"
,
275
.long_name =
NULL_IF_CONFIG_SMALL
(
"Apple CAF (Core Audio Format)"
),
276
.mime_type =
"audio/x-caf"
,
277
.extensions =
"caf"
,
278
.priv_data_size =
sizeof
(
CAFContext
),
279
.audio_codec =
AV_CODEC_ID_PCM_S16BE
,
280
.video_codec =
AV_CODEC_ID_NONE
,
281
.
write_header
=
caf_write_header
,
282
.
write_packet
=
caf_write_packet
,
283
.
write_trailer
=
caf_write_trailer
,
284
.codec_tag = (
const
AVCodecTag
*
const
[]){
ff_codec_caf_tags
, 0},
285
};
Generated on Sun Mar 23 2014 23:50:10 for FFmpeg by
1.8.2