Commit | Line | Data |
---|---|---|
115329f1 | 1 | /* |
7fbde343 | 2 | * MP3 muxer and demuxer |
6a58e151 FB |
3 | * Copyright (c) 2003 Fabrice Bellard. |
4 | * | |
b78e7197 DB |
5 | * This file is part of FFmpeg. |
6 | * | |
7 | * FFmpeg is free software; you can redistribute it and/or | |
6a58e151 FB |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either | |
b78e7197 | 10 | * version 2.1 of the License, or (at your option) any later version. |
6a58e151 | 11 | * |
b78e7197 | 12 | * FFmpeg is distributed in the hope that it will be useful, |
6a58e151 FB |
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 | |
b78e7197 | 18 | * License along with FFmpeg; if not, write to the Free Software |
5509bffa | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
6a58e151 FB |
20 | */ |
21 | #include "avformat.h" | |
abade142 | 22 | #include "mpegaudio.h" |
6a58e151 | 23 | |
cb2578d5 AÖ |
24 | #define ID3v2_HEADER_SIZE 10 |
25 | #define ID3v1_TAG_SIZE 128 | |
6a58e151 | 26 | |
cb2578d5 | 27 | #define ID3v1_GENRE_MAX 125 |
6a58e151 | 28 | |
cb2578d5 | 29 | static const char *id3v1_genre_str[ID3v1_GENRE_MAX + 1] = { |
6a58e151 FB |
30 | [0] = "Blues", |
31 | [1] = "Classic Rock", | |
32 | [2] = "Country", | |
33 | [3] = "Dance", | |
34 | [4] = "Disco", | |
35 | [5] = "Funk", | |
36 | [6] = "Grunge", | |
37 | [7] = "Hip-Hop", | |
38 | [8] = "Jazz", | |
39 | [9] = "Metal", | |
40 | [10] = "New Age", | |
41 | [11] = "Oldies", | |
42 | [12] = "Other", | |
43 | [13] = "Pop", | |
44 | [14] = "R&B", | |
45 | [15] = "Rap", | |
46 | [16] = "Reggae", | |
47 | [17] = "Rock", | |
48 | [18] = "Techno", | |
49 | [19] = "Industrial", | |
50 | [20] = "Alternative", | |
51 | [21] = "Ska", | |
52 | [22] = "Death Metal", | |
53 | [23] = "Pranks", | |
54 | [24] = "Soundtrack", | |
55 | [25] = "Euro-Techno", | |
56 | [26] = "Ambient", | |
57 | [27] = "Trip-Hop", | |
58 | [28] = "Vocal", | |
59 | [29] = "Jazz+Funk", | |
60 | [30] = "Fusion", | |
61 | [31] = "Trance", | |
62 | [32] = "Classical", | |
63 | [33] = "Instrumental", | |
64 | [34] = "Acid", | |
65 | [35] = "House", | |
66 | [36] = "Game", | |
67 | [37] = "Sound Clip", | |
68 | [38] = "Gospel", | |
69 | [39] = "Noise", | |
70 | [40] = "AlternRock", | |
71 | [41] = "Bass", | |
72 | [42] = "Soul", | |
73 | [43] = "Punk", | |
74 | [44] = "Space", | |
75 | [45] = "Meditative", | |
76 | [46] = "Instrumental Pop", | |
77 | [47] = "Instrumental Rock", | |
78 | [48] = "Ethnic", | |
79 | [49] = "Gothic", | |
80 | [50] = "Darkwave", | |
81 | [51] = "Techno-Industrial", | |
82 | [52] = "Electronic", | |
83 | [53] = "Pop-Folk", | |
84 | [54] = "Eurodance", | |
85 | [55] = "Dream", | |
86 | [56] = "Southern Rock", | |
87 | [57] = "Comedy", | |
88 | [58] = "Cult", | |
89 | [59] = "Gangsta", | |
90 | [60] = "Top 40", | |
91 | [61] = "Christian Rap", | |
92 | [62] = "Pop/Funk", | |
93 | [63] = "Jungle", | |
94 | [64] = "Native American", | |
95 | [65] = "Cabaret", | |
96 | [66] = "New Wave", | |
97 | [67] = "Psychadelic", | |
98 | [68] = "Rave", | |
99 | [69] = "Showtunes", | |
100 | [70] = "Trailer", | |
101 | [71] = "Lo-Fi", | |
102 | [72] = "Tribal", | |
103 | [73] = "Acid Punk", | |
104 | [74] = "Acid Jazz", | |
105 | [75] = "Polka", | |
106 | [76] = "Retro", | |
107 | [77] = "Musical", | |
108 | [78] = "Rock & Roll", | |
109 | [79] = "Hard Rock", | |
110 | [80] = "Folk", | |
111 | [81] = "Folk-Rock", | |
112 | [82] = "National Folk", | |
113 | [83] = "Swing", | |
114 | [84] = "Fast Fusion", | |
115 | [85] = "Bebob", | |
116 | [86] = "Latin", | |
117 | [87] = "Revival", | |
118 | [88] = "Celtic", | |
119 | [89] = "Bluegrass", | |
120 | [90] = "Avantgarde", | |
121 | [91] = "Gothic Rock", | |
122 | [92] = "Progressive Rock", | |
123 | [93] = "Psychedelic Rock", | |
124 | [94] = "Symphonic Rock", | |
125 | [95] = "Slow Rock", | |
126 | [96] = "Big Band", | |
127 | [97] = "Chorus", | |
128 | [98] = "Easy Listening", | |
129 | [99] = "Acoustic", | |
130 | [100] = "Humour", | |
131 | [101] = "Speech", | |
132 | [102] = "Chanson", | |
133 | [103] = "Opera", | |
134 | [104] = "Chamber Music", | |
135 | [105] = "Sonata", | |
136 | [106] = "Symphony", | |
137 | [107] = "Booty Bass", | |
138 | [108] = "Primus", | |
139 | [109] = "Porn Groove", | |
140 | [110] = "Satire", | |
141 | [111] = "Slow Jam", | |
142 | [112] = "Club", | |
143 | [113] = "Tango", | |
144 | [114] = "Samba", | |
145 | [115] = "Folklore", | |
146 | [116] = "Ballad", | |
147 | [117] = "Power Ballad", | |
148 | [118] = "Rhythmic Soul", | |
149 | [119] = "Freestyle", | |
150 | [120] = "Duet", | |
151 | [121] = "Punk Rock", | |
152 | [122] = "Drum Solo", | |
153 | [123] = "A capella", | |
154 | [124] = "Euro-House", | |
155 | [125] = "Dance Hall", | |
156 | }; | |
157 | ||
cb2578d5 AÖ |
158 | /* buf must be ID3v2_HEADER_SIZE byte long */ |
159 | static int id3v2_match(const uint8_t *buf) | |
6a58e151 FB |
160 | { |
161 | return (buf[0] == 'I' && | |
162 | buf[1] == 'D' && | |
163 | buf[2] == '3' && | |
164 | buf[3] != 0xff && | |
165 | buf[4] != 0xff && | |
166 | (buf[6] & 0x80) == 0 && | |
167 | (buf[7] & 0x80) == 0 && | |
168 | (buf[8] & 0x80) == 0 && | |
169 | (buf[9] & 0x80) == 0); | |
170 | } | |
171 | ||
52b53f86 AÖ |
172 | static unsigned int id3v2_get_size(ByteIOContext *s, int len) |
173 | { | |
174 | int v=0; | |
175 | while(len--) | |
176 | v= (v<<7) + (get_byte(s)&0x7F); | |
177 | return v; | |
178 | } | |
179 | ||
180 | static void id3v2_read_ttag(AVFormatContext *s, int taglen, char *dst, int dstlen) | |
181 | { | |
182 | char *q; | |
183 | int len; | |
184 | ||
185 | if(taglen < 1) | |
186 | return; | |
187 | ||
188 | taglen--; /* account for encoding type byte */ | |
189 | dstlen--; /* Leave space for zero terminator */ | |
190 | ||
191 | switch(get_byte(&s->pb)) { /* encoding type */ | |
192 | ||
193 | case 0: /* ISO-8859-1 (0 - 255 maps directly into unicode) */ | |
194 | q = dst; | |
195 | while(taglen--) { | |
196 | uint8_t tmp; | |
197 | PUT_UTF8(get_byte(&s->pb), tmp, if (q - dst < dstlen - 1) *q++ = tmp;) | |
198 | } | |
199 | *q = '\0'; | |
200 | break; | |
201 | ||
202 | case 3: /* UTF-8 */ | |
203 | len = FFMIN(taglen, dstlen); | |
204 | get_buffer(&s->pb, dst, len); | |
205 | dst[len] = 0; | |
206 | break; | |
207 | } | |
208 | } | |
209 | ||
210 | /** | |
211 | * ID3v2 parser | |
212 | * | |
213 | * Handles ID3v2.2, 2.3 and 2.4. | |
214 | * | |
215 | */ | |
216 | ||
217 | static void id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags) | |
218 | { | |
219 | int isv34, tlen; | |
220 | uint32_t tag; | |
221 | offset_t next; | |
222 | char tmp[16]; | |
223 | int taghdrlen; | |
224 | const char *reason; | |
225 | ||
226 | switch(version) { | |
227 | case 2: | |
228 | if(flags & 0x40) { | |
229 | reason = "compression"; | |
230 | goto error; | |
231 | } | |
232 | isv34 = 0; | |
233 | taghdrlen = 6; | |
234 | break; | |
235 | ||
236 | case 3 ... 4: | |
237 | isv34 = 1; | |
238 | taghdrlen = 10; | |
239 | break; | |
240 | ||
241 | default: | |
242 | reason = "version"; | |
243 | goto error; | |
244 | } | |
245 | ||
246 | if(flags & 0x80) { | |
247 | reason = "unsynchronization"; | |
248 | goto error; | |
249 | } | |
250 | ||
251 | if(isv34 && flags & 0x40) /* Extended header present, just skip over it */ | |
252 | url_fskip(&s->pb, id3v2_get_size(&s->pb, 4)); | |
253 | ||
254 | while(len >= taghdrlen) { | |
255 | if(isv34) { | |
256 | tag = get_be32(&s->pb); | |
257 | tlen = id3v2_get_size(&s->pb, 4); | |
258 | get_be16(&s->pb); /* flags */ | |
259 | } else { | |
260 | tag = get_be24(&s->pb); | |
261 | tlen = id3v2_get_size(&s->pb, 3); | |
262 | } | |
263 | len -= taghdrlen + tlen; | |
264 | ||
265 | if(len < 0) | |
266 | break; | |
267 | ||
268 | next = url_ftell(&s->pb) + tlen; | |
269 | ||
270 | switch(tag) { | |
271 | case MKBETAG('T', 'I', 'T', '2'): | |
272 | case MKBETAG(0, 'T', 'T', '2'): | |
273 | id3v2_read_ttag(s, tlen, s->title, sizeof(s->title)); | |
274 | break; | |
275 | case MKBETAG('T', 'P', 'E', '1'): | |
276 | case MKBETAG(0, 'T', 'P', '1'): | |
277 | id3v2_read_ttag(s, tlen, s->author, sizeof(s->author)); | |
278 | break; | |
279 | case MKBETAG('T', 'A', 'L', 'B'): | |
280 | case MKBETAG(0, 'T', 'A', 'L'): | |
281 | id3v2_read_ttag(s, tlen, s->album, sizeof(s->album)); | |
282 | break; | |
283 | case MKBETAG('T', 'C', 'O', 'N'): | |
284 | case MKBETAG(0, 'T', 'C', 'O'): | |
285 | id3v2_read_ttag(s, tlen, s->genre, sizeof(s->genre)); | |
286 | break; | |
287 | case MKBETAG('T', 'C', 'O', 'P'): | |
288 | case MKBETAG(0, 'T', 'C', 'R'): | |
289 | id3v2_read_ttag(s, tlen, s->copyright, sizeof(s->copyright)); | |
290 | break; | |
291 | case MKBETAG('T', 'R', 'C', 'K'): | |
292 | case MKBETAG(0, 'T', 'R', 'K'): | |
293 | id3v2_read_ttag(s, tlen, tmp, sizeof(tmp)); | |
294 | s->track = atoi(tmp); | |
295 | break; | |
296 | case 0: | |
297 | /* padding, skip to end */ | |
298 | url_fskip(&s->pb, len); | |
299 | len = 0; | |
300 | continue; | |
301 | } | |
302 | /* Skip to end of tag */ | |
303 | url_fseek(&s->pb, next, SEEK_SET); | |
304 | } | |
305 | ||
306 | if(version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */ | |
307 | url_fskip(&s->pb, 10); | |
308 | return; | |
309 | ||
310 | error: | |
311 | av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason); | |
312 | url_fskip(&s->pb, len); | |
313 | } | |
314 | ||
cb2578d5 AÖ |
315 | static void id3v1_get_string(char *str, int str_size, |
316 | const uint8_t *buf, int buf_size) | |
6a58e151 FB |
317 | { |
318 | int i, c; | |
319 | char *q; | |
320 | ||
321 | q = str; | |
322 | for(i = 0; i < buf_size; i++) { | |
323 | c = buf[i]; | |
324 | if (c == '\0') | |
325 | break; | |
326 | if ((q - str) >= str_size - 1) | |
327 | break; | |
328 | *q++ = c; | |
329 | } | |
330 | *q = '\0'; | |
331 | } | |
332 | ||
cb2578d5 AÖ |
333 | /* 'buf' must be ID3v1_TAG_SIZE byte long */ |
334 | static int id3v1_parse_tag(AVFormatContext *s, const uint8_t *buf) | |
6a58e151 FB |
335 | { |
336 | char str[5]; | |
337 | int genre; | |
115329f1 | 338 | |
6a58e151 FB |
339 | if (!(buf[0] == 'T' && |
340 | buf[1] == 'A' && | |
341 | buf[2] == 'G')) | |
342 | return -1; | |
cb2578d5 AÖ |
343 | id3v1_get_string(s->title, sizeof(s->title), buf + 3, 30); |
344 | id3v1_get_string(s->author, sizeof(s->author), buf + 33, 30); | |
345 | id3v1_get_string(s->album, sizeof(s->album), buf + 63, 30); | |
346 | id3v1_get_string(str, sizeof(str), buf + 93, 4); | |
6a58e151 | 347 | s->year = atoi(str); |
cb2578d5 | 348 | id3v1_get_string(s->comment, sizeof(s->comment), buf + 97, 30); |
6a58e151 FB |
349 | if (buf[125] == 0 && buf[126] != 0) |
350 | s->track = buf[126]; | |
351 | genre = buf[127]; | |
cb2578d5 AÖ |
352 | if (genre <= ID3v1_GENRE_MAX) |
353 | pstrcpy(s->genre, sizeof(s->genre), id3v1_genre_str[genre]); | |
6a58e151 FB |
354 | return 0; |
355 | } | |
356 | ||
cb2578d5 | 357 | static void id3v1_create_tag(AVFormatContext *s, uint8_t *buf) |
6a58e151 FB |
358 | { |
359 | int v, i; | |
360 | ||
cb2578d5 | 361 | memset(buf, 0, ID3v1_TAG_SIZE); /* fail safe */ |
6a58e151 FB |
362 | buf[0] = 'T'; |
363 | buf[1] = 'A'; | |
364 | buf[2] = 'G'; | |
365 | strncpy(buf + 3, s->title, 30); | |
366 | strncpy(buf + 33, s->author, 30); | |
367 | strncpy(buf + 63, s->album, 30); | |
368 | v = s->year; | |
369 | if (v > 0) { | |
370 | for(i = 0;i < 4; i++) { | |
371 | buf[96 - i] = '0' + (v % 10); | |
372 | v = v / 10; | |
373 | } | |
374 | } | |
375 | strncpy(buf + 97, s->comment, 30); | |
376 | if (s->track != 0) { | |
377 | buf[125] = 0; | |
378 | buf[126] = s->track; | |
379 | } | |
cb2578d5 AÖ |
380 | for(i = 0; i <= ID3v1_GENRE_MAX; i++) { |
381 | if (!strcasecmp(s->genre, id3v1_genre_str[i])) { | |
6a58e151 FB |
382 | buf[127] = i; |
383 | break; | |
384 | } | |
385 | } | |
386 | } | |
387 | ||
388 | /* mp3 read */ | |
dc4ed3b1 MR |
389 | |
390 | static int mp3_read_probe(AVProbeData *p) | |
391 | { | |
22668218 | 392 | int max_frames, first_frames; |
498c544a | 393 | int fsize, frames, sample_rate; |
abade142 AÖ |
394 | uint32_t header; |
395 | uint8_t *buf, *buf2, *end; | |
396 | AVCodecContext avctx; | |
dc4ed3b1 | 397 | |
cb2578d5 AÖ |
398 | if(id3v2_match(p->buf)) |
399 | return AVPROBE_SCORE_MAX/2+1; // this must be less than mpeg-ps because some retards put id3v2 tags before mpeg-ps files | |
dc4ed3b1 | 400 | |
abade142 AÖ |
401 | max_frames = 0; |
402 | buf = p->buf; | |
403 | end = buf + FFMIN(4096, p->buf_size - sizeof(uint32_t)); | |
dc4ed3b1 | 404 | |
abade142 AÖ |
405 | for(; buf < end; buf++) { |
406 | buf2 = buf; | |
dc4ed3b1 | 407 | |
d0702de9 | 408 | for(frames = 0; buf2 < end; frames++) { |
abade142 | 409 | header = (buf2[0] << 24) | (buf2[1] << 16) | (buf2[2] << 8) | buf2[3]; |
ca6e50af | 410 | fsize = ff_mpa_decode_header(&avctx, header, &sample_rate); |
abade142 AÖ |
411 | if(fsize < 0) |
412 | break; | |
413 | buf2 += fsize; | |
414 | } | |
415 | max_frames = FFMAX(max_frames, frames); | |
22668218 MN |
416 | if(buf == p->buf) |
417 | first_frames= frames; | |
abade142 | 418 | } |
22668218 MN |
419 | if (first_frames>=3) return AVPROBE_SCORE_MAX/2+1; |
420 | else if(max_frames>=3) return AVPROBE_SCORE_MAX/4; | |
421 | else if(max_frames>=1) return 1; | |
abade142 | 422 | else return 0; |
dc4ed3b1 MR |
423 | } |
424 | ||
6a58e151 FB |
425 | static int mp3_read_header(AVFormatContext *s, |
426 | AVFormatParameters *ap) | |
427 | { | |
428 | AVStream *st; | |
cb2578d5 | 429 | uint8_t buf[ID3v1_TAG_SIZE]; |
6a58e151 FB |
430 | int len, ret, filesize; |
431 | ||
432 | st = av_new_stream(s, 0); | |
433 | if (!st) | |
434 | return AVERROR_NOMEM; | |
435 | ||
01f4895c MN |
436 | st->codec->codec_type = CODEC_TYPE_AUDIO; |
437 | st->codec->codec_id = CODEC_ID_MP3; | |
57004ff1 | 438 | st->need_parsing = AVSTREAM_PARSE_FULL; |
115329f1 | 439 | |
6a58e151 FB |
440 | /* try to get the TAG */ |
441 | if (!url_is_streamed(&s->pb)) { | |
442 | /* XXX: change that */ | |
a965c478 | 443 | filesize = url_fsize(&s->pb); |
6a58e151 FB |
444 | if (filesize > 128) { |
445 | url_fseek(&s->pb, filesize - 128, SEEK_SET); | |
cb2578d5 AÖ |
446 | ret = get_buffer(&s->pb, buf, ID3v1_TAG_SIZE); |
447 | if (ret == ID3v1_TAG_SIZE) { | |
448 | id3v1_parse_tag(s, buf); | |
6a58e151 FB |
449 | } |
450 | url_fseek(&s->pb, 0, SEEK_SET); | |
451 | } | |
452 | } | |
453 | ||
cb2578d5 AÖ |
454 | /* if ID3v2 header found, skip it */ |
455 | ret = get_buffer(&s->pb, buf, ID3v2_HEADER_SIZE); | |
456 | if (ret != ID3v2_HEADER_SIZE) | |
6a58e151 | 457 | return -1; |
cb2578d5 | 458 | if (id3v2_match(buf)) { |
52b53f86 | 459 | /* parse ID3v2 header */ |
6a58e151 FB |
460 | len = ((buf[6] & 0x7f) << 21) | |
461 | ((buf[7] & 0x7f) << 14) | | |
462 | ((buf[8] & 0x7f) << 7) | | |
463 | (buf[9] & 0x7f); | |
52b53f86 | 464 | id3v2_parse(s, len, buf[3], buf[5]); |
6a58e151 FB |
465 | } else { |
466 | url_fseek(&s->pb, 0, SEEK_SET); | |
467 | } | |
468 | ||
469 | /* the parameters will be extracted from the compressed bitstream */ | |
470 | return 0; | |
471 | } | |
472 | ||
473 | #define MP3_PACKET_SIZE 1024 | |
474 | ||
475 | static int mp3_read_packet(AVFormatContext *s, AVPacket *pkt) | |
476 | { | |
477 | int ret, size; | |
478 | // AVStream *st = s->streams[0]; | |
115329f1 | 479 | |
6a58e151 FB |
480 | size= MP3_PACKET_SIZE; |
481 | ||
2692067a | 482 | ret= av_get_packet(&s->pb, pkt, size); |
6a58e151 FB |
483 | |
484 | pkt->stream_index = 0; | |
6a58e151 | 485 | if (ret <= 0) { |
0bd586c5 | 486 | return AVERROR_IO; |
6a58e151 FB |
487 | } |
488 | /* note: we need to modify the packet size here to handle the last | |
489 | packet */ | |
490 | pkt->size = ret; | |
491 | return ret; | |
492 | } | |
493 | ||
494 | static int mp3_read_close(AVFormatContext *s) | |
495 | { | |
496 | return 0; | |
497 | } | |
498 | ||
a9e35095 | 499 | #ifdef CONFIG_MUXERS |
6a58e151 | 500 | /* simple formats */ |
0dc56bfa AÖ |
501 | |
502 | static void id3v2_put_size(AVFormatContext *s, int size) | |
503 | { | |
504 | put_byte(&s->pb, size >> 21 & 0x7f); | |
505 | put_byte(&s->pb, size >> 14 & 0x7f); | |
506 | put_byte(&s->pb, size >> 7 & 0x7f); | |
507 | put_byte(&s->pb, size & 0x7f); | |
508 | } | |
509 | ||
510 | static void id3v2_put_ttag(AVFormatContext *s, char *string, uint32_t tag) | |
511 | { | |
512 | int len = strlen(string); | |
513 | put_be32(&s->pb, tag); | |
514 | id3v2_put_size(s, len + 1); | |
515 | put_be16(&s->pb, 0); | |
516 | put_byte(&s->pb, 3); /* UTF-8 */ | |
517 | put_buffer(&s->pb, string, len); | |
518 | } | |
519 | ||
520 | ||
521 | /** | |
522 | * Write an ID3v2.4 header at beginning of stream | |
523 | */ | |
524 | ||
6a58e151 FB |
525 | static int mp3_write_header(struct AVFormatContext *s) |
526 | { | |
0dc56bfa AÖ |
527 | int totlen = 0; |
528 | char tracktxt[10]; | |
529 | ||
530 | if(s->track) | |
531 | snprintf(tracktxt, sizeof(tracktxt) - 1, "%d", s->track); | |
532 | ||
533 | if(s->title[0]) totlen += 11 + strlen(s->title); | |
534 | if(s->author[0]) totlen += 11 + strlen(s->author); | |
535 | if(s->album[0]) totlen += 11 + strlen(s->album); | |
536 | if(s->genre[0]) totlen += 11 + strlen(s->genre); | |
537 | if(s->copyright[0]) totlen += 11 + strlen(s->copyright); | |
538 | if(s->track) totlen += 11 + strlen(tracktxt); | |
539 | if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) | |
540 | totlen += strlen(LIBAVFORMAT_IDENT) + 11; | |
541 | ||
542 | if(totlen == 0) | |
543 | return 0; | |
544 | ||
545 | put_be32(&s->pb, MKBETAG('I', 'D', '3', 0x04)); /* ID3v2.4 */ | |
546 | put_byte(&s->pb, 0); | |
547 | put_byte(&s->pb, 0); /* flags */ | |
548 | ||
549 | id3v2_put_size(s, totlen); | |
550 | ||
551 | if(s->title[0]) id3v2_put_ttag(s, s->title, MKBETAG('T', 'I', 'T', '2')); | |
552 | if(s->author[0]) id3v2_put_ttag(s, s->author, MKBETAG('T', 'P', 'E', '1')); | |
553 | if(s->album[0]) id3v2_put_ttag(s, s->album, MKBETAG('T', 'A', 'L', 'B')); | |
554 | if(s->genre[0]) id3v2_put_ttag(s, s->genre, MKBETAG('T', 'C', 'O', 'N')); | |
555 | if(s->copyright[0]) id3v2_put_ttag(s, s->copyright, MKBETAG('T', 'C', 'O', 'P')); | |
556 | if(s->track) id3v2_put_ttag(s, tracktxt, MKBETAG('T', 'R', 'C', 'K')); | |
557 | if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) | |
558 | id3v2_put_ttag(s, LIBAVFORMAT_IDENT, MKBETAG('T', 'E', 'N', 'C')); | |
6a58e151 FB |
559 | return 0; |
560 | } | |
561 | ||
e928649b | 562 | static int mp3_write_packet(struct AVFormatContext *s, AVPacket *pkt) |
6a58e151 | 563 | { |
e928649b | 564 | put_buffer(&s->pb, pkt->data, pkt->size); |
6a58e151 FB |
565 | put_flush_packet(&s->pb); |
566 | return 0; | |
567 | } | |
568 | ||
569 | static int mp3_write_trailer(struct AVFormatContext *s) | |
570 | { | |
cb2578d5 | 571 | uint8_t buf[ID3v1_TAG_SIZE]; |
6a58e151 | 572 | |
cb2578d5 | 573 | /* write the id3v1 tag */ |
6a58e151 | 574 | if (s->title[0] != '\0') { |
cb2578d5 AÖ |
575 | id3v1_create_tag(s, buf); |
576 | put_buffer(&s->pb, buf, ID3v1_TAG_SIZE); | |
6a58e151 FB |
577 | put_flush_packet(&s->pb); |
578 | } | |
579 | return 0; | |
580 | } | |
a9e35095 | 581 | #endif //CONFIG_MUXERS |
6a58e151 | 582 | |
ff70e601 | 583 | #ifdef CONFIG_MP3_DEMUXER |
d2a067d1 | 584 | AVInputFormat mp3_demuxer = { |
6a58e151 FB |
585 | "mp3", |
586 | "MPEG audio", | |
587 | 0, | |
dc4ed3b1 | 588 | mp3_read_probe, |
6a58e151 FB |
589 | mp3_read_header, |
590 | mp3_read_packet, | |
591 | mp3_read_close, | |
e9b78eeb | 592 | .flags= AVFMT_GENERIC_INDEX, |
e0827ba4 | 593 | .extensions = "mp2,mp3,m2a", /* XXX: use probe */ |
6a58e151 | 594 | }; |
ff70e601 MR |
595 | #endif |
596 | #ifdef CONFIG_MP2_MUXER | |
d2a067d1 | 597 | AVOutputFormat mp2_muxer = { |
6a58e151 FB |
598 | "mp2", |
599 | "MPEG audio layer 2", | |
600 | "audio/x-mpeg", | |
6ebe07fb | 601 | #ifdef CONFIG_LIBMP3LAME |
e0827ba4 | 602 | "mp2,m2a", |
6a58e151 | 603 | #else |
e0827ba4 | 604 | "mp2,mp3,m2a", |
6a58e151 FB |
605 | #endif |
606 | 0, | |
607 | CODEC_ID_MP2, | |
608 | 0, | |
609 | mp3_write_header, | |
610 | mp3_write_packet, | |
611 | mp3_write_trailer, | |
612 | }; | |
ff70e601 MR |
613 | #endif |
614 | #ifdef CONFIG_MP3_MUXER | |
d2a067d1 | 615 | AVOutputFormat mp3_muxer = { |
6a58e151 FB |
616 | "mp3", |
617 | "MPEG audio layer 3", | |
618 | "audio/x-mpeg", | |
619 | "mp3", | |
620 | 0, | |
621 | CODEC_ID_MP3, | |
622 | 0, | |
623 | mp3_write_header, | |
624 | mp3_write_packet, | |
625 | mp3_write_trailer, | |
626 | }; | |
627 | #endif |