Extract video thumbnails from the largest sync sample among the first 20.
Also fixes OMXCodec seek behaviour on the very first call to OMXCodec::read()
diff --git a/include/media/stagefright/AMRExtractor.h b/include/media/stagefright/AMRExtractor.h
index c8710d3..debf006 100644
--- a/include/media/stagefright/AMRExtractor.h
+++ b/include/media/stagefright/AMRExtractor.h
@@ -30,7 +30,7 @@
virtual size_t countTracks();
virtual sp<MediaSource> getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index);
+ virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
static sp<MetaData> makeAMRFormat(bool isWide);
diff --git a/include/media/stagefright/MP3Extractor.h b/include/media/stagefright/MP3Extractor.h
index 11ba01d..074973b 100644
--- a/include/media/stagefright/MP3Extractor.h
+++ b/include/media/stagefright/MP3Extractor.h
@@ -32,7 +32,7 @@
virtual size_t countTracks();
virtual sp<MediaSource> getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index);
+ virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
protected:
virtual ~MP3Extractor();
diff --git a/include/media/stagefright/MPEG4Extractor.h b/include/media/stagefright/MPEG4Extractor.h
index 932e30f..ce4736d 100644
--- a/include/media/stagefright/MPEG4Extractor.h
+++ b/include/media/stagefright/MPEG4Extractor.h
@@ -33,7 +33,7 @@
size_t countTracks();
sp<MediaSource> getTrack(size_t index);
- sp<MetaData> getTrackMetaData(size_t index);
+ sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
protected:
virtual ~MPEG4Extractor();
@@ -44,6 +44,7 @@
sp<MetaData> meta;
uint32_t timescale;
sp<SampleTable> sampleTable;
+ bool includes_expensive_metadata;
};
sp<DataSource> mDataSource;
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 67e45bd..4d6b989 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -33,7 +33,12 @@
virtual size_t countTracks() = 0;
virtual sp<MediaSource> getTrack(size_t index) = 0;
- virtual sp<MetaData> getTrackMetaData(size_t index) = 0;
+
+ enum GetTrackMetaDataFlags {
+ kIncludeExtensiveMetaData = 1
+ };
+ virtual sp<MetaData> getTrackMetaData(
+ size_t index, uint32_t flags = 0) = 0;
protected:
MediaExtractor() {}
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index d48ea41..c2d8f98 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -46,6 +46,7 @@
kKeyDecoderComponent = 'decC', // cstring
kKeyBufferID = 'bfID',
kKeyMaxInputSize = 'inpS',
+ kKeyThumbnailTime = 'thbT', // int64_t (usecs)
};
enum {
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index c069128..5ac59c8 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -108,6 +108,9 @@
return NULL;
}
+ sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
+ i, MediaExtractor::kIncludeExtensiveMetaData);
+
sp<MediaSource> source = mExtractor->getTrack(i);
if (source.get() == NULL) {
@@ -132,6 +135,12 @@
// Read one output buffer, ignore format change notifications
// and spurious empty buffers.
+ MediaSource::ReadOptions options;
+ int64_t thumbNailTime;
+ if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
+ options.setSeekTo(thumbNailTime);
+ }
+
MediaBuffer *buffer = NULL;
status_t err;
do {
@@ -139,7 +148,8 @@
buffer->release();
buffer = NULL;
}
- err = decoder->read(&buffer);
+ err = decoder->read(&buffer, &options);
+ options.clearSeekTo();
} while (err == INFO_FORMAT_CHANGED
|| (buffer != NULL && buffer->range_length() == 0));
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 1660351..74f055e 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -86,7 +86,7 @@
return new AMRSource(mDataSource, mIsWide);
}
-sp<MetaData> AMRExtractor::getTrackMetaData(size_t index) {
+sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) {
if (mInitCheck != OK || index != 0) {
return NULL;
}
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index b7dd9ba..78b8eb2 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -393,7 +393,7 @@
mMeta, mDataSource, mFirstFramePos, mFixedHeader);
}
-sp<MetaData> MP3Extractor::getTrackMetaData(size_t index) {
+sp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) {
if (mFirstFramePos < 0 || index != 0) {
return NULL;
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index da714f8..382133c 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -179,7 +179,8 @@
return n;
}
-sp<MetaData> MPEG4Extractor::getTrackMetaData(size_t index) {
+sp<MetaData> MPEG4Extractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
status_t err;
if ((err = readMetaData()) != OK) {
return NULL;
@@ -199,6 +200,25 @@
return NULL;
}
+ if ((flags & kIncludeExtensiveMetaData)
+ && !track->includes_expensive_metadata) {
+ track->includes_expensive_metadata = true;
+
+ const char *mime;
+ CHECK(track->meta->findCString(kKeyMIMEType, &mime));
+ if (!strncasecmp("video/", mime, 6)) {
+ uint32_t sampleIndex;
+ uint32_t sampleTime;
+ if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
+ && track->sampleTable->getDecodingTime(
+ sampleIndex, &sampleTime) == OK) {
+ track->meta->setInt64(
+ kKeyThumbnailTime,
+ ((int64_t)sampleTime * 1000000) / track->timescale);
+ }
+ }
+ }
+
return track->meta;
}
@@ -353,6 +373,7 @@
mLastTrack = track;
track->meta = new MetaData;
+ track->includes_expensive_metadata = false;
track->timescale = 0;
track->sampleTable = new SampleTable(mDataSource);
track->meta->setCString(kKeyMIMEType, "application/octet-stream");
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index ff001e8..f8c0bda 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1943,9 +1943,24 @@
return UNKNOWN_ERROR;
}
+ bool seeking = false;
+ int64_t seekTimeUs;
+ if (options && options->getSeekTo(&seekTimeUs)) {
+ seeking = true;
+ }
+
if (mInitialBufferSubmit) {
mInitialBufferSubmit = false;
+ if (seeking) {
+ CHECK(seekTimeUs >= 0);
+ mSeekTimeUs = seekTimeUs;
+
+ // There's no reason to trigger the code below, there's
+ // nothing to flush yet.
+ seeking = false;
+ }
+
drainInputBuffers();
if (mState == EXECUTING) {
@@ -1955,8 +1970,7 @@
}
}
- int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ if (seeking) {
CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
mSignalledEOS = false;
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 5c5bb4d..3eed52a 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -575,5 +575,52 @@
return OK;
}
+status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
+ if (mSyncSampleOffset < 0) {
+ // All samples are sync-samples.
+ *sample_index = 0;
+ return OK;
+ }
+
+ uint32_t bestSampleIndex = 0;
+ size_t maxSampleSize = 0;
+
+ static const size_t kMaxNumSyncSamplesToScan = 20;
+
+ // Consider the first kMaxNumSyncSamplesToScan sync samples and
+ // pick the one with the largest (compressed) size as the thumbnail.
+
+ size_t numSamplesToScan = mNumSyncSamples;
+ if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
+ numSamplesToScan = kMaxNumSyncSamplesToScan;
+ }
+
+ for (size_t i = 0; i < numSamplesToScan; ++i) {
+ uint32_t x;
+ if (mDataSource->read_at(
+ mSyncSampleOffset + 8 + i * 4, &x, 4) != 4) {
+ return ERROR_IO;
+ }
+ x = ntohl(x);
+ --x;
+
+ // Now x is a sample index.
+ size_t sampleSize;
+ status_t err = getSampleSize(x, &sampleSize);
+ if (err != OK) {
+ return err;
+ }
+
+ if (i == 0 || sampleSize > maxSampleSize) {
+ bestSampleIndex = x;
+ maxSampleSize = sampleSize;
+ }
+ }
+
+ *sample_index = bestSampleIndex;
+
+ return OK;
+}
+
} // namespace android
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 34a0649..ead3431 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -75,6 +75,8 @@
status_t findClosestSyncSample(
uint32_t start_sample_index, uint32_t *sample_index);
+ status_t findThumbnailSample(uint32_t *sample_index);
+
protected:
~SampleTable();