/** Fix a QuickTime/iPod issue with long audio files. * * This function checks if the <b>file</b> is a long audio file (more than * about 6 1/2 hours) and modifies the timescale if necessary to allow * playback of the file in QuickTime player and on some iPod models. * * @param file the opened MP4 file */ void ChapterUtility::fixQtScale(MP4FileHandle file) { // get around a QuickTime/iPod issue with storing the number of samples in a signed 32Bit value if( INT_MAX < MP4GetDuration(file)) { bool isVideoTrack = false; if( MP4_IS_VALID_TRACK_ID(getReferencingTrack( file, isVideoTrack )) & isVideoTrack ) { // if it is a video, everything is different return; } // timescale too high, lower it MP4ChangeMovieTimeScale(file, 1000); } }
bool mediaM4A(Artwork *art, const char *filePath) { MP4FileHandle mp4file = MP4Read(filePath); if (mp4file == MP4_INVALID_FILE_HANDLE) { return false; } uint16_t numvalue, numvalue2; char *value; u_int8_t numbool; art->filetype = FILETYPE_M4A; if (MP4GetMetadataArtist(mp4file, &value) && value != NULL) { art->artist = (QString::fromUtf8(value)).trimmed(); free(value); } if (MP4GetMetadataYear(mp4file, &value) && value != NULL) { art->year = QString(value).toInt(); free(value); } if (MP4GetMetadataAlbum(mp4file, &value) && value != NULL) { art->album = (QString::fromUtf8(value)).trimmed(); free(value); } if (MP4GetMetadataName(mp4file, &value) && value != NULL) { art->track = (QString::fromUtf8(value)).trimmed(); free(value); } if (MP4GetMetadataWriter(mp4file, &value) && value != NULL) { // composer free(value); } if (MP4GetMetadataTrack(mp4file, &numvalue, &numvalue2)) { art->trackNo = numvalue; art->trackCount = numvalue2; } if (MP4GetMetadataDisk(mp4file, &numvalue, &numvalue2)) { art->discNo = numvalue; art->discCount = numvalue2; } if (MP4GetMetadataGenre(mp4file, &value) && value != NULL) { art->genre = (QString::fromUtf8(value)).trimmed(); free(value); } if (MP4GetMetadataCompilation(mp4file, &numbool)) { art->type = numbool ? ARTWORK_COMPILATION : ARTWORK_NORMAL; } /* art->bitrate = 0; art->sampleRate = 0; art->channels = 0; */ MP4Duration duration = MP4GetDuration(mp4file); if (duration != MP4_INVALID_DURATION) { u_int64_t timescale = MP4GetTimeScale(mp4file); u_int64_t msectime = (duration * (u_int64_t) 1000) / timescale; u_int64_t sectime, mintime, hrtime; if (msectime == 0) { hrtime = mintime = sectime = (u_int64_t) 0; } else { hrtime = msectime / (u_int64_t) (3600 * 1000); msectime -= hrtime * (u_int64_t) (3600 * 1000); mintime = msectime / (u_int64_t) (60 * 1000); msectime -= (mintime * (u_int64_t) (60 * 1000)); sectime = msectime / (u_int64_t) (1000); msectime -= sectime * (u_int64_t)(1000); } art->duration = hrtime * 3600 + mintime * 60 + sectime; } art->makeSearchable(); if (!art->hasCover()) { uint8_t *cover = NULL; uint32_t cover_size; if (MP4GetMetadataCoverArt(mp4file, &cover, &cover_size)) { if (saveImage(art, (const char*) cover, cover_size)) { qDebug() << "MP4: invalid image in " << filePath; } } if (cover) { free(cover); } } MP4Close(mp4file); return true; }
double MP4Streamer::GetDuration() { return MP4GetDuration(mp4)/MP4GetTimeScale(mp4); }