2 * Copyright (C) 2013, Fluendo S.A.
3 * Author: Andoni Morales <amorales@fluendo.com>
5 * Copyright (C) 2014,2018 Collabora Ltd.
6 * Author: Matthieu Bouron <matthieu.bouron@collabora.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation
11 * version 2.1 of the License.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include "gstjniutils.h"
29 #include "gstamcsurfacetexture-jni.h"
31 struct _GstAmcSurfaceTextureJNI
37 jmethodID set_context_id;
38 GstAmcSurfaceTextureOnFrameAvailableCallback callback;
45 jmethodID constructor;
46 jmethodID set_on_frame_available_listener;
47 jmethodID update_tex_image;
48 jmethodID detach_from_gl_context;
49 jmethodID attach_to_gl_context;
50 jmethodID get_transform_matrix;
51 jmethodID get_timestamp;
56 G_DEFINE_TYPE (GstAmcSurfaceTextureJNI, gst_amc_surface_texture_jni,
57 GST_TYPE_AMC_SURFACE_TEXTURE);
60 gst_amc_surface_texture_static_init (void)
65 env = gst_amc_jni_get_env ();
67 surface_texture.jklass = gst_amc_jni_get_class (env, &err,
68 "android/graphics/SurfaceTexture");
69 if (!surface_texture.jklass) {
70 GST_ERROR ("Failed to get android.graphics.SurfaceTexture class: %s",
76 surface_texture.constructor =
77 gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, "<init>",
79 if (!surface_texture.constructor) {
83 surface_texture.set_on_frame_available_listener =
84 gst_amc_jni_get_method_id (env, &err, surface_texture.jklass,
85 "setOnFrameAvailableListener",
86 "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V");
87 if (!surface_texture.set_on_frame_available_listener) {
91 surface_texture.update_tex_image =
92 gst_amc_jni_get_method_id (env, &err, surface_texture.jklass,
93 "updateTexImage", "()V");
94 if (!surface_texture.update_tex_image) {
98 surface_texture.detach_from_gl_context =
99 gst_amc_jni_get_method_id (env, &err, surface_texture.jklass,
100 "detachFromGLContext", "()V");
101 if (!surface_texture.detach_from_gl_context) {
105 surface_texture.attach_to_gl_context =
106 gst_amc_jni_get_method_id (env, &err, surface_texture.jklass,
107 "attachToGLContext", "(I)V");
108 if (!surface_texture.attach_to_gl_context) {
112 surface_texture.get_transform_matrix =
113 gst_amc_jni_get_method_id (env, &err, surface_texture.jklass,
114 "getTransformMatrix", "([F)V");
115 if (!surface_texture.get_transform_matrix) {
119 surface_texture.get_timestamp =
120 gst_amc_jni_get_method_id (env, &err, surface_texture.jklass,
121 "getTimestamp", "()J");
122 if (!surface_texture.get_timestamp) {
126 surface_texture.release =
127 gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, "release",
129 if (!surface_texture.release) {
136 GST_ERROR ("Failed to get android.graphics.SurfaceTexture methods: %s",
138 g_clear_error (&err);
139 gst_amc_jni_object_unref (env, surface_texture.constructor);
144 gst_amc_surface_texture_jni_update_tex_image (GstAmcSurfaceTexture * base,
147 GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
150 env = gst_amc_jni_get_env ();
152 return gst_amc_jni_call_void_method (env, err, self->jobject,
153 surface_texture.update_tex_image);
157 gst_amc_surface_texture_jni_detach_from_gl_context (GstAmcSurfaceTexture * base,
160 GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
164 env = gst_amc_jni_get_env ();
167 gst_amc_jni_call_void_method (env, err, self->jobject,
168 surface_texture.detach_from_gl_context);
169 self->texture_id = 0;
174 gst_amc_surface_texture_jni_attach_to_gl_context (GstAmcSurfaceTexture * base,
175 gint texture_id, GError ** err)
177 GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
181 env = gst_amc_jni_get_env ();
184 gst_amc_jni_call_void_method (env, err, self->jobject,
185 surface_texture.attach_to_gl_context, texture_id);
186 self->texture_id = texture_id;
191 gst_amc_surface_texture_jni_get_transform_matrix (GstAmcSurfaceTexture * base,
192 gfloat * matrix, GError ** err)
194 GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
199 jfloatArray floatarray;
201 env = gst_amc_jni_get_env ();
203 floatarray = (*env)->NewFloatArray (env, size);
205 gst_amc_jni_call_void_method (env, err, self->jobject,
206 surface_texture.get_transform_matrix, floatarray);
208 (*env)->GetFloatArrayRegion (env, floatarray, 0, size, (jfloat *) matrix);
209 (*env)->DeleteLocalRef (env, floatarray);
216 gst_amc_surface_texture_jni_get_timestamp (GstAmcSurfaceTexture * base,
217 gint64 * result, GError ** err)
219 GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
222 env = gst_amc_jni_get_env ();
224 return gst_amc_jni_call_long_method (env, err, self->jobject,
225 surface_texture.get_timestamp, result);
229 gst_amc_surface_texture_jni_release (GstAmcSurfaceTexture * base, GError ** err)
231 GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
234 env = gst_amc_jni_get_env ();
236 return gst_amc_jni_call_void_method (env, err, self->jobject,
237 surface_texture.release);
241 on_frame_available_cb (JNIEnv * env, jobject thiz,
242 long long context, jobject surfaceTexture)
244 GstAmcSurfaceTextureJNI *self = JLONG_TO_GPOINTER (context);
246 self->callback (GST_AMC_SURFACE_TEXTURE (self), self->user_data);
250 create_listener (GstAmcSurfaceTextureJNI * self, JNIEnv * env, GError ** err)
252 jclass listener_cls = NULL;
253 jmethodID constructor_id = 0;
255 JNINativeMethod amcOnFrameAvailableListener = {
256 "native_onFrameAvailable",
257 "(JLandroid/graphics/SurfaceTexture;)V",
258 (void *) on_frame_available_cb,
262 gst_amc_jni_get_application_class (env,
263 "org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener",
269 (*env)->RegisterNatives (env, listener_cls, &amcOnFrameAvailableListener, 1);
270 if ((*env)->ExceptionCheck (env)) {
271 (*env)->ExceptionClear (env);
276 gst_amc_jni_get_method_id (env, err, listener_cls, "<init>", "()V");
277 if (!constructor_id) {
281 self->set_context_id =
282 gst_amc_jni_get_method_id (env, err, listener_cls, "setContext", "(J)V");
283 if (!self->set_context_id) {
288 gst_amc_jni_new_object (env, err, TRUE, listener_cls, constructor_id);
289 if (!self->listener) {
293 if (!gst_amc_jni_call_void_method (env, err, self->listener,
294 self->set_context_id, GPOINTER_TO_JLONG (self))) {
295 gst_amc_jni_object_unref (env, self->listener);
296 self->listener = NULL;
300 gst_amc_jni_object_unref (env, listener_cls);
302 return self->listener != NULL;
306 remove_listener (GstAmcSurfaceTextureJNI * self, JNIEnv * env, GError ** err)
308 if (self->listener) {
309 if (!gst_amc_jni_call_void_method (env, err, self->listener,
310 self->set_context_id, GPOINTER_TO_JLONG (NULL)))
313 gst_amc_jni_object_unref (env, self->listener);
314 self->listener = NULL;
321 gst_amc_surface_texture_jni_set_on_frame_available_callback
322 (GstAmcSurfaceTexture * base,
323 GstAmcSurfaceTextureOnFrameAvailableCallback callback, gpointer user_data,
326 GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
329 env = gst_amc_jni_get_env ();
331 if (!remove_listener (self, env, err))
334 self->callback = callback;
335 self->user_data = user_data;
336 if (callback == NULL)
339 if (!create_listener (self, env, err))
342 if (!gst_amc_jni_call_void_method (env, err, self->jobject,
343 surface_texture.set_on_frame_available_listener, self->listener)) {
344 remove_listener (self, env, NULL);
352 gst_amc_surface_texture_jni_dispose (GObject * object)
354 GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (object);
358 env = gst_amc_jni_get_env ();
360 if (!gst_amc_surface_texture_jni_release (GST_AMC_SURFACE_TEXTURE (self),
362 GST_ERROR ("Could not release surface texture: %s", err->message);
363 g_clear_error (&err);
366 remove_listener (self, env, NULL);
369 gst_amc_jni_object_unref (env, self->jobject);
372 G_OBJECT_CLASS (gst_amc_surface_texture_jni_parent_class)->dispose (object);
376 gst_amc_surface_texture_jni_class_init (GstAmcSurfaceTextureJNIClass * klass)
378 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
379 GstAmcSurfaceTextureClass *surface_texture_class =
380 GST_AMC_SURFACE_TEXTURE_CLASS (klass);
382 gobject_class->dispose = gst_amc_surface_texture_jni_dispose;
384 surface_texture_class->update_tex_image =
385 gst_amc_surface_texture_jni_update_tex_image;
386 surface_texture_class->detach_from_gl_context =
387 gst_amc_surface_texture_jni_detach_from_gl_context;
388 surface_texture_class->attach_to_gl_context =
389 gst_amc_surface_texture_jni_attach_to_gl_context;
390 surface_texture_class->get_transform_matrix =
391 gst_amc_surface_texture_jni_get_transform_matrix;
392 surface_texture_class->get_timestamp =
393 gst_amc_surface_texture_jni_get_timestamp;
394 surface_texture_class->release = gst_amc_surface_texture_jni_release;
395 surface_texture_class->set_on_frame_available_callback =
396 gst_amc_surface_texture_jni_set_on_frame_available_callback;
400 gst_amc_surface_texture_jni_init (GstAmcSurfaceTextureJNI * self)
404 GstAmcSurfaceTextureJNI *
405 gst_amc_surface_texture_jni_new (GError ** err)
407 GstAmcSurfaceTextureJNI *self = NULL;
410 self = g_object_new (GST_TYPE_AMC_SURFACE_TEXTURE_JNI, NULL);
411 env = gst_amc_jni_get_env ();
413 self->texture_id = 0;
416 gst_amc_jni_new_object (env, err, TRUE, surface_texture.jklass,
417 surface_texture.constructor, self->texture_id);
418 if (self->jobject == NULL) {
422 if (!gst_amc_surface_texture_jni_detach_from_gl_context ((GstAmcSurfaceTexture
431 g_object_unref (self);
436 gst_amc_surface_texture_jni_get_jobject (GstAmcSurfaceTextureJNI * self)
438 return self->jobject;