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, see <http://www.gnu.org/licenses/>. 21 */ 22 23/* 24 * This file is derived from mt-daap project. 25 */ 26 27static int 28_get_mp3tags(char *file, struct song_metadata *psong) 29{ 30 struct id3_file *pid3file; 31 struct id3_tag *pid3tag; 32 struct id3_frame *pid3frame; 33 int err; 34 int index; 35 int used; 36 unsigned char *utf8_text; 37 int genre = WINAMP_GENRE_UNKNOWN; 38 int have_utf8; 39 int have_text; 40 id3_ucs4_t const *native_text; 41 char *tmp; 42 int got_numeric_genre; 43 id3_byte_t const *image; 44 id3_length_t image_size = 0; 45 46 pid3file = id3_file_open(file, ID3_FILE_MODE_READONLY); 47 if(!pid3file) 48 { 49 DPRINTF(E_ERROR, L_SCANNER, "Cannot open %s\n", file); 50 return -1; 51 } 52 53 pid3tag = id3_file_tag(pid3file); 54 55 if(!pid3tag) 56 { 57 err = errno; 58 id3_file_close(pid3file); 59 errno = err; 60 DPRINTF(E_WARN, L_SCANNER, "Cannot get ID3 tag for %s\n", file); 61 return -1; 62 } 63 64 index = 0; 65 while((pid3frame = id3_tag_findframe(pid3tag, "", index))) 66 { 67 used = 0; 68 utf8_text = NULL; 69 native_text = NULL; 70 have_utf8 = 0; 71 have_text = 0; 72 73 if(!strcmp(pid3frame->id, "YTCP")) /* for id3v2.2 */ 74 { 75 psong->compilation = 1; 76 DPRINTF(E_DEBUG, L_SCANNER, "Compilation: %d [%s]\n", psong->compilation, basename(file)); 77 } 78 else if(!strcmp(pid3frame->id, "APIC") && !image_size) 79 { 80 if( (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpeg") == 0) || 81 (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpg") == 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 free(utf8_text); 237 238 native_text = id3_field_getfullstring(&pid3frame->fields[3]); 239 if(native_text) 240 { 241 utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); 242 if(utf8_text) 243 { 244 free(psong->comment); 245 psong->comment = (char*)utf8_text; 246 } 247 } 248 } 249 else 250 { 251 free(utf8_text); 252 } 253 } 254 } 255 256 index++; 257 } 258 259 id3_file_close(pid3file); 260 //DEBUG DPRINTF(E_INFO, L_SCANNER, "Got id3 tag successfully for file=%s\n", file); 261 return 0; 262} 263 264// _decode_mp3_frame 265static int 266_decode_mp3_frame(unsigned char *frame, struct mp3_frameinfo *pfi) 267{ 268 int ver; 269 int layer_index; 270 int sample_index; 271 int bitrate_index; 272 int samplerate_index; 273 274 if((frame[0] != 0xFF) || (frame[1] < 224)) 275 { 276 pfi->is_valid = 0; 277 return -1; 278 } 279 280 ver = (frame[1] & 0x18) >> 3; 281 pfi->layer = 4 - ((frame[1] & 0x6) >> 1); 282 283 layer_index = sample_index = -1; 284 285 switch(ver) 286 { 287 case 0: 288 pfi->mpeg_version = 0x25; // 2.5 289 sample_index = 2; 290 if(pfi->layer == 1) 291 layer_index = 3; 292 if((pfi->layer == 2) || (pfi->layer == 3)) 293 layer_index = 4; 294 break; 295 case 2: 296 pfi->mpeg_version = 0x20; // 2.0 297 sample_index = 1; 298 if(pfi->layer == 1) 299 layer_index = 3; 300 if((pfi->layer == 2) || (pfi->layer == 3)) 301 layer_index = 4; 302 break; 303 case 3: 304 pfi->mpeg_version = 0x10; // 1.0 305 sample_index = 0; 306 if(pfi->layer == 1) 307 layer_index = 0; 308 if(pfi->layer == 2) 309 layer_index = 1; 310 if(pfi->layer == 3) 311 layer_index = 2; 312 break; 313 } 314 315 if((layer_index < 0) || (layer_index > 4)) 316 { 317 pfi->is_valid = 0; 318 return -1; 319 } 320 321 if((sample_index < 0) || (sample_index >= 2)) 322 { 323 pfi->is_valid = 0; 324 return -1; 325 } 326 327 if(pfi->layer == 1) pfi->samples_per_frame = 384; 328 if(pfi->layer == 2) pfi->samples_per_frame = 1152; 329 if(pfi->layer == 3) 330 { 331 if(pfi->mpeg_version == 0x10) 332 pfi->samples_per_frame = 1152; 333 else 334 pfi->samples_per_frame = 576; 335 } 336 337 bitrate_index = (frame[2] & 0xF0) >> 4; 338 samplerate_index = (frame[2] & 0x0C) >> 2; 339 340 if((bitrate_index == 0xF) || (bitrate_index == 0x0)) 341 { 342 pfi->is_valid = 0; 343 return -1; 344 } 345 346 if(samplerate_index == 3) 347 { 348 pfi->is_valid = 0; 349 return -1; 350 } 351 352 353 pfi->bitrate = bitrate_tbl[layer_index][bitrate_index]; 354 pfi->samplerate = sample_rate_tbl[sample_index][samplerate_index]; 355 356 if((frame[3] & 0xC0 >> 6) == 3) 357 pfi->stereo = 0; 358 else 359 pfi->stereo = 1; 360 361 if(frame[2] & 0x02) 362 pfi->padding = 1; 363 else 364 pfi->padding = 0; 365 366 if(pfi->mpeg_version == 0x10) 367 { 368 if(pfi->stereo) 369 pfi->xing_offset = 32; 370 else 371 pfi->xing_offset = 17; 372 } 373 else 374 { 375 if(pfi->stereo) 376 pfi->xing_offset = 17; 377 else 378 pfi->xing_offset = 9; 379 } 380 381 pfi->crc_protected = frame[1] & 0xFE; 382 383 if(pfi->layer == 1) 384 pfi->frame_length = (12 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding) * 4; 385 else 386 pfi->frame_length = 144 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding; 387 388 if((pfi->frame_length > 2880) || (pfi->frame_length <= 0)) 389 { 390 pfi->is_valid = 0; 391 return -1; 392 } 393 394 pfi->is_valid = 1; 395 return 0; 396} 397 398// _mp3_get_average_bitrate 399// read from midle of file, and estimate 400static void _mp3_get_average_bitrate(FILE *infile, struct mp3_frameinfo *pfi, const char *fname) 401{ 402 off_t file_size; 403 unsigned char frame_buffer[2900]; 404 unsigned char header[4]; 405 int index = 0; 406 int found = 0; 407 off_t pos; 408 struct mp3_frameinfo fi; 409 int frame_count = 0; 410 int bitrate_total = 0; 411 412 fseek(infile, 0, SEEK_END); 413 file_size = ftell(infile); 414 415 pos = file_size >> 1; 416 417 /* now, find the first frame */ 418 fseek(infile, pos, SEEK_SET); 419 if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) != sizeof(frame_buffer)) 420 return; 421 422 while(!found) 423 { 424 while((frame_buffer[index] != 0xFF) && (index < (sizeof(frame_buffer) - 4))) 425 index++; 426 427 if(index >= (sizeof(frame_buffer) - 4)) // max mp3 framesize = 2880 428 { 429 DPRINTF(E_DEBUG, L_SCANNER, "Could not find frame for %s\n", basename((char *)fname)); 430 return; 431 } 432 433 if(!_decode_mp3_frame(&frame_buffer[index], &fi)) 434 { 435 /* see if next frame is valid */ 436 fseek(infile, pos + index + fi.frame_length, SEEK_SET); 437 if(fread(header, 1, sizeof(header), infile) != sizeof(header)) 438 { 439 DPRINTF(E_DEBUG, L_SCANNER, "Could not read frame header for %s\n", basename((char *)fname)); 440 return; 441 } 442 443 if(!_decode_mp3_frame(header, &fi)) 444 found = 1; 445 } 446 447 if(!found) 448 index++; 449 } 450 451 pos += index; 452 453 // got first frame 454 while(frame_count < 10) 455 { 456 fseek(infile, pos, SEEK_SET); 457 if(fread(header, 1, sizeof(header), infile) != sizeof(header)) 458 { 459 DPRINTF(E_DEBUG, L_SCANNER, "Could not read frame header for %s\n", basename((char *)fname)); 460 return; 461 } 462 if(_decode_mp3_frame(header, &fi)) 463 { 464 DPRINTF(E_DEBUG, L_SCANNER, "Invalid frame header while averaging %s\n", basename((char *)fname)); 465 return; 466 } 467 468 bitrate_total += fi.bitrate; 469 frame_count++; 470 pos += fi.frame_length; 471 } 472 473 pfi->bitrate = bitrate_total / frame_count; 474 475 return; 476} 477 478// _mp3_get_frame_count 479// do brute scan 480static void __attribute__((unused)) 481_mp3_get_frame_count(FILE *infile, struct mp3_frameinfo *pfi) 482{ 483 int pos; 484 int frames = 0; 485 unsigned char frame_buffer[4]; 486 struct mp3_frameinfo fi; 487 off_t file_size; 488 int err = 0; 489 int cbr = 1; 490 int last_bitrate = 0; 491 492 fseek(infile, 0, SEEK_END); 493 file_size = ftell(infile); 494 495 pos = pfi->frame_offset; 496 497 while(1) 498 { 499 err = 1; 500 501 fseek(infile, pos, SEEK_SET); 502 if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) == sizeof(frame_buffer)) 503 { 504 // valid frame? 505 if(!_decode_mp3_frame(frame_buffer, &fi)) 506 { 507 frames++; 508 pos += fi.frame_length; 509 err = 0; 510 511 if((last_bitrate) && (fi.bitrate != last_bitrate)) 512 cbr = 0; 513 last_bitrate = fi.bitrate; 514 515 // no sense to scan cbr 516 if(cbr && (frames > 100)) 517 { 518 DPRINTF(E_DEBUG, L_SCANNER, "File appears to be CBR... quitting frame _mp3_get_frame_count()\n"); 519 return; 520 } 521 } 522 } 523 524 if(err) 525 { 526 if(pos > (file_size - 4096)) 527 { 528 pfi->number_of_frames = frames; 529 return; 530 } 531 else 532 { 533 DPRINTF(E_ERROR, L_SCANNER, "Frame count aborted on error. Pos=%d, Count=%d\n", 534 pos, frames); 535 return; 536 } 537 } 538 } 539} 540 541// _get_mp3fileinfo 542static int 543_get_mp3fileinfo(char *file, struct song_metadata *psong) 544{ 545 FILE *infile; 546 struct id3header *pid3; 547 struct mp3_frameinfo fi; 548 unsigned int size = 0; 549 unsigned int n_read; 550 off_t fp_size = 0; 551 off_t file_size; 552 unsigned char buffer[1024]; 553 int index; 554 555 int xing_flags; 556 int found; 557 558 int first_check = 0; 559 char frame_buffer[4]; 560 561 char id3v1taghdr[4]; 562 563 if(!(infile = fopen(file, "rb"))) 564 { 565 DPRINTF(E_ERROR, L_SCANNER, "Could not open %s for reading\n", file); 566 return -1; 567 } 568 569 memset((void*)&fi, 0, sizeof(fi)); 570 571 fseek(infile, 0, SEEK_END); 572 file_size = ftell(infile); 573 fseek(infile, 0, SEEK_SET); 574 575 if(fread(buffer, 1, sizeof(buffer), infile) != sizeof(buffer)) 576 { 577 if(ferror(infile)) 578 { 579 DPRINTF(E_ERROR, L_SCANNER, "Error reading: %s [%s]\n", strerror(errno), file); 580 } 581 else 582 { 583 DPRINTF(E_WARN, L_SCANNER, "File too small. Probably corrupted. [%s]\n", file); 584 } 585 fclose(infile); 586 return -1; 587 } 588 589 pid3 = (struct id3header*)buffer; 590 591 found = 0; 592 fp_size = 0; 593 594 if(strncmp((char*)pid3->id, "ID3", 3) == 0) 595 { 596 char tagversion[16]; 597 598 /* found an ID3 header... */ 599 size = (pid3->size[0] << 21 | pid3->size[1] << 14 | 600 pid3->size[2] << 7 | pid3->size[3]); 601 fp_size = size + sizeof(struct id3header); 602 first_check = 1; 603 604 snprintf(tagversion, sizeof(tagversion), "ID3v2.%d.%d", 605 pid3->version[0], pid3->version[1]); 606 psong->tagversion = strdup(tagversion); 607 } 608 609 index = 0; 610 611 /* Here we start the brute-force header seeking. Sure wish there 612 * weren't so many crappy mp3 files out there 613 */ 614 615 while(!found) 616 { 617 fseek(infile, fp_size, SEEK_SET); 618 if((n_read = fread(buffer, 1, sizeof(buffer), infile)) < 4) // at least mp3 frame header size (i.e. 4 bytes) 619 { 620 fclose(infile); 621 return 0; 622 } 623 624 index = 0; 625 while(!found) 626 { 627 while((buffer[index] != 0xFF) && (index < (n_read - 50))) 628 index++; 629 630 if((first_check) && (index)) 631 { 632 fp_size = 0; 633 first_check = 0; 634 if(n_read < sizeof(buffer)) 635 { 636 fclose(infile); 637 return 0; 638 } 639 break; 640 } 641 642 if(index > (n_read - 50)) 643 { 644 fp_size += index; 645 if(n_read < sizeof(buffer)) 646 { 647 fclose(infile); 648 return 0; 649 } 650 break; 651 } 652 653 if(!_decode_mp3_frame(&buffer[index], &fi)) 654 { 655 if(!strncasecmp((char*)&buffer[index + fi.xing_offset + 4], "XING", 4)) 656 { 657 /* no need to check further... if there is a xing header there, 658 * this is definately a valid frame */ 659 found = 1; 660 fp_size += index; 661 } 662 else 663 { 664 /* No Xing... check for next frame to validate current fram is correct */ 665 fseek(infile, fp_size + index + fi.frame_length, SEEK_SET); 666 if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) == sizeof(frame_buffer)) 667 { 668 if(!_decode_mp3_frame((unsigned char*)frame_buffer, &fi)) 669 { 670 found = 1; 671 fp_size += index; 672 } 673 } 674 else 675 { 676 DPRINTF(E_ERROR, L_SCANNER, "Could not read frame header: %s\n", file); 677 fclose(infile); 678 return 0; 679 } 680 681 if(!found) 682 { 683 // cannot find second frame. Song may be too short. So assume first frame is valid. 684 found = 1; 685 fp_size += index; 686 } 687 } 688 } 689 690 if(!found) 691 { 692 index++; 693 if(first_check) 694 { 695 DPRINTF(E_INFO, L_SCANNER, "Bad header... dropping back for full frame search [%s]\n", psong->path); 696 first_check = 0; 697 fp_size = 0; 698 break; 699 } 700 } 701 } 702 } 703 704 fi.frame_offset = fp_size; 705 706 psong->audio_offset = fp_size; 707 psong->audio_size = file_size - fp_size; 708 // check if last 128 bytes is ID3v1.0 ID3v1.1 tag 709 fseek(infile, file_size - 128, SEEK_SET); 710 if(fread(id3v1taghdr, 1, 4, infile) == 4) 711 { 712 if(id3v1taghdr[0] == 'T' && id3v1taghdr[1] == 'A' && id3v1taghdr[2] == 'G') 713 { 714 psong->audio_size -= 128; 715 } 716 } 717 718 if(_decode_mp3_frame(&buffer[index], &fi)) 719 { 720 fclose(infile); 721 DPRINTF(E_ERROR, L_SCANNER, "Could not find sync frame: %s\n", file); 722 return 0; 723 } 724 725 /* now check for an XING header */ 726 psong->vbr_scale = -1; 727 if(!strncasecmp((char*)&buffer[index + fi.xing_offset + 4], "XING", 4)) 728 { 729 xing_flags = buffer[index+fi.xing_offset+4+4] << 24 | 730 buffer[index+fi.xing_offset+4+5] << 16 | 731 buffer[index+fi.xing_offset+4+6] << 8 | 732 buffer[index+fi.xing_offset+4+7]; 733 psong->vbr_scale = 78; 734 735 if(xing_flags & 0x1) 736 { 737 /* Frames field is valid... */ 738 fi.number_of_frames = buffer[index+fi.xing_offset+4+8] << 24 | 739 buffer[index+fi.xing_offset+4+9] << 16 | 740 buffer[index+fi.xing_offset+4+10] << 8 | 741 buffer[index+fi.xing_offset+4+11]; 742 } 743 } 744 745 if((fi.number_of_frames == 0) && (!psong->song_length)) 746 { 747 _mp3_get_average_bitrate(infile, &fi, file); 748 } 749 750 psong->bitrate = fi.bitrate * 1000; 751 psong->samplerate = fi.samplerate; 752 753 if(!psong->song_length) 754 { 755 if(fi.number_of_frames) 756 { 757 psong->song_length = (int)((double)(fi.number_of_frames * fi.samples_per_frame * 1000.) / 758 (double)fi.samplerate); 759 psong->vbr_scale = 78; 760 } 761 else 762 { 763 psong->song_length = (int)((double)(file_size - fp_size) * 8. / 764 (double)fi.bitrate); 765 } 766 } 767 psong->channels = fi.stereo ? 2 : 1; 768 769 fclose(infile); 770 //DEBUG DPRINTF(E_INFO, L_SCANNER, "Got fileinfo successfully for file=%s song_length=%d\n", file, psong->song_length); 771 772 psong->blockalignment = 1; 773 xasprintf(&(psong->dlna_pn), "MP3"); 774 775 return 0; 776} 777