am e981c334: Extract video thumbnails from the largest sync sample among the first 20.

Merge commit 'e981c33446a98d5ccc0d73c1a840696d77cf0732' into eclair-mr2-plus-aosp

* commit 'e981c33446a98d5ccc0d73c1a840696d77cf0732':
  Extract video thumbnails from the largest sync sample among the first 20.
This commit is contained in:
Andreas Huber
2009-10-22 14:49:35 -07:00
committed by Android Git Automerger
12 changed files with 111 additions and 10 deletions

View File

@@ -30,7 +30,7 @@ public:
virtual size_t countTracks(); virtual size_t countTracks();
virtual sp<MediaSource> getTrack(size_t index); 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); static sp<MetaData> makeAMRFormat(bool isWide);

View File

@@ -32,7 +32,7 @@ public:
virtual size_t countTracks(); virtual size_t countTracks();
virtual sp<MediaSource> getTrack(size_t index); 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: protected:
virtual ~MP3Extractor(); virtual ~MP3Extractor();

View File

@@ -33,7 +33,7 @@ public:
size_t countTracks(); size_t countTracks();
sp<MediaSource> getTrack(size_t index); sp<MediaSource> getTrack(size_t index);
sp<MetaData> getTrackMetaData(size_t index); sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
protected: protected:
virtual ~MPEG4Extractor(); virtual ~MPEG4Extractor();
@@ -44,6 +44,7 @@ private:
sp<MetaData> meta; sp<MetaData> meta;
uint32_t timescale; uint32_t timescale;
sp<SampleTable> sampleTable; sp<SampleTable> sampleTable;
bool includes_expensive_metadata;
}; };
sp<DataSource> mDataSource; sp<DataSource> mDataSource;

View File

@@ -33,7 +33,12 @@ public:
virtual size_t countTracks() = 0; virtual size_t countTracks() = 0;
virtual sp<MediaSource> getTrack(size_t index) = 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: protected:
MediaExtractor() {} MediaExtractor() {}

View File

@@ -46,6 +46,7 @@ enum {
kKeyDecoderComponent = 'decC', // cstring kKeyDecoderComponent = 'decC', // cstring
kKeyBufferID = 'bfID', kKeyBufferID = 'bfID',
kKeyMaxInputSize = 'inpS', kKeyMaxInputSize = 'inpS',
kKeyThumbnailTime = 'thbT', // int64_t (usecs)
}; };
enum { enum {

View File

@@ -108,6 +108,9 @@ VideoFrame *StagefrightMetadataRetriever::captureFrame() {
return NULL; return NULL;
} }
sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
i, MediaExtractor::kIncludeExtensiveMetaData);
sp<MediaSource> source = mExtractor->getTrack(i); sp<MediaSource> source = mExtractor->getTrack(i);
if (source.get() == NULL) { if (source.get() == NULL) {
@@ -132,6 +135,12 @@ VideoFrame *StagefrightMetadataRetriever::captureFrame() {
// Read one output buffer, ignore format change notifications // Read one output buffer, ignore format change notifications
// and spurious empty buffers. // and spurious empty buffers.
MediaSource::ReadOptions options;
int64_t thumbNailTime;
if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
options.setSeekTo(thumbNailTime);
}
MediaBuffer *buffer = NULL; MediaBuffer *buffer = NULL;
status_t err; status_t err;
do { do {
@@ -139,7 +148,8 @@ VideoFrame *StagefrightMetadataRetriever::captureFrame() {
buffer->release(); buffer->release();
buffer = NULL; buffer = NULL;
} }
err = decoder->read(&buffer); err = decoder->read(&buffer, &options);
options.clearSeekTo();
} while (err == INFO_FORMAT_CHANGED } while (err == INFO_FORMAT_CHANGED
|| (buffer != NULL && buffer->range_length() == 0)); || (buffer != NULL && buffer->range_length() == 0));

View File

@@ -86,7 +86,7 @@ sp<MediaSource> AMRExtractor::getTrack(size_t index) {
return new AMRSource(mDataSource, mIsWide); 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) { if (mInitCheck != OK || index != 0) {
return NULL; return NULL;
} }

View File

@@ -393,7 +393,7 @@ sp<MediaSource> MP3Extractor::getTrack(size_t index) {
mMeta, mDataSource, mFirstFramePos, mFixedHeader); 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) { if (mFirstFramePos < 0 || index != 0) {
return NULL; return NULL;
} }

View File

@@ -179,7 +179,8 @@ size_t MPEG4Extractor::countTracks() {
return n; return n;
} }
sp<MetaData> MPEG4Extractor::getTrackMetaData(size_t index) { sp<MetaData> MPEG4Extractor::getTrackMetaData(
size_t index, uint32_t flags) {
status_t err; status_t err;
if ((err = readMetaData()) != OK) { if ((err = readMetaData()) != OK) {
return NULL; return NULL;
@@ -199,6 +200,25 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData(size_t index) {
return NULL; 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; return track->meta;
} }
@@ -353,6 +373,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
mLastTrack = track; mLastTrack = track;
track->meta = new MetaData; track->meta = new MetaData;
track->includes_expensive_metadata = false;
track->timescale = 0; track->timescale = 0;
track->sampleTable = new SampleTable(mDataSource); track->sampleTable = new SampleTable(mDataSource);
track->meta->setCString(kKeyMIMEType, "application/octet-stream"); track->meta->setCString(kKeyMIMEType, "application/octet-stream");

View File

@@ -1943,9 +1943,24 @@ status_t OMXCodec::read(
return UNKNOWN_ERROR; return UNKNOWN_ERROR;
} }
bool seeking = false;
int64_t seekTimeUs;
if (options && options->getSeekTo(&seekTimeUs)) {
seeking = true;
}
if (mInitialBufferSubmit) { if (mInitialBufferSubmit) {
mInitialBufferSubmit = false; 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(); drainInputBuffers();
if (mState == EXECUTING) { if (mState == EXECUTING) {
@@ -1955,8 +1970,7 @@ status_t OMXCodec::read(
} }
} }
int64_t seekTimeUs; if (seeking) {
if (options && options->getSeekTo(&seekTimeUs)) {
CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6); CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
mSignalledEOS = false; mSignalledEOS = false;

View File

@@ -575,5 +575,52 @@ status_t SampleTable::findClosestSyncSample(
return OK; 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 } // namespace android

View File

@@ -75,6 +75,8 @@ public:
status_t findClosestSyncSample( status_t findClosestSyncSample(
uint32_t start_sample_index, uint32_t *sample_index); uint32_t start_sample_index, uint32_t *sample_index);
status_t findThumbnailSample(uint32_t *sample_index);
protected: protected:
~SampleTable(); ~SampleTable();