summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Nelissen <marcone@google.com>2012-08-24 09:55:44 -0700
committerMarco Nelissen <marcone@google.com>2012-08-24 10:36:51 -0700
commitc209a06cfdcf633f12a299245312e3ac32bff27c (patch)
tree036c6847186f84384127378e914da23326f3a969
parent6715d1effaa70abf261112d2771d4d555cc109c2 (diff)
downloadframeworks_base-c209a06cfdcf633f12a299245312e3ac32bff27c.zip
frameworks_base-c209a06cfdcf633f12a299245312e3ac32bff27c.tar.gz
frameworks_base-c209a06cfdcf633f12a299245312e3ac32bff27c.tar.bz2
Let apps provide a custom data source for extractors
Adds android.media.DataSource, which is modeled after its native namesake, and a new method on MediaExtractor that lets apps specify their implementation of a DataSource as the source of data for the extractor. Change-Id: If1b169bd18d2691ebc4f8996494dfc8ee0894b6c
-rw-r--r--media/java/android/media/DataSource.java43
-rw-r--r--media/java/android/media/MediaExtractor.java7
-rw-r--r--media/jni/android_media_MediaExtractor.cpp100
-rw-r--r--media/jni/android_media_MediaExtractor.h2
4 files changed, 152 insertions, 0 deletions
diff --git a/media/java/android/media/DataSource.java b/media/java/android/media/DataSource.java
new file mode 100644
index 0000000..347bd5f
--- /dev/null
+++ b/media/java/android/media/DataSource.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.media;
+
+import java.io.Closeable;
+
+/**
+ * An abstraction for a media data source, e.g. a file or an http stream
+ * {@hide}
+ */
+public interface DataSource extends Closeable {
+ /**
+ * Reads data from the data source at the requested position
+ *
+ * @param offset where in the source to read
+ * @param buffer the buffer to read the data into
+ * @param size how many bytes to read
+ * @return the number of bytes read, or -1 if there was an error
+ */
+ public int readAt(long offset, byte[] buffer, int size);
+
+ /**
+ * Gets the size of the data source.
+ *
+ * @return size of data source, or -1 if the length is unknown
+ */
+ public long getSize();
+}
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 687d3a5..4b8d3cb 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -22,6 +22,7 @@ import android.content.res.AssetFileDescriptor;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.net.Uri;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -60,6 +61,12 @@ final public class MediaExtractor {
}
/**
+ * Sets the DataSource object to be used as the data source for this extractor
+ * {@hide}
+ */
+ public native final void setDataSource(DataSource source);
+
+ /**
* Sets the data source as a content Uri.
*
* @param context the Context to use when resolving the Uri
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 351ff04..23949fa 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -44,6 +44,72 @@ struct fields_t {
static fields_t gFields;
+class JavaDataSourceBridge : public DataSource {
+ jmethodID mReadMethod;
+ jmethodID mGetSizeMethod;
+ jmethodID mCloseMethod;
+ jobject mDataSource;
+ public:
+ JavaDataSourceBridge(JNIEnv *env, jobject source) {
+ mDataSource = env->NewGlobalRef(source);
+
+ jclass datasourceclass = env->GetObjectClass(mDataSource);
+ CHECK(datasourceclass != NULL);
+
+ mReadMethod = env->GetMethodID(datasourceclass, "readAt", "(J[BI)I");
+ CHECK(mReadMethod != NULL);
+
+ mGetSizeMethod = env->GetMethodID(datasourceclass, "getSize", "()J");
+ CHECK(mGetSizeMethod != NULL);
+
+ mCloseMethod = env->GetMethodID(datasourceclass, "close", "()V");
+ CHECK(mCloseMethod != NULL);
+ }
+
+ ~JavaDataSourceBridge() {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mDataSource, mCloseMethod);
+ env->DeleteGlobalRef(mDataSource);
+ }
+
+ virtual status_t initCheck() const {
+ return OK;
+ }
+
+ virtual ssize_t readAt(off64_t offset, void* buffer, size_t size) {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ // XXX could optimize this by reusing the same array
+ jbyteArray byteArrayObj = env->NewByteArray(size);
+ env->DeleteLocalRef(env->GetObjectClass(mDataSource));
+ env->DeleteLocalRef(env->GetObjectClass(byteArrayObj));
+ ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, size);
+ env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer);
+ env->DeleteLocalRef(byteArrayObj);
+ if (env->ExceptionCheck()) {
+ ALOGW("Exception occurred while reading %d at %lld", size, offset);
+ LOGW_EX(env);
+ env->ExceptionClear();
+ return -1;
+ }
+ return numread;
+ }
+
+ virtual status_t getSize(off64_t *size) {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ CHECK(size != NULL);
+
+ int64_t len = env->CallLongMethod(mDataSource, mGetSizeMethod);
+ if (len < 0) {
+ *size = ERROR_UNSUPPORTED;
+ } else {
+ *size = len;
+ }
+ return OK;
+ }
+};
+
////////////////////////////////////////////////////////////////////////////////
JMediaExtractor::JMediaExtractor(JNIEnv *env, jobject thiz)
@@ -76,6 +142,10 @@ status_t JMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) {
return mImpl->setDataSource(fd, offset, size);
}
+status_t JMediaExtractor::setDataSource(const sp<DataSource> &datasource) {
+ return mImpl->setDataSource(datasource);
+}
+
size_t JMediaExtractor::countTracks() const {
return mImpl->countTracks();
}
@@ -625,6 +695,33 @@ static void android_media_MediaExtractor_setDataSourceFd(
}
}
+static void android_media_MediaExtractor_setDataSourceCallback(
+ JNIEnv *env, jobject thiz,
+ jobject callbackObj) {
+ sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+ if (extractor == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+
+ if (callbackObj == NULL) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ return;
+ }
+
+ sp<JavaDataSourceBridge> bridge = new JavaDataSourceBridge(env, callbackObj);
+ status_t err = extractor->setDataSource(bridge);
+
+ if (err != OK) {
+ jniThrowException(
+ env,
+ "java/io/IOException",
+ "Failed to instantiate extractor.");
+ return;
+ }
+}
+
static jlong android_media_MediaExtractor_getCachedDurationUs(
JNIEnv *env, jobject thiz) {
sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
@@ -713,6 +810,9 @@ static JNINativeMethod gMethods[] = {
{ "setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
(void *)android_media_MediaExtractor_setDataSourceFd },
+ { "setDataSource", "(Landroid/media/DataSource;)V",
+ (void *)android_media_MediaExtractor_setDataSourceCallback },
+
{ "getCachedDuration", "()J",
(void *)android_media_MediaExtractor_getCachedDurationUs },
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index 2d4627e..03900db 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -19,6 +19,7 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/DataSource.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
@@ -39,6 +40,7 @@ struct JMediaExtractor : public RefBase {
const KeyedVector<String8, String8> *headers);
status_t setDataSource(int fd, off64_t offset, off64_t size);
+ status_t setDataSource(const sp<DataSource> &source);
size_t countTracks() const;
status_t getTrackFormat(size_t index, jobject *format) const;