Squashed commit of the following:
commit cb11364feefc200f10af6a01f776803acba2792a
Author: Andreas Huber <andih@google.com>
Date: Thu Jan 14 14:05:36 2010 -0800
Even if the decoder didn't extract the thumbnail at the specified time, accept it for now.
commit a54c0244b305caf11e67db49b7d3d8dba5f77751
Author: Andreas Huber <andih@google.com>
Date: Thu Jan 14 11:37:15 2010 -0800
Add some checks to make sure we extract the correct thumbnail frame, also revert to the hardware decoders for thumnbail extraction if the software decoders failed.
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index c7877a9..020887c 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -107,6 +107,104 @@
return OK;
}
+static VideoFrame *extractVideoFrameWithCodecFlags(
+ OMXClient *client,
+ const sp<MetaData> &trackMeta,
+ const sp<MediaSource> &source, uint32_t flags) {
+ sp<MediaSource> decoder =
+ OMXCodec::Create(
+ client->interface(), source->getFormat(), false, source,
+ NULL, flags);
+
+ if (decoder.get() == NULL) {
+ LOGV("unable to instantiate video decoder.");
+
+ return NULL;
+ }
+
+ decoder->start();
+
+ // 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);
+ } else {
+ thumbNailTime = -1;
+ }
+
+ MediaBuffer *buffer = NULL;
+ status_t err;
+ do {
+ if (buffer != NULL) {
+ buffer->release();
+ buffer = NULL;
+ }
+ err = decoder->read(&buffer, &options);
+ options.clearSeekTo();
+ } while (err == INFO_FORMAT_CHANGED
+ || (buffer != NULL && buffer->range_length() == 0));
+
+ if (err != OK) {
+ CHECK_EQ(buffer, NULL);
+
+ LOGV("decoding frame failed.");
+ decoder->stop();
+
+ return NULL;
+ }
+
+ LOGV("successfully decoded video frame.");
+
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ if (thumbNailTime >= 0) {
+ if (timeUs != thumbNailTime) {
+ const char *mime;
+ CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
+
+ LOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
+ thumbNailTime, timeUs, mime);
+ }
+ }
+
+ sp<MetaData> meta = decoder->getFormat();
+
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ VideoFrame *frame = new VideoFrame;
+ frame->mWidth = width;
+ frame->mHeight = height;
+ frame->mDisplayWidth = width;
+ frame->mDisplayHeight = height;
+ frame->mSize = width * height * 2;
+ frame->mData = new uint8_t[frame->mSize];
+
+ int32_t srcFormat;
+ CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
+
+ ColorConverter converter(
+ (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
+ CHECK(converter.isValid());
+
+ converter.convert(
+ width, height,
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ 0,
+ frame->mData, width * 2);
+
+ buffer->release();
+ buffer = NULL;
+
+ decoder->stop();
+
+ return frame;
+}
+
VideoFrame *StagefrightMetadataRetriever::captureFrame() {
LOGV("captureFrame");
@@ -143,85 +241,17 @@
return NULL;
}
- sp<MetaData> meta = source->getFormat();
+ VideoFrame *frame =
+ extractVideoFrameWithCodecFlags(
+ &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs);
- sp<MediaSource> decoder =
- OMXCodec::Create(
- mClient.interface(), meta, false, source,
- NULL, OMXCodec::kPreferSoftwareCodecs);
+ if (frame == NULL) {
+ LOGV("Software decoder failed to extract thumbnail, "
+ "trying hardware decoder.");
- if (decoder.get() == NULL) {
- LOGV("unable to instantiate video decoder.");
-
- return NULL;
+ frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0);
}
- decoder->start();
-
- // 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 {
- if (buffer != NULL) {
- buffer->release();
- buffer = NULL;
- }
- err = decoder->read(&buffer, &options);
- options.clearSeekTo();
- } while (err == INFO_FORMAT_CHANGED
- || (buffer != NULL && buffer->range_length() == 0));
-
- if (err != OK) {
- CHECK_EQ(buffer, NULL);
-
- LOGV("decoding frame failed.");
- decoder->stop();
-
- return NULL;
- }
-
- LOGV("successfully decoded video frame.");
-
- meta = decoder->getFormat();
-
- int32_t width, height;
- CHECK(meta->findInt32(kKeyWidth, &width));
- CHECK(meta->findInt32(kKeyHeight, &height));
-
- VideoFrame *frame = new VideoFrame;
- frame->mWidth = width;
- frame->mHeight = height;
- frame->mDisplayWidth = width;
- frame->mDisplayHeight = height;
- frame->mSize = width * height * 2;
- frame->mData = new uint8_t[frame->mSize];
-
- int32_t srcFormat;
- CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
-
- ColorConverter converter(
- (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
- CHECK(converter.isValid());
-
- converter.convert(
- width, height,
- (const uint8_t *)buffer->data() + buffer->range_offset(),
- 0,
- frame->mData, width * 2);
-
- buffer->release();
- buffer = NULL;
-
- decoder->stop();
-
return frame;
}