SurfaceTexture.cpp revision 84293fb9625a3ab7d7d302436bea05441b8d7316
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
215// ----------------------------------------------------------------------------
216
217static JNINativeMethod gSurfaceTextureMethods[] = {
218    {"nativeClassInit",          "()V",   (void*)SurfaceTexture_classInit },
219    {"nativeInit",               "(ILjava/lang/Object;)V", (void*)SurfaceTexture_init },
220    {"nativeFinalize",           "()V",   (void*)SurfaceTexture_finalize },
221    {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
222    {"nativeUpdateTexImage",     "()V",   (void*)SurfaceTexture_updateTexImage },
223    {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
224    {"nativeGetTimestamp",       "()J",   (void*)SurfaceTexture_getTimestamp }
225};
226
227int register_android_graphics_SurfaceTexture(JNIEnv* env)
228{
229    int err = 0;
230    err = AndroidRuntime::registerNativeMethods(env, kSurfaceTextureClassPathName,
231            gSurfaceTextureMethods, NELEM(gSurfaceTextureMethods));
232    return err;
233}
234
235} // namespace android
236