diff options
author | Chong Zhang <chz@google.com> | 2015-04-28 13:38:48 -0700 |
---|---|---|
committer | Chong Zhang <chz@google.com> | 2015-05-01 18:30:09 -0700 |
commit | 8034d60f6e044deafe48501dfbfe17c31284bc17 (patch) | |
tree | f60e8b6b1127a035cb75e89dda649bcc0159aaf3 /media | |
parent | 574f53793d6441ebf55ca8811588ad37d9451a9a (diff) | |
download | frameworks_base-8034d60f6e044deafe48501dfbfe17c31284bc17.zip frameworks_base-8034d60f6e044deafe48501dfbfe17c31284bc17.tar.gz frameworks_base-8034d60f6e044deafe48501dfbfe17c31284bc17.tar.bz2 |
MediaCodec: implement persistent input surface APIs
Bug: 19127604
Bug: 19489395
Change-Id: If0d723c9ecd6fe81d9df210bd2fd026b8603ea4a
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/MediaCodec.java | 24 | ||||
-rw-r--r-- | media/jni/android_media_MediaCodec.cpp | 164 | ||||
-rw-r--r-- | media/jni/android_media_MediaCodec.h | 2 |
3 files changed, 185 insertions, 5 deletions
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index d22cfda..f4a5bc3 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -681,12 +681,20 @@ final public class MediaCodec { */ @NonNull public static Surface createPersistentInputSurface() { - // TODO implement this - return new PersistentSurface(); + return native_createPersistentInputSurface(); } static class PersistentSurface extends Surface { - PersistentSurface() {} + @SuppressWarnings("unused") + PersistentSurface() {} // used by native + + @Override + public void release() { + native_releasePersistentInputSurface(this); + super.release(); + } + + private long mPersistentObject; }; /** @@ -700,9 +708,17 @@ final public class MediaCodec { * {@link #createPersistentInputSurface}. */ public void usePersistentInputSurface(@NonNull Surface surface) { - throw new IllegalArgumentException("not implemented"); + if (!(surface instanceof PersistentSurface)) { + throw new IllegalArgumentException("not a PersistentSurface"); + } + native_usePersistentInputSurface(surface); } + @NonNull + private static native final PersistentSurface native_createPersistentInputSurface(); + private static native final void native_releasePersistentInputSurface(@NonNull Surface surface); + private native final void native_usePersistentInputSurface(@NonNull Surface surface); + private native final void native_setCallback(@Nullable Callback cb); private native final void native_configure( diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index e34f9ed..a09c5c0 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -39,7 +39,7 @@ #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/foundation/AString.h> #include <media/stagefright/MediaErrors.h> - +#include <media/stagefright/PersistentSurface.h> #include <nativehelper/ScopedLocalRef.h> #include <system/window.h> @@ -75,6 +75,14 @@ static struct ExceptionReason { jint reasonReclaimed; } gExceptionReason; +static struct { + jclass clazz; + jfieldID mLock; + jfieldID mPersistentObject; + jmethodID ctor; + jmethodID setNativeObjectLocked; +} gPersistentSurfaceClassInfo; + struct fields_t { jfieldID context; jmethodID postEventFromNativeID; @@ -87,6 +95,7 @@ struct fields_t { }; static fields_t gFields; +static const void *sRefBaseOwner; //////////////////////////////////////////////////////////////////////////////// @@ -250,6 +259,11 @@ status_t JMediaCodec::createInputSurface( return mCodec->createInputSurface(bufferProducer); } +status_t JMediaCodec::usePersistentInputSurface( + const sp<PersistentSurface> &surface) { + return mCodec->usePersistentInputSurface(surface); +} + status_t JMediaCodec::start() { return mCodec->start(); } @@ -869,6 +883,120 @@ static void android_media_MediaCodec_native_configure( throwExceptionAsNecessary(env, err); } +sp<PersistentSurface> android_media_MediaCodec_getPersistentInputSurface( + JNIEnv* env, jobject object) { + sp<PersistentSurface> persistentSurface; + + jobject lock = env->GetObjectField( + object, gPersistentSurfaceClassInfo.mLock); + if (env->MonitorEnter(lock) == JNI_OK) { + persistentSurface = reinterpret_cast<PersistentSurface *>( + env->GetLongField(object, + gPersistentSurfaceClassInfo.mPersistentObject)); + env->MonitorExit(lock); + } + env->DeleteLocalRef(lock); + + return persistentSurface; +} + +static jobject android_media_MediaCodec_createPersistentInputSurface( + JNIEnv* env, jclass /* clazz */) { + ALOGV("android_media_MediaCodec_createPersistentInputSurface"); + sp<PersistentSurface> persistentSurface = + MediaCodec::CreatePersistentInputSurface(); + + if (persistentSurface == NULL) { + return NULL; + } + + sp<Surface> surface = new Surface( + persistentSurface->getBufferProducer(), true); + if (surface == NULL) { + return NULL; + } + + jobject object = env->NewObject( + gPersistentSurfaceClassInfo.clazz, + gPersistentSurfaceClassInfo.ctor); + + if (object == NULL) { + if (env->ExceptionCheck()) { + ALOGE("Could not create PersistentSurface."); + env->ExceptionClear(); + } + return NULL; + } + + jobject lock = env->GetObjectField( + object, gPersistentSurfaceClassInfo.mLock); + if (env->MonitorEnter(lock) == JNI_OK) { + env->CallVoidMethod( + object, + gPersistentSurfaceClassInfo.setNativeObjectLocked, + (jlong)surface.get()); + env->SetLongField( + object, + gPersistentSurfaceClassInfo.mPersistentObject, + (jlong)persistentSurface.get()); + env->MonitorExit(lock); + } else { + env->DeleteLocalRef(object); + object = NULL; + } + env->DeleteLocalRef(lock); + + if (object != NULL) { + surface->incStrong(&sRefBaseOwner); + persistentSurface->incStrong(&sRefBaseOwner); + } + + return object; +} + +static void android_media_MediaCodec_releasePersistentInputSurface( + JNIEnv* env, jclass /* clazz */, jobject object) { + sp<PersistentSurface> persistentSurface; + + jobject lock = env->GetObjectField( + object, gPersistentSurfaceClassInfo.mLock); + if (env->MonitorEnter(lock) == JNI_OK) { + persistentSurface = reinterpret_cast<PersistentSurface *>( + env->GetLongField( + object, gPersistentSurfaceClassInfo.mPersistentObject)); + env->SetLongField( + object, + gPersistentSurfaceClassInfo.mPersistentObject, + (jlong)0); + env->MonitorExit(lock); + } + env->DeleteLocalRef(lock); + + if (persistentSurface != NULL) { + persistentSurface->decStrong(&sRefBaseOwner); + } + // no need to release surface as it will be released by Surface's jni +} + +static void android_media_MediaCodec_usePersistentInputSurface( + JNIEnv* env, jobject thiz, jobject object) { + ALOGV("android_media_MediaCodec_usePersistentInputSurface"); + + sp<JMediaCodec> codec = getMediaCodec(env, thiz); + if (codec == NULL) { + throwExceptionAsNecessary(env, INVALID_OPERATION); + return; + } + + sp<PersistentSurface> persistentSurface = + android_media_MediaCodec_getPersistentInputSurface(env, object); + + status_t err = codec->usePersistentInputSurface(persistentSurface); + if (err != NO_ERROR) { + throwExceptionAsNecessary(env, err); + } +} + static jobject android_media_MediaCodec_createInputSurface(JNIEnv* env, jobject thiz) { ALOGV("android_media_MediaCodec_createInputSurface"); @@ -1471,6 +1599,29 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) { CHECK(field != NULL); gExceptionReason.reasonReclaimed = env->GetStaticIntField(clazz.get(), field); + + clazz.reset(env->FindClass("android/view/Surface")); + CHECK(clazz.get() != NULL); + + field = env->GetFieldID(clazz.get(), "mLock", "Ljava/lang/Object;"); + CHECK(field != NULL); + gPersistentSurfaceClassInfo.mLock = field; + + jmethodID method = env->GetMethodID(clazz.get(), "setNativeObjectLocked", "(J)V"); + CHECK(method != NULL); + gPersistentSurfaceClassInfo.setNativeObjectLocked = method; + + clazz.reset(env->FindClass("android/media/MediaCodec$PersistentSurface")); + CHECK(clazz.get() != NULL); + gPersistentSurfaceClassInfo.clazz = (jclass)env->NewGlobalRef(clazz.get()); + + method = env->GetMethodID(clazz.get(), "<init>", "()V"); + CHECK(method != NULL); + gPersistentSurfaceClassInfo.ctor = method; + + field = env->GetFieldID(clazz.get(), "mPersistentObject", "J"); + CHECK(field != NULL); + gPersistentSurfaceClassInfo.mPersistentObject = field; } static void android_media_MediaCodec_native_setup( @@ -1521,6 +1672,17 @@ static JNINativeMethod gMethods[] = { { "native_reset", "()V", (void *)android_media_MediaCodec_reset }, + { "native_releasePersistentInputSurface", + "(Landroid/view/Surface;)V", + (void *)android_media_MediaCodec_releasePersistentInputSurface}, + + { "native_createPersistentInputSurface", + "()Landroid/media/MediaCodec$PersistentSurface;", + (void *)android_media_MediaCodec_createPersistentInputSurface }, + + { "native_usePersistentInputSurface", "(Landroid/view/Surface;)V", + (void *)android_media_MediaCodec_usePersistentInputSurface }, + { "native_setCallback", "(Landroid/media/MediaCodec$Callback;)V", (void *)android_media_MediaCodec_native_setCallback }, diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index 9f2785a..4721d2d 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -33,6 +33,7 @@ struct AString; struct ICrypto; struct IGraphicBufferProducer; struct MediaCodec; +struct PersistentSurface; class Surface; struct JMediaCodec : public AHandler { @@ -54,6 +55,7 @@ struct JMediaCodec : public AHandler { int flags); status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer); + status_t usePersistentInputSurface(const sp<PersistentSurface> &surface); status_t start(); status_t stop(); |