Merge "Unhide the android.media.[Media]DataSource interface."
This commit is contained in:
committed by
Android (Google) Code Review
commit
56d16568c0
@@ -15564,6 +15564,11 @@ package android.media {
|
||||
ctor public MediaCryptoException(java.lang.String);
|
||||
}
|
||||
|
||||
public abstract interface MediaDataSource implements java.io.Closeable {
|
||||
method public abstract long getSize();
|
||||
method public abstract int readAt(long, byte[], int);
|
||||
}
|
||||
|
||||
public class MediaDescription implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public java.lang.CharSequence getDescription();
|
||||
@@ -15699,6 +15704,7 @@ package android.media {
|
||||
method public final void release();
|
||||
method public void seekTo(long, int);
|
||||
method public void selectTrack(int);
|
||||
method public final void setDataSource(android.media.MediaDataSource) throws java.io.IOException, java.lang.IllegalArgumentException;
|
||||
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>) throws java.io.IOException;
|
||||
method public final void setDataSource(java.lang.String) throws java.io.IOException;
|
||||
@@ -15878,6 +15884,7 @@ package android.media {
|
||||
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.lang.IllegalArgumentException;
|
||||
method public void setDataSource(java.io.FileDescriptor) throws java.lang.IllegalArgumentException;
|
||||
method public void setDataSource(android.content.Context, android.net.Uri) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
|
||||
method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException;
|
||||
field public static final int METADATA_KEY_ALBUM = 1; // 0x1
|
||||
field public static final int METADATA_KEY_ALBUMARTIST = 13; // 0xd
|
||||
field public static final int METADATA_KEY_ARTIST = 2; // 0x2
|
||||
@@ -15962,6 +15969,7 @@ package android.media {
|
||||
method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
|
||||
method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||
method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||
method public void setDisplay(android.view.SurfaceHolder);
|
||||
method public void setLooping(boolean);
|
||||
method public void setNextMediaPlayer(android.media.MediaPlayer);
|
||||
|
||||
@@ -16776,6 +16776,11 @@ package android.media {
|
||||
ctor public MediaCryptoException(java.lang.String);
|
||||
}
|
||||
|
||||
public abstract interface MediaDataSource implements java.io.Closeable {
|
||||
method public abstract long getSize();
|
||||
method public abstract int readAt(long, byte[], int);
|
||||
}
|
||||
|
||||
public class MediaDescription implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public java.lang.CharSequence getDescription();
|
||||
@@ -16912,6 +16917,7 @@ package android.media {
|
||||
method public final void release();
|
||||
method public void seekTo(long, int);
|
||||
method public void selectTrack(int);
|
||||
method public final void setDataSource(android.media.MediaDataSource) throws java.io.IOException, java.lang.IllegalArgumentException;
|
||||
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>) throws java.io.IOException;
|
||||
method public final void setDataSource(java.lang.String) throws java.io.IOException;
|
||||
@@ -17091,6 +17097,7 @@ package android.media {
|
||||
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.lang.IllegalArgumentException;
|
||||
method public void setDataSource(java.io.FileDescriptor) throws java.lang.IllegalArgumentException;
|
||||
method public void setDataSource(android.content.Context, android.net.Uri) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
|
||||
method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException;
|
||||
field public static final int METADATA_KEY_ALBUM = 1; // 0x1
|
||||
field public static final int METADATA_KEY_ALBUMARTIST = 13; // 0xd
|
||||
field public static final int METADATA_KEY_ARTIST = 2; // 0x2
|
||||
@@ -17175,6 +17182,7 @@ package android.media {
|
||||
method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
|
||||
method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||
method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
|
||||
method public void setDisplay(android.view.SurfaceHolder);
|
||||
method public void setLooping(boolean);
|
||||
method public void setNextMediaPlayer(android.media.MediaPlayer);
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
62
media/java/android/media/MediaDataSource.java
Normal file
62
media/java/android/media/MediaDataSource.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* For supplying media data to the framework. Implement this if your app has
|
||||
* special requirements for the way media data is obtained.
|
||||
*
|
||||
* <p class="note">Methods of this interface may be called on multiple different
|
||||
* threads. There will be a thread synchronization point between each call to ensure that
|
||||
* modifications to the state of your MediaDataSource are visible to future calls. This means
|
||||
* you don't need to do your own synchronization unless you're modifying the
|
||||
* MediaDataSource from another thread while it's being used by the framework.</p>
|
||||
*/
|
||||
public interface MediaDataSource extends Closeable {
|
||||
/**
|
||||
* Called to request data from the given position.
|
||||
*
|
||||
* Implementations should should write up to {@code size} bytes into
|
||||
* {@code buffer}, and return the number of bytes written.
|
||||
*
|
||||
* Return {@code 0} to indicate that {@code position} is at, or beyond, the
|
||||
* end of the source.
|
||||
*
|
||||
* Return {@code -1} to indicate that a fatal error occurred. The failed
|
||||
* read will not be retried, so transient errors should be handled
|
||||
* internally.
|
||||
*
|
||||
* Throwing an exception from this method will have the same effect as
|
||||
* returning {@code -1}.
|
||||
*
|
||||
* @param position the position in the data source to read from.
|
||||
* @param buffer the buffer to read the data into.
|
||||
* @param size the number of bytes to read.
|
||||
* @return the number of bytes read, or -1 if there was an error.
|
||||
*/
|
||||
public int readAt(long position, byte[] buffer, int size);
|
||||
|
||||
/**
|
||||
* Called to get the size of the data source.
|
||||
*
|
||||
* @return the size of data source in bytes, or -1 if the size is unknown.
|
||||
*/
|
||||
public long getSize();
|
||||
}
|
||||
@@ -66,10 +66,11 @@ final public class MediaExtractor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the DataSource object to be used as the data source for this extractor
|
||||
* {@hide}
|
||||
* Sets the data source (MediaDataSource) to use.
|
||||
*
|
||||
* @param dataSource the MediaDataSource for the media you want to extract from
|
||||
*/
|
||||
public native final void setDataSource(DataSource source) throws IOException;
|
||||
public native final void setDataSource(MediaDataSource dataSource) throws IllegalArgumentException, IOException;
|
||||
|
||||
/**
|
||||
* Sets the data source as a content Uri.
|
||||
|
||||
@@ -203,7 +203,20 @@ public class MediaMetadataRetriever
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method after setDataSource(). This method retrieves the
|
||||
* Sets the data source (MediaDataSource) to use.
|
||||
*
|
||||
* @param dataSource the MediaDataSource for the media you want to play
|
||||
*/
|
||||
public void setDataSource(MediaDataSource dataSource)
|
||||
throws IllegalArgumentException {
|
||||
_setDataSource(dataSource);
|
||||
}
|
||||
|
||||
private native void _setDataSource(MediaDataSource dataSource)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Call this method after setDataSource(). This method retrieves the
|
||||
* meta data value associated with the keyCode.
|
||||
*
|
||||
* The keyCode currently supported is listed below as METADATA_XXX
|
||||
|
||||
@@ -181,7 +181,8 @@ import java.lang.ref.WeakReference;
|
||||
* {@link #setDataSource(FileDescriptor)}, or
|
||||
* {@link #setDataSource(String)}, or
|
||||
* {@link #setDataSource(Context, Uri)}, or
|
||||
* {@link #setDataSource(FileDescriptor, long, long)} transfers a
|
||||
* {@link #setDataSource(FileDescriptor, long, long)}, or
|
||||
* {@link #setDataSource(MediaDataSource)} transfers a
|
||||
* MediaPlayer object in the <em>Idle</em> state to the
|
||||
* <em>Initialized</em> state.
|
||||
* <ul>
|
||||
@@ -1126,6 +1127,20 @@ public class MediaPlayer implements SubtitleController.Listener
|
||||
private native void _setDataSource(FileDescriptor fd, long offset, long length)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Sets the data source (MediaDataSource) to use.
|
||||
*
|
||||
* @param dataSource the MediaDataSource for the media you want to play
|
||||
* @throws IllegalStateException if it is called in an invalid state
|
||||
*/
|
||||
public void setDataSource(MediaDataSource dataSource)
|
||||
throws IllegalArgumentException, IllegalStateException {
|
||||
_setDataSource(dataSource);
|
||||
}
|
||||
|
||||
private native void _setDataSource(MediaDataSource dataSource)
|
||||
throws IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Prepares the player for playback, synchronously.
|
||||
*
|
||||
|
||||
@@ -7,6 +7,7 @@ LOCAL_SRC_FILES:= \
|
||||
android_media_MediaCrypto.cpp \
|
||||
android_media_MediaCodec.cpp \
|
||||
android_media_MediaCodecList.cpp \
|
||||
android_media_MediaDataSource.cpp \
|
||||
android_media_MediaDrm.cpp \
|
||||
android_media_MediaExtractor.cpp \
|
||||
android_media_MediaHTTPConnection.cpp \
|
||||
|
||||
148
media/jni/android_media_MediaDataSource.cpp
Normal file
148
media/jni/android_media_MediaDataSource.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "JMediaDataSource-JNI"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "android_media_MediaDataSource.h"
|
||||
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "android_runtime/Log.h"
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
|
||||
#include <binder/MemoryDealer.h>
|
||||
#include <media/stagefright/foundation/ADebug.h>
|
||||
#include <nativehelper/ScopedLocalRef.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
JMediaDataSource::JMediaDataSource(JNIEnv* env, jobject source)
|
||||
: mJavaObjStatus(OK), mSizeIsCached(false), mCachedSize(0), mMemory(NULL) {
|
||||
mMediaDataSourceObj = env->NewGlobalRef(source);
|
||||
CHECK(mMediaDataSourceObj != NULL);
|
||||
|
||||
ScopedLocalRef<jclass> mediaDataSourceClass(env, env->GetObjectClass(mMediaDataSourceObj));
|
||||
CHECK(mediaDataSourceClass.get() != NULL);
|
||||
|
||||
mReadMethod = env->GetMethodID(mediaDataSourceClass.get(), "readAt", "(J[BI)I");
|
||||
CHECK(mReadMethod != NULL);
|
||||
mGetSizeMethod = env->GetMethodID(mediaDataSourceClass.get(), "getSize", "()J");
|
||||
CHECK(mGetSizeMethod != NULL);
|
||||
mCloseMethod = env->GetMethodID(mediaDataSourceClass.get(), "close", "()V");
|
||||
CHECK(mCloseMethod != NULL);
|
||||
|
||||
ScopedLocalRef<jbyteArray> tmp(env, env->NewByteArray(kBufferSize));
|
||||
mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get());
|
||||
CHECK(mByteArrayObj != NULL);
|
||||
|
||||
sp<MemoryDealer> memoryDealer = new MemoryDealer(kBufferSize, "JMediaDataSource");
|
||||
mMemory = memoryDealer->allocate(kBufferSize);
|
||||
if (mMemory == NULL) {
|
||||
ALOGE("Failed to allocate memory!");
|
||||
}
|
||||
}
|
||||
|
||||
JMediaDataSource::~JMediaDataSource() {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
env->DeleteGlobalRef(mMediaDataSourceObj);
|
||||
env->DeleteGlobalRef(mByteArrayObj);
|
||||
}
|
||||
|
||||
sp<IMemory> JMediaDataSource::getIMemory() {
|
||||
Mutex::Autolock lock(mLock);
|
||||
return mMemory;
|
||||
}
|
||||
|
||||
ssize_t JMediaDataSource::readAt(off64_t offset, size_t size) {
|
||||
Mutex::Autolock lock(mLock);
|
||||
|
||||
if (mJavaObjStatus != OK || mMemory == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (size > kBufferSize) {
|
||||
size = kBufferSize;
|
||||
}
|
||||
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
jint numread = env->CallIntMethod(mMediaDataSourceObj, mReadMethod,
|
||||
(jlong)offset, mByteArrayObj, (jint)size);
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGW("An exception occurred in readAt()");
|
||||
LOGW_EX(env);
|
||||
env->ExceptionClear();
|
||||
mJavaObjStatus = UNKNOWN_ERROR;
|
||||
return -1;
|
||||
}
|
||||
if (numread < 0) {
|
||||
ALOGW("An error occurred in readAt()");
|
||||
mJavaObjStatus = UNKNOWN_ERROR;
|
||||
return -1;
|
||||
}
|
||||
if ((size_t)numread > size) {
|
||||
ALOGE("readAt read too many bytes.");
|
||||
mJavaObjStatus = UNKNOWN_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ALOGV("readAt %lld / %zu => %d.", (long long)offset, size, numread);
|
||||
env->GetByteArrayRegion(mByteArrayObj, 0, numread, (jbyte*)mMemory->pointer());
|
||||
return numread;
|
||||
}
|
||||
|
||||
status_t JMediaDataSource::getSize(off64_t* size) {
|
||||
Mutex::Autolock lock(mLock);
|
||||
|
||||
if (mJavaObjStatus != OK) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
if (mSizeIsCached) {
|
||||
return mCachedSize;
|
||||
}
|
||||
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
*size = env->CallLongMethod(mMediaDataSourceObj, mGetSizeMethod);
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGW("An exception occurred in getSize()");
|
||||
LOGW_EX(env);
|
||||
env->ExceptionClear();
|
||||
// After returning an error, size shouldn't be used by callers.
|
||||
*size = UNKNOWN_ERROR;
|
||||
mJavaObjStatus = UNKNOWN_ERROR;
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// The minimum size should be -1, which indicates unknown size.
|
||||
if (*size < 0) {
|
||||
*size = -1;
|
||||
}
|
||||
|
||||
mCachedSize = *size;
|
||||
mSizeIsCached = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
void JMediaDataSource::close() {
|
||||
Mutex::Autolock lock(mLock);
|
||||
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
env->CallVoidMethod(mMediaDataSourceObj, mCloseMethod);
|
||||
// The closed state is effectively the same as an error state.
|
||||
mJavaObjStatus = UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
73
media/jni/android_media_MediaDataSource.h
Normal file
73
media/jni/android_media_MediaDataSource.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_MEDIA_MEDIADATASOURCE_H_
|
||||
#define _ANDROID_MEDIA_MEDIADATASOURCE_H_
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
#include <media/IDataSource.h>
|
||||
#include <media/stagefright/foundation/ABase.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// The native counterpart to a Java android.media.MediaDataSource. It inherits from
|
||||
// IDataSource so that it can be accessed remotely.
|
||||
//
|
||||
// If the java DataSource returns an error or throws an exception it
|
||||
// will be considered to be in a broken state, and the only further call this
|
||||
// will make is to close().
|
||||
class JMediaDataSource : public BnDataSource {
|
||||
public:
|
||||
enum {
|
||||
kBufferSize = 64 * 1024,
|
||||
};
|
||||
|
||||
JMediaDataSource(JNIEnv *env, jobject source);
|
||||
virtual ~JMediaDataSource();
|
||||
|
||||
virtual sp<IMemory> getIMemory();
|
||||
virtual ssize_t readAt(off64_t offset, size_t size);
|
||||
virtual status_t getSize(off64_t* size);
|
||||
virtual void close();
|
||||
|
||||
private:
|
||||
// Protect all member variables with mLock because this object will be
|
||||
// accessed on different binder worker threads.
|
||||
Mutex mLock;
|
||||
|
||||
// The status of the java DataSource. Set to OK unless an error occurred or
|
||||
// close() was called.
|
||||
status_t mJavaObjStatus;
|
||||
// Only call the java getSize() once so the app can't change the size on us.
|
||||
bool mSizeIsCached;
|
||||
off64_t mCachedSize;
|
||||
sp<IMemory> mMemory;
|
||||
|
||||
jobject mMediaDataSourceObj;
|
||||
jmethodID mReadMethod;
|
||||
jmethodID mGetSizeMethod;
|
||||
jmethodID mCloseMethod;
|
||||
jbyteArray mByteArrayObj;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(JMediaDataSource);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _ANDROID_MEDIA_MEDIADATASOURCE_H_
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "android_runtime/Log.h"
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "android_media_MediaDataSource.h"
|
||||
|
||||
#include <media/IMediaHTTPService.h>
|
||||
#include <media/hardware/CryptoAPI.h>
|
||||
@@ -50,74 +51,6 @@ 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, (jint)size);
|
||||
env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer);
|
||||
env->DeleteLocalRef(byteArrayObj);
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGW("Exception occurred while reading %zu at %lld", size, (long long)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)
|
||||
: mClass(NULL),
|
||||
mObject(NULL) {
|
||||
@@ -777,7 +710,8 @@ static void android_media_MediaExtractor_setDataSourceCallback(
|
||||
return;
|
||||
}
|
||||
|
||||
sp<JavaDataSourceBridge> bridge = new JavaDataSourceBridge(env, callbackObj);
|
||||
sp<DataSource> bridge =
|
||||
DataSource::CreateFromIDataSource(new JMediaDataSource(env, callbackObj));
|
||||
status_t err = extractor->setDataSource(bridge);
|
||||
|
||||
if (err != OK) {
|
||||
@@ -881,7 +815,7 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
|
||||
(void *)android_media_MediaExtractor_setDataSourceFd },
|
||||
|
||||
{ "setDataSource", "(Landroid/media/DataSource;)V",
|
||||
{ "setDataSource", "(Landroid/media/MediaDataSource;)V",
|
||||
(void *)android_media_MediaExtractor_setDataSourceCallback },
|
||||
|
||||
{ "getCachedDuration", "()J",
|
||||
|
||||
@@ -134,7 +134,6 @@ static jobject android_media_MediaHTTPConnection_native_getIMemory(
|
||||
static jint android_media_MediaHTTPConnection_native_readAt(
|
||||
JNIEnv *env, jobject thiz, jlong offset, jint size) {
|
||||
sp<JMediaHTTPConnection> conn = getObject(env, thiz);
|
||||
|
||||
if (size > JMediaHTTPConnection::kBufferSize) {
|
||||
size = JMediaHTTPConnection::kBufferSize;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "android_media_MediaDataSource.h"
|
||||
#include "android_media_Utils.h"
|
||||
#include "android_util_Binder.h"
|
||||
|
||||
@@ -171,6 +172,23 @@ static void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jo
|
||||
process_media_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed");
|
||||
}
|
||||
|
||||
static void android_media_MediaMetadataRetriever_setDataSourceCallback(JNIEnv *env, jobject thiz, jobject dataSource)
|
||||
{
|
||||
ALOGV("setDataSourceCallback");
|
||||
MediaMetadataRetriever* retriever = getRetriever(env, thiz);
|
||||
if (retriever == 0) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
|
||||
return;
|
||||
}
|
||||
if (dataSource == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
sp<IDataSource> callbackDataSource = new JMediaDataSource(env, dataSource);
|
||||
process_media_retriever_call(env, retriever->setDataSource(callbackDataSource), "java/lang/RuntimeException", "setDataSourceCallback failed");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void rotate0(T* dst, const T* src, size_t width, size_t height)
|
||||
{
|
||||
@@ -457,6 +475,7 @@ static JNINativeMethod nativeMethods[] = {
|
||||
},
|
||||
|
||||
{"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
|
||||
{"_setDataSource", "(Landroid/media/MediaDataSource;)V", (void *)android_media_MediaMetadataRetriever_setDataSourceCallback},
|
||||
{"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
|
||||
{"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata},
|
||||
{"getEmbeddedPicture", "(I)[B", (void *)android_media_MediaMetadataRetriever_getEmbeddedPicture},
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "utils/Errors.h" // for status_t
|
||||
#include "utils/KeyedVector.h"
|
||||
#include "utils/String8.h"
|
||||
#include "android_media_MediaDataSource.h"
|
||||
#include "android_media_Utils.h"
|
||||
|
||||
#include "android_os_Parcel.h"
|
||||
@@ -251,6 +252,23 @@ android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fil
|
||||
process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
|
||||
}
|
||||
|
||||
static void
|
||||
android_media_MediaPlayer_setDataSourceCallback(JNIEnv *env, jobject thiz, jobject dataSource)
|
||||
{
|
||||
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
|
||||
if (mp == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataSource == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
sp<IDataSource> callbackDataSource = new JMediaDataSource(env, dataSource);
|
||||
process_media_player_call(env, thiz, mp->setDataSource(callbackDataSource), "java/lang/RuntimeException", "setDataSourceCallback failed." );
|
||||
}
|
||||
|
||||
static sp<IGraphicBufferProducer>
|
||||
getVideoSurfaceTexture(JNIEnv* env, jobject thiz) {
|
||||
IGraphicBufferProducer * const p = (IGraphicBufferProducer*)env->GetLongField(thiz, fields.surface_texture);
|
||||
@@ -871,7 +889,8 @@ static JNINativeMethod gMethods[] = {
|
||||
(void *)android_media_MediaPlayer_setDataSourceAndHeaders
|
||||
},
|
||||
|
||||
{"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
|
||||
{"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
|
||||
{"_setDataSource", "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback },
|
||||
{"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer_setVideoSurface},
|
||||
{"_prepare", "()V", (void *)android_media_MediaPlayer_prepare},
|
||||
{"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync},
|
||||
|
||||
Reference in New Issue
Block a user