Mercurial > libavformat.hg
annotate mp3.c @ 1960:c0289552590f libavformat
Change the vhook code to send real timestamps to the filters instead of the
current time of day, which is useless, and which the filters could just as
easily query for themselves.
patch by Bobby Bingham, uhmmmm gmail com
author | diego |
---|---|
date | Thu, 29 Mar 2007 05:24:35 +0000 |
parents | 5d72afc6c8aa |
children | 1a3c9056982a |
rev | line source |
---|---|
885 | 1 /* |
1415
3b00fb8ef8e4
replace coder/decoder file description in libavformat by muxer/demuxer
aurel
parents:
1358
diff
changeset
|
2 * MP3 muxer and demuxer |
234 | 3 * Copyright (c) 2003 Fabrice Bellard. |
4 * | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1321
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1321
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1321
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
234 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1321
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
234 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1321
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
234 | 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 | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1321
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
885
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
234 | 20 */ |
21 #include "avformat.h" | |
1308
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
22 #include "mpegaudio.h" |
234 | 23 |
24 #define ID3_HEADER_SIZE 10 | |
25 #define ID3_TAG_SIZE 128 | |
26 | |
27 #define ID3_GENRE_MAX 125 | |
28 | |
29 static const char *id3_genre_str[ID3_GENRE_MAX + 1] = { | |
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 | |
158 /* buf must be ID3_HEADER_SIZE byte long */ | |
159 static int id3_match(const uint8_t *buf) | |
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 | |
885 | 172 static void id3_get_string(char *str, int str_size, |
234 | 173 const uint8_t *buf, int buf_size) |
174 { | |
175 int i, c; | |
176 char *q; | |
177 | |
178 q = str; | |
179 for(i = 0; i < buf_size; i++) { | |
180 c = buf[i]; | |
181 if (c == '\0') | |
182 break; | |
183 if ((q - str) >= str_size - 1) | |
184 break; | |
185 *q++ = c; | |
186 } | |
187 *q = '\0'; | |
188 } | |
189 | |
190 /* 'buf' must be ID3_TAG_SIZE byte long */ | |
191 static int id3_parse_tag(AVFormatContext *s, const uint8_t *buf) | |
192 { | |
193 char str[5]; | |
194 int genre; | |
885 | 195 |
234 | 196 if (!(buf[0] == 'T' && |
197 buf[1] == 'A' && | |
198 buf[2] == 'G')) | |
199 return -1; | |
200 id3_get_string(s->title, sizeof(s->title), buf + 3, 30); | |
201 id3_get_string(s->author, sizeof(s->author), buf + 33, 30); | |
202 id3_get_string(s->album, sizeof(s->album), buf + 63, 30); | |
203 id3_get_string(str, sizeof(str), buf + 93, 4); | |
204 s->year = atoi(str); | |
205 id3_get_string(s->comment, sizeof(s->comment), buf + 97, 30); | |
206 if (buf[125] == 0 && buf[126] != 0) | |
207 s->track = buf[126]; | |
208 genre = buf[127]; | |
209 if (genre <= ID3_GENRE_MAX) | |
210 pstrcpy(s->genre, sizeof(s->genre), id3_genre_str[genre]); | |
211 return 0; | |
212 } | |
213 | |
214 static void id3_create_tag(AVFormatContext *s, uint8_t *buf) | |
215 { | |
216 int v, i; | |
217 | |
218 memset(buf, 0, ID3_TAG_SIZE); /* fail safe */ | |
219 buf[0] = 'T'; | |
220 buf[1] = 'A'; | |
221 buf[2] = 'G'; | |
222 strncpy(buf + 3, s->title, 30); | |
223 strncpy(buf + 33, s->author, 30); | |
224 strncpy(buf + 63, s->album, 30); | |
225 v = s->year; | |
226 if (v > 0) { | |
227 for(i = 0;i < 4; i++) { | |
228 buf[96 - i] = '0' + (v % 10); | |
229 v = v / 10; | |
230 } | |
231 } | |
232 strncpy(buf + 97, s->comment, 30); | |
233 if (s->track != 0) { | |
234 buf[125] = 0; | |
235 buf[126] = s->track; | |
236 } | |
237 for(i = 0; i <= ID3_GENRE_MAX; i++) { | |
238 if (!strcasecmp(s->genre, id3_genre_str[i])) { | |
239 buf[127] = i; | |
240 break; | |
241 } | |
242 } | |
243 } | |
244 | |
245 /* mp3 read */ | |
1107 | 246 |
247 static int mp3_read_probe(AVProbeData *p) | |
248 { | |
1321
9eeb01383e30
reduce scores if the mp3 frames dont start from the begin of the file (fixes flv deteted as mp3 issues)
michael
parents:
1312
diff
changeset
|
249 int max_frames, first_frames; |
1433
dababce8f69e
dont set the sampling rate just because 1 mp3 packet header says so (fixes playback speed on some old mencoder generated avis which where then dumped to mp3)
michael
parents:
1415
diff
changeset
|
250 int fsize, frames, sample_rate; |
1308
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
251 uint32_t header; |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
252 uint8_t *buf, *buf2, *end; |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
253 AVCodecContext avctx; |
1107 | 254 |
1308
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
255 if(p->buf_size < ID3_HEADER_SIZE) |
1107 | 256 return 0; |
257 | |
1308
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
258 if(id3_match(p->buf)) |
1469 | 259 return AVPROBE_SCORE_MAX/2+1; // this must be less then mpeg-ps because some retards put id3 tage before mpeg-ps files |
1107 | 260 |
1308
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
261 max_frames = 0; |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
262 buf = p->buf; |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
263 end = buf + FFMIN(4096, p->buf_size - sizeof(uint32_t)); |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
264 |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
265 for(; buf < end; buf++) { |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
266 buf2 = buf; |
1107 | 267 |
1312 | 268 for(frames = 0; buf2 < end; frames++) { |
1308
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
269 header = (buf2[0] << 24) | (buf2[1] << 16) | (buf2[2] << 8) | buf2[3]; |
1433
dababce8f69e
dont set the sampling rate just because 1 mp3 packet header says so (fixes playback speed on some old mencoder generated avis which where then dumped to mp3)
michael
parents:
1415
diff
changeset
|
270 fsize = mpa_decode_header(&avctx, header, &sample_rate); |
1308
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
271 if(fsize < 0) |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
272 break; |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
273 buf2 += fsize; |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
274 } |
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
275 max_frames = FFMAX(max_frames, frames); |
1321
9eeb01383e30
reduce scores if the mp3 frames dont start from the begin of the file (fixes flv deteted as mp3 issues)
michael
parents:
1312
diff
changeset
|
276 if(buf == p->buf) |
9eeb01383e30
reduce scores if the mp3 frames dont start from the begin of the file (fixes flv deteted as mp3 issues)
michael
parents:
1312
diff
changeset
|
277 first_frames= frames; |
1308
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
278 } |
1321
9eeb01383e30
reduce scores if the mp3 frames dont start from the begin of the file (fixes flv deteted as mp3 issues)
michael
parents:
1312
diff
changeset
|
279 if (first_frames>=3) return AVPROBE_SCORE_MAX/2+1; |
9eeb01383e30
reduce scores if the mp3 frames dont start from the begin of the file (fixes flv deteted as mp3 issues)
michael
parents:
1312
diff
changeset
|
280 else if(max_frames>=3) return AVPROBE_SCORE_MAX/4; |
9eeb01383e30
reduce scores if the mp3 frames dont start from the begin of the file (fixes flv deteted as mp3 issues)
michael
parents:
1312
diff
changeset
|
281 else if(max_frames>=1) return 1; |
1308
866d43ed0a67
allow ffmpeg to read mp3s beginning with partial frames
gpoirier
parents:
1169
diff
changeset
|
282 else return 0; |
1107 | 283 } |
284 | |
234 | 285 static int mp3_read_header(AVFormatContext *s, |
286 AVFormatParameters *ap) | |
287 { | |
288 AVStream *st; | |
289 uint8_t buf[ID3_TAG_SIZE]; | |
290 int len, ret, filesize; | |
291 | |
292 st = av_new_stream(s, 0); | |
293 if (!st) | |
294 return AVERROR_NOMEM; | |
295 | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
814
diff
changeset
|
296 st->codec->codec_type = CODEC_TYPE_AUDIO; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
814
diff
changeset
|
297 st->codec->codec_id = CODEC_ID_MP3; |
307 | 298 st->need_parsing = 1; |
885 | 299 |
234 | 300 /* try to get the TAG */ |
301 if (!url_is_streamed(&s->pb)) { | |
302 /* XXX: change that */ | |
764
cdb845a57ae4
drop most url_fileno() calls (allows to use ByteIOContext directly in caller apps instead of URLProtocol)
aurel
parents:
482
diff
changeset
|
303 filesize = url_fsize(&s->pb); |
234 | 304 if (filesize > 128) { |
305 url_fseek(&s->pb, filesize - 128, SEEK_SET); | |
306 ret = get_buffer(&s->pb, buf, ID3_TAG_SIZE); | |
307 if (ret == ID3_TAG_SIZE) { | |
308 id3_parse_tag(s, buf); | |
309 } | |
310 url_fseek(&s->pb, 0, SEEK_SET); | |
311 } | |
312 } | |
313 | |
314 /* if ID3 header found, skip it */ | |
315 ret = get_buffer(&s->pb, buf, ID3_HEADER_SIZE); | |
316 if (ret != ID3_HEADER_SIZE) | |
317 return -1; | |
318 if (id3_match(buf)) { | |
319 /* skip ID3 header */ | |
320 len = ((buf[6] & 0x7f) << 21) | | |
321 ((buf[7] & 0x7f) << 14) | | |
322 ((buf[8] & 0x7f) << 7) | | |
323 (buf[9] & 0x7f); | |
324 url_fskip(&s->pb, len); | |
325 } else { | |
326 url_fseek(&s->pb, 0, SEEK_SET); | |
327 } | |
328 | |
329 /* the parameters will be extracted from the compressed bitstream */ | |
330 return 0; | |
331 } | |
332 | |
333 #define MP3_PACKET_SIZE 1024 | |
334 | |
335 static int mp3_read_packet(AVFormatContext *s, AVPacket *pkt) | |
336 { | |
337 int ret, size; | |
338 // AVStream *st = s->streams[0]; | |
885 | 339 |
234 | 340 size= MP3_PACKET_SIZE; |
341 | |
775 | 342 ret= av_get_packet(&s->pb, pkt, size); |
234 | 343 |
344 pkt->stream_index = 0; | |
345 if (ret <= 0) { | |
482 | 346 return AVERROR_IO; |
234 | 347 } |
348 /* note: we need to modify the packet size here to handle the last | |
349 packet */ | |
350 pkt->size = ret; | |
351 return ret; | |
352 } | |
353 | |
354 static int mp3_read_close(AVFormatContext *s) | |
355 { | |
356 return 0; | |
357 } | |
358 | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
359 #ifdef CONFIG_MUXERS |
234 | 360 /* simple formats */ |
361 static int mp3_write_header(struct AVFormatContext *s) | |
362 { | |
363 return 0; | |
364 } | |
365 | |
468 | 366 static int mp3_write_packet(struct AVFormatContext *s, AVPacket *pkt) |
234 | 367 { |
468 | 368 put_buffer(&s->pb, pkt->data, pkt->size); |
234 | 369 put_flush_packet(&s->pb); |
370 return 0; | |
371 } | |
372 | |
373 static int mp3_write_trailer(struct AVFormatContext *s) | |
374 { | |
375 uint8_t buf[ID3_TAG_SIZE]; | |
376 | |
377 /* write the id3 header */ | |
378 if (s->title[0] != '\0') { | |
379 id3_create_tag(s, buf); | |
380 put_buffer(&s->pb, buf, ID3_TAG_SIZE); | |
381 put_flush_packet(&s->pb); | |
382 } | |
383 return 0; | |
384 } | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
385 #endif //CONFIG_MUXERS |
234 | 386 |
1169 | 387 #ifdef CONFIG_MP3_DEMUXER |
1167 | 388 AVInputFormat mp3_demuxer = { |
234 | 389 "mp3", |
390 "MPEG audio", | |
391 0, | |
1107 | 392 mp3_read_probe, |
234 | 393 mp3_read_header, |
394 mp3_read_packet, | |
395 mp3_read_close, | |
1756 | 396 .flags= AVFMT_GENERIC_INDEX, |
814 | 397 .extensions = "mp2,mp3,m2a", /* XXX: use probe */ |
234 | 398 }; |
1169 | 399 #endif |
400 #ifdef CONFIG_MP2_MUXER | |
1167 | 401 AVOutputFormat mp2_muxer = { |
234 | 402 "mp2", |
403 "MPEG audio layer 2", | |
404 "audio/x-mpeg", | |
1622 | 405 #ifdef CONFIG_LIBMP3LAME |
814 | 406 "mp2,m2a", |
234 | 407 #else |
814 | 408 "mp2,mp3,m2a", |
234 | 409 #endif |
410 0, | |
411 CODEC_ID_MP2, | |
412 0, | |
413 mp3_write_header, | |
414 mp3_write_packet, | |
415 mp3_write_trailer, | |
416 }; | |
1169 | 417 #endif |
418 #ifdef CONFIG_MP3_MUXER | |
1167 | 419 AVOutputFormat mp3_muxer = { |
234 | 420 "mp3", |
421 "MPEG audio layer 3", | |
422 "audio/x-mpeg", | |
423 "mp3", | |
424 0, | |
425 CODEC_ID_MP3, | |
426 0, | |
427 mp3_write_header, | |
428 mp3_write_packet, | |
429 mp3_write_trailer, | |
430 }; | |
431 #endif |