Merge "Let apps provide a custom data source for extractors" into jb-mr1-dev

This commit is contained in:
Marco Nelissen
2012-08-24 10:59:15 -07:00
committed by Android (Google) Code Review
4 changed files with 152 additions and 0 deletions

View File

@@ -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();
}

View File

@@ -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;
@@ -59,6 +60,12 @@ final public class MediaExtractor {
native_setup();
}
/**
* 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.
*

View File

@@ -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 },

View File

@@ -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;