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,
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
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
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
216
static
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
246
static
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
274
AVOutputFormat
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
};
Generated on Sun Mar 8 2015 02:35:09 for FFmpeg by
1.8.2