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