The MediaExtractor can now unselect tracks and has more control over seeking.
Change-Id: I12c28bf31fe9fb4057352999fa38213ae289a417
related-to-bug: 6276111
diff --git a/api/current.txt b/api/current.txt
index d04025c..28eb8f1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11076,15 +11076,20 @@
method public boolean hasCacheReachedEndOfStream();
method public int readSampleData(java.nio.ByteBuffer, int);
method public final void release();
- method public void seekTo(long);
+ method public void seekTo(long, int);
method public void selectTrack(int);
method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
method public final void setDataSource(java.lang.String);
method public final void setDataSource(java.io.FileDescriptor);
method public final void setDataSource(java.io.FileDescriptor, long, long);
+ method public void unselectTrack(int);
field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2
field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
+ field public static final int SEEK_TO_CLOSEST = 3; // 0x3
+ field public static final int SEEK_TO_CLOSEST_SYNC = 2; // 0x2
+ field public static final int SEEK_TO_NEXT_SYNC = 1; // 0x1
+ field public static final int SEEK_TO_PREVIOUS_SYNC = 0; // 0x0
}
public class MediaMetadataRetriever {
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 9fdb81f..5fe58a8 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -191,17 +191,33 @@
/** Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and
* {@link #getSampleTime} only retrieve information for the subset of tracks
- * selected by the call below.
- * Selecting the same track multiple times has no effect, the track
+ * selected.
+ * Selecting the same track multiple times has no effect, the track is
* only selected once.
- * Media data will be returned in the order of their timestamps.
*/
public native void selectTrack(int index);
- /** All selected tracks seek near the requested time. The next sample
- * returned for each selected track will be a sync sample.
+ /** Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and
+ * {@link #getSampleTime} only retrieve information for the subset of tracks
+ * selected.
*/
- public native void seekTo(long timeUs);
+ public native void unselectTrack(int index);
+
+ /** If possible, seek to a sync sample at or before the specified time */
+ public static final int SEEK_TO_PREVIOUS_SYNC = 0;
+ /** If possible, seek to a sync sample at or after the specified time */
+ public static final int SEEK_TO_NEXT_SYNC = 1;
+ /** If possible, seek to the sync sample closest to the specified time */
+ public static final int SEEK_TO_CLOSEST_SYNC = 2;
+ /** If possible, seek to a sample closest to the specified time, which may
+ * NOT be a sync sample!
+ */
+ public static final int SEEK_TO_CLOSEST = 3;
+
+ /** All selected tracks seek near the requested time according to the
+ * specified mode.
+ */
+ public native void seekTo(long timeUs, int mode);
/** Advance to the next sample. Returns false if no more sample data
* is available (end of stream).
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 0518331..9e1920c 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -96,8 +96,13 @@
return mImpl->selectTrack(index);
}
-status_t JMediaExtractor::seekTo(int64_t timeUs) {
- return mImpl->seekTo(timeUs);
+status_t JMediaExtractor::unselectTrack(size_t index) {
+ return mImpl->unselectTrack(index);
+}
+
+status_t JMediaExtractor::seekTo(
+ int64_t timeUs, MediaSource::ReadOptions::SeekMode mode) {
+ return mImpl->seekTo(timeUs, mode);
}
status_t JMediaExtractor::advance() {
@@ -281,8 +286,8 @@
}
}
-static void android_media_MediaExtractor_seekTo(
- JNIEnv *env, jobject thiz, jlong timeUs) {
+static void android_media_MediaExtractor_unselectTrack(
+ JNIEnv *env, jobject thiz, jint index) {
sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
if (extractor == NULL) {
@@ -290,7 +295,30 @@
return;
}
- extractor->seekTo(timeUs);
+ status_t err = extractor->unselectTrack(index);
+
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ return;
+ }
+}
+
+static void android_media_MediaExtractor_seekTo(
+ JNIEnv *env, jobject thiz, jlong timeUs, jint mode) {
+ sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+ if (extractor == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+
+ if (mode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC
+ || mode > MediaSource::ReadOptions::SEEK_CLOSEST) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ return;
+ }
+
+ extractor->seekTo(timeUs, (MediaSource::ReadOptions::SeekMode)mode);
}
static jboolean android_media_MediaExtractor_advance(
@@ -648,7 +676,10 @@
{ "selectTrack", "(I)V", (void *)android_media_MediaExtractor_selectTrack },
- { "seekTo", "(J)V", (void *)android_media_MediaExtractor_seekTo },
+ { "unselectTrack", "(I)V",
+ (void *)android_media_MediaExtractor_unselectTrack },
+
+ { "seekTo", "(JI)V", (void *)android_media_MediaExtractor_seekTo },
{ "advance", "()Z", (void *)android_media_MediaExtractor_advance },
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index ef0c48b..2d4627e 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -18,6 +18,7 @@
#define _ANDROID_MEDIA_MEDIAEXTRACTOR_H_
#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSource.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
@@ -43,8 +44,9 @@
status_t getTrackFormat(size_t index, jobject *format) const;
status_t selectTrack(size_t index);
+ status_t unselectTrack(size_t index);
- status_t seekTo(int64_t timeUs);
+ status_t seekTo(int64_t timeUs, MediaSource::ReadOptions::SeekMode mode);
status_t advance();
status_t readSampleData(jobject byteBuf, size_t offset, size_t *sampleSize);