xref: /third_party/ffmpeg/libavformat/id3v1.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * ID3v1 header parser
3cabdff1aSopenharmony_ci * Copyright (c) 2003 Fabrice Bellard
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include "id3v1.h"
23cabdff1aSopenharmony_ci#include "libavutil/dict.h"
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci/* See Genre List at http://id3.org/id3v2.3.0 */
26cabdff1aSopenharmony_ciconst char * const ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1] = {
27cabdff1aSopenharmony_ci      [0] = "Blues",
28cabdff1aSopenharmony_ci      [1] = "Classic Rock",
29cabdff1aSopenharmony_ci      [2] = "Country",
30cabdff1aSopenharmony_ci      [3] = "Dance",
31cabdff1aSopenharmony_ci      [4] = "Disco",
32cabdff1aSopenharmony_ci      [5] = "Funk",
33cabdff1aSopenharmony_ci      [6] = "Grunge",
34cabdff1aSopenharmony_ci      [7] = "Hip-Hop",
35cabdff1aSopenharmony_ci      [8] = "Jazz",
36cabdff1aSopenharmony_ci      [9] = "Metal",
37cabdff1aSopenharmony_ci     [10] = "New Age",
38cabdff1aSopenharmony_ci     [11] = "Oldies",
39cabdff1aSopenharmony_ci     [12] = "Other",
40cabdff1aSopenharmony_ci     [13] = "Pop",
41cabdff1aSopenharmony_ci     [14] = "R&B",
42cabdff1aSopenharmony_ci     [15] = "Rap",
43cabdff1aSopenharmony_ci     [16] = "Reggae",
44cabdff1aSopenharmony_ci     [17] = "Rock",
45cabdff1aSopenharmony_ci     [18] = "Techno",
46cabdff1aSopenharmony_ci     [19] = "Industrial",
47cabdff1aSopenharmony_ci     [20] = "Alternative",
48cabdff1aSopenharmony_ci     [21] = "Ska",
49cabdff1aSopenharmony_ci     [22] = "Death Metal",
50cabdff1aSopenharmony_ci     [23] = "Pranks",
51cabdff1aSopenharmony_ci     [24] = "Soundtrack",
52cabdff1aSopenharmony_ci     [25] = "Euro-Techno",
53cabdff1aSopenharmony_ci     [26] = "Ambient",
54cabdff1aSopenharmony_ci     [27] = "Trip-Hop",
55cabdff1aSopenharmony_ci     [28] = "Vocal",
56cabdff1aSopenharmony_ci     [29] = "Jazz+Funk",
57cabdff1aSopenharmony_ci     [30] = "Fusion",
58cabdff1aSopenharmony_ci     [31] = "Trance",
59cabdff1aSopenharmony_ci     [32] = "Classical",
60cabdff1aSopenharmony_ci     [33] = "Instrumental",
61cabdff1aSopenharmony_ci     [34] = "Acid",
62cabdff1aSopenharmony_ci     [35] = "House",
63cabdff1aSopenharmony_ci     [36] = "Game",
64cabdff1aSopenharmony_ci     [37] = "Sound Clip",
65cabdff1aSopenharmony_ci     [38] = "Gospel",
66cabdff1aSopenharmony_ci     [39] = "Noise",
67cabdff1aSopenharmony_ci     [40] = "AlternRock",
68cabdff1aSopenharmony_ci     [41] = "Bass",
69cabdff1aSopenharmony_ci     [42] = "Soul",
70cabdff1aSopenharmony_ci     [43] = "Punk",
71cabdff1aSopenharmony_ci     [44] = "Space",
72cabdff1aSopenharmony_ci     [45] = "Meditative",
73cabdff1aSopenharmony_ci     [46] = "Instrumental Pop",
74cabdff1aSopenharmony_ci     [47] = "Instrumental Rock",
75cabdff1aSopenharmony_ci     [48] = "Ethnic",
76cabdff1aSopenharmony_ci     [49] = "Gothic",
77cabdff1aSopenharmony_ci     [50] = "Darkwave",
78cabdff1aSopenharmony_ci     [51] = "Techno-Industrial",
79cabdff1aSopenharmony_ci     [52] = "Electronic",
80cabdff1aSopenharmony_ci     [53] = "Pop-Folk",
81cabdff1aSopenharmony_ci     [54] = "Eurodance",
82cabdff1aSopenharmony_ci     [55] = "Dream",
83cabdff1aSopenharmony_ci     [56] = "Southern Rock",
84cabdff1aSopenharmony_ci     [57] = "Comedy",
85cabdff1aSopenharmony_ci     [58] = "Cult",
86cabdff1aSopenharmony_ci     [59] = "Gangsta",
87cabdff1aSopenharmony_ci     [60] = "Top 40",
88cabdff1aSopenharmony_ci     [61] = "Christian Rap",
89cabdff1aSopenharmony_ci     [62] = "Pop/Funk",
90cabdff1aSopenharmony_ci     [63] = "Jungle",
91cabdff1aSopenharmony_ci     [64] = "Native American",
92cabdff1aSopenharmony_ci     [65] = "Cabaret",
93cabdff1aSopenharmony_ci     [66] = "New Wave",
94cabdff1aSopenharmony_ci     [67] = "Psychedelic",
95cabdff1aSopenharmony_ci     [68] = "Rave",
96cabdff1aSopenharmony_ci     [69] = "Showtunes",
97cabdff1aSopenharmony_ci     [70] = "Trailer",
98cabdff1aSopenharmony_ci     [71] = "Lo-Fi",
99cabdff1aSopenharmony_ci     [72] = "Tribal",
100cabdff1aSopenharmony_ci     [73] = "Acid Punk",
101cabdff1aSopenharmony_ci     [74] = "Acid Jazz",
102cabdff1aSopenharmony_ci     [75] = "Polka",
103cabdff1aSopenharmony_ci     [76] = "Retro",
104cabdff1aSopenharmony_ci     [77] = "Musical",
105cabdff1aSopenharmony_ci     [78] = "Rock & Roll",
106cabdff1aSopenharmony_ci     [79] = "Hard Rock",
107cabdff1aSopenharmony_ci     [80] = "Folk",
108cabdff1aSopenharmony_ci     [81] = "Folk-Rock",
109cabdff1aSopenharmony_ci     [82] = "National Folk",
110cabdff1aSopenharmony_ci     [83] = "Swing",
111cabdff1aSopenharmony_ci     [84] = "Fast Fusion",
112cabdff1aSopenharmony_ci     [85] = "Bebop",
113cabdff1aSopenharmony_ci     [86] = "Latin",
114cabdff1aSopenharmony_ci     [87] = "Revival",
115cabdff1aSopenharmony_ci     [88] = "Celtic",
116cabdff1aSopenharmony_ci     [89] = "Bluegrass",
117cabdff1aSopenharmony_ci     [90] = "Avantgarde",
118cabdff1aSopenharmony_ci     [91] = "Gothic Rock",
119cabdff1aSopenharmony_ci     [92] = "Progressive Rock",
120cabdff1aSopenharmony_ci     [93] = "Psychedelic Rock",
121cabdff1aSopenharmony_ci     [94] = "Symphonic Rock",
122cabdff1aSopenharmony_ci     [95] = "Slow Rock",
123cabdff1aSopenharmony_ci     [96] = "Big Band",
124cabdff1aSopenharmony_ci     [97] = "Chorus",
125cabdff1aSopenharmony_ci     [98] = "Easy Listening",
126cabdff1aSopenharmony_ci     [99] = "Acoustic",
127cabdff1aSopenharmony_ci    [100] = "Humour",
128cabdff1aSopenharmony_ci    [101] = "Speech",
129cabdff1aSopenharmony_ci    [102] = "Chanson",
130cabdff1aSopenharmony_ci    [103] = "Opera",
131cabdff1aSopenharmony_ci    [104] = "Chamber Music",
132cabdff1aSopenharmony_ci    [105] = "Sonata",
133cabdff1aSopenharmony_ci    [106] = "Symphony",
134cabdff1aSopenharmony_ci    [107] = "Booty Bass",
135cabdff1aSopenharmony_ci    [108] = "Primus",
136cabdff1aSopenharmony_ci    [109] = "Porn Groove",
137cabdff1aSopenharmony_ci    [110] = "Satire",
138cabdff1aSopenharmony_ci    [111] = "Slow Jam",
139cabdff1aSopenharmony_ci    [112] = "Club",
140cabdff1aSopenharmony_ci    [113] = "Tango",
141cabdff1aSopenharmony_ci    [114] = "Samba",
142cabdff1aSopenharmony_ci    [115] = "Folklore",
143cabdff1aSopenharmony_ci    [116] = "Ballad",
144cabdff1aSopenharmony_ci    [117] = "Power Ballad",
145cabdff1aSopenharmony_ci    [118] = "Rhythmic Soul",
146cabdff1aSopenharmony_ci    [119] = "Freestyle",
147cabdff1aSopenharmony_ci    [120] = "Duet",
148cabdff1aSopenharmony_ci    [121] = "Punk Rock",
149cabdff1aSopenharmony_ci    [122] = "Drum Solo",
150cabdff1aSopenharmony_ci    [123] = "A Cappella",
151cabdff1aSopenharmony_ci    [124] = "Euro-House",
152cabdff1aSopenharmony_ci    [125] = "Dance Hall",
153cabdff1aSopenharmony_ci    [126] = "Goa",
154cabdff1aSopenharmony_ci    [127] = "Drum & Bass",
155cabdff1aSopenharmony_ci    [128] = "Club-House",
156cabdff1aSopenharmony_ci    [129] = "Hardcore Techno",
157cabdff1aSopenharmony_ci    [130] = "Terror",
158cabdff1aSopenharmony_ci    [131] = "Indie",
159cabdff1aSopenharmony_ci    [132] = "BritPop",
160cabdff1aSopenharmony_ci    [133] = "Negerpunk",
161cabdff1aSopenharmony_ci    [134] = "Polsk Punk",
162cabdff1aSopenharmony_ci    [135] = "Beat",
163cabdff1aSopenharmony_ci    [136] = "Christian Gangsta Rap",
164cabdff1aSopenharmony_ci    [137] = "Heavy Metal",
165cabdff1aSopenharmony_ci    [138] = "Black Metal",
166cabdff1aSopenharmony_ci    [139] = "Crossover",
167cabdff1aSopenharmony_ci    [140] = "Contemporary Christian",
168cabdff1aSopenharmony_ci    [141] = "Christian Rock",
169cabdff1aSopenharmony_ci    [142] = "Merengue",
170cabdff1aSopenharmony_ci    [143] = "Salsa",
171cabdff1aSopenharmony_ci    [144] = "Thrash Metal",
172cabdff1aSopenharmony_ci    [145] = "Anime",
173cabdff1aSopenharmony_ci    [146] = "Jpop",
174cabdff1aSopenharmony_ci    [147] = "Synthpop",
175cabdff1aSopenharmony_ci    [148] = "Abstract",
176cabdff1aSopenharmony_ci    [149] = "Art Rock",
177cabdff1aSopenharmony_ci    [150] = "Baroque",
178cabdff1aSopenharmony_ci    [151] = "Bhangra",
179cabdff1aSopenharmony_ci    [152] = "Big Beat",
180cabdff1aSopenharmony_ci    [153] = "Breakbeat",
181cabdff1aSopenharmony_ci    [154] = "Chillout",
182cabdff1aSopenharmony_ci    [155] = "Downtempo",
183cabdff1aSopenharmony_ci    [156] = "Dub",
184cabdff1aSopenharmony_ci    [157] = "EBM",
185cabdff1aSopenharmony_ci    [158] = "Eclectic",
186cabdff1aSopenharmony_ci    [159] = "Electro",
187cabdff1aSopenharmony_ci    [160] = "Electroclash",
188cabdff1aSopenharmony_ci    [161] = "Emo",
189cabdff1aSopenharmony_ci    [162] = "Experimental",
190cabdff1aSopenharmony_ci    [163] = "Garage",
191cabdff1aSopenharmony_ci    [164] = "Global",
192cabdff1aSopenharmony_ci    [165] = "IDM",
193cabdff1aSopenharmony_ci    [166] = "Illbient",
194cabdff1aSopenharmony_ci    [167] = "Industro-Goth",
195cabdff1aSopenharmony_ci    [168] = "Jam Band",
196cabdff1aSopenharmony_ci    [169] = "Krautrock",
197cabdff1aSopenharmony_ci    [170] = "Leftfield",
198cabdff1aSopenharmony_ci    [171] = "Lounge",
199cabdff1aSopenharmony_ci    [172] = "Math Rock",
200cabdff1aSopenharmony_ci    [173] = "New Romantic",
201cabdff1aSopenharmony_ci    [174] = "Nu-Breakz",
202cabdff1aSopenharmony_ci    [175] = "Post-Punk",
203cabdff1aSopenharmony_ci    [176] = "Post-Rock",
204cabdff1aSopenharmony_ci    [177] = "Psytrance",
205cabdff1aSopenharmony_ci    [178] = "Shoegaze",
206cabdff1aSopenharmony_ci    [179] = "Space Rock",
207cabdff1aSopenharmony_ci    [180] = "Trop Rock",
208cabdff1aSopenharmony_ci    [181] = "World Music",
209cabdff1aSopenharmony_ci    [182] = "Neoclassical",
210cabdff1aSopenharmony_ci    [183] = "Audiobook",
211cabdff1aSopenharmony_ci    [184] = "Audio Theatre",
212cabdff1aSopenharmony_ci    [185] = "Neue Deutsche Welle",
213cabdff1aSopenharmony_ci    [186] = "Podcast",
214cabdff1aSopenharmony_ci    [187] = "Indie Rock",
215cabdff1aSopenharmony_ci    [188] = "G-Funk",
216cabdff1aSopenharmony_ci    [189] = "Dubstep",
217cabdff1aSopenharmony_ci    [190] = "Garage Rock",
218cabdff1aSopenharmony_ci    [191] = "Psybient"
219cabdff1aSopenharmony_ci};
220cabdff1aSopenharmony_ci
221cabdff1aSopenharmony_cistatic void get_string(AVFormatContext *s, const char *key,
222cabdff1aSopenharmony_ci                       const uint8_t *buf, int buf_size)
223cabdff1aSopenharmony_ci{
224cabdff1aSopenharmony_ci    int i, c;
225cabdff1aSopenharmony_ci    char *q, str[512], *first_free_space = NULL;
226cabdff1aSopenharmony_ci
227cabdff1aSopenharmony_ci    q = str;
228cabdff1aSopenharmony_ci    for(i = 0; i < buf_size; i++) {
229cabdff1aSopenharmony_ci        c = buf[i];
230cabdff1aSopenharmony_ci        if (c == '\0')
231cabdff1aSopenharmony_ci            break;
232cabdff1aSopenharmony_ci        if ((q - str) >= sizeof(str) - 1)
233cabdff1aSopenharmony_ci            break;
234cabdff1aSopenharmony_ci        if (c == ' ') {
235cabdff1aSopenharmony_ci            if (!first_free_space)
236cabdff1aSopenharmony_ci                first_free_space = q;
237cabdff1aSopenharmony_ci        } else {
238cabdff1aSopenharmony_ci            first_free_space = NULL;
239cabdff1aSopenharmony_ci        }
240cabdff1aSopenharmony_ci        *q++ = c;
241cabdff1aSopenharmony_ci    }
242cabdff1aSopenharmony_ci    *q = '\0';
243cabdff1aSopenharmony_ci
244cabdff1aSopenharmony_ci    if (first_free_space)
245cabdff1aSopenharmony_ci        *first_free_space = '\0';
246cabdff1aSopenharmony_ci
247cabdff1aSopenharmony_ci    if (*str)
248cabdff1aSopenharmony_ci        av_dict_set(&s->metadata, key, str, 0);
249cabdff1aSopenharmony_ci}
250cabdff1aSopenharmony_ci
251cabdff1aSopenharmony_ci/**
252cabdff1aSopenharmony_ci * Parse an ID3v1 tag
253cabdff1aSopenharmony_ci *
254cabdff1aSopenharmony_ci * @param buf ID3v1_TAG_SIZE long buffer containing the tag
255cabdff1aSopenharmony_ci */
256cabdff1aSopenharmony_cistatic int parse_tag(AVFormatContext *s, const uint8_t *buf)
257cabdff1aSopenharmony_ci{
258cabdff1aSopenharmony_ci    int genre;
259cabdff1aSopenharmony_ci
260cabdff1aSopenharmony_ci    if (!(buf[0] == 'T' &&
261cabdff1aSopenharmony_ci          buf[1] == 'A' &&
262cabdff1aSopenharmony_ci          buf[2] == 'G'))
263cabdff1aSopenharmony_ci        return -1;
264cabdff1aSopenharmony_ci    get_string(s, "title",   buf +  3, 30);
265cabdff1aSopenharmony_ci    get_string(s, "artist",  buf + 33, 30);
266cabdff1aSopenharmony_ci    get_string(s, "album",   buf + 63, 30);
267cabdff1aSopenharmony_ci    get_string(s, "date",    buf + 93,  4);
268cabdff1aSopenharmony_ci    get_string(s, "comment", buf + 97, 30);
269cabdff1aSopenharmony_ci    if (buf[125] == 0 && buf[126] != 0) {
270cabdff1aSopenharmony_ci        av_dict_set_int(&s->metadata, "track", buf[126], 0);
271cabdff1aSopenharmony_ci    }
272cabdff1aSopenharmony_ci    genre = buf[127];
273cabdff1aSopenharmony_ci    if (genre <= ID3v1_GENRE_MAX)
274cabdff1aSopenharmony_ci        av_dict_set(&s->metadata, "genre", ff_id3v1_genre_str[genre], 0);
275cabdff1aSopenharmony_ci    return 0;
276cabdff1aSopenharmony_ci}
277cabdff1aSopenharmony_ci
278cabdff1aSopenharmony_civoid ff_id3v1_read(AVFormatContext *s)
279cabdff1aSopenharmony_ci{
280cabdff1aSopenharmony_ci    int ret;
281cabdff1aSopenharmony_ci    uint8_t buf[ID3v1_TAG_SIZE];
282cabdff1aSopenharmony_ci    int64_t filesize, position = avio_tell(s->pb);
283cabdff1aSopenharmony_ci
284cabdff1aSopenharmony_ci    if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
285cabdff1aSopenharmony_ci        /* XXX: change that */
286cabdff1aSopenharmony_ci        filesize = avio_size(s->pb);
287cabdff1aSopenharmony_ci        if (filesize > 128) {
288cabdff1aSopenharmony_ci            avio_seek(s->pb, filesize - 128, SEEK_SET);
289cabdff1aSopenharmony_ci            ret = avio_read(s->pb, buf, ID3v1_TAG_SIZE);
290cabdff1aSopenharmony_ci            if (ret == ID3v1_TAG_SIZE) {
291cabdff1aSopenharmony_ci                parse_tag(s, buf);
292cabdff1aSopenharmony_ci            }
293cabdff1aSopenharmony_ci            avio_seek(s->pb, position, SEEK_SET);
294cabdff1aSopenharmony_ci        }
295cabdff1aSopenharmony_ci    }
296cabdff1aSopenharmony_ci}
297