SurfaceTexture.cpp revision 050316184b01c0d1a01c46afae7429b89a27c31b
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    jobject mWeakThiz;
95    jclass mClazz;
96};
97
98JNISurfaceTextureContext::JNISurfaceTextureContext(JNIEnv* env,
99        jobject weakThiz, jclass clazz) :
100    mWeakThiz(env->NewGlobalRef(weakThiz)),
101    mClazz((jclass)env->NewGlobalRef(clazz))
102{}
103
104JNISurfaceTextureContext::~JNISurfaceTextureContext()
105{
106    JNIEnv *env = AndroidRuntime::getJNIEnv();
107    env->DeleteGlobalRef(mWeakThiz);
108    env->DeleteGlobalRef(mClazz);
109}
110
111void JNISurfaceTextureContext::onFrameAvailable()
112{
113    JNIEnv *env = AndroidRuntime::getJNIEnv();
114    env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
115}
116
117// ----------------------------------------------------------------------------
118
119static void SurfaceTexture_classInit(JNIEnv* env, jclass clazz)
120{
121    fields.surfaceTexture = env->GetFieldID(clazz,
122            ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I");
123    if (fields.surfaceTexture == NULL) {
124        LOGE("can't find android/graphics/SurfaceTexture.%s",
125                ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID);
126    }
127
128    fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
129            "(Ljava/lang/Object;)V");
130    if (fields.postEvent == NULL) {
131        LOGE("can't find android/graphics/SurfaceTexture.postEventFromNative");
132    }
133}
134
135static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jint texName,
136        jobject weakThiz)
137{
138    sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName));
139    if (surfaceTexture == 0) {
140        jniThrowException(env, OutOfResourcesException,
141                "Unable to create native SurfaceTexture");
142        return;
143    }
144    SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture);
145
146    jclass clazz = env->GetObjectClass(thiz);
147    if (clazz == NULL) {
148        jniThrowRuntimeException(env,
149                "Can't find android/graphics/SurfaceTexture");
150        return;
151    }
152
153    sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
154            clazz));
155    surfaceTexture->setFrameAvailableListener(ctx);
156}
157
158static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz)
159{
160    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
161    surfaceTexture->setFrameAvailableListener(0);
162    SurfaceTexture_setSurfaceTexture(env, thiz, 0);
163}
164
165static void SurfaceTexture_setDefaultBufferSize(
166        JNIEnv* env, jobject thiz, jint width, jint height)
167{
168    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
169    surfaceTexture->setDefaultBufferSize(width, height);
170}
171
172static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz)
173{
174    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
175    surfaceTexture->updateTexImage();
176}
177
178static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz,
179        jfloatArray jmtx)
180{
181    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
182    float* mtx = env->GetFloatArrayElements(jmtx, NULL);
183    surfaceTexture->getTransformMatrix(mtx);
184    env->ReleaseFloatArrayElements(jmtx, mtx, 0);
185}
186
187static jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz)
188{
189    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
190    return surfaceTexture->getTimestamp();
191}
192
193// ----------------------------------------------------------------------------
194
195static JNINativeMethod gSurfaceTextureMethods[] = {
196    {"nativeClassInit",          "()V",   (void*)SurfaceTexture_classInit },
197    {"nativeInit",               "(ILjava/lang/Object;)V", (void*)SurfaceTexture_init },
198    {"nativeFinalize",           "()V",   (void*)SurfaceTexture_finalize },
199    {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
200    {"nativeUpdateTexImage",     "()V",   (void*)SurfaceTexture_updateTexImage },
201    {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
202    {"nativeGetTimestamp",       "()J",   (void*)SurfaceTexture_getTimestamp }
203};
204
205int register_android_graphics_SurfaceTexture(JNIEnv* env)
206{
207    int err = 0;
208    err = AndroidRuntime::registerNativeMethods(env, kSurfaceTextureClassPathName,
209            gSurfaceTextureMethods, NELEM(gSurfaceTextureMethods));
210    return err;
211}
212
213} // namespace android
214