summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/stagefright/stagefright.cpp8
-rw-r--r--include/media/IMediaMetadataRetriever.h3
-rw-r--r--include/media/MediaMetadataRetrieverInterface.h5
-rw-r--r--include/media/mediametadataretriever.h3
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java109
-rw-r--r--media/jni/android_media_MediaMetadataRetriever.cpp26
-rw-r--r--media/libmedia/IMediaMetadataRetriever.cpp34
-rw-r--r--media/libmedia/mediametadataretriever.cpp17
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp23
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.h3
-rw-r--r--media/libstagefright/StagefrightMetadataRetriever.cpp31
-rw-r--r--media/libstagefright/include/StagefrightMetadataRetriever.h2
12 files changed, 157 insertions, 107 deletions
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 7e7f6d1..07e506a 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -681,10 +681,12 @@ int main(int argc, char **argv) {
METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL),
(status_t)OK);
- sp<IMemory> mem = retriever->captureFrame();
+ sp<IMemory> mem =
+ retriever->getFrameAtTime(-1,
+ MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
if (mem != NULL) {
- printf("captureFrame(%s) => OK\n", filename);
+ printf("getFrameAtTime(%s) => OK\n", filename);
VideoFrame *frame = (VideoFrame *)mem->pointer();
@@ -704,7 +706,7 @@ int main(int argc, char **argv) {
if (mem != NULL) {
printf("extractAlbumArt(%s) => OK\n", filename);
} else {
- printf("both captureFrame and extractAlbumArt "
+ printf("both getFrameAtTime and extractAlbumArt "
"failed on file '%s'.\n", filename);
}
}
diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h
index 9baba8e..e517cf0 100644
--- a/include/media/IMediaMetadataRetriever.h
+++ b/include/media/IMediaMetadataRetriever.h
@@ -33,8 +33,7 @@ public:
virtual status_t setDataSource(const char* srcUrl) = 0;
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
virtual status_t setMode(int mode) = 0;
- virtual status_t getMode(int* mode) const = 0;
- virtual sp<IMemory> captureFrame() = 0;
+ virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option) = 0;
virtual sp<IMemory> extractAlbumArt() = 0;
virtual const char* extractMetadata(int keyCode) = 0;
};
diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h
index ff57774..717849d 100644
--- a/include/media/MediaMetadataRetrieverInterface.h
+++ b/include/media/MediaMetadataRetrieverInterface.h
@@ -33,8 +33,7 @@ public:
virtual status_t setDataSource(const char *url) = 0;
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
virtual status_t setMode(int mode) = 0;
- virtual status_t getMode(int* mode) const = 0;
- virtual VideoFrame* captureFrame() = 0;
+ virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) = 0;
virtual MediaAlbumArt* extractAlbumArt() = 0;
virtual const char* extractMetadata(int keyCode) = 0;
};
@@ -67,7 +66,7 @@ public:
}
virtual status_t getMode(int* mode) const { *mode = mMode; return NO_ERROR; }
- virtual VideoFrame* captureFrame() { return NULL; }
+ virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) { return NULL; }
virtual MediaAlbumArt* extractAlbumArt() { return NULL; }
virtual const char* extractMetadata(int keyCode) { return NULL; }
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index dbbcc49..ed54b37 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -81,8 +81,7 @@ public:
status_t setDataSource(const char* dataSourceUrl);
status_t setDataSource(int fd, int64_t offset, int64_t length);
status_t setMode(int mode);
- status_t getMode(int* mode);
- sp<IMemory> captureFrame();
+ sp<IMemory> getFrameAtTime(int64_t timeUs, int option);
sp<IMemory> extractAlbumArt();
const char* extractMetadata(int keyCode);
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 681751b..c92fc23 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -71,12 +71,6 @@ public class MediaMetadataRetriever
public native void setMode(int mode);
/**
- * @return the current mode of operation. A negative return value indicates
- * some runtime error has occurred.
- */
- public native int getMode();
-
- /**
* Sets the data source (file pathname) to use. Call this
* method before the rest of the methods in this class. This method may be
* time-consuming.
@@ -190,13 +184,94 @@ public class MediaMetadataRetriever
/**
* Call this method after setDataSource(). This method finds a
- * representative frame if successful and returns it as a bitmap. This is
- * useful for generating a thumbnail for an input media source.
- *
+ * representative frame close to the given time position by considering
+ * the given option if possible, and returns it as a bitmap. This is
+ * useful for generating a thumbnail for an input data source or just
+ * obtain and display a frame at the given time position.
+ *
+ * @param timeUs The time position where the frame will be retrieved.
+ * When retrieving the frame at the given time position, there is no
+ * guarantee that the data source has a frame located at the position.
+ * When this happens, a frame nearby will be returned. If timeUs is
+ * negative, time position and option will ignored, and any frame
+ * that the implementation considers as representative may be returned.
+ *
+ * @param option a hint on how the frame is found. Use
+ * {@link OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame
+ * that has a timestamp earlier than or the same as timeUs. Use
+ * {@link OPTION_NEXT_SYNC} if one wants to retrieve a sync frame
+ * that has a timestamp later than or the same as timeUs. Use
+ * {@link OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame
+ * that has a timestamp closest to or the same as timeUs. Use
+ * {@link OPTION_CLOSEST} if one wants to retrieve a frame that may
+ * or may not be a sync frame but is closest to or the same as timeUs.
+ * {@link OPTION_CLOSEST} often has larger performance overhead compared
+ * to the other options if there is no sync frame located at timeUs.
+ *
* @return A Bitmap containing a representative video frame, which
* can be null, if such a frame cannot be retrieved.
*/
- public native Bitmap captureFrame();
+ public Bitmap getFrameAtTime(long timeUs, int option) {
+ if (option < OPTION_PREVIOUS_SYNC ||
+ option > OPTION_CLOSEST) {
+ throw new IllegalArgumentException("Unsupported option: " + option);
+ }
+
+ return _getFrameAtTime(timeUs, option);
+ }
+
+ /**
+ * Call this method after setDataSource(). This method finds a
+ * representative frame close to the given time position if possible,
+ * and returns it as a bitmap. This is useful for generating a thumbnail
+ * for an input data source. Call this method if one does not care
+ * how the frame is found as long as it is close to the given time;
+ * otherwise, please call {@link getFrameAtTime(long, int)}.
+ *
+ * @param timeUs The time position where the frame will be retrieved.
+ * When retrieving the frame at the given time position, there is no
+ * guarentee that the data source has a frame located at the position.
+ * When this happens, a frame nearby will be returned. If timeUs is
+ * negative, time position and option will ignored, and any frame
+ * that the implementation considers as representative may be returned.
+ *
+ * @return A Bitmap containing a representative video frame, which
+ * can be null, if such a frame cannot be retrieved.
+ *
+ * @see #getFrameAtTime(long, int)
+ */
+ public Bitmap getFrameAtTime(long timeUs) {
+ return getFrameAtTime(timeUs, OPTION_CLOSEST_SYNC);
+ }
+
+ /**
+ * Call this method after setDataSource(). This method finds a
+ * representative frame at any time position if possible,
+ * and returns it as a bitmap. This is useful for generating a thumbnail
+ * for an input data source. Call this method if one does not
+ * care about where the frame is located; otherwise, please call
+ * {@link getFrameAtTime(long)} or {@link getFrameAtTime(long, int)}
+ *
+ * @return A Bitmap containing a representative video frame, which
+ * can be null, if such a frame cannot be retrieved.
+ *
+ * @see #getFrameAtTime(long)
+ * @see #getFrameAtTime(long, int)
+ */
+ public Bitmap getFrameAtTime() {
+ return getFrameAtTime(-1, OPTION_CLOSEST_SYNC);
+ }
+
+ /**
+ * FIXME
+ * To be removed and replaced by getFrameAt().
+ */
+ public Bitmap captureFrame() {
+ return _getFrameAtTime(-1, OPTION_CLOSEST_SYNC);
+ }
+
+ private native Bitmap _getFrameAtTime(long timeUs, int option);
+
/**
* Call this method after setDataSource(). This method finds the optional
@@ -229,6 +304,20 @@ public class MediaMetadataRetriever
public static final int MODE_GET_METADATA_ONLY = 0x01;
public static final int MODE_CAPTURE_FRAME_ONLY = 0x02;
+ /**
+ * Option used in method {@link getFrameAtTime(long, int)} to get a
+ * frame at a specified location.
+ *
+ * @see #getFrameAtTime(long, int)
+ */
+ /* Do not change these values without updating their counterparts
+ * in include/media/stagefright/MediaSource.h!
+ */
+ public static final int OPTION_PREVIOUS_SYNC = 0x00;
+ public static final int OPTION_NEXT_SYNC = 0x01;
+ public static final int OPTION_CLOSEST_SYNC = 0x02;
+ public static final int OPTION_CLOSEST = 0x03;
+
/*
* Do not change these values without updating their counterparts
* in include/media/mediametadataretriever.h!
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 63e9dc8..5904bfe 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -142,22 +142,9 @@ static void android_media_MediaMetadataRetriever_setMode(JNIEnv *env, jobject th
process_media_retriever_call(env, retriever->setMode(mode), "java/lang/RuntimeException", "setMode failed");
}
-static int android_media_MediaMetadataRetriever_getMode(JNIEnv *env, jobject thiz)
+static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option)
{
- LOGV("getMode");
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
- if (retriever == 0) {
- jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
- return -1; // Error
- }
- int mode = -1;
- retriever->getMode(&mode);
- return mode;
-}
-
-static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jobject thiz)
-{
- LOGV("captureFrame");
+ LOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
MediaMetadataRetriever* retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
@@ -166,12 +153,12 @@ static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jo
// Call native method to retrieve a video frame
VideoFrame *videoFrame = NULL;
- sp<IMemory> frameMemory = retriever->captureFrame();
+ sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option);
if (frameMemory != 0) { // cast the shared structure to a VideoFrame object
videoFrame = static_cast<VideoFrame *>(frameMemory->pointer());
}
if (videoFrame == NULL) {
- LOGE("captureFrame: videoFrame is a NULL pointer");
+ LOGE("getFrameAtTime: videoFrame is a NULL pointer");
return NULL;
}
@@ -213,7 +200,7 @@ static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jo
// Create a SkBitmap to hold the pixels
SkBitmap *bitmap = new SkBitmap();
if (bitmap == NULL) {
- LOGE("captureFrame: cannot instantiate a SkBitmap object.");
+ LOGE("getFrameAtTime: cannot instantiate a SkBitmap object.");
return NULL;
}
bitmap->setConfig(SkBitmap::kRGB_565_Config, videoFrame->mDisplayWidth, videoFrame->mDisplayHeight);
@@ -366,8 +353,7 @@ static JNINativeMethod nativeMethods[] = {
{"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaMetadataRetriever_setDataSource},
{"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
{"setMode", "(I)V", (void *)android_media_MediaMetadataRetriever_setMode},
- {"getMode", "()I", (void *)android_media_MediaMetadataRetriever_getMode},
- {"captureFrame", "()Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_captureFrame},
+ {"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
{"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata},
{"extractAlbumArt", "()[B", (void *)android_media_MediaMetadataRetriever_extractAlbumArt},
{"release", "()V", (void *)android_media_MediaMetadataRetriever_release},
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index e529d25..0193e25 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -82,8 +82,7 @@ enum {
SET_DATA_SOURCE_URL,
SET_DATA_SOURCE_FD,
SET_MODE,
- GET_MODE,
- CAPTURE_FRAME,
+ GET_FRAME_AT_TIME,
EXTRACT_ALBUM_ART,
EXTRACT_METADATA,
};
@@ -133,23 +132,17 @@ public:
return reply.readInt32();
}
- status_t getMode(int* mode) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
- remote()->transact(GET_MODE, data, &reply);
- *mode = reply.readInt32();
- return reply.readInt32();
- }
-
- sp<IMemory> captureFrame()
+ sp<IMemory> getFrameAtTime(int64_t timeUs, int option)
{
+ LOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
Parcel data, reply;
data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+ data.writeInt64(timeUs);
+ data.writeInt32(option);
#ifndef DISABLE_GROUP_SCHEDULE_HACK
sendSchedPolicy(data);
#endif
- remote()->transact(CAPTURE_FRAME, data, &reply);
+ remote()->transact(GET_FRAME_AT_TIME, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
return NULL;
@@ -222,20 +215,15 @@ status_t BnMediaMetadataRetriever::onTransact(
reply->writeInt32(setMode(mode));
return NO_ERROR;
} break;
- case GET_MODE: {
- CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
- int mode;
- status_t status = getMode(&mode);
- reply->writeInt32(mode);
- reply->writeInt32(status);
- return NO_ERROR;
- } break;
- case CAPTURE_FRAME: {
+ case GET_FRAME_AT_TIME: {
CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+ int64_t timeUs = data.readInt64();
+ int option = data.readInt32();
+ LOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
#ifndef DISABLE_GROUP_SCHEDULE_HACK
setSchedPolicy(data);
#endif
- sp<IMemory> bitmap = captureFrame();
+ sp<IMemory> bitmap = getFrameAtTime(timeUs, option);
if (bitmap != 0) { // Don't send NULL across the binder interface
reply->writeInt32(NO_ERROR);
reply->writeStrongBinder(bitmap->asBinder());
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index e2712ba..39b5bc3 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -134,26 +134,15 @@ status_t MediaMetadataRetriever::setMode(int mode)
return mRetriever->setMode(mode);
}
-status_t MediaMetadataRetriever::getMode(int* mode)
+sp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option)
{
- LOGV("getMode");
- Mutex::Autolock _l(mLock);
- if (mRetriever == 0) {
- LOGE("retriever is not initialized");
- return INVALID_OPERATION;
- }
- return mRetriever->getMode(mode);
-}
-
-sp<IMemory> MediaMetadataRetriever::captureFrame()
-{
- LOGV("captureFrame");
+ LOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
Mutex::Autolock _l(mLock);
if (mRetriever == 0) {
LOGE("retriever is not initialized");
return NULL;
}
- return mRetriever->captureFrame();
+ return mRetriever->getFrameAtTime(timeUs, option);
}
const char* MediaMetadataRetriever::extractMetadata(int keyCode)
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index b069345..abaec02 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -196,33 +196,16 @@ status_t MetadataRetrieverClient::setMode(int mode)
return NO_ERROR;
}
-status_t MetadataRetrieverClient::getMode(int* mode) const
+sp<IMemory> MetadataRetrieverClient::getFrameAtTime(int64_t timeUs, int option)
{
- LOGV("getMode");
- Mutex::Autolock lock(mLock);
-
- // TODO:
- // This may not be necessary.
- // If setDataSource() has not been called, return the cached value
- // otherwise, return the value retrieved from the retriever
- if (mRetriever == NULL) {
- *mode = mMode;
- } else {
- mRetriever->getMode(mode);
- }
- return NO_ERROR;
-}
-
-sp<IMemory> MetadataRetrieverClient::captureFrame()
-{
- LOGV("captureFrame");
+ LOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
Mutex::Autolock lock(mLock);
mThumbnail.clear();
if (mRetriever == NULL) {
LOGE("retriever is not initialized");
return NULL;
}
- VideoFrame *frame = mRetriever->captureFrame();
+ VideoFrame *frame = mRetriever->getFrameAtTime(timeUs, option);
if (frame == NULL) {
LOGE("failed to capture a video frame");
return NULL;
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index 4aab94f..8b4c0c7 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -44,8 +44,7 @@ public:
virtual status_t setDataSource(const char *url);
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
virtual status_t setMode(int mode);
- virtual status_t getMode(int* mode) const;
- virtual sp<IMemory> captureFrame();
+ virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option);
virtual sp<IMemory> extractAlbumArt();
virtual const char* extractMetadata(int keyCode);
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 763a914..c28de93 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -108,7 +108,10 @@ status_t StagefrightMetadataRetriever::setDataSource(
static VideoFrame *extractVideoFrameWithCodecFlags(
OMXClient *client,
const sp<MetaData> &trackMeta,
- const sp<MediaSource> &source, uint32_t flags) {
+ const sp<MediaSource> &source,
+ uint32_t flags,
+ int64_t frameTimeUs,
+ int seekMode) {
sp<MediaSource> decoder =
OMXCodec::Create(
client->interface(), source->getFormat(), false, source,
@@ -130,11 +133,22 @@ static VideoFrame *extractVideoFrameWithCodecFlags(
// and spurious empty buffers.
MediaSource::ReadOptions options;
+ if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC ||
+ seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) {
+
+ LOGE("Unknown seek mode: %d", seekMode);
+ return NULL;
+ }
+
+ MediaSource::ReadOptions::SeekMode mode =
+ static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
+
int64_t thumbNailTime;
- if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
- options.setSeekTo(thumbNailTime);
+ if (frameTimeUs < 0 && trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
+ options.setSeekTo(thumbNailTime, mode);
} else {
thumbNailTime = -1;
+ options.setSeekTo(frameTimeUs, mode);
}
MediaBuffer *buffer = NULL;
@@ -238,9 +252,10 @@ static VideoFrame *extractVideoFrameWithCodecFlags(
return frame;
}
-VideoFrame *StagefrightMetadataRetriever::captureFrame() {
- LOGV("captureFrame");
+VideoFrame *StagefrightMetadataRetriever::getFrameAtTime(
+ int64_t timeUs, int option) {
+ LOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
if (0 == (mMode & METADATA_MODE_FRAME_CAPTURE_ONLY)) {
LOGV("captureFrame disabled by mode (0x%08x)", mMode);
@@ -282,13 +297,15 @@ VideoFrame *StagefrightMetadataRetriever::captureFrame() {
VideoFrame *frame =
extractVideoFrameWithCodecFlags(
- &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs);
+ &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs,
+ timeUs, option);
if (frame == NULL) {
LOGV("Software decoder failed to extract thumbnail, "
"trying hardware decoder.");
- frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0);
+ frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0,
+ timeUs, option);
}
return frame;
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h
index b80387f..07b1ec8 100644
--- a/media/libstagefright/include/StagefrightMetadataRetriever.h
+++ b/media/libstagefright/include/StagefrightMetadataRetriever.h
@@ -35,7 +35,7 @@ struct StagefrightMetadataRetriever : public MediaMetadataRetrieverInterface {
virtual status_t setDataSource(const char *url);
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual VideoFrame *captureFrame();
+ virtual VideoFrame *getFrameAtTime(int64_t timeUs, int option);
virtual MediaAlbumArt *extractAlbumArt();
virtual const char *extractMetadata(int keyCode);