summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/mediametadataretriever.h6
-rw-r--r--media/libmedia/MediaProfiles.cpp3
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp112
-rw-r--r--media/libstagefright/StagefrightMetadataRetriever.cpp49
-rw-r--r--media/libstagefright/include/MPEG4Extractor.h6
5 files changed, 168 insertions, 8 deletions
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index e905006..a5cb949 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -47,6 +47,12 @@ enum {
METADATA_KEY_ALBUMARTIST = 13,
METADATA_KEY_DISC_NUMBER = 14,
METADATA_KEY_COMPILATION = 15,
+ METADATA_KEY_HAS_AUDIO = 16,
+ METADATA_KEY_HAS_VIDEO = 17,
+ METADATA_KEY_VIDEO_WIDTH = 18,
+ METADATA_KEY_VIDEO_HEIGHT = 19,
+ METADATA_KEY_BITRATE = 20,
+
// Add more here...
};
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 7fb7aed..ca5bc38 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -721,6 +721,9 @@ MediaProfiles::createDefaultCamcorderProfiles(MediaProfiles *profiles)
createDefaultCamcorderTimeLapseHighProfiles(&highTimeLapseProfile, &highSpecificTimeLapseProfile);
profiles->mCamcorderProfiles.add(highTimeLapseProfile);
profiles->mCamcorderProfiles.add(highSpecificTimeLapseProfile);
+
+ // We only have the back-facing camera support by default.
+ profiles->mCameraIds.add(0);
}
/*static*/ void
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 7b96d01..1ca2d6d 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -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),
@@ -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;
@@ -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) {
@@ -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.
@@ -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];
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index ea3b801..c371cd0 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -411,6 +411,12 @@ void StagefrightMetadataRetriever::parseMetaData() {
mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
+ bool hasAudio = false;
+ bool hasVideo = false;
+ int32_t videoWidth = -1;
+ int32_t videoHeight = -1;
+ int32_t audioBitrate = -1;
+
// The overall duration is the duration of the longest track.
int64_t maxDurationUs = 0;
for (size_t i = 0; i < numTracks; ++i) {
@@ -422,12 +428,55 @@ void StagefrightMetadataRetriever::parseMetaData() {
maxDurationUs = durationUs;
}
}
+
+ const char *mime;
+ if (trackMeta->findCString(kKeyMIMEType, &mime)) {
+ if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
+ hasAudio = true;
+
+ if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
+ audioBitrate = -1;
+ }
+ } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
+ hasVideo = true;
+
+ CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
+ CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
+ }
+ }
}
// The duration value is a string representing the duration in ms.
sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
+ if (hasAudio) {
+ mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
+ }
+
+ if (hasVideo) {
+ mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
+
+ sprintf(tmp, "%d", videoWidth);
+ mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
+
+ sprintf(tmp, "%d", videoHeight);
+ mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
+ }
+
+ if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
+ sprintf(tmp, "%ld", audioBitrate);
+ mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+ } else {
+ off64_t sourceSize;
+ if (mSource->getSize(&sourceSize) == OK) {
+ int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
+
+ sprintf(tmp, "%lld", avgBitRate);
+ mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+ }
+ }
+
if (numTracks == 1) {
const char *fileMIME;
CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 04e8a6a..d9ef208 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -57,7 +57,7 @@ private:
};
sp<DataSource> mDataSource;
- bool mHaveMetadata;
+ status_t mInitCheck;
bool mHasVideo;
Track *mFirstTrack, *mLastTrack;
@@ -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 &);
};