FFmpeg  4.3.9
id3v1.c
Go to the documentation of this file.
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] = "Psychedelic",
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] = "Bebop",
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 Cappella",
152  [124] = "Euro-House",
153  [125] = "Dance Hall",
154  [126] = "Goa",
155  [127] = "Drum & Bass",
156  [128] = "Club-House",
157  [129] = "Hardcore Techno",
158  [130] = "Terror",
159  [131] = "Indie",
160  [132] = "BritPop",
161  [133] = "Negerpunk",
162  [134] = "Polsk Punk",
163  [135] = "Beat",
164  [136] = "Christian Gangsta Rap",
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  [148] = "Abstract",
177  [149] = "Art Rock",
178  [150] = "Baroque",
179  [151] = "Bhangra",
180  [152] = "Big Beat",
181  [153] = "Breakbeat",
182  [154] = "Chillout",
183  [155] = "Downtempo",
184  [156] = "Dub",
185  [157] = "EBM",
186  [158] = "Eclectic",
187  [159] = "Electro",
188  [160] = "Electroclash",
189  [161] = "Emo",
190  [162] = "Experimental",
191  [163] = "Garage",
192  [164] = "Global",
193  [165] = "IDM",
194  [166] = "Illbient",
195  [167] = "Industro-Goth",
196  [168] = "Jam Band",
197  [169] = "Krautrock",
198  [170] = "Leftfield",
199  [171] = "Lounge",
200  [172] = "Math Rock",
201  [173] = "New Romantic",
202  [174] = "Nu-Breakz",
203  [175] = "Post-Punk",
204  [176] = "Post-Rock",
205  [177] = "Psytrance",
206  [178] = "Shoegaze",
207  [179] = "Space Rock",
208  [180] = "Trop Rock",
209  [181] = "World Music",
210  [182] = "Neoclassical",
211  [183] = "Audiobook",
212  [184] = "Audio Theatre",
213  [185] = "Neue Deutsche Welle",
214  [186] = "Podcast",
215  [187] = "Indie Rock",
216  [188] = "G-Funk",
217  [189] = "Dubstep",
218  [190] = "Garage Rock",
219  [191] = "Psybient"
220 };
221 
222 static void get_string(AVFormatContext *s, const char *key,
223  const uint8_t *buf, int buf_size)
224 {
225  int i, c;
226  char *q, str[512], *first_free_space = NULL;
227 
228  q = str;
229  for(i = 0; i < buf_size; i++) {
230  c = buf[i];
231  if (c == '\0')
232  break;
233  if ((q - str) >= sizeof(str) - 1)
234  break;
235  if (c == ' ') {
236  if (!first_free_space)
237  first_free_space = q;
238  } else {
239  first_free_space = NULL;
240  }
241  *q++ = c;
242  }
243  *q = '\0';
244 
245  if (first_free_space)
246  *first_free_space = '\0';
247 
248  if (*str)
249  av_dict_set(&s->metadata, key, str, 0);
250 }
251 
252 /**
253  * Parse an ID3v1 tag
254  *
255  * @param buf ID3v1_TAG_SIZE long buffer containing the tag
256  */
257 static int parse_tag(AVFormatContext *s, const uint8_t *buf)
258 {
259  int genre;
260 
261  if (!(buf[0] == 'T' &&
262  buf[1] == 'A' &&
263  buf[2] == 'G'))
264  return -1;
265  get_string(s, "title", buf + 3, 30);
266  get_string(s, "artist", buf + 33, 30);
267  get_string(s, "album", buf + 63, 30);
268  get_string(s, "date", buf + 93, 4);
269  get_string(s, "comment", buf + 97, 30);
270  if (buf[125] == 0 && buf[126] != 0) {
271  av_dict_set_int(&s->metadata, "track", buf[126], 0);
272  }
273  genre = buf[127];
274  if (genre <= ID3v1_GENRE_MAX)
275  av_dict_set(&s->metadata, "genre", ff_id3v1_genre_str[genre], 0);
276  return 0;
277 }
278 
280 {
281  int ret;
282  uint8_t buf[ID3v1_TAG_SIZE];
283  int64_t filesize, position = avio_tell(s->pb);
284 
285  if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
286  /* XXX: change that */
287  filesize = avio_size(s->pb);
288  if (filesize > 128) {
289  avio_seek(s->pb, filesize - 128, SEEK_SET);
290  ret = avio_read(s->pb, buf, ID3v1_TAG_SIZE);
291  if (ret == ID3v1_TAG_SIZE) {
292  parse_tag(s, buf);
293  }
294  avio_seek(s->pb, position, SEEK_SET);
295  }
296  }
297 }
#define NULL
Definition: coverity.c:32
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition: aviobuf.c:334
void ff_id3v1_read(AVFormatContext *s)
Read an ID3v1 tag.
Definition: id3v1.c:279
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:241
const char * key
Format I/O context.
Definition: avformat.h:1351
Public dictionary API.
uint8_t
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:625
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1591
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:260
#define s(width, name)
Definition: cbs_vp9.c:257
#define AVIO_SEEKABLE_NORMAL
Seeking works like for a local file.
Definition: avio.h:40
static void get_string(AVFormatContext *s, const char *key, const uint8_t *buf, int buf_size)
Definition: id3v1.c:222
Libavcodec external API header.
AVIOContext * pb
I/O context.
Definition: avformat.h:1393
long long int64_t
Definition: coverity.c:34
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
static int parse_tag(AVFormatContext *s, const uint8_t *buf)
Parse an ID3v1 tag.
Definition: id3v1.c:257
static double c[64]
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set that converts the value to a string and stores it...
Definition: dict.c:147
#define ID3v1_TAG_SIZE
Definition: id3v1.h:27
#define ID3v1_GENRE_MAX
Definition: id3v1.h:29
const char *const ff_id3v1_genre_str[ID3v1_GENRE_MAX+1]
ID3v1 genres.
Definition: id3v1.c:27