diff --git a/tagutils/tagutils-aac.c b/tagutils/tagutils-aac.c index 25bb110..21b5c47 100644 --- a/tagutils/tagutils-aac.c +++ b/tagutils/tagutils-aac.c @@ -244,6 +244,28 @@ _aac_lookforatom(FILE *aac_fp, char *atom_path, unsigned int *atom_length) return ftell(aac_fp) - 8; } +int +_aac_check_extended_descriptor(FILE *infile) +{ + short int i; + unsigned char buf[3]; + + if( !fread((void *)&buf, 3, 1, infile) ) + return -1; + for( i=0; i<3; i++ ) + { + if( (buf[i] != 0x80) && + (buf[i] != 0x81) && + (buf[i] != 0xFE) ) + { + fseek(infile, -3, SEEK_CUR); + return 0; + } + } + + return 0; +} + // _get_aacfileinfo int _get_aacfileinfo(char *file, struct song_metadata *psong) @@ -302,28 +324,49 @@ _get_aacfileinfo(char *file, struct song_metadata *psong) psong->bitrate = 0; + // see if it is aac or alac + atom_offset = _aac_lookforatom(infile, "moov:trak:mdia:minf:stbl:stsd:alac", (unsigned int*)&atom_length); + if(atom_offset != -1) { + fseek(infile, atom_offset + 32, SEEK_SET); + fread(buffer, sizeof(unsigned char), 2, infile); + + psong->samplerate = (buffer[0] << 8) | (buffer[1]); + goto bad_esds; + } + // get samplerate from 'mp4a' (not from 'mdhd') atom_offset = _aac_lookforatom(infile, "moov:trak:mdia:minf:stbl:stsd:mp4a", (unsigned int*)&atom_length); if(atom_offset != -1) { fseek(infile, atom_offset + 32, SEEK_SET); - fread(buffer, sizeof(unsigned char), 2, infile); psong->samplerate = (buffer[0] << 8) | (buffer[1]); fseek(infile, 2, SEEK_CUR); - // get bitrate fomr 'esds' + // get bitrate from 'esds' atom_offset = _aac_findatom(infile, atom_length - (ftell(infile) - atom_offset), "esds", &atom_length); if(atom_offset != -1) { - fseek(infile, atom_offset + 26, SEEK_CUR); // +22 is max bitrate, +26 is average bitrate + // skip the version number + fseek(infile, atom_offset + 4, SEEK_CUR); + // should be 0x03, to signify the descriptor type (section) + fread((void *)&buffer, 1, 1, infile); + if( (buffer[0] != 0x03) || (_aac_check_extended_descriptor(infile) != 0) ) + goto bad_esds; + fseek(infile, 4, SEEK_CUR); + fread((void *)&buffer, 1, 1, infile); + if( (buffer[0] != 0x04) || (_aac_check_extended_descriptor(infile) != 0) ) + goto bad_esds; + fseek(infile, 10, SEEK_CUR); // 10 bytes into section 4 should be average bitrate. max bitrate is 6 bytes in. fread((void *)&bitrate, sizeof(unsigned int), 1, infile); psong->bitrate = ntohl(bitrate); - - fseek(infile, 5, SEEK_CUR); // 5 bytes past bitrate is setup data + fread((void *)&buffer, 1, 1, infile); + if( (buffer[0] != 0x05) || (_aac_check_extended_descriptor(infile) != 0) ) + goto bad_esds; + fseek(infile, 1, SEEK_CUR); // 1 bytes into section 5 should be the setup data fread((void *)&buffer, 2, 1, infile); profile_id = (buffer[0] >> 3); // first 5 bits of setup data is the Audo Profile ID /* Frequency index: (((buffer[0] & 0x7) << 1) | (buffer[1] >> 7))) */ @@ -331,6 +374,7 @@ _get_aacfileinfo(char *file, struct song_metadata *psong) psong->channels = (samples == 7 ? 8 : samples); } } +bad_esds: atom_offset = _aac_lookforatom(infile, "mdat", (unsigned int*)&atom_length); psong->audio_size = atom_length - 8; @@ -338,13 +382,14 @@ _get_aacfileinfo(char *file, struct song_metadata *psong) if(!psong->bitrate) { - DPRINTF(E_DEBUG, L_SCANNER, "No 'esds' atom. Guess bitrate.\n"); + /* Dont' scare people with this for now. Could be Apple Lossless? + DPRINTF(E_DEBUG, L_SCANNER, "No 'esds' atom. Guess bitrate. [%s]\n", basename(file)); */ if((atom_offset != -1) && (psong->song_length)) { psong->bitrate = atom_length * 1000 / psong->song_length / 128; } /* If this is an obviously wrong bitrate, try something different */ - if((psong->bitrate < 16000) && (psong->song_length)) + if((psong->bitrate < 16000) && (psong->song_length > 1000)) { psong->bitrate = (file_size * 8) / (psong->song_length / 1000); } @@ -373,7 +418,7 @@ _get_aacfileinfo(char *file, struct song_metadata *psong) psong->channels, psong->bitrate); break; default: - DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC type [%d]\n", profile_id); + DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC type %d [%s]\n", profile_id, basename(file)); break; } diff --git a/tagutils/tagutils-asf.c b/tagutils/tagutils-asf.c index 938cec5..50996cd 100644 --- a/tagutils/tagutils-asf.c +++ b/tagutils/tagutils-asf.c @@ -61,7 +61,9 @@ _asf_read_audio_stream(FILE *fp, struct song_metadata *psong, int size) { case WMAV1: case WMAV2: - if( psong->bitrate < 193000 ) + if( (psong->bitrate/1000+1) >= 385 || psong->samplerate > 48000 ) + asprintf(&(psong->dlna_pn), "WMAPRO"); + else if( (psong->bitrate / 1000)+1 < 192 ) asprintf(&(psong->dlna_pn), "WMABASE"); else asprintf(&(psong->dlna_pn), "WMAFULL"); @@ -105,7 +107,9 @@ _asf_read_media_stream(FILE *fp, struct song_metadata *psong, __u32 size) { case WMAV1: case WMAV2: - if( psong->bitrate < 193000 ) + if( (psong->bitrate/1000+1) >= 385 || psong->samplerate > 48000 ) + asprintf(&(psong->dlna_pn), "WMAPRO"); + else if( (psong->bitrate / 1000)+1 < 192 ) asprintf(&(psong->dlna_pn), "WMABASE"); else asprintf(&(psong->dlna_pn), "WMAFULL"); diff --git a/tagutils/tagutils.c b/tagutils/tagutils.c index 54c6ab9..1cb171e 100644 --- a/tagutils/tagutils.c +++ b/tagutils/tagutils.c @@ -257,7 +257,6 @@ int readtags(char *path, struct song_metadata *psong, struct stat *stat, char *lang, char *type) { char *fname; - int found = 0; if(lang_index == -1) lang_index = _lang2cp(lang); @@ -277,19 +276,11 @@ readtags(char *path, struct song_metadata *psong, struct stat *stat, char *lang, } // get tag - found |= _get_tags(path, psong); - - // get fileinfo - found |= _get_fileinfo(path, psong); - - // - if(!found) + if( _get_tags(path, psong) == 0 ) { _make_composite_tags(psong); - return 0; - } - else - { - return -1; } + + // get fileinfo + return _get_fileinfo(path, psong); }