yading@11
|
1 /*
|
yading@11
|
2 * MP3 muxer
|
yading@11
|
3 * Copyright (c) 2003 Fabrice Bellard
|
yading@11
|
4 *
|
yading@11
|
5 * This file is part of FFmpeg.
|
yading@11
|
6 *
|
yading@11
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@11
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
9 * License as published by the Free Software Foundation; either
|
yading@11
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
11 *
|
yading@11
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@11
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
15 * Lesser General Public License for more details.
|
yading@11
|
16 *
|
yading@11
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@11
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
20 */
|
yading@11
|
21
|
yading@11
|
22 #include "avformat.h"
|
yading@11
|
23 #include "avio_internal.h"
|
yading@11
|
24 #include "id3v1.h"
|
yading@11
|
25 #include "id3v2.h"
|
yading@11
|
26 #include "rawenc.h"
|
yading@11
|
27 #include "libavutil/avstring.h"
|
yading@11
|
28 #include "libavcodec/mpegaudio.h"
|
yading@11
|
29 #include "libavcodec/mpegaudiodata.h"
|
yading@11
|
30 #include "libavcodec/mpegaudiodecheader.h"
|
yading@11
|
31 #include "libavutil/intreadwrite.h"
|
yading@11
|
32 #include "libavutil/opt.h"
|
yading@11
|
33 #include "libavcodec/mpegaudio.h"
|
yading@11
|
34 #include "libavcodec/mpegaudiodata.h"
|
yading@11
|
35 #include "libavcodec/mpegaudiodecheader.h"
|
yading@11
|
36 #include "libavformat/avio_internal.h"
|
yading@11
|
37 #include "libavutil/dict.h"
|
yading@11
|
38 #include "libavutil/avassert.h"
|
yading@11
|
39
|
yading@11
|
40 static int id3v1_set_string(AVFormatContext *s, const char *key,
|
yading@11
|
41 uint8_t *buf, int buf_size)
|
yading@11
|
42 {
|
yading@11
|
43 AVDictionaryEntry *tag;
|
yading@11
|
44 if ((tag = av_dict_get(s->metadata, key, NULL, 0)))
|
yading@11
|
45 av_strlcpy(buf, tag->value, buf_size);
|
yading@11
|
46 return !!tag;
|
yading@11
|
47 }
|
yading@11
|
48
|
yading@11
|
49 static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf)
|
yading@11
|
50 {
|
yading@11
|
51 AVDictionaryEntry *tag;
|
yading@11
|
52 int i, count = 0;
|
yading@11
|
53
|
yading@11
|
54 memset(buf, 0, ID3v1_TAG_SIZE); /* fail safe */
|
yading@11
|
55 buf[0] = 'T';
|
yading@11
|
56 buf[1] = 'A';
|
yading@11
|
57 buf[2] = 'G';
|
yading@11
|
58 /* we knowingly overspecify each tag length by one byte to compensate for the mandatory null byte added by av_strlcpy */
|
yading@11
|
59 count += id3v1_set_string(s, "TIT2", buf + 3, 30 + 1); //title
|
yading@11
|
60 count += id3v1_set_string(s, "TPE1", buf + 33, 30 + 1); //author|artist
|
yading@11
|
61 count += id3v1_set_string(s, "TALB", buf + 63, 30 + 1); //album
|
yading@11
|
62 count += id3v1_set_string(s, "TDRL", buf + 93, 4 + 1); //date
|
yading@11
|
63 count += id3v1_set_string(s, "comment", buf + 97, 30 + 1);
|
yading@11
|
64 if ((tag = av_dict_get(s->metadata, "TRCK", NULL, 0))) { //track
|
yading@11
|
65 buf[125] = 0;
|
yading@11
|
66 buf[126] = atoi(tag->value);
|
yading@11
|
67 count++;
|
yading@11
|
68 }
|
yading@11
|
69 buf[127] = 0xFF; /* default to unknown genre */
|
yading@11
|
70 if ((tag = av_dict_get(s->metadata, "TCON", NULL, 0))) { //genre
|
yading@11
|
71 for(i = 0; i <= ID3v1_GENRE_MAX; i++) {
|
yading@11
|
72 if (!av_strcasecmp(tag->value, ff_id3v1_genre_str[i])) {
|
yading@11
|
73 buf[127] = i;
|
yading@11
|
74 count++;
|
yading@11
|
75 break;
|
yading@11
|
76 }
|
yading@11
|
77 }
|
yading@11
|
78 }
|
yading@11
|
79 return count;
|
yading@11
|
80 }
|
yading@11
|
81
|
yading@11
|
82 #define XING_NUM_BAGS 400
|
yading@11
|
83 #define XING_TOC_SIZE 100
|
yading@11
|
84 // maximum size of the xing frame: offset/Xing/flags/frames/size/TOC
|
yading@11
|
85 #define XING_MAX_SIZE (32 + 4 + 4 + 4 + 4 + XING_TOC_SIZE)
|
yading@11
|
86
|
yading@11
|
87 typedef struct MP3Context {
|
yading@11
|
88 const AVClass *class;
|
yading@11
|
89 ID3v2EncContext id3;
|
yading@11
|
90 int id3v2_version;
|
yading@11
|
91 int write_id3v1;
|
yading@11
|
92
|
yading@11
|
93 /* xing header */
|
yading@11
|
94 int64_t xing_offset;
|
yading@11
|
95 int32_t frames;
|
yading@11
|
96 int32_t size;
|
yading@11
|
97 uint32_t want;
|
yading@11
|
98 uint32_t seen;
|
yading@11
|
99 uint32_t pos;
|
yading@11
|
100 uint64_t bag[XING_NUM_BAGS];
|
yading@11
|
101 int initial_bitrate;
|
yading@11
|
102 int has_variable_bitrate;
|
yading@11
|
103
|
yading@11
|
104 /* index of the audio stream */
|
yading@11
|
105 int audio_stream_idx;
|
yading@11
|
106 /* number of attached pictures we still need to write */
|
yading@11
|
107 int pics_to_write;
|
yading@11
|
108
|
yading@11
|
109 /* audio packets are queued here until we get all the attached pictures */
|
yading@11
|
110 AVPacketList *queue, *queue_end;
|
yading@11
|
111 } MP3Context;
|
yading@11
|
112
|
yading@11
|
113 static const uint8_t xing_offtbl[2][2] = {{32, 17}, {17, 9}};
|
yading@11
|
114
|
yading@11
|
115 /*
|
yading@11
|
116 * Write an empty XING header and initialize respective data.
|
yading@11
|
117 */
|
yading@11
|
118 static int mp3_write_xing(AVFormatContext *s)
|
yading@11
|
119 {
|
yading@11
|
120 MP3Context *mp3 = s->priv_data;
|
yading@11
|
121 AVCodecContext *codec = s->streams[mp3->audio_stream_idx]->codec;
|
yading@11
|
122 int bitrate_idx;
|
yading@11
|
123 int best_bitrate_idx = -1;
|
yading@11
|
124 int best_bitrate_error= INT_MAX;
|
yading@11
|
125 int xing_offset;
|
yading@11
|
126 int32_t header, mask;
|
yading@11
|
127 MPADecodeHeader c;
|
yading@11
|
128 int srate_idx, ver = 0, i, channels;
|
yading@11
|
129 int needed;
|
yading@11
|
130 const char *vendor = (codec->flags & CODEC_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT;
|
yading@11
|
131
|
yading@11
|
132 if (!s->pb->seekable)
|
yading@11
|
133 return 0;
|
yading@11
|
134
|
yading@11
|
135 for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) {
|
yading@11
|
136 const uint16_t base_freq = avpriv_mpa_freq_tab[i];
|
yading@11
|
137
|
yading@11
|
138 if (codec->sample_rate == base_freq) ver = 0x3; // MPEG 1
|
yading@11
|
139 else if (codec->sample_rate == base_freq / 2) ver = 0x2; // MPEG 2
|
yading@11
|
140 else if (codec->sample_rate == base_freq / 4) ver = 0x0; // MPEG 2.5
|
yading@11
|
141 else continue;
|
yading@11
|
142
|
yading@11
|
143 srate_idx = i;
|
yading@11
|
144 break;
|
yading@11
|
145 }
|
yading@11
|
146 if (i == FF_ARRAY_ELEMS(avpriv_mpa_freq_tab)) {
|
yading@11
|
147 av_log(s, AV_LOG_WARNING, "Unsupported sample rate, not writing Xing header.\n");
|
yading@11
|
148 return -1;
|
yading@11
|
149 }
|
yading@11
|
150
|
yading@11
|
151 switch (codec->channels) {
|
yading@11
|
152 case 1: channels = MPA_MONO; break;
|
yading@11
|
153 case 2: channels = MPA_STEREO; break;
|
yading@11
|
154 default: av_log(s, AV_LOG_WARNING, "Unsupported number of channels, "
|
yading@11
|
155 "not writing Xing header.\n");
|
yading@11
|
156 return -1;
|
yading@11
|
157 }
|
yading@11
|
158
|
yading@11
|
159 /* dummy MPEG audio header */
|
yading@11
|
160 header = 0xffU << 24; // sync
|
yading@11
|
161 header |= (0x7 << 5 | ver << 3 | 0x1 << 1 | 0x1) << 16; // sync/audio-version/layer 3/no crc*/
|
yading@11
|
162 header |= (srate_idx << 2) << 8;
|
yading@11
|
163 header |= channels << 6;
|
yading@11
|
164
|
yading@11
|
165 for (bitrate_idx=1; bitrate_idx<15; bitrate_idx++) {
|
yading@11
|
166 int error;
|
yading@11
|
167 avpriv_mpegaudio_decode_header(&c, header | (bitrate_idx << (4+8)));
|
yading@11
|
168 error= FFABS(c.bit_rate - codec->bit_rate);
|
yading@11
|
169 if(error < best_bitrate_error){
|
yading@11
|
170 best_bitrate_error= error;
|
yading@11
|
171 best_bitrate_idx = bitrate_idx;
|
yading@11
|
172 }
|
yading@11
|
173 }
|
yading@11
|
174 av_assert0(best_bitrate_idx >= 0);
|
yading@11
|
175
|
yading@11
|
176 for (bitrate_idx= best_bitrate_idx;; bitrate_idx++) {
|
yading@11
|
177 if (15 == bitrate_idx)
|
yading@11
|
178 return -1;
|
yading@11
|
179 mask = bitrate_idx << (4+8);
|
yading@11
|
180 header |= mask;
|
yading@11
|
181 avpriv_mpegaudio_decode_header(&c, header);
|
yading@11
|
182 xing_offset=xing_offtbl[c.lsf == 1][c.nb_channels == 1];
|
yading@11
|
183 needed = 4 // header
|
yading@11
|
184 + xing_offset
|
yading@11
|
185 + 4 // xing tag
|
yading@11
|
186 + 4 // frames/size/toc flags
|
yading@11
|
187 + 4 // frames
|
yading@11
|
188 + 4 // size
|
yading@11
|
189 + XING_TOC_SIZE // toc
|
yading@11
|
190 + 24
|
yading@11
|
191 ;
|
yading@11
|
192
|
yading@11
|
193 if (needed <= c.frame_size)
|
yading@11
|
194 break;
|
yading@11
|
195 header &= ~mask;
|
yading@11
|
196 }
|
yading@11
|
197
|
yading@11
|
198 avio_wb32(s->pb, header);
|
yading@11
|
199
|
yading@11
|
200 ffio_fill(s->pb, 0, xing_offset);
|
yading@11
|
201 mp3->xing_offset = avio_tell(s->pb);
|
yading@11
|
202 ffio_wfourcc(s->pb, "Xing");
|
yading@11
|
203 avio_wb32(s->pb, 0x01 | 0x02 | 0x04); // frames / size / TOC
|
yading@11
|
204
|
yading@11
|
205 mp3->size = c.frame_size;
|
yading@11
|
206 mp3->want=1;
|
yading@11
|
207 mp3->seen=0;
|
yading@11
|
208 mp3->pos=0;
|
yading@11
|
209
|
yading@11
|
210 avio_wb32(s->pb, 0); // frames
|
yading@11
|
211 avio_wb32(s->pb, 0); // size
|
yading@11
|
212
|
yading@11
|
213 // toc
|
yading@11
|
214 for (i = 0; i < XING_TOC_SIZE; ++i)
|
yading@11
|
215 avio_w8(s->pb, (uint8_t)(255 * i / XING_TOC_SIZE));
|
yading@11
|
216
|
yading@11
|
217 for (i = 0; i < strlen(vendor); ++i)
|
yading@11
|
218 avio_w8(s->pb, vendor[i]);
|
yading@11
|
219 for (; i < 21; ++i)
|
yading@11
|
220 avio_w8(s->pb, 0);
|
yading@11
|
221 avio_wb24(s->pb, FFMAX(codec->delay - 528 - 1, 0)<<12);
|
yading@11
|
222
|
yading@11
|
223 ffio_fill(s->pb, 0, c.frame_size - needed);
|
yading@11
|
224
|
yading@11
|
225 return 0;
|
yading@11
|
226 }
|
yading@11
|
227
|
yading@11
|
228 /*
|
yading@11
|
229 * Add a frame to XING data.
|
yading@11
|
230 * Following lame's "VbrTag.c".
|
yading@11
|
231 */
|
yading@11
|
232 static void mp3_xing_add_frame(MP3Context *mp3, AVPacket *pkt)
|
yading@11
|
233 {
|
yading@11
|
234 int i;
|
yading@11
|
235
|
yading@11
|
236 mp3->frames++;
|
yading@11
|
237 mp3->seen++;
|
yading@11
|
238 mp3->size += pkt->size;
|
yading@11
|
239
|
yading@11
|
240 if (mp3->want == mp3->seen) {
|
yading@11
|
241 mp3->bag[mp3->pos] = mp3->size;
|
yading@11
|
242
|
yading@11
|
243 if (XING_NUM_BAGS == ++mp3->pos) {
|
yading@11
|
244 /* shrink table to half size by throwing away each second bag. */
|
yading@11
|
245 for (i = 1; i < XING_NUM_BAGS; i += 2)
|
yading@11
|
246 mp3->bag[i >> 1] = mp3->bag[i];
|
yading@11
|
247
|
yading@11
|
248 /* double wanted amount per bag. */
|
yading@11
|
249 mp3->want *= 2;
|
yading@11
|
250 /* adjust current position to half of table size. */
|
yading@11
|
251 mp3->pos = XING_NUM_BAGS / 2;
|
yading@11
|
252 }
|
yading@11
|
253
|
yading@11
|
254 mp3->seen = 0;
|
yading@11
|
255 }
|
yading@11
|
256 }
|
yading@11
|
257
|
yading@11
|
258 static int mp3_write_audio_packet(AVFormatContext *s, AVPacket *pkt)
|
yading@11
|
259 {
|
yading@11
|
260 MP3Context *mp3 = s->priv_data;
|
yading@11
|
261
|
yading@11
|
262 if (pkt->data && pkt->size >= 4) {
|
yading@11
|
263 MPADecodeHeader c;
|
yading@11
|
264 int av_unused base;
|
yading@11
|
265 uint32_t head = AV_RB32(pkt->data);
|
yading@11
|
266
|
yading@11
|
267 if (ff_mpa_check_header(head) < 0) {
|
yading@11
|
268 av_log(s, AV_LOG_WARNING, "Audio packet of size %d (starting with %08X...) "
|
yading@11
|
269 "is invalid, writing it anyway.\n", pkt->size, head);
|
yading@11
|
270 return ff_raw_write_packet(s, pkt);
|
yading@11
|
271 }
|
yading@11
|
272 avpriv_mpegaudio_decode_header(&c, head);
|
yading@11
|
273
|
yading@11
|
274 if (!mp3->initial_bitrate)
|
yading@11
|
275 mp3->initial_bitrate = c.bit_rate;
|
yading@11
|
276 if ((c.bit_rate == 0) || (mp3->initial_bitrate != c.bit_rate))
|
yading@11
|
277 mp3->has_variable_bitrate = 1;
|
yading@11
|
278
|
yading@11
|
279 #ifdef FILTER_VBR_HEADERS
|
yading@11
|
280 /* filter out XING and INFO headers. */
|
yading@11
|
281 base = 4 + xing_offtbl[c.lsf == 1][c.nb_channels == 1];
|
yading@11
|
282
|
yading@11
|
283 if (base + 4 <= pkt->size) {
|
yading@11
|
284 uint32_t v = AV_RB32(pkt->data + base);
|
yading@11
|
285
|
yading@11
|
286 if (MKBETAG('X','i','n','g') == v || MKBETAG('I','n','f','o') == v)
|
yading@11
|
287 return 0;
|
yading@11
|
288 }
|
yading@11
|
289
|
yading@11
|
290 /* filter out VBRI headers. */
|
yading@11
|
291 base = 4 + 32;
|
yading@11
|
292
|
yading@11
|
293 if (base + 4 <= pkt->size && MKBETAG('V','B','R','I') == AV_RB32(pkt->data + base))
|
yading@11
|
294 return 0;
|
yading@11
|
295 #endif
|
yading@11
|
296
|
yading@11
|
297 if (mp3->xing_offset)
|
yading@11
|
298 mp3_xing_add_frame(mp3, pkt);
|
yading@11
|
299 }
|
yading@11
|
300
|
yading@11
|
301 return ff_raw_write_packet(s, pkt);
|
yading@11
|
302 }
|
yading@11
|
303
|
yading@11
|
304 static int mp3_queue_flush(AVFormatContext *s)
|
yading@11
|
305 {
|
yading@11
|
306 MP3Context *mp3 = s->priv_data;
|
yading@11
|
307 AVPacketList *pktl;
|
yading@11
|
308 int ret = 0, write = 1;
|
yading@11
|
309
|
yading@11
|
310 ff_id3v2_finish(&mp3->id3, s->pb);
|
yading@11
|
311 mp3_write_xing(s);
|
yading@11
|
312
|
yading@11
|
313 while ((pktl = mp3->queue)) {
|
yading@11
|
314 if (write && (ret = mp3_write_audio_packet(s, &pktl->pkt)) < 0)
|
yading@11
|
315 write = 0;
|
yading@11
|
316 av_free_packet(&pktl->pkt);
|
yading@11
|
317 mp3->queue = pktl->next;
|
yading@11
|
318 av_freep(&pktl);
|
yading@11
|
319 }
|
yading@11
|
320 mp3->queue_end = NULL;
|
yading@11
|
321 return ret;
|
yading@11
|
322 }
|
yading@11
|
323
|
yading@11
|
324 static void mp3_update_xing(AVFormatContext *s)
|
yading@11
|
325 {
|
yading@11
|
326 MP3Context *mp3 = s->priv_data;
|
yading@11
|
327 int i;
|
yading@11
|
328
|
yading@11
|
329 /* replace "Xing" identification string with "Info" for CBR files. */
|
yading@11
|
330 if (!mp3->has_variable_bitrate) {
|
yading@11
|
331 avio_seek(s->pb, mp3->xing_offset, SEEK_SET);
|
yading@11
|
332 ffio_wfourcc(s->pb, "Info");
|
yading@11
|
333 }
|
yading@11
|
334
|
yading@11
|
335 avio_seek(s->pb, mp3->xing_offset + 8, SEEK_SET);
|
yading@11
|
336 avio_wb32(s->pb, mp3->frames);
|
yading@11
|
337 avio_wb32(s->pb, mp3->size);
|
yading@11
|
338
|
yading@11
|
339 avio_w8(s->pb, 0); // first toc entry has to be zero.
|
yading@11
|
340
|
yading@11
|
341 for (i = 1; i < XING_TOC_SIZE; ++i) {
|
yading@11
|
342 int j = i * mp3->pos / XING_TOC_SIZE;
|
yading@11
|
343 int seek_point = 256LL * mp3->bag[j] / mp3->size;
|
yading@11
|
344 avio_w8(s->pb, FFMIN(seek_point, 255));
|
yading@11
|
345 }
|
yading@11
|
346
|
yading@11
|
347 avio_seek(s->pb, 0, SEEK_END);
|
yading@11
|
348 }
|
yading@11
|
349
|
yading@11
|
350 static int mp3_write_trailer(struct AVFormatContext *s)
|
yading@11
|
351 {
|
yading@11
|
352 uint8_t buf[ID3v1_TAG_SIZE];
|
yading@11
|
353 MP3Context *mp3 = s->priv_data;
|
yading@11
|
354
|
yading@11
|
355 if (mp3->pics_to_write) {
|
yading@11
|
356 av_log(s, AV_LOG_WARNING, "No packets were sent for some of the "
|
yading@11
|
357 "attached pictures.\n");
|
yading@11
|
358 mp3_queue_flush(s);
|
yading@11
|
359 }
|
yading@11
|
360
|
yading@11
|
361 /* write the id3v1 tag */
|
yading@11
|
362 if (mp3->write_id3v1 && id3v1_create_tag(s, buf) > 0) {
|
yading@11
|
363 avio_write(s->pb, buf, ID3v1_TAG_SIZE);
|
yading@11
|
364 }
|
yading@11
|
365
|
yading@11
|
366 if (mp3->xing_offset)
|
yading@11
|
367 mp3_update_xing(s);
|
yading@11
|
368
|
yading@11
|
369 return 0;
|
yading@11
|
370 }
|
yading@11
|
371
|
yading@11
|
372 static int query_codec(enum AVCodecID id, int std_compliance)
|
yading@11
|
373 {
|
yading@11
|
374 const CodecMime *cm= ff_id3v2_mime_tags;
|
yading@11
|
375 while(cm->id != AV_CODEC_ID_NONE) {
|
yading@11
|
376 if(id == cm->id)
|
yading@11
|
377 return MKTAG('A', 'P', 'I', 'C');
|
yading@11
|
378 cm++;
|
yading@11
|
379 }
|
yading@11
|
380 return -1;
|
yading@11
|
381 }
|
yading@11
|
382
|
yading@11
|
383 #if CONFIG_MP2_MUXER
|
yading@11
|
384 AVOutputFormat ff_mp2_muxer = {
|
yading@11
|
385 .name = "mp2",
|
yading@11
|
386 .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"),
|
yading@11
|
387 .mime_type = "audio/x-mpeg",
|
yading@11
|
388 .extensions = "mp2,m2a",
|
yading@11
|
389 .audio_codec = AV_CODEC_ID_MP2,
|
yading@11
|
390 .video_codec = AV_CODEC_ID_NONE,
|
yading@11
|
391 .write_packet = ff_raw_write_packet,
|
yading@11
|
392 .flags = AVFMT_NOTIMESTAMPS,
|
yading@11
|
393 };
|
yading@11
|
394 #endif
|
yading@11
|
395
|
yading@11
|
396 #if CONFIG_MP3_MUXER
|
yading@11
|
397
|
yading@11
|
398 static const AVOption options[] = {
|
yading@11
|
399 { "id3v2_version", "Select ID3v2 version to write. Currently 3 and 4 are supported.",
|
yading@11
|
400 offsetof(MP3Context, id3v2_version), AV_OPT_TYPE_INT, {.i64 = 4}, 3, 4, AV_OPT_FLAG_ENCODING_PARAM},
|
yading@11
|
401 { "write_id3v1", "Enable ID3v1 writing. ID3v1 tags are written in UTF-8 which may not be supported by most software.",
|
yading@11
|
402 offsetof(MP3Context, write_id3v1), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
|
yading@11
|
403 { NULL },
|
yading@11
|
404 };
|
yading@11
|
405
|
yading@11
|
406 static const AVClass mp3_muxer_class = {
|
yading@11
|
407 .class_name = "MP3 muxer",
|
yading@11
|
408 .item_name = av_default_item_name,
|
yading@11
|
409 .option = options,
|
yading@11
|
410 .version = LIBAVUTIL_VERSION_INT,
|
yading@11
|
411 };
|
yading@11
|
412
|
yading@11
|
413 static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt)
|
yading@11
|
414 {
|
yading@11
|
415 MP3Context *mp3 = s->priv_data;
|
yading@11
|
416
|
yading@11
|
417 if (pkt->stream_index == mp3->audio_stream_idx) {
|
yading@11
|
418 if (mp3->pics_to_write) {
|
yading@11
|
419 /* buffer audio packets until we get all the pictures */
|
yading@11
|
420 AVPacketList *pktl = av_mallocz(sizeof(*pktl));
|
yading@11
|
421 if (!pktl)
|
yading@11
|
422 return AVERROR(ENOMEM);
|
yading@11
|
423
|
yading@11
|
424 pktl->pkt = *pkt;
|
yading@11
|
425 pktl->pkt.buf = av_buffer_ref(pkt->buf);
|
yading@11
|
426 if (!pktl->pkt.buf) {
|
yading@11
|
427 av_freep(&pktl);
|
yading@11
|
428 return AVERROR(ENOMEM);
|
yading@11
|
429 }
|
yading@11
|
430
|
yading@11
|
431 if (mp3->queue_end)
|
yading@11
|
432 mp3->queue_end->next = pktl;
|
yading@11
|
433 else
|
yading@11
|
434 mp3->queue = pktl;
|
yading@11
|
435 mp3->queue_end = pktl;
|
yading@11
|
436 } else
|
yading@11
|
437 return mp3_write_audio_packet(s, pkt);
|
yading@11
|
438 } else {
|
yading@11
|
439 int ret;
|
yading@11
|
440
|
yading@11
|
441 /* warn only once for each stream */
|
yading@11
|
442 if (s->streams[pkt->stream_index]->nb_frames == 1) {
|
yading@11
|
443 av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
|
yading@11
|
444 " ignoring.\n", pkt->stream_index);
|
yading@11
|
445 }
|
yading@11
|
446 if (!mp3->pics_to_write || s->streams[pkt->stream_index]->nb_frames >= 1)
|
yading@11
|
447 return 0;
|
yading@11
|
448
|
yading@11
|
449 if ((ret = ff_id3v2_write_apic(s, &mp3->id3, pkt)) < 0)
|
yading@11
|
450 return ret;
|
yading@11
|
451 mp3->pics_to_write--;
|
yading@11
|
452
|
yading@11
|
453 /* flush the buffered audio packets */
|
yading@11
|
454 if (!mp3->pics_to_write &&
|
yading@11
|
455 (ret = mp3_queue_flush(s)) < 0)
|
yading@11
|
456 return ret;
|
yading@11
|
457 }
|
yading@11
|
458
|
yading@11
|
459 return 0;
|
yading@11
|
460 }
|
yading@11
|
461
|
yading@11
|
462 /**
|
yading@11
|
463 * Write an ID3v2 header at beginning of stream
|
yading@11
|
464 */
|
yading@11
|
465
|
yading@11
|
466 static int mp3_write_header(struct AVFormatContext *s)
|
yading@11
|
467 {
|
yading@11
|
468 MP3Context *mp3 = s->priv_data;
|
yading@11
|
469 int ret, i;
|
yading@11
|
470
|
yading@11
|
471 /* check the streams -- we want exactly one audio and arbitrary number of
|
yading@11
|
472 * video (attached pictures) */
|
yading@11
|
473 mp3->audio_stream_idx = -1;
|
yading@11
|
474 for (i = 0; i < s->nb_streams; i++) {
|
yading@11
|
475 AVStream *st = s->streams[i];
|
yading@11
|
476 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
|
yading@11
|
477 if (mp3->audio_stream_idx >= 0 || st->codec->codec_id != AV_CODEC_ID_MP3) {
|
yading@11
|
478 av_log(s, AV_LOG_ERROR, "Invalid audio stream. Exactly one MP3 "
|
yading@11
|
479 "audio stream is required.\n");
|
yading@11
|
480 return AVERROR(EINVAL);
|
yading@11
|
481 }
|
yading@11
|
482 mp3->audio_stream_idx = i;
|
yading@11
|
483 } else if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO) {
|
yading@11
|
484 av_log(s, AV_LOG_ERROR, "Only audio streams and pictures are allowed in MP3.\n");
|
yading@11
|
485 return AVERROR(EINVAL);
|
yading@11
|
486 }
|
yading@11
|
487 }
|
yading@11
|
488 if (mp3->audio_stream_idx < 0) {
|
yading@11
|
489 av_log(s, AV_LOG_ERROR, "No audio stream present.\n");
|
yading@11
|
490 return AVERROR(EINVAL);
|
yading@11
|
491 }
|
yading@11
|
492 mp3->pics_to_write = s->nb_streams - 1;
|
yading@11
|
493
|
yading@11
|
494 ff_id3v2_start(&mp3->id3, s->pb, mp3->id3v2_version, ID3v2_DEFAULT_MAGIC);
|
yading@11
|
495 ret = ff_id3v2_write_metadata(s, &mp3->id3);
|
yading@11
|
496 if (ret < 0)
|
yading@11
|
497 return ret;
|
yading@11
|
498
|
yading@11
|
499 if (!mp3->pics_to_write) {
|
yading@11
|
500 ff_id3v2_finish(&mp3->id3, s->pb);
|
yading@11
|
501 mp3_write_xing(s);
|
yading@11
|
502 }
|
yading@11
|
503
|
yading@11
|
504 return 0;
|
yading@11
|
505 }
|
yading@11
|
506
|
yading@11
|
507 AVOutputFormat ff_mp3_muxer = {
|
yading@11
|
508 .name = "mp3",
|
yading@11
|
509 .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"),
|
yading@11
|
510 .mime_type = "audio/x-mpeg",
|
yading@11
|
511 .extensions = "mp3",
|
yading@11
|
512 .priv_data_size = sizeof(MP3Context),
|
yading@11
|
513 .audio_codec = AV_CODEC_ID_MP3,
|
yading@11
|
514 .video_codec = AV_CODEC_ID_PNG,
|
yading@11
|
515 .write_header = mp3_write_header,
|
yading@11
|
516 .write_packet = mp3_write_packet,
|
yading@11
|
517 .write_trailer = mp3_write_trailer,
|
yading@11
|
518 .query_codec = query_codec,
|
yading@11
|
519 .flags = AVFMT_NOTIMESTAMPS,
|
yading@11
|
520 .priv_class = &mp3_muxer_class,
|
yading@11
|
521 };
|
yading@11
|
522 #endif
|