Loading media/libstagefright/MPEG4Extractor.cpp +105 −7 Original line number Diff line number Diff line Loading @@ -262,7 +262,7 @@ static const char *FourCC2MIME(uint32_t fourcc) { MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source) : mDataSource(source), mHaveMetadata(false), mInitCheck(NO_INIT), mHasVideo(false), mFirstTrack(NULL), mLastTrack(NULL), Loading Loading @@ -361,8 +361,8 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData( } status_t MPEG4Extractor::readMetaData() { if (mHaveMetadata) { return OK; if (mInitCheck != NO_INIT) { return mInitCheck; } off64_t offset = 0; Loading @@ -370,17 +370,20 @@ status_t MPEG4Extractor::readMetaData() { while ((err = parseChunk(&offset, 0)) == OK) { } if (mHaveMetadata) { if (mInitCheck == OK) { if (mHasVideo) { mFileMetaData->setCString(kKeyMIMEType, "video/mp4"); } else { mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); } return OK; mInitCheck = verifyIfStreamable(); } else { mInitCheck = err; } return err; CHECK_NE(err, (status_t)NO_INIT); return mInitCheck; } void MPEG4Extractor::setDrmFlag(bool flag) { Loading Loading @@ -755,7 +758,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return err; } } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { mHaveMetadata = true; mInitCheck = OK; if (!mIsDrm) { return UNKNOWN_ERROR; // Return a dummy error. Loading Loading @@ -2077,6 +2080,101 @@ status_t MPEG4Source::read( } } MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix( const char *mimePrefix) { for (Track *track = mFirstTrack; track != NULL; track = track->next) { const char *mime; if (track->meta != NULL && track->meta->findCString(kKeyMIMEType, &mime) && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) { return track; } } return NULL; } status_t MPEG4Extractor::verifyIfStreamable() { if (!(mDataSource->flags() & DataSource::kIsCachingDataSource)) { return OK; } Track *audio = findTrackByMimePrefix("audio/"); Track *video = findTrackByMimePrefix("video/"); if (audio == NULL || video == NULL) { return OK; } sp<SampleTable> audioSamples = audio->sampleTable; sp<SampleTable> videoSamples = video->sampleTable; off64_t maxOffsetDiff = 0; int64_t maxOffsetTimeUs = -1; for (uint32_t i = 0; i < videoSamples->countSamples(); ++i) { off64_t videoOffset; uint32_t videoTime; bool isSync; CHECK_EQ((status_t)OK, videoSamples->getMetaDataForSample( i, &videoOffset, NULL, &videoTime, &isSync)); int64_t videoTimeUs = (int64_t)(videoTime * 1E6 / video->timescale); uint32_t reqAudioTime = (videoTimeUs * audio->timescale) / 1000000; uint32_t j; if (audioSamples->findSampleAtTime( reqAudioTime, &j, SampleTable::kFlagClosest) != OK) { continue; } off64_t audioOffset; uint32_t audioTime; CHECK_EQ((status_t)OK, audioSamples->getMetaDataForSample( j, &audioOffset, NULL, &audioTime)); int64_t audioTimeUs = (int64_t)(audioTime * 1E6 / audio->timescale); off64_t offsetDiff = videoOffset - audioOffset; if (offsetDiff < 0) { offsetDiff = -offsetDiff; } #if 0 printf("%s%d/%d videoTime %.2f secs audioTime %.2f secs " "videoOffset %lld audioOffset %lld offsetDiff %lld\n", isSync ? "*" : " ", i, j, videoTimeUs / 1E6, audioTimeUs / 1E6, videoOffset, audioOffset, offsetDiff); #endif if (offsetDiff > maxOffsetDiff) { maxOffsetDiff = offsetDiff; maxOffsetTimeUs = videoTimeUs; } } #if 0 printf("max offset diff: %lld at video time: %.2f secs\n", maxOffsetDiff, maxOffsetTimeUs / 1E6); #endif if (maxOffsetDiff < 1024 * 1024) { return OK; } LOGE("This content is not streamable, " "max offset diff: %lld at video time: %.2f secs", maxOffsetDiff, maxOffsetTimeUs / 1E6); return ERROR_UNSUPPORTED; } static bool LegacySniffMPEG4( const sp<DataSource> &source, String8 *mimeType, float *confidence) { uint8_t header[8]; Loading media/libstagefright/include/MPEG4Extractor.h +5 −1 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ private: }; sp<DataSource> mDataSource; bool mHaveMetadata; status_t mInitCheck; bool mHasVideo; Track *mFirstTrack, *mLastTrack; Loading Loading @@ -90,6 +90,10 @@ private: status_t parseTrackHeader(off64_t data_offset, off64_t data_size); Track *findTrackByMimePrefix(const char *mimePrefix); status_t verifyIfStreamable(); MPEG4Extractor(const MPEG4Extractor &); MPEG4Extractor &operator=(const MPEG4Extractor &); }; Loading Loading
media/libstagefright/MPEG4Extractor.cpp +105 −7 Original line number Diff line number Diff line Loading @@ -262,7 +262,7 @@ static const char *FourCC2MIME(uint32_t fourcc) { MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source) : mDataSource(source), mHaveMetadata(false), mInitCheck(NO_INIT), mHasVideo(false), mFirstTrack(NULL), mLastTrack(NULL), Loading Loading @@ -361,8 +361,8 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData( } status_t MPEG4Extractor::readMetaData() { if (mHaveMetadata) { return OK; if (mInitCheck != NO_INIT) { return mInitCheck; } off64_t offset = 0; Loading @@ -370,17 +370,20 @@ status_t MPEG4Extractor::readMetaData() { while ((err = parseChunk(&offset, 0)) == OK) { } if (mHaveMetadata) { if (mInitCheck == OK) { if (mHasVideo) { mFileMetaData->setCString(kKeyMIMEType, "video/mp4"); } else { mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); } return OK; mInitCheck = verifyIfStreamable(); } else { mInitCheck = err; } return err; CHECK_NE(err, (status_t)NO_INIT); return mInitCheck; } void MPEG4Extractor::setDrmFlag(bool flag) { Loading Loading @@ -755,7 +758,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return err; } } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { mHaveMetadata = true; mInitCheck = OK; if (!mIsDrm) { return UNKNOWN_ERROR; // Return a dummy error. Loading Loading @@ -2077,6 +2080,101 @@ status_t MPEG4Source::read( } } MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix( const char *mimePrefix) { for (Track *track = mFirstTrack; track != NULL; track = track->next) { const char *mime; if (track->meta != NULL && track->meta->findCString(kKeyMIMEType, &mime) && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) { return track; } } return NULL; } status_t MPEG4Extractor::verifyIfStreamable() { if (!(mDataSource->flags() & DataSource::kIsCachingDataSource)) { return OK; } Track *audio = findTrackByMimePrefix("audio/"); Track *video = findTrackByMimePrefix("video/"); if (audio == NULL || video == NULL) { return OK; } sp<SampleTable> audioSamples = audio->sampleTable; sp<SampleTable> videoSamples = video->sampleTable; off64_t maxOffsetDiff = 0; int64_t maxOffsetTimeUs = -1; for (uint32_t i = 0; i < videoSamples->countSamples(); ++i) { off64_t videoOffset; uint32_t videoTime; bool isSync; CHECK_EQ((status_t)OK, videoSamples->getMetaDataForSample( i, &videoOffset, NULL, &videoTime, &isSync)); int64_t videoTimeUs = (int64_t)(videoTime * 1E6 / video->timescale); uint32_t reqAudioTime = (videoTimeUs * audio->timescale) / 1000000; uint32_t j; if (audioSamples->findSampleAtTime( reqAudioTime, &j, SampleTable::kFlagClosest) != OK) { continue; } off64_t audioOffset; uint32_t audioTime; CHECK_EQ((status_t)OK, audioSamples->getMetaDataForSample( j, &audioOffset, NULL, &audioTime)); int64_t audioTimeUs = (int64_t)(audioTime * 1E6 / audio->timescale); off64_t offsetDiff = videoOffset - audioOffset; if (offsetDiff < 0) { offsetDiff = -offsetDiff; } #if 0 printf("%s%d/%d videoTime %.2f secs audioTime %.2f secs " "videoOffset %lld audioOffset %lld offsetDiff %lld\n", isSync ? "*" : " ", i, j, videoTimeUs / 1E6, audioTimeUs / 1E6, videoOffset, audioOffset, offsetDiff); #endif if (offsetDiff > maxOffsetDiff) { maxOffsetDiff = offsetDiff; maxOffsetTimeUs = videoTimeUs; } } #if 0 printf("max offset diff: %lld at video time: %.2f secs\n", maxOffsetDiff, maxOffsetTimeUs / 1E6); #endif if (maxOffsetDiff < 1024 * 1024) { return OK; } LOGE("This content is not streamable, " "max offset diff: %lld at video time: %.2f secs", maxOffsetDiff, maxOffsetTimeUs / 1E6); return ERROR_UNSUPPORTED; } static bool LegacySniffMPEG4( const sp<DataSource> &source, String8 *mimeType, float *confidence) { uint8_t header[8]; Loading
media/libstagefright/include/MPEG4Extractor.h +5 −1 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ private: }; sp<DataSource> mDataSource; bool mHaveMetadata; status_t mInitCheck; bool mHasVideo; Track *mFirstTrack, *mLastTrack; Loading Loading @@ -90,6 +90,10 @@ private: status_t parseTrackHeader(off64_t data_offset, off64_t data_size); Track *findTrackByMimePrefix(const char *mimePrefix); status_t verifyIfStreamable(); MPEG4Extractor(const MPEG4Extractor &); MPEG4Extractor &operator=(const MPEG4Extractor &); }; Loading