mp3_extractor.c (12255B)
1 /* 2 This file is part of libextractor. 3 Copyright (C) 2002, 2003, 2004, 2006, 2009 Vidyut Samanta and Christian Grothoff 4 5 libextractor is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 2, or (at your 8 option) any later version. 9 10 libextractor is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with libextractor; see the file COPYING. If not, write to the 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 20 21 Some of this code is based on AVInfo 1.0 alpha 11 22 (c) George Shuklin, gs]AT[shounen.ru, 2002-2004 23 http://shounen.ru/soft/avinfo/ 24 25 */ 26 27 #define DEBUG_EXTRACT_MP3 0 28 29 #include "platform.h" 30 #include "extractor.h" 31 #include "convert.h" 32 #include <string.h> 33 #include <stdio.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <unistd.h> 37 #include <stdlib.h> 38 39 #include "extractor_plugins.h" 40 41 #include "le_architecture.h" 42 43 #define LARGEST_FRAME_SIZE 8065 44 45 enum 46 { MPEG_ERR = 0, MPEG_V1 = 1, MPEG_V2 = 2, MPEG_V25 = 3 }; 47 48 enum 49 { LAYER_ERR = 0, LAYER_1 = 1, LAYER_2 = 2, LAYER_3 = 3 }; 50 51 #define MPA_SYNC_MASK ((unsigned int) 0xFFE00000) 52 #if __BYTE_ORDER == __BIG_ENDIAN 53 #define MPA_SYNC_MASK_MEM ((unsigned int) 0xFFE00000) 54 #else 55 #define MPA_SYNC_MASK_MEM ((unsigned int) 0x0000E0FF) 56 #endif 57 #define MPA_LAST_SYNC_BIT_MASK ((unsigned int) 0x00100000) 58 #define MPA_VERSION_MASK ((unsigned int) 0x00080000) 59 #define MPA_LAYER_MASK ((unsigned int) 0x3) 60 #define MPA_LAYER_SHIFT 17 61 #define MPA_BITRATE_MASK ((unsigned int) 0xF) 62 #define MPA_BITRATE_SHIFT 12 63 #define MPA_FREQ_MASK ((unsigned int) 0x3) 64 #define MPA_FREQ_SHIFT 10 65 #define MPA_CHMODE_MASK ((unsigned int) 0x3) 66 #define MPA_CHMODE_SHIFT 6 67 #define MPA_PADDING_SHIFT 9 68 #define MPA_COPYRIGHT_SHIFT 3 69 #define MPA_ORIGINAL_SHIFT 2 70 71 static const unsigned int bitrate_table[16][6] = { 72 {0, 0, 0, 0, 0, 0}, 73 {32, 32, 32, 32, 8, 8}, 74 {64, 48, 40, 48, 16, 16}, 75 {96, 56, 48, 56, 24, 24}, 76 {128, 64, 56, 64, 32, 32}, 77 {160, 80, 64, 80, 40, 40}, 78 {192, 96, 80, 96, 48, 48}, 79 {224, 112, 96, 112, 56, 56}, 80 {256, 128, 112, 128, 64, 64}, 81 {288, 160, 128, 144, 80, 80}, 82 {320, 192, 160, 160, 96, 96}, 83 {352, 224, 192, 176, 112, 112}, 84 {384, 256, 224, 192, 128, 128}, 85 {416, 320, 256, 224, 144, 144}, 86 {448, 384, 320, 256, 160, 160}, 87 {-1, -1, -1, -1, -1, -1} 88 }; 89 static const int freq_table[4][3] = { 90 {44100, 22050, 11025}, 91 {48000, 24000, 12000}, 92 {32000, 16000, 8000} 93 }; 94 static const char *const channel_modes[4] = { 95 gettext_noop ("stereo"), 96 gettext_noop ("joint stereo"), 97 gettext_noop ("dual channel"), 98 gettext_noop ("mono") 99 }; 100 static const char *const mpeg_versions[3] = { 101 gettext_noop ("MPEG-1"), 102 gettext_noop ("MPEG-2"), 103 gettext_noop ("MPEG-2.5") 104 }; 105 static const char *const layer_names[3] = { 106 gettext_noop ("Layer I"), 107 gettext_noop ("Layer II"), 108 gettext_noop ("Layer III") 109 }; 110 111 112 #define OK 0 113 #define SYSERR 1 114 #define INVALID_ID3 2 115 116 #define ADDR(s,t) do { if (0 != proc (proc_cls, "mp3", t, \ 117 EXTRACTOR_METAFORMAT_UTF8, "text/plain", \ 118 s, strlen (s) + 1)) return 1; \ 119 } while (0) 120 121 struct mp3_state 122 { 123 int state; 124 125 uint32_t header; 126 int sample_rate; 127 char mpeg_ver; 128 char layer; 129 char vbr_flag; 130 int ch; 131 char copyright_flag; 132 char original_flag; 133 int avg_bps; 134 int bitrate; 135 136 int64_t number_of_frames; 137 int64_t number_of_valid_frames; 138 }; 139 140 enum MP3State 141 { 142 MP3_LOOKING_FOR_FRAME = 0, 143 MP3_READING_FRAME = 1, 144 }; 145 146 static struct mp3_state * 147 EXTRACTOR_mp3_init_state_method () 148 { 149 struct mp3_state *state; 150 state = malloc (sizeof (struct mp3_state)); 151 if (state == NULL) 152 return NULL; 153 state->header = 0; 154 state->sample_rate = 0; 155 state->number_of_frames = 0; 156 state->number_of_valid_frames = 0; 157 state->mpeg_ver = 0; 158 state->layer = 0; 159 state->vbr_flag = 0; 160 state->ch = 0; 161 state->copyright_flag = 0; 162 state->original_flag = 0; 163 state->avg_bps = 0; 164 state->bitrate = 0; 165 state->state = 0; 166 return state; 167 } 168 169 170 static int 171 EXTRACTOR_mp3_discard_state_method (struct mp3_state *state) 172 { 173 if (state != NULL) 174 { 175 free (state); 176 } 177 return 1; 178 } 179 180 181 static int 182 calculate_frame_statistics_and_maybe_report_it (struct 183 EXTRACTOR_PluginList *plugin, 184 struct mp3_state *state, 185 EXTRACTOR_MetaDataProcessor proc, 186 void *proc_cls) 187 { 188 int length; 189 char format[512]; 190 191 if ((((double) state->number_of_valid_frames 192 / (double) state->number_of_frames) < 0.8) || 193 (state->number_of_valid_frames <= 2) ) 194 /* Unlikely to be an mp3 file */ 195 return 0; 196 ADDR ("audio/mpeg", EXTRACTOR_METATYPE_MIMETYPE); 197 state->avg_bps = state->avg_bps / state->number_of_valid_frames; 198 if (state->sample_rate > 0) 199 length = 1152 * state->number_of_valid_frames / state->sample_rate; 200 else if ((state->avg_bps > 0) || (state->bitrate > 0)) 201 length = plugin->fsize / (state->avg_bps ? state->avg_bps : state->bitrate ? 202 state->bitrate : 1) / 125; 203 else 204 length = 0; 205 206 ADDR (mpeg_versions[state->mpeg_ver - 1], EXTRACTOR_METATYPE_FORMAT_VERSION); 207 snprintf (format, 208 sizeof (format), 209 "%s %s audio, %d kbps (%s), %d Hz, %s, %s, %s", 210 mpeg_versions[state->mpeg_ver - 1], 211 layer_names[state->layer - 1], 212 state->avg_bps, 213 state->vbr_flag ? _ ("VBR") : _ ("CBR"), 214 state->sample_rate, 215 channel_modes[state->ch], 216 state->copyright_flag ? _ ("copyright") : _ ("no copyright"), 217 state->original_flag ? _ ("original") : _ ("copy") ); 218 219 ADDR (format, EXTRACTOR_METATYPE_RESOURCE_TYPE); 220 snprintf (format, 221 sizeof (format), "%dm%02d", 222 length / 60, length % 60); 223 ADDR (format, EXTRACTOR_METATYPE_DURATION); 224 return 0; 225 } 226 227 228 int 229 EXTRACTOR_mp3_extract_method (struct EXTRACTOR_PluginList *plugin, 230 EXTRACTOR_MetaDataProcessor proc, 231 void *proc_cls) 232 { 233 int64_t offset = 0; 234 int64_t round_offset; 235 int64_t read_result; 236 int64_t i; 237 unsigned char *data; 238 struct mp3_state *state; 239 240 int start_anew = 0; 241 242 char mpeg_ver = 0; 243 char layer = 0; 244 int idx_num = 0; 245 int bitrate = 0; /*used for each frame */ 246 int copyright_flag = 0; 247 int original_flag = 0; 248 int sample_rate = 0; 249 int ch = 0; 250 int frame_size; 251 252 if (plugin == NULL) 253 return 1; 254 255 state = EXTRACTOR_mp3_init_state_method (); 256 if (state == NULL) 257 return 1; 258 259 while (1) 260 { 261 switch (state->state) 262 { 263 case MP3_LOOKING_FOR_FRAME: 264 /* Look for a frame header */ 265 round_offset = offset = pl_get_pos (plugin); 266 while (1) 267 { 268 pl_seek (plugin, offset, SEEK_SET); 269 read_result = pl_read (plugin, &data, 1024 * 1024); 270 if (read_result < 4) 271 { 272 calculate_frame_statistics_and_maybe_report_it (plugin, state, proc, 273 proc_cls); 274 return EXTRACTOR_mp3_discard_state_method (state); 275 } 276 for (i = 0; i + 3 < read_result; i++) 277 if (((*((uint32_t *) &data[i])) & MPA_SYNC_MASK_MEM) == 278 MPA_SYNC_MASK_MEM) 279 break; 280 if (i + 3 >= 1024 * 1024) 281 offset += read_result - 3; 282 else 283 break; 284 if (offset > round_offset + 31 * 1024 * 1024) 285 { 286 if (((state->number_of_valid_frames > 2) && 287 ( ((double) state->number_of_valid_frames 288 / (double) state->number_of_frames) < 0.8) )) 289 { 290 calculate_frame_statistics_and_maybe_report_it (plugin, state, proc, 291 proc_cls); 292 } 293 return EXTRACTOR_mp3_discard_state_method (state); 294 } 295 } 296 pl_seek (plugin, offset + i, SEEK_SET); 297 if (4 != pl_read (plugin, &data, 4)) 298 { 299 calculate_frame_statistics_and_maybe_report_it (plugin, state, proc, 300 proc_cls); 301 return EXTRACTOR_mp3_discard_state_method (state); 302 } 303 state->header = (data[0] << 24) | (data[1] << 16) 304 | (data[2] << 8) | data[3]; 305 if ((state->header & MPA_SYNC_MASK) == MPA_SYNC_MASK) 306 { 307 state->state = MP3_READING_FRAME; 308 break; 309 } 310 break; 311 case MP3_READING_FRAME: 312 state->number_of_frames += 1; 313 start_anew = 0; 314 switch (state->header & (MPA_LAST_SYNC_BIT_MASK | MPA_VERSION_MASK)) 315 { 316 case (MPA_LAST_SYNC_BIT_MASK | MPA_VERSION_MASK): 317 mpeg_ver = MPEG_V1; 318 break; 319 case (MPA_LAST_SYNC_BIT_MASK): 320 mpeg_ver = MPEG_V2; 321 break; 322 case 0: 323 mpeg_ver = MPEG_V25; 324 break; 325 case (MPA_VERSION_MASK): 326 default: 327 state->state = MP3_LOOKING_FOR_FRAME; 328 offset += 1; 329 start_anew = 1; 330 } 331 if (start_anew) 332 break; 333 switch (state->header & (MPA_LAYER_MASK << MPA_LAYER_SHIFT)) 334 { 335 case (0x1 << MPA_LAYER_SHIFT): 336 layer = LAYER_3; 337 break; 338 case (0x2 << MPA_LAYER_SHIFT): 339 layer = LAYER_2; 340 break; 341 case (0x3 << MPA_LAYER_SHIFT): 342 layer = LAYER_1; 343 break; 344 case 0x0: 345 default: 346 state->state = MP3_LOOKING_FOR_FRAME; 347 offset += 1; 348 start_anew = 1; 349 } 350 if (start_anew) 351 break; 352 if (mpeg_ver < MPEG_V25) 353 idx_num = (mpeg_ver - 1) * 3 + layer - 1; 354 else 355 idx_num = 2 + layer; 356 bitrate = 1000 * bitrate_table[(state->header >> MPA_BITRATE_SHIFT) 357 & MPA_BITRATE_MASK][idx_num]; 358 if (bitrate < 0) 359 { 360 /*error in header */ 361 state->state = MP3_LOOKING_FOR_FRAME; 362 offset += 1; 363 break; 364 } 365 sample_rate = freq_table[(state->header >> MPA_FREQ_SHIFT) 366 & MPA_FREQ_MASK][mpeg_ver - 1]; 367 if (sample_rate <= 0) 368 { 369 /*error in header */ 370 state->state = MP3_LOOKING_FOR_FRAME; 371 offset += 1; 372 break; 373 } 374 ch = ((state->header >> MPA_CHMODE_SHIFT) & MPA_CHMODE_MASK); 375 copyright_flag = (state->header >> MPA_COPYRIGHT_SHIFT) & 0x1; 376 original_flag = (state->header >> MPA_ORIGINAL_SHIFT) & 0x1; 377 if (layer == LAYER_1) 378 frame_size = (12 * bitrate / sample_rate + ((state->header 379 >> MPA_PADDING_SHIFT) 380 & 0x1)) * 4; 381 else 382 frame_size = 144 * bitrate / sample_rate + ((state->header 383 >> MPA_PADDING_SHIFT) 384 & 0x1); 385 if (frame_size < 8) 386 { 387 /*error in header */ 388 state->state = MP3_LOOKING_FOR_FRAME; 389 offset += 1; 390 break; 391 } 392 393 /* Only save data from valid frames in the state */ 394 state->avg_bps += bitrate / 1000; 395 state->sample_rate = sample_rate; 396 state->mpeg_ver = mpeg_ver; 397 state->layer = layer; 398 state->ch = ch; 399 state->copyright_flag = copyright_flag; 400 state->original_flag = original_flag; 401 state->bitrate = bitrate; 402 403 state->number_of_valid_frames += 1; 404 if (state->avg_bps / state->number_of_valid_frames != bitrate / 1000) 405 state->vbr_flag = 1; 406 pl_seek (plugin, frame_size - 4, SEEK_CUR); 407 state->state = MP3_LOOKING_FOR_FRAME; 408 break; 409 } 410 } 411 return 1; 412 } 413 414 415 /* end of mp3_extractor.c */