Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6148 | serge | 1 | /* |
2 | * ID3v1 header parser |
||
3 | * Copyright (c) 2003 Fabrice Bellard |
||
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 "id3v1.h" |
||
23 | #include "libavcodec/avcodec.h" |
||
24 | #include "libavutil/dict.h" |
||
25 | |||
26 | /* See Genre List at http://id3.org/id3v2.3.0 */ |
||
27 | const char * const ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1] = { |
||
28 | [0] = "Blues", |
||
29 | [1] = "Classic Rock", |
||
30 | [2] = "Country", |
||
31 | [3] = "Dance", |
||
32 | [4] = "Disco", |
||
33 | [5] = "Funk", |
||
34 | [6] = "Grunge", |
||
35 | [7] = "Hip-Hop", |
||
36 | [8] = "Jazz", |
||
37 | [9] = "Metal", |
||
38 | [10] = "New Age", |
||
39 | [11] = "Oldies", |
||
40 | [12] = "Other", |
||
41 | [13] = "Pop", |
||
42 | [14] = "R&B", |
||
43 | [15] = "Rap", |
||
44 | [16] = "Reggae", |
||
45 | [17] = "Rock", |
||
46 | [18] = "Techno", |
||
47 | [19] = "Industrial", |
||
48 | [20] = "Alternative", |
||
49 | [21] = "Ska", |
||
50 | [22] = "Death Metal", |
||
51 | [23] = "Pranks", |
||
52 | [24] = "Soundtrack", |
||
53 | [25] = "Euro-Techno", |
||
54 | [26] = "Ambient", |
||
55 | [27] = "Trip-Hop", |
||
56 | [28] = "Vocal", |
||
57 | [29] = "Jazz+Funk", |
||
58 | [30] = "Fusion", |
||
59 | [31] = "Trance", |
||
60 | [32] = "Classical", |
||
61 | [33] = "Instrumental", |
||
62 | [34] = "Acid", |
||
63 | [35] = "House", |
||
64 | [36] = "Game", |
||
65 | [37] = "Sound Clip", |
||
66 | [38] = "Gospel", |
||
67 | [39] = "Noise", |
||
68 | [40] = "AlternRock", |
||
69 | [41] = "Bass", |
||
70 | [42] = "Soul", |
||
71 | [43] = "Punk", |
||
72 | [44] = "Space", |
||
73 | [45] = "Meditative", |
||
74 | [46] = "Instrumental Pop", |
||
75 | [47] = "Instrumental Rock", |
||
76 | [48] = "Ethnic", |
||
77 | [49] = "Gothic", |
||
78 | [50] = "Darkwave", |
||
79 | [51] = "Techno-Industrial", |
||
80 | [52] = "Electronic", |
||
81 | [53] = "Pop-Folk", |
||
82 | [54] = "Eurodance", |
||
83 | [55] = "Dream", |
||
84 | [56] = "Southern Rock", |
||
85 | [57] = "Comedy", |
||
86 | [58] = "Cult", |
||
87 | [59] = "Gangsta", |
||
88 | [60] = "Top 40", |
||
89 | [61] = "Christian Rap", |
||
90 | [62] = "Pop/Funk", |
||
91 | [63] = "Jungle", |
||
92 | [64] = "Native American", |
||
93 | [65] = "Cabaret", |
||
94 | [66] = "New Wave", |
||
95 | [67] = "Psychadelic", /* sic, the misspelling is used in the specification */ |
||
96 | [68] = "Rave", |
||
97 | [69] = "Showtunes", |
||
98 | [70] = "Trailer", |
||
99 | [71] = "Lo-Fi", |
||
100 | [72] = "Tribal", |
||
101 | [73] = "Acid Punk", |
||
102 | [74] = "Acid Jazz", |
||
103 | [75] = "Polka", |
||
104 | [76] = "Retro", |
||
105 | [77] = "Musical", |
||
106 | [78] = "Rock & Roll", |
||
107 | [79] = "Hard Rock", |
||
108 | [80] = "Folk", |
||
109 | [81] = "Folk-Rock", |
||
110 | [82] = "National Folk", |
||
111 | [83] = "Swing", |
||
112 | [84] = "Fast Fusion", |
||
113 | [85] = "Bebob", |
||
114 | [86] = "Latin", |
||
115 | [87] = "Revival", |
||
116 | [88] = "Celtic", |
||
117 | [89] = "Bluegrass", |
||
118 | [90] = "Avantgarde", |
||
119 | [91] = "Gothic Rock", |
||
120 | [92] = "Progressive Rock", |
||
121 | [93] = "Psychedelic Rock", |
||
122 | [94] = "Symphonic Rock", |
||
123 | [95] = "Slow Rock", |
||
124 | [96] = "Big Band", |
||
125 | [97] = "Chorus", |
||
126 | [98] = "Easy Listening", |
||
127 | [99] = "Acoustic", |
||
128 | [100] = "Humour", |
||
129 | [101] = "Speech", |
||
130 | [102] = "Chanson", |
||
131 | [103] = "Opera", |
||
132 | [104] = "Chamber Music", |
||
133 | [105] = "Sonata", |
||
134 | [106] = "Symphony", |
||
135 | [107] = "Booty Bass", |
||
136 | [108] = "Primus", |
||
137 | [109] = "Porn Groove", |
||
138 | [110] = "Satire", |
||
139 | [111] = "Slow Jam", |
||
140 | [112] = "Club", |
||
141 | [113] = "Tango", |
||
142 | [114] = "Samba", |
||
143 | [115] = "Folklore", |
||
144 | [116] = "Ballad", |
||
145 | [117] = "Power Ballad", |
||
146 | [118] = "Rhythmic Soul", |
||
147 | [119] = "Freestyle", |
||
148 | [120] = "Duet", |
||
149 | [121] = "Punk Rock", |
||
150 | [122] = "Drum Solo", |
||
151 | [123] = "A capella", |
||
152 | [124] = "Euro-House", |
||
153 | [125] = "Dance Hall", |
||
154 | [126] = "Goa", |
||
155 | [127] = "Drum & Bass", |
||
156 | [128] = "Club-House", |
||
157 | [129] = "Hardcore", |
||
158 | [130] = "Terror", |
||
159 | [131] = "Indie", |
||
160 | [132] = "BritPop", |
||
161 | [133] = "Negerpunk", |
||
162 | [134] = "Polsk Punk", |
||
163 | [135] = "Beat", |
||
164 | [136] = "Christian Gangsta", |
||
165 | [137] = "Heavy Metal", |
||
166 | [138] = "Black Metal", |
||
167 | [139] = "Crossover", |
||
168 | [140] = "Contemporary Christian", |
||
169 | [141] = "Christian Rock", |
||
170 | [142] = "Merengue", |
||
171 | [143] = "Salsa", |
||
172 | [144] = "Thrash Metal", |
||
173 | [145] = "Anime", |
||
174 | [146] = "JPop", |
||
175 | [147] = "SynthPop", |
||
176 | }; |
||
177 | |||
178 | static void get_string(AVFormatContext *s, const char *key, |
||
179 | const uint8_t *buf, int buf_size) |
||
180 | { |
||
181 | int i, c; |
||
182 | char *q, str[512]; |
||
183 | |||
184 | q = str; |
||
185 | for(i = 0; i < buf_size; i++) { |
||
186 | c = buf[i]; |
||
187 | if (c == '\0') |
||
188 | break; |
||
189 | if ((q - str) >= sizeof(str) - 1) |
||
190 | break; |
||
191 | *q++ = c; |
||
192 | } |
||
193 | *q = '\0'; |
||
194 | |||
195 | if (*str) |
||
196 | av_dict_set(&s->metadata, key, str, 0); |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * Parse an ID3v1 tag |
||
201 | * |
||
202 | * @param buf ID3v1_TAG_SIZE long buffer containing the tag |
||
203 | */ |
||
204 | static int parse_tag(AVFormatContext *s, const uint8_t *buf) |
||
205 | { |
||
206 | char str[5]; |
||
207 | int genre; |
||
208 | |||
209 | if (!(buf[0] == 'T' && |
||
210 | buf[1] == 'A' && |
||
211 | buf[2] == 'G')) |
||
212 | return -1; |
||
213 | get_string(s, "title", buf + 3, 30); |
||
214 | get_string(s, "artist", buf + 33, 30); |
||
215 | get_string(s, "album", buf + 63, 30); |
||
216 | get_string(s, "date", buf + 93, 4); |
||
217 | get_string(s, "comment", buf + 97, 30); |
||
218 | if (buf[125] == 0 && buf[126] != 0) { |
||
219 | snprintf(str, sizeof(str), "%d", buf[126]); |
||
220 | av_dict_set(&s->metadata, "track", str, 0); |
||
221 | } |
||
222 | genre = buf[127]; |
||
223 | if (genre <= ID3v1_GENRE_MAX) |
||
224 | av_dict_set(&s->metadata, "genre", ff_id3v1_genre_str[genre], 0); |
||
225 | return 0; |
||
226 | } |
||
227 | |||
228 | void ff_id3v1_read(AVFormatContext *s) |
||
229 | { |
||
230 | int ret; |
||
231 | uint8_t buf[ID3v1_TAG_SIZE]; |
||
232 | int64_t filesize, position = avio_tell(s->pb); |
||
233 | |||
234 | if (s->pb->seekable) { |
||
235 | /* XXX: change that */ |
||
236 | filesize = avio_size(s->pb); |
||
237 | if (filesize > 128) { |
||
238 | avio_seek(s->pb, filesize - 128, SEEK_SET); |
||
239 | ret = avio_read(s->pb, buf, ID3v1_TAG_SIZE); |
||
240 | if (ret == ID3v1_TAG_SIZE) { |
||
241 | parse_tag(s, buf); |
||
242 | } |
||
243 | avio_seek(s->pb, position, SEEK_SET); |
||
244 | } |
||
245 | } |
||
246 | }=>> |