1//========================================================================= 2// FILENAME : tagutils-mp3.c 3// DESCRIPTION : MP3 metadata reader 4//========================================================================= 5// Copyright (c) 2008- NETGEAR, Inc. All Rights Reserved. 6//========================================================================= 7 8/* 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24/* 25 * This file is derived from mt-daap project. 26 */ 27 28static int 29_get_mp3tags(char *file, struct song_metadata *psong) 30{ 31 struct id3_file *pid3file; 32 struct id3_tag *pid3tag; 33 struct id3_frame *pid3frame; 34 int err; 35 int index; 36 int used; 37 unsigned char *utf8_text; 38 int genre = WINAMP_GENRE_UNKNOWN; 39 int have_utf8; 40 int have_text; 41 id3_ucs4_t const *native_text; 42 char *tmp; 43 int got_numeric_genre; 44 id3_byte_t const *image; 45 id3_length_t image_size = 0; 46 47 pid3file = id3_file_open(file, ID3_FILE_MODE_READONLY); 48 if(!pid3file) 49 { 50 DPRINTF(E_ERROR, L_SCANNER, "Cannot open %s\n", file); 51 return -1; 52 } 53 54 pid3tag = id3_file_tag(pid3file); 55 56 if(!pid3tag) 57 { 58 err = errno; 59 id3_file_close(pid3file); 60 errno = err; 61 DPRINTF(E_WARN, L_SCANNER, "Cannot get ID3 tag for %s\n", file); 62 return -1; 63 } 64 65 index = 0; 66 while((pid3frame = id3_tag_findframe(pid3tag, "", index))) 67 { 68 used = 0; 69 utf8_text = NULL; 70 native_text = NULL; 71 have_utf8 = 0; 72 have_text = 0; 73 74 if(!strcmp(pid3frame->id, "YTCP")) /* for id3v2.2 */ 75 { 76 psong->compilation = 1; 77 DPRINTF(E_DEBUG, L_SCANNER, "Compilation: %d [%s]\n", psong->compilation, basename(file)); 78 } 79 else if(!strcmp(pid3frame->id, "APIC") && !image_size) 80 { 81 if( (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpeg") == 0) || 82 (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "jpeg") == 0) ) 83 { 84 image = id3_field_getbinarydata(&pid3frame->fields[4], &image_size); 85 if( image_size ) 86 { 87 psong->image = malloc(image_size); 88 memcpy(psong->image, image, image_size); 89 psong->image_size = image_size; 90 //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Found thumbnail: %d\n", psong->image_size); 91 } 92 } 93 } 94 95 if(((pid3frame->id[0] == 'T') || (strcmp(pid3frame->id, "COMM") == 0)) && 96 (id3_field_getnstrings(&pid3frame->fields[1]))) 97 have_text = 1; 98 99 if(have_text) 100 { 101 native_text = id3_field_getstrings(&pid3frame->fields[1], 0); 102 103 if(native_text) 104 { 105 have_utf8 = 1; 106 if(lang_index >= 0) 107 utf8_text = _get_utf8_text(native_text); // through iconv 108 else 109 utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); 110 111 if(!strcmp(pid3frame->id, "TIT2")) 112 { 113 used = 1; 114 psong->title = (char*)utf8_text; 115 } 116 else if(!strcmp(pid3frame->id, "TPE1")) 117 { 118 used = 1; 119 psong->contributor[ROLE_ARTIST] = (char*)utf8_text; 120 } 121 else if(!strcmp(pid3frame->id, "TALB")) 122 { 123 used = 1; 124 psong->album = (char*)utf8_text; 125 } 126 else if(!strcmp(pid3frame->id, "TCOM")) 127 { 128 used = 1; 129 psong->contributor[ROLE_COMPOSER] = (char*)utf8_text; 130 } 131 else if(!strcmp(pid3frame->id, "TIT1")) 132 { 133 used = 1; 134 psong->grouping = (char*)utf8_text; 135 } 136 else if(!strcmp(pid3frame->id, "TPE2")) 137 { 138 used = 1; 139 psong->contributor[ROLE_BAND] = (char*)utf8_text; 140 } 141 else if(!strcmp(pid3frame->id, "TPE3")) 142 { 143 used = 1; 144 psong->contributor[ROLE_CONDUCTOR] = (char*)utf8_text; 145 } 146 else if(!strcmp(pid3frame->id, "TCON")) 147 { 148 used = 1; 149 psong->genre = (char*)utf8_text; 150 got_numeric_genre = 0; 151 if(psong->genre) 152 { 153 if(!strlen(psong->genre)) 154 { 155 genre = WINAMP_GENRE_UNKNOWN; 156 got_numeric_genre = 1; 157 } 158 else if(isdigit(psong->genre[0])) 159 { 160 genre = atoi(psong->genre); 161 got_numeric_genre = 1; 162 } 163 else if((psong->genre[0] == '(') && (isdigit(psong->genre[1]))) 164 { 165 genre = atoi((char*)&psong->genre[1]); 166 got_numeric_genre = 1; 167 } 168 169 if(got_numeric_genre) 170 { 171 if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN)) 172 genre = WINAMP_GENRE_UNKNOWN; 173 free(psong->genre); 174 psong->genre = strdup(winamp_genre[genre]); 175 } 176 } 177 } 178 else if(!strcmp(pid3frame->id, "COMM")) 179 { 180 used = 1; 181 psong->comment = (char*)utf8_text; 182 } 183 else if(!strcmp(pid3frame->id, "TPOS")) 184 { 185 tmp = (char*)utf8_text; 186 strsep(&tmp, "/"); 187 if(tmp) 188 { 189 psong->total_discs = atoi(tmp); 190 } 191 psong->disc = atoi((char*)utf8_text); 192 } 193 else if(!strcmp(pid3frame->id, "TRCK")) 194 { 195 tmp = (char*)utf8_text; 196 strsep(&tmp, "/"); 197 if(tmp) 198 { 199 psong->total_tracks = atoi(tmp); 200 } 201 psong->track = atoi((char*)utf8_text); 202 } 203 else if(!strcmp(pid3frame->id, "TDRC")) 204 { 205 psong->year = atoi((char*)utf8_text); 206 } 207 else if(!strcmp(pid3frame->id, "TLEN")) 208 { 209 psong->song_length = atoi((char*)utf8_text); 210 } 211 else if(!strcmp(pid3frame->id, "TBPM")) 212 { 213 psong->bpm = atoi((char*)utf8_text); 214 } 215 else if(!strcmp(pid3frame->id, "TCMP")) 216 { 217 psong->compilation = (char)atoi((char*)utf8_text); 218 } 219 } 220 } 221 222 // check if text tag 223 if((!used) && (have_utf8) && (utf8_text)) 224 free(utf8_text); 225 226 // v2 COMM 227 if((!strcmp(pid3frame->id, "COMM")) && (pid3frame->nfields == 4)) 228 { 229 native_text = id3_field_getstring(&pid3frame->fields[2]); 230 if(native_text) 231 { 232 utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); 233 if((utf8_text) && (strncasecmp((char*)utf8_text, "iTun", 4) != 0)) 234 { 235 // read comment 236 if(utf8_text) 237 free(utf8_text); 238 239 native_text = id3_field_getfullstring(&pid3frame->fields[3]); 240 if(native_text) 241 { 242 utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); 243 if(utf8_text) 244 { 245 if (psong->comment) 246 free(psong->comment); 247 psong->comment = (char*)utf8_text; 248 } 249 } 250 } 251 else 252 { 253 if(utf8_text) 254 free(utf8_text); 255 } 256 } 257 } 258 259 index++; 260 } 261 262 id3_file_close(pid3file); 263 //DEBUG DPRINTF(E_INFO, L_SCANNER, "Got id3 tag successfully for file=%s\n", file); 264 return 0; 265} 266 267// _decode_mp3_frame 268static int 269_decode_mp3_frame(unsigned char *frame, struct mp3_frameinfo *pfi) 270{ 271 int ver; 272 int layer_index; 273 int sample_index; 274 int bitrate_index; 275 int samplerate_index; 276 277 if((frame[0] != 0xFF) || (frame[1] < 224)) 278 { 279 pfi->is_valid = 0; 280 return -1; 281 } 282 283 ver = (frame[1] & 0x18) >> 3; 284 pfi->layer = 4 - ((frame[1] & 0x6) >> 1); 285 286 layer_index = sample_index = -1; 287 288 switch(ver) 289 { 290 case 0: 291 pfi->mpeg_version = 0x25; // 2.5 292 sample_index = 2; 293 if(pfi->layer == 1) 294 layer_index = 3; 295 if((pfi->layer == 2) || (pfi->layer == 3)) 296 layer_index = 4; 297 break; 298 case 2: 299 pfi->mpeg_version = 0x20; // 2.0 300 sample_index = 1; 301 if(pfi->layer == 1) 302 layer_index = 3; 303 if((pfi->layer == 2) || (pfi->layer == 3)) 304 layer_index = 4; 305 break; 306 case 3: 307 pfi->mpeg_version = 0x10; // 1.0 308 sample_index = 0; 309 if(pfi->layer == 1) 310 layer_index = 0; 311 if(pfi->layer == 2) 312 layer_index = 1; 313 if(pfi->layer == 3) 314 layer_index = 2; 315 break; 316 } 317 318 if((layer_index < 0) || (layer_index > 4)) 319 { 320 pfi->is_valid = 0; 321 return -1; 322 } 323 324 if((sample_index < 0) || (sample_index >= 2)) 325 { 326 pfi->is_valid = 0; 327 return -1; 328 } 329 330 if(pfi->layer == 1) pfi->samples_per_frame = 384; 331 if(pfi->layer == 2) pfi->samples_per_frame = 1152; 332 if(pfi->layer == 3) 333 { 334 if(pfi->mpeg_version == 0x10) 335 pfi->samples_per_frame = 1152; 336 else 337 pfi->samples_per_frame = 576; 338 } 339 340 bitrate_index = (frame[2] & 0xF0) >> 4; 341 samplerate_index = (frame[2] & 0x0C) >> 2; 342 343 if((bitrate_index == 0xF) || (bitrate_index == 0x0)) 344 { 345 pfi->is_valid = 0; 346 return -1; 347 } 348 349 if(samplerate_index == 3) 350 { 351 pfi->is_valid = 0; 352 return -1; 353 } 354 355 356 pfi->bitrate = bitrate_tbl[layer_index][bitrate_index]; 357 pfi->samplerate = sample_rate_tbl[sample_index][samplerate_index]; 358 359 if((frame[3] & 0xC0 >> 6) == 3) 360 pfi->stereo = 0; 361 else 362 pfi->stereo = 1; 363 364 if(frame[2] & 0x02) 365 pfi->padding = 1; 366 else 367 pfi->padding = 0; 368 369 if(pfi->mpeg_version == 0x10) 370 { 371 if(pfi->stereo) 372 pfi->xing_offset = 32; 373 else 374 pfi->xing_offset = 17; 375 } 376 else 377 { 378 if(pfi->stereo) 379 pfi->xing_offset = 17; 380 else 381 pfi->xing_offset = 9; 382 } 383 384 pfi->crc_protected = frame[1] & 0xFE; 385 386 if(pfi->layer == 1) 387 pfi->frame_length = (12 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding) * 4; 388 else 389 pfi->frame_length = 144 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding; 390 391 if((pfi->frame_length > 2880) || (pfi->frame_length <= 0)) 392 { 393 pfi->is_valid = 0; 394 return -1; 395 } 396 397 pfi->is_valid = 1; 398 return 0; 399} 400 401// _mp3_get_average_bitrate 402// read from midle of file, and estimate 403static void _mp3_get_average_bitrate(FILE *infile, struct mp3_frameinfo *pfi, const char *fname) 404{ 405 off_t file_size; 406 unsigned char frame_buffer[2900]; 407 unsigned char header[4]; 408 int index = 0; 409 int found = 0; 410 off_t pos; 411 struct mp3_frameinfo fi; 412 int frame_count = 0; 413 int bitrate_total = 0; 414 415 fseek(infile, 0, SEEK_END); 416 file_size = ftell(infile); 417 418 pos = file_size >> 1; 419 420 /* now, find the first frame */ 421 fseek(infile, pos, SEEK_SET); 422 if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) != sizeof(frame_buffer)) 423 return; 424 425 while(!found) 426 { 427 while((frame_buffer[index] != 0xFF) && (index < (sizeof(frame_buffer) - 4))) 428 index++; 429 430 if(index >= (sizeof(frame_buffer) - 4)) // max mp3 framesize = 2880 431 { 432 DPRINTF(E_DEBUG, L_SCANNER, "Could not find frame for %s\n", basename((char *)fname)); 433 return; 434 } 435 436 if(!_decode_mp3_frame(&frame_buffer[index], &fi)) 437 { 438 /* see if next frame is valid */ 439 fseek(infile, pos + index + fi.frame_length, SEEK_SET); 440 if(fread(header, 1, sizeof(header), infile) != sizeof(header)) 441 { 442 DPRINTF(E_DEBUG, L_SCANNER, "Could not read frame header for %s\n", basename((char *)fname)); 443 return; 444 } 445 446 if(!_decode_mp3_frame(header, &fi)) 447 found = 1; 448 } 449 450 if(!found) 451 index++; 452 } 453 454 pos += index; 455 456 // got first frame 457 while(frame_count < 10) 458 { 459 fseek(infile, pos, SEEK_SET); 460 if(fread(header, 1, sizeof(header), infile) != sizeof(header)) 461 { 462 DPRINTF(E_DEBUG, L_SCANNER, "Could not read frame header for %s\n", basename((char *)fname)); 463 return; 464 } 465 if(_decode_mp3_frame(header, &fi)) 466 { 467 DPRINTF(E_DEBUG, L_SCANNER, "Invalid frame header while averaging %s\n", basename((char *)fname)); 468 return; 469 } 470 471 bitrate_total += fi.bitrate; 472 frame_count++; 473 pos += fi.frame_length; 474 } 475 476 pfi->bitrate = bitrate_total / frame_count; 477 478 return; 479} 480 481// _mp3_get_frame_count 482// do brute scan 483static void __attribute__((unused)) 484_mp3_get_frame_count(FILE *infile, struct mp3_frameinfo *pfi) 485{ 486 int pos; 487 int frames = 0; 488 unsigned char frame_buffer[4]; 489 struct mp3_frameinfo fi; 490 off_t file_size; 491 int err = 0; 492 int cbr = 1; 493 int last_bitrate = 0; 494 495 fseek(infile, 0, SEEK_END); 496 file_size = ftell(infile); 497 498 pos = pfi->frame_offset; 499 500 while(1) 501 { 502 err = 1; 503 504 fseek(infile, pos, SEEK_SET); 505 if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) == sizeof(frame_buffer)) 506 { 507 // valid frame? 508 if(!_decode_mp3_frame(frame_buffer, &fi)) 509 { 510 frames++; 511 pos += fi.frame_length; 512 err = 0; 513 514 if((last_bitrate) && (fi.bitrate != last_bitrate)) 515 cbr = 0; 516 last_bitrate = fi.bitrate; 517 518 // no sense to scan cbr 519 if(cbr && (frames > 100)) 520 { 521 DPRINTF(E_DEBUG, L_SCANNER, "File appears to be CBR... quitting frame _mp3_get_frame_count()\n"); 522 return; 523 } 524 } 525 } 526 527 if(err) 528 { 529 if(pos > (file_size - 4096)) 530 { 531 pfi->number_of_frames = frames; 532 return; 533 } 534 else 535 { 536 DPRINTF(E_ERROR, L_SCANNER, "Frame count aborted on error. Pos=%d, Count=%d\n", 537 pos, frames); 538 return; 539 } 540 } 541 } 542} 543 544// _get_mp3fileinfo 545static int 546_get_mp3fileinfo(char *file, struct song_metadata *psong) 547{ 548 FILE *infile; 549 struct id3header *pid3; 550 struct mp3_frameinfo fi; 551 unsigned int size = 0; 552 unsigned int n_read; 553 off_t fp_size = 0; 554 off_t file_size; 555 unsigned char buffer[1024]; 556 int index; 557 558 int xing_flags; 559 int found; 560 561 int first_check = 0; 562 char frame_buffer[4]; 563 564 char id3v1taghdr[4]; 565 566 if(!(infile = fopen(file, "rb"))) 567 { 568 DPRINTF(E_ERROR, L_SCANNER, "Could not open %s for reading\n", file); 569 return -1; 570 } 571 572 memset((void*)&fi, 0, sizeof(fi)); 573 574 fseek(infile, 0, SEEK_END); 575 file_size = ftell(infile); 576 fseek(infile, 0, SEEK_SET); 577 578 if(fread(buffer, 1, sizeof(buffer), infile) != sizeof(buffer)) 579 { 580 if(ferror(infile)) 581 { 582 DPRINTF(E_ERROR, L_SCANNER, "Error reading: %s [%s]\n", strerror(errno), file); 583 } 584 else 585 { 586 DPRINTF(E_WARN, L_SCANNER, "File too small. Probably corrupted. [%s]\n", file); 587 } 588 fclose(infile); 589 return -1; 590 } 591 592 pid3 = (struct id3header*)buffer; 593 594 found = 0; 595 fp_size = 0; 596 597 if(strncmp((char*)pid3->id, "ID3", 3) == 0) 598 { 599 char tagversion[16]; 600 601 /* found an ID3 header... */ 602 size = (pid3->size[0] << 21 | pid3->size[1] << 14 | 603 pid3->size[2] << 7 | pid3->size[3]); 604 fp_size = size + sizeof(struct id3header); 605 first_check = 1; 606 607 snprintf(tagversion, sizeof(tagversion), "ID3v2.%d.%d", 608 pid3->version[0], pid3->version[1]); 609 psong->tagversion = strdup(tagversion); 610 } 611 612 index = 0; 613 614 /* Here we start the brute-force header seeking. Sure wish there 615 * weren't so many crappy mp3 files out there 616 */ 617 618 while(!found) 619 { 620 fseek(infile, fp_size, SEEK_SET); 621 if((n_read = fread(buffer, 1, sizeof(buffer), infile)) < 4) // at least mp3 frame header size (i.e. 4 bytes) 622 { 623 fclose(infile); 624 return 0; 625 } 626 627 index = 0; 628 while(!found) 629 { 630 while((buffer[index] != 0xFF) && (index < (n_read - 50))) 631 index++; 632 633 if((first_check) && (index)) 634 { 635 fp_size = 0; 636 first_check = 0; 637 if(n_read < sizeof(buffer)) 638 { 639 fclose(infile); 640 return 0; 641 } 642 break; 643 } 644 645 if(index > (n_read - 50)) 646 { 647 fp_size += index; 648 if(n_read < sizeof(buffer)) 649 { 650 fclose(infile); 651 return 0; 652 } 653 break; 654 } 655 656 if(!_decode_mp3_frame(&buffer[index], &fi)) 657 { 658 if(!strncasecmp((char*)&buffer[index + fi.xing_offset + 4], "XING", 4)) 659 { 660 /* no need to check further... if there is a xing header there, 661 * this is definately a valid frame */ 662 found = 1; 663 fp_size += index; 664 } 665 else 666 { 667 /* No Xing... check for next frame to validate current fram is correct */ 668 fseek(infile, fp_size + index + fi.frame_length, SEEK_SET); 669 if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) == sizeof(frame_buffer)) 670 { 671 if(!_decode_mp3_frame((unsigned char*)frame_buffer, &fi)) 672 { 673 found = 1; 674 fp_size += index; 675 } 676 } 677 else 678 { 679 DPRINTF(E_ERROR, L_SCANNER, "Could not read frame header: %s\n", file); 680 fclose(infile); 681 return 0; 682 } 683 684 if(!found) 685 { 686 // cannot find second frame. Song may be too short. So assume first frame is valid. 687 found = 1; 688 fp_size += index; 689 } 690 } 691 } 692 693 if(!found) 694 { 695 index++; 696 if(first_check) 697 { 698 DPRINTF(E_INFO, L_SCANNER, "Bad header... dropping back for full frame search [%s]\n", psong->path); 699 first_check = 0; 700 fp_size = 0; 701 break; 702 } 703 } 704 } 705 } 706 707 fi.frame_offset = fp_size; 708 709 psong->audio_offset = fp_size; 710 psong->audio_size = file_size - fp_size; 711 // check if last 128 bytes is ID3v1.0 ID3v1.1 tag 712 fseek(infile, file_size - 128, SEEK_SET); 713 if(fread(id3v1taghdr, 1, 4, infile) == 4) 714 { 715 if(id3v1taghdr[0] == 'T' && id3v1taghdr[1] == 'A' && id3v1taghdr[2] == 'G') 716 { 717 psong->audio_size -= 128; 718 } 719 } 720 721 if(_decode_mp3_frame(&buffer[index], &fi)) 722 { 723 fclose(infile); 724 DPRINTF(E_ERROR, L_SCANNER, "Could not find sync frame: %s\n", file); 725 return 0; 726 } 727 728 /* now check for an XING header */ 729 psong->vbr_scale = -1; 730 if(!strncasecmp((char*)&buffer[index + fi.xing_offset + 4], "XING", 4)) 731 { 732 xing_flags = *((int*)&buffer[index + fi.xing_offset + 4 + 4]); 733 xing_flags = ntohs(xing_flags); 734 psong->vbr_scale = 78; 735 736 if(xing_flags & 0x1) 737 { 738 /* Frames field is valid... */ 739 fi.number_of_frames = *((int*)&buffer[index + fi.xing_offset + 4 + 8]); 740 fi.number_of_frames = ntohs(fi.number_of_frames); 741 } 742 } 743 744 if((fi.number_of_frames == 0) && (!psong->song_length)) 745 { 746 _mp3_get_average_bitrate(infile, &fi, file); 747 } 748 749 psong->bitrate = fi.bitrate * 1000; 750 psong->samplerate = fi.samplerate; 751 752 if(!psong->song_length) 753 { 754 if(fi.number_of_frames) 755 { 756 psong->song_length = (int)((double)(fi.number_of_frames * fi.samples_per_frame * 1000.) / 757 (double)fi.samplerate); 758 psong->vbr_scale = 78; 759 } 760 else 761 { 762 psong->song_length = (int)((double)(file_size - fp_size) * 8. / 763 (double)fi.bitrate); 764 } 765 } 766 psong->channels = fi.stereo ? 2 : 1; 767 768 fclose(infile); 769 //DEBUG DPRINTF(E_INFO, L_SCANNER, "Got fileinfo successfully for file=%s song_length=%d\n", file, psong->song_length); 770 771 psong->blockalignment = 1; 772 asprintf(&(psong->dlna_pn), "MP3"); 773 774 return 0; 775} 776