SurfaceTexture.cpp revision 925bcaabde5a21687b51caa7ab329310a819f068
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "SurfaceTexture" 18 19#include <stdio.h> 20 21#include <gui/SurfaceTexture.h> 22#include <gui/SurfaceTextureClient.h> 23 24#include <android_runtime/AndroidRuntime.h> 25 26#include <utils/Log.h> 27#include <utils/misc.h> 28 29#include "jni.h" 30#include "JNIHelp.h" 31 32// ---------------------------------------------------------------------------- 33 34namespace android { 35 36static const char* const OutOfResourcesException = 37 "android/graphics/SurfaceTexture$OutOfResourcesException"; 38const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture"; 39 40struct fields_t { 41 jfieldID surfaceTexture; 42 jmethodID postEvent; 43}; 44static fields_t fields; 45 46// ---------------------------------------------------------------------------- 47 48static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz, 49 const sp<SurfaceTexture>& surfaceTexture) 50{ 51 SurfaceTexture* const p = 52 (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture); 53 if (surfaceTexture.get()) { 54 surfaceTexture->incStrong(thiz); 55 } 56 if (p) { 57 p->decStrong(thiz); 58 } 59 env->SetIntField(thiz, fields.surfaceTexture, (int)surfaceTexture.get()); 60} 61 62sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz) 63{ 64 sp<SurfaceTexture> surfaceTexture( 65 (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture)); 66 return surfaceTexture; 67} 68 69sp<ANativeWindow> android_SurfaceTexture_getNativeWindow( 70 JNIEnv* env, jobject thiz) 71{ 72 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 73 sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ? 74 new SurfaceTextureClient(surfaceTexture) : NULL); 75 return surfaceTextureClient; 76} 77 78bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz) 79{ 80 jclass surfaceTextureClass = env->FindClass(kSurfaceTextureClassPathName); 81 return env->IsInstanceOf(thiz, surfaceTextureClass); 82} 83 84// ---------------------------------------------------------------------------- 85 86class JNISurfaceTextureContext : public SurfaceTexture::FrameAvailableListener 87{ 88public: 89 JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz); 90 virtual ~JNISurfaceTextureContext(); 91 virtual void onFrameAvailable(); 92 93private: 94 static JNIEnv* getJNIEnv(); 95 96 jobject mWeakThiz; 97 jclass mClazz; 98}; 99 100JNISurfaceTextureContext::JNISurfaceTextureContext(JNIEnv* env, 101 jobject weakThiz, jclass clazz) : 102 mWeakThiz(env->NewGlobalRef(weakThiz)), 103 mClazz((jclass)env->NewGlobalRef(clazz)) 104{} 105 106JNIEnv* JNISurfaceTextureContext::getJNIEnv() { 107 JNIEnv* env; 108 JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL}; 109 JavaVM* vm = AndroidRuntime::getJavaVM(); 110 int result = vm->AttachCurrentThread(&env, (void*) &args); 111 if (result != JNI_OK) { 112 LOGE("thread attach failed: %#x", result); 113 return NULL; 114 } 115 return env; 116} 117 118JNISurfaceTextureContext::~JNISurfaceTextureContext() 119{ 120 JNIEnv* env = getJNIEnv(); 121 if (env != NULL) { 122 env->DeleteGlobalRef(mWeakThiz); 123 env->DeleteGlobalRef(mClazz); 124 } else { 125 LOGW("leaking JNI object references"); 126 } 127} 128 129void JNISurfaceTextureContext::onFrameAvailable() 130{ 131 JNIEnv *env = getJNIEnv(); 132 if (env != NULL) { 133 env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz); 134 } else { 135 LOGW("onFrameAvailable event will not posted"); 136 } 137} 138 139// ---------------------------------------------------------------------------- 140 141static void SurfaceTexture_classInit(JNIEnv* env, jclass clazz) 142{ 143 fields.surfaceTexture = env->GetFieldID(clazz, 144 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I"); 145 if (fields.surfaceTexture == NULL) { 146 LOGE("can't find android/graphics/SurfaceTexture.%s", 147 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID); 148 } 149 150 fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative", 151 "(Ljava/lang/Object;)V"); 152 if (fields.postEvent == NULL) { 153 LOGE("can't find android/graphics/SurfaceTexture.postEventFromNative"); 154 } 155} 156 157static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jint texName, 158 jobject weakThiz) 159{ 160 sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName)); 161 if (surfaceTexture == 0) { 162 jniThrowException(env, OutOfResourcesException, 163 "Unable to create native SurfaceTexture"); 164 return; 165 } 166 SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture); 167 168 jclass clazz = env->GetObjectClass(thiz); 169 if (clazz == NULL) { 170 jniThrowRuntimeException(env, 171 "Can't find android/graphics/SurfaceTexture"); 172 return; 173 } 174 175 sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz, 176 clazz)); 177 surfaceTexture->setFrameAvailableListener(ctx); 178} 179 180static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz) 181{ 182 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 183 surfaceTexture->setFrameAvailableListener(0); 184 SurfaceTexture_setSurfaceTexture(env, thiz, 0); 185} 186 187static void SurfaceTexture_setDefaultBufferSize( 188 JNIEnv* env, jobject thiz, jint width, jint height) 189{ 190 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 191 surfaceTexture->setDefaultBufferSize(width, height); 192} 193 194static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz) 195{ 196 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 197 surfaceTexture->updateTexImage(); 198} 199 200static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz, 201 jfloatArray jmtx) 202{ 203 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 204 float* mtx = env->GetFloatArrayElements(jmtx, NULL); 205 surfaceTexture->getTransformMatrix(mtx); 206 env->ReleaseFloatArrayElements(jmtx, mtx, 0); 207} 208 209static jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz) 210{ 211 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 212 return surfaceTexture->getTimestamp(); 213} 214 215static jint SurfaceTexture_getQueuedCount(JNIEnv* env, jobject thiz) 216{ 217 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 218 return surfaceTexture->getQueuedCount(); 219} 220 221// ---------------------------------------------------------------------------- 222 223static JNINativeMethod gSurfaceTextureMethods[] = { 224 {"nativeClassInit", "()V", (void*)SurfaceTexture_classInit }, 225 {"nativeInit", "(ILjava/lang/Object;)V", (void*)SurfaceTexture_init }, 226 {"nativeFinalize", "()V", (void*)SurfaceTexture_finalize }, 227 {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize }, 228 {"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage }, 229 {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix }, 230 {"nativeGetTimestamp", "()J", (void*)SurfaceTexture_getTimestamp }, 231 {"nativeGetQueuedCount", "()I", (void*)SurfaceTexture_getQueuedCount } 232}; 233 234int register_android_graphics_SurfaceTexture(JNIEnv* env) 235{ 236 int err = 0; 237 err = AndroidRuntime::registerNativeMethods(env, kSurfaceTextureClassPathName, 238 gSurfaceTextureMethods, NELEM(gSurfaceTextureMethods)); 239 return err; 240} 241 242} // namespace android 243