Loading media/java/android/media/DataSource.java 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * 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(); } media/java/android/media/MediaExtractor.java +7 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading media/jni/android_media_MediaExtractor.cpp +100 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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(); } Loading Loading @@ -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); Loading Loading @@ -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 }, Loading media/jni/android_media_MediaExtractor.h +2 −0 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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; Loading Loading
media/java/android/media/DataSource.java 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * 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(); }
media/java/android/media/MediaExtractor.java +7 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading
media/jni/android_media_MediaExtractor.cpp +100 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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(); } Loading Loading @@ -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); Loading Loading @@ -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 }, Loading
media/jni/android_media_MediaExtractor.h +2 −0 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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; Loading