Libav 0.7.1
|
00001 /* 00002 * ID3v1 header parser 00003 * Copyright (c) 2003 Fabrice Bellard 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "id3v1.h" 00023 #include "libavcodec/avcodec.h" 00024 #include "libavutil/dict.h" 00025 00026 const char * const ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1] = { 00027 [0] = "Blues", 00028 [1] = "Classic Rock", 00029 [2] = "Country", 00030 [3] = "Dance", 00031 [4] = "Disco", 00032 [5] = "Funk", 00033 [6] = "Grunge", 00034 [7] = "Hip-Hop", 00035 [8] = "Jazz", 00036 [9] = "Metal", 00037 [10] = "New Age", 00038 [11] = "Oldies", 00039 [12] = "Other", 00040 [13] = "Pop", 00041 [14] = "R&B", 00042 [15] = "Rap", 00043 [16] = "Reggae", 00044 [17] = "Rock", 00045 [18] = "Techno", 00046 [19] = "Industrial", 00047 [20] = "Alternative", 00048 [21] = "Ska", 00049 [22] = "Death Metal", 00050 [23] = "Pranks", 00051 [24] = "Soundtrack", 00052 [25] = "Euro-Techno", 00053 [26] = "Ambient", 00054 [27] = "Trip-Hop", 00055 [28] = "Vocal", 00056 [29] = "Jazz+Funk", 00057 [30] = "Fusion", 00058 [31] = "Trance", 00059 [32] = "Classical", 00060 [33] = "Instrumental", 00061 [34] = "Acid", 00062 [35] = "House", 00063 [36] = "Game", 00064 [37] = "Sound Clip", 00065 [38] = "Gospel", 00066 [39] = "Noise", 00067 [40] = "AlternRock", 00068 [41] = "Bass", 00069 [42] = "Soul", 00070 [43] = "Punk", 00071 [44] = "Space", 00072 [45] = "Meditative", 00073 [46] = "Instrumental Pop", 00074 [47] = "Instrumental Rock", 00075 [48] = "Ethnic", 00076 [49] = "Gothic", 00077 [50] = "Darkwave", 00078 [51] = "Techno-Industrial", 00079 [52] = "Electronic", 00080 [53] = "Pop-Folk", 00081 [54] = "Eurodance", 00082 [55] = "Dream", 00083 [56] = "Southern Rock", 00084 [57] = "Comedy", 00085 [58] = "Cult", 00086 [59] = "Gangsta", 00087 [60] = "Top 40", 00088 [61] = "Christian Rap", 00089 [62] = "Pop/Funk", 00090 [63] = "Jungle", 00091 [64] = "Native American", 00092 [65] = "Cabaret", 00093 [66] = "New Wave", 00094 [67] = "Psychadelic", 00095 [68] = "Rave", 00096 [69] = "Showtunes", 00097 [70] = "Trailer", 00098 [71] = "Lo-Fi", 00099 [72] = "Tribal", 00100 [73] = "Acid Punk", 00101 [74] = "Acid Jazz", 00102 [75] = "Polka", 00103 [76] = "Retro", 00104 [77] = "Musical", 00105 [78] = "Rock & Roll", 00106 [79] = "Hard Rock", 00107 [80] = "Folk", 00108 [81] = "Folk-Rock", 00109 [82] = "National Folk", 00110 [83] = "Swing", 00111 [84] = "Fast Fusion", 00112 [85] = "Bebob", 00113 [86] = "Latin", 00114 [87] = "Revival", 00115 [88] = "Celtic", 00116 [89] = "Bluegrass", 00117 [90] = "Avantgarde", 00118 [91] = "Gothic Rock", 00119 [92] = "Progressive Rock", 00120 [93] = "Psychedelic Rock", 00121 [94] = "Symphonic Rock", 00122 [95] = "Slow Rock", 00123 [96] = "Big Band", 00124 [97] = "Chorus", 00125 [98] = "Easy Listening", 00126 [99] = "Acoustic", 00127 [100] = "Humour", 00128 [101] = "Speech", 00129 [102] = "Chanson", 00130 [103] = "Opera", 00131 [104] = "Chamber Music", 00132 [105] = "Sonata", 00133 [106] = "Symphony", 00134 [107] = "Booty Bass", 00135 [108] = "Primus", 00136 [109] = "Porn Groove", 00137 [110] = "Satire", 00138 [111] = "Slow Jam", 00139 [112] = "Club", 00140 [113] = "Tango", 00141 [114] = "Samba", 00142 [115] = "Folklore", 00143 [116] = "Ballad", 00144 [117] = "Power Ballad", 00145 [118] = "Rhythmic Soul", 00146 [119] = "Freestyle", 00147 [120] = "Duet", 00148 [121] = "Punk Rock", 00149 [122] = "Drum Solo", 00150 [123] = "A capella", 00151 [124] = "Euro-House", 00152 [125] = "Dance Hall", 00153 [126] = "Goa", 00154 [127] = "Drum & Bass", 00155 [128] = "Club-House", 00156 [129] = "Hardcore", 00157 [130] = "Terror", 00158 [131] = "Indie", 00159 [132] = "BritPop", 00160 [133] = "Negerpunk", 00161 [134] = "Polsk Punk", 00162 [135] = "Beat", 00163 [136] = "Christian Gangsta", 00164 [137] = "Heavy Metal", 00165 [138] = "Black Metal", 00166 [139] = "Crossover", 00167 [140] = "Contemporary Christian", 00168 [141] = "Christian Rock", 00169 [142] = "Merengue", 00170 [143] = "Salsa", 00171 [144] = "Thrash Metal", 00172 [145] = "Anime", 00173 [146] = "JPop", 00174 [147] = "SynthPop", 00175 }; 00176 00177 static void get_string(AVFormatContext *s, const char *key, 00178 const uint8_t *buf, int buf_size) 00179 { 00180 int i, c; 00181 char *q, str[512]; 00182 00183 q = str; 00184 for(i = 0; i < buf_size; i++) { 00185 c = buf[i]; 00186 if (c == '\0') 00187 break; 00188 if ((q - str) >= sizeof(str) - 1) 00189 break; 00190 *q++ = c; 00191 } 00192 *q = '\0'; 00193 00194 if (*str) 00195 av_dict_set(&s->metadata, key, str, 0); 00196 } 00197 00203 static int parse_tag(AVFormatContext *s, const uint8_t *buf) 00204 { 00205 char str[5]; 00206 int genre; 00207 00208 if (!(buf[0] == 'T' && 00209 buf[1] == 'A' && 00210 buf[2] == 'G')) 00211 return -1; 00212 get_string(s, "title", buf + 3, 30); 00213 get_string(s, "artist", buf + 33, 30); 00214 get_string(s, "album", buf + 63, 30); 00215 get_string(s, "date", buf + 93, 4); 00216 get_string(s, "comment", buf + 97, 30); 00217 if (buf[125] == 0 && buf[126] != 0) { 00218 snprintf(str, sizeof(str), "%d", buf[126]); 00219 av_dict_set(&s->metadata, "track", str, 0); 00220 } 00221 genre = buf[127]; 00222 if (genre <= ID3v1_GENRE_MAX) 00223 av_dict_set(&s->metadata, "genre", ff_id3v1_genre_str[genre], 0); 00224 return 0; 00225 } 00226 00227 void ff_id3v1_read(AVFormatContext *s) 00228 { 00229 int ret; 00230 uint8_t buf[ID3v1_TAG_SIZE]; 00231 int64_t filesize, position = avio_tell(s->pb); 00232 00233 if (s->pb->seekable) { 00234 /* XXX: change that */ 00235 filesize = avio_size(s->pb); 00236 if (filesize > 128) { 00237 avio_seek(s->pb, filesize - 128, SEEK_SET); 00238 ret = avio_read(s->pb, buf, ID3v1_TAG_SIZE); 00239 if (ret == ID3v1_TAG_SIZE) { 00240 parse_tag(s, buf); 00241 } 00242 avio_seek(s->pb, position, SEEK_SET); 00243 } 00244 } 00245 }