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