Imported Debian version 2.5.2~trusty
[deb_ffmpeg.git] / ffmpeg / libavformat / id3v1.c
... / ...
CommitLineData
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 */
27const 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
178static 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 */
204static int parse_tag(AVFormatContext *s, const uint8_t *buf)
205{
206 int genre;
207
208 if (!(buf[0] == 'T' &&
209 buf[1] == 'A' &&
210 buf[2] == 'G'))
211 return -1;
212 get_string(s, "title", buf + 3, 30);
213 get_string(s, "artist", buf + 33, 30);
214 get_string(s, "album", buf + 63, 30);
215 get_string(s, "date", buf + 93, 4);
216 get_string(s, "comment", buf + 97, 30);
217 if (buf[125] == 0 && buf[126] != 0) {
218 av_dict_set_int(&s->metadata, "track", buf[126], 0);
219 }
220 genre = buf[127];
221 if (genre <= ID3v1_GENRE_MAX)
222 av_dict_set(&s->metadata, "genre", ff_id3v1_genre_str[genre], 0);
223 return 0;
224}
225
226void ff_id3v1_read(AVFormatContext *s)
227{
228 int ret;
229 uint8_t buf[ID3v1_TAG_SIZE];
230 int64_t filesize, position = avio_tell(s->pb);
231
232 if (s->pb->seekable) {
233 /* XXX: change that */
234 filesize = avio_size(s->pb);
235 if (filesize > 128) {
236 avio_seek(s->pb, filesize - 128, SEEK_SET);
237 ret = avio_read(s->pb, buf, ID3v1_TAG_SIZE);
238 if (ret == ID3v1_TAG_SIZE) {
239 parse_tag(s, buf);
240 }
241 avio_seek(s->pb, position, SEEK_SET);
242 }
243 }
244}