Loading media/java/android/media/MediaCodec.java +20 −4 Original line number Diff line number Diff line Loading @@ -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; }; /** Loading @@ -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( Loading media/jni/android_media_MediaCodec.cpp +163 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; Loading @@ -87,6 +95,7 @@ struct fields_t { }; static fields_t gFields; static const void *sRefBaseOwner; //////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -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(); } Loading Loading @@ -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"); Loading Loading @@ -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( Loading Loading @@ -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 }, Loading media/jni/android_media_MediaCodec.h +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ struct AString; struct ICrypto; struct IGraphicBufferProducer; struct MediaCodec; struct PersistentSurface; class Surface; struct JMediaCodec : public AHandler { Loading @@ -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(); Loading Loading
media/java/android/media/MediaCodec.java +20 −4 Original line number Diff line number Diff line Loading @@ -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; }; /** Loading @@ -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( Loading
media/jni/android_media_MediaCodec.cpp +163 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; Loading @@ -87,6 +95,7 @@ struct fields_t { }; static fields_t gFields; static const void *sRefBaseOwner; //////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -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(); } Loading Loading @@ -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"); Loading Loading @@ -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( Loading Loading @@ -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 }, Loading
media/jni/android_media_MediaCodec.h +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ struct AString; struct ICrypto; struct IGraphicBufferProducer; struct MediaCodec; struct PersistentSurface; class Surface; struct JMediaCodec : public AHandler { Loading @@ -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(); Loading