Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
mp3enc.c
Go to the documentation of this file.
1
/*
2
* MP3 muxer
3
* Copyright (c) 2003 Fabrice Bellard
4
*
5
* This file is part of Libav.
6
*
7
* Libav 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
* Libav 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 Libav; 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 "
avio_internal.h
"
24
#include "
id3v1.h
"
25
#include "
id3v2.h
"
26
#include "
rawenc.h
"
27
#include "
libavutil/avstring.h
"
28
#include "
libavcodec/mpegaudio.h
"
29
#include "
libavcodec/mpegaudiodata.h
"
30
#include "
libavcodec/mpegaudiodecheader.h
"
31
#include "
libavutil/intreadwrite.h
"
32
#include "
libavutil/opt.h
"
33
#include "
libavutil/dict.h
"
34
35
static
int
id3v1_set_string
(
AVFormatContext
*s,
const
char
*key,
36
uint8_t *buf,
int
buf_size)
37
{
38
AVDictionaryEntry
*
tag
;
39
if
((tag =
av_dict_get
(s->
metadata
, key,
NULL
, 0)))
40
av_strlcpy
(buf, tag->
value
, buf_size);
41
return
!!
tag
;
42
}
43
44
static
int
id3v1_create_tag
(
AVFormatContext
*s, uint8_t *buf)
45
{
46
AVDictionaryEntry
*
tag
;
47
int
i, count = 0;
48
49
memset(buf, 0,
ID3v1_TAG_SIZE
);
/* fail safe */
50
buf[0] =
'T'
;
51
buf[1] =
'A'
;
52
buf[2] =
'G'
;
53
count +=
id3v1_set_string
(s,
"TIT2"
, buf + 3, 30);
//title
54
count +=
id3v1_set_string
(s,
"TPE1"
, buf + 33, 30);
//author|artist
55
count +=
id3v1_set_string
(s,
"TALB"
, buf + 63, 30);
//album
56
count +=
id3v1_set_string
(s,
"TDRL"
, buf + 93, 4);
//date
57
count +=
id3v1_set_string
(s,
"comment"
, buf + 97, 30);
58
if
((tag =
av_dict_get
(s->
metadata
,
"TRCK"
,
NULL
, 0))) {
//track
59
buf[125] = 0;
60
buf[126] = atoi(tag->
value
);
61
count++;
62
}
63
buf[127] = 0xFF;
/* default to unknown genre */
64
if
((tag =
av_dict_get
(s->
metadata
,
"TCON"
,
NULL
, 0))) {
//genre
65
for
(i = 0; i <=
ID3v1_GENRE_MAX
; i++) {
66
if
(!
av_strcasecmp
(tag->
value
,
ff_id3v1_genre_str
[i])) {
67
buf[127] = i;
68
count++;
69
break
;
70
}
71
}
72
}
73
return
count;
74
}
75
76
typedef
struct
MP3Context
{
77
const
AVClass
*
class
;
78
int
id3v2_version
;
79
int
write_id3v1
;
80
int64_t
nb_frames_offset
;
81
}
MP3Context
;
82
83
static
int
mp3_write_trailer
(
struct
AVFormatContext
*s)
84
{
85
uint8_t buf[
ID3v1_TAG_SIZE
];
86
MP3Context
*mp3 = s->
priv_data
;
87
88
/* write the id3v1 tag */
89
if
(mp3 && mp3->
write_id3v1
&&
id3v1_create_tag
(s, buf) > 0) {
90
avio_write
(s->
pb
, buf,
ID3v1_TAG_SIZE
);
91
}
92
93
/* write number of frames */
94
if
(mp3 && mp3->
nb_frames_offset
) {
95
avio_seek
(s->
pb
, mp3->
nb_frames_offset
, SEEK_SET);
96
avio_wb32
(s->
pb
, s->
streams
[0]->
nb_frames
);
97
avio_seek
(s->
pb
, 0, SEEK_END);
98
}
99
100
avio_flush
(s->
pb
);
101
102
return
0;
103
}
104
105
#if CONFIG_MP2_MUXER
106
AVOutputFormat
ff_mp2_muxer = {
107
.
name
=
"mp2"
,
108
.long_name =
NULL_IF_CONFIG_SMALL
(
"MPEG audio layer 2"
),
109
.mime_type =
"audio/x-mpeg"
,
110
.extensions =
"mp2,m2a"
,
111
.audio_codec =
CODEC_ID_MP2
,
112
.video_codec =
CODEC_ID_NONE
,
113
.write_packet =
ff_raw_write_packet
,
114
.write_trailer =
mp3_write_trailer
,
115
};
116
#endif
117
118
#if CONFIG_MP3_MUXER
119
120
static
const
AVOption
options
[] = {
121
{
"id3v2_version"
,
"Select ID3v2 version to write. Currently 3 and 4 are supported."
,
122
offsetof(
MP3Context
, id3v2_version),
AV_OPT_TYPE_INT
, {.dbl = 4}, 3, 4,
AV_OPT_FLAG_ENCODING_PARAM
},
123
{
"write_id3v1"
,
"Enable ID3v1 writing. ID3v1 tags are written in UTF-8 which may not be supported by most software."
,
124
offsetof(
MP3Context
, write_id3v1),
AV_OPT_TYPE_INT
, {.dbl = 0}, 0, 1,
AV_OPT_FLAG_ENCODING_PARAM
},
125
{
NULL
},
126
};
127
128
static
const
AVClass
mp3_muxer_class = {
129
.
class_name
=
"MP3 muxer"
,
130
.item_name =
av_default_item_name
,
131
.option =
options
,
132
.version =
LIBAVUTIL_VERSION_INT
,
133
};
134
135
/* insert a dummy frame containing number of frames */
136
static
void
mp3_write_xing(
AVFormatContext
*s)
137
{
138
AVCodecContext
*codec = s->
streams
[0]->
codec
;
139
MP3Context
*mp3 = s->
priv_data
;
140
int
bitrate_idx = 1;
// 32 kbps
141
int64_t xing_offset = (codec->
channels
== 2) ? 32 : 17;
142
int32_t header;
143
MPADecodeHeader
mpah;
144
int
srate_idx, i, channels;
145
146
for
(i = 0; i <
FF_ARRAY_ELEMS
(
avpriv_mpa_freq_tab
); i++)
147
if
(
avpriv_mpa_freq_tab
[i] == codec->
sample_rate
) {
148
srate_idx = i;
149
break
;
150
}
151
if
(i ==
FF_ARRAY_ELEMS
(
avpriv_mpa_freq_tab
)) {
152
av_log
(s,
AV_LOG_ERROR
,
"Unsupported sample rate.\n"
);
153
return
;
154
}
155
156
switch
(codec->
channels
) {
157
case
1: channels =
MPA_MONO
;
break
;
158
case
2: channels =
MPA_STEREO
;
break
;
159
default
:
av_log
(s,
AV_LOG_ERROR
,
"Unsupported number of channels.\n"
);
return
;
160
}
161
162
/* dummy MPEG audio header */
163
header = 0xff << 24;
// sync
164
header |= (0x7 << 5 | 0x3 << 3 | 0x1 << 1 | 0x1) << 16;
// sync/mpeg-1/layer 3/no crc*/
165
header |= (bitrate_idx << 4 | srate_idx << 2) << 8;
166
header |= channels << 6;
167
avio_wb32
(s->
pb
, header);
168
169
avpriv_mpegaudio_decode_header
(&mpah, header);
170
171
ffio_fill
(s->
pb
, 0, xing_offset);
172
ffio_wfourcc
(s->
pb
,
"Xing"
);
173
avio_wb32
(s->
pb
, 0x1);
// only number of frames
174
mp3->
nb_frames_offset
=
avio_tell
(s->
pb
);
175
avio_wb32
(s->
pb
, 0);
176
177
mpah.frame_size -= 4 + xing_offset + 4 + 4 + 4;
178
ffio_fill
(s->
pb
, 0, mpah.frame_size);
179
}
180
185
static
int
mp3_write_header(
struct
AVFormatContext
*s)
186
{
187
MP3Context
*mp3 = s->
priv_data
;
188
int
ret;
189
190
ret =
ff_id3v2_write
(s, mp3->
id3v2_version
,
ID3v2_DEFAULT_MAGIC
);
191
if
(ret < 0)
192
return
ret;
193
194
if
(s->
pb
->
seekable
)
195
mp3_write_xing(s);
196
197
return
0;
198
}
199
200
AVOutputFormat
ff_mp3_muxer = {
201
.
name
=
"mp3"
,
202
.long_name =
NULL_IF_CONFIG_SMALL
(
"MPEG audio layer 3"
),
203
.mime_type =
"audio/x-mpeg"
,
204
.extensions =
"mp3"
,
205
.priv_data_size =
sizeof
(
MP3Context
),
206
.audio_codec =
CODEC_ID_MP3
,
207
.video_codec =
CODEC_ID_NONE
,
208
.
write_header
= mp3_write_header,
209
.
write_packet
=
ff_raw_write_packet
,
210
.
write_trailer
=
mp3_write_trailer
,
211
.
flags
=
AVFMT_NOTIMESTAMPS
,
212
.priv_class = &mp3_muxer_class,
213
};
214
#endif