amc: Remove unused gst_amc_surface_texture_set_default_buffer_size()
[platform/upstream/gstreamer.git] / sys / androidmedia / jni / gstamcsurfacetexture-jni.c
1 /*
2  * Copyright (C) 2013, Fluendo S.A.
3  *   Author: Andoni Morales <amorales@fluendo.com>
4  *
5  * Copyright (C) 2014,2018 Collabora Ltd.
6  *   Author: Matthieu Bouron <matthieu.bouron@collabora.com>
7  *
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.
12  *
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.
17  *
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
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "gstjniutils.h"
29 #include "gstamcsurfacetexture-jni.h"
30
31 struct _GstAmcSurfaceTextureJNI
32 {
33   jobject jobject;
34   gint texture_id;
35
36   jobject listener;
37   jmethodID set_context_id;
38   GstAmcSurfaceTextureOnFrameAvailableCallback callback;
39   gpointer user_data;
40 };
41
42 static struct
43 {
44   jclass jklass;
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;
52   jmethodID release;
53 } surface_texture;
54
55
56 G_DEFINE_TYPE (GstAmcSurfaceTextureJNI, gst_amc_surface_texture_jni,
57     GST_TYPE_AMC_SURFACE_TEXTURE);
58
59 gboolean
60 gst_amc_surface_texture_static_init (void)
61 {
62   JNIEnv *env;
63   GError *err = NULL;
64
65   env = gst_amc_jni_get_env ();
66
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",
71         err->message);
72     g_clear_error (&err);
73     return FALSE;
74   }
75
76   surface_texture.constructor =
77       gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, "<init>",
78       "(I)V");
79   if (!surface_texture.constructor) {
80     goto error;
81   }
82
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) {
88     goto error;
89   }
90
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) {
95     goto error;
96   }
97
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) {
102     goto error;
103   }
104
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) {
109     goto error;
110   }
111
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) {
116     goto error;
117   }
118
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) {
123     goto error;
124   }
125
126   surface_texture.release =
127       gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, "release",
128       "()V");
129   if (!surface_texture.release) {
130     goto error;
131   }
132
133   return TRUE;
134
135 error:
136   GST_ERROR ("Failed to get android.graphics.SurfaceTexture methods: %s",
137       err->message);
138   g_clear_error (&err);
139   gst_amc_jni_object_unref (env, surface_texture.constructor);
140   return FALSE;
141 }
142
143 static gboolean
144 gst_amc_surface_texture_jni_update_tex_image (GstAmcSurfaceTexture * base,
145     GError ** err)
146 {
147   GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
148   JNIEnv *env;
149
150   env = gst_amc_jni_get_env ();
151
152   return gst_amc_jni_call_void_method (env, err, self->jobject,
153       surface_texture.update_tex_image);
154 }
155
156 static gboolean
157 gst_amc_surface_texture_jni_detach_from_gl_context (GstAmcSurfaceTexture * base,
158     GError ** err)
159 {
160   GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
161   JNIEnv *env;
162   gboolean ret;
163
164   env = gst_amc_jni_get_env ();
165
166   ret =
167       gst_amc_jni_call_void_method (env, err, self->jobject,
168       surface_texture.detach_from_gl_context);
169   self->texture_id = 0;
170   return ret;
171 }
172
173 static gboolean
174 gst_amc_surface_texture_jni_attach_to_gl_context (GstAmcSurfaceTexture * base,
175     gint texture_id, GError ** err)
176 {
177   GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
178   JNIEnv *env;
179   gboolean ret;
180
181   env = gst_amc_jni_get_env ();
182
183   ret =
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;
187   return ret;
188 }
189
190 static gboolean
191 gst_amc_surface_texture_jni_get_transform_matrix (GstAmcSurfaceTexture * base,
192     gfloat * matrix, GError ** err)
193 {
194   GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
195   JNIEnv *env;
196   gboolean ret;
197   /* 4x4 Matrix */
198   jsize size = 16;
199   jfloatArray floatarray;
200
201   env = gst_amc_jni_get_env ();
202
203   floatarray = (*env)->NewFloatArray (env, size);
204   ret =
205       gst_amc_jni_call_void_method (env, err, self->jobject,
206       surface_texture.get_transform_matrix, floatarray);
207   if (ret) {
208     (*env)->GetFloatArrayRegion (env, floatarray, 0, size, (jfloat *) matrix);
209     (*env)->DeleteLocalRef (env, floatarray);
210   }
211
212   return ret;
213 }
214
215 static gboolean
216 gst_amc_surface_texture_jni_get_timestamp (GstAmcSurfaceTexture * base,
217     gint64 * result, GError ** err)
218 {
219   GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
220   JNIEnv *env;
221
222   env = gst_amc_jni_get_env ();
223
224   return gst_amc_jni_call_long_method (env, err, self->jobject,
225       surface_texture.get_timestamp, result);
226 }
227
228 static gboolean
229 gst_amc_surface_texture_jni_release (GstAmcSurfaceTexture * base, GError ** err)
230 {
231   GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
232   JNIEnv *env;
233
234   env = gst_amc_jni_get_env ();
235
236   return gst_amc_jni_call_void_method (env, err, self->jobject,
237       surface_texture.release);
238 }
239
240 static void
241 on_frame_available_cb (JNIEnv * env, jobject thiz,
242     long long context, jobject surfaceTexture)
243 {
244   GstAmcSurfaceTextureJNI *self = JLONG_TO_GPOINTER (context);
245
246   self->callback (GST_AMC_SURFACE_TEXTURE (self), self->user_data);
247 }
248
249 static gboolean
250 create_listener (GstAmcSurfaceTextureJNI * self, JNIEnv * env, GError ** err)
251 {
252   jclass listener_cls = NULL;
253   jmethodID constructor_id = 0;
254
255   JNINativeMethod amcOnFrameAvailableListener = {
256     "native_onFrameAvailable",
257     "(JLandroid/graphics/SurfaceTexture;)V",
258     (void *) on_frame_available_cb,
259   };
260
261   listener_cls =
262       gst_amc_jni_get_application_class (env,
263       "org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener",
264       err);
265   if (!listener_cls) {
266     return FALSE;
267   }
268
269   (*env)->RegisterNatives (env, listener_cls, &amcOnFrameAvailableListener, 1);
270   if ((*env)->ExceptionCheck (env)) {
271     (*env)->ExceptionClear (env);
272     goto done;
273   }
274
275   constructor_id =
276       gst_amc_jni_get_method_id (env, err, listener_cls, "<init>", "()V");
277   if (!constructor_id) {
278     goto done;
279   }
280
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) {
284     goto done;
285   }
286
287   self->listener =
288       gst_amc_jni_new_object (env, err, TRUE, listener_cls, constructor_id);
289   if (!self->listener) {
290     goto done;
291   }
292
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;
297   }
298
299 done:
300   gst_amc_jni_object_unref (env, listener_cls);
301
302   return self->listener != NULL;
303 }
304
305 static gboolean
306 remove_listener (GstAmcSurfaceTextureJNI * self, JNIEnv * env, GError ** err)
307 {
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)))
311       return FALSE;
312
313     gst_amc_jni_object_unref (env, self->listener);
314     self->listener = NULL;
315   }
316
317   return TRUE;
318 }
319
320 static gboolean
321     gst_amc_surface_texture_jni_set_on_frame_available_callback
322     (GstAmcSurfaceTexture * base,
323     GstAmcSurfaceTextureOnFrameAvailableCallback callback, gpointer user_data,
324     GError ** err)
325 {
326   GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base);
327   JNIEnv *env;
328
329   env = gst_amc_jni_get_env ();
330
331   if (!remove_listener (self, env, err))
332     return FALSE;
333
334   self->callback = callback;
335   self->user_data = user_data;
336   if (callback == NULL)
337     return TRUE;
338
339   if (!create_listener (self, env, err))
340     return FALSE;
341
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);
345     return FALSE;
346   }
347
348   return TRUE;
349 }
350
351 static void
352 gst_amc_surface_texture_jni_dispose (GObject * object)
353 {
354   GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (object);
355   JNIEnv *env;
356   GError *err = NULL;
357
358   env = gst_amc_jni_get_env ();
359
360   if (!gst_amc_surface_texture_jni_release (GST_AMC_SURFACE_TEXTURE (self),
361           &err)) {
362     GST_ERROR ("Could not release surface texture: %s", err->message);
363     g_clear_error (&err);
364   }
365
366   remove_listener (self, env, NULL);
367
368   if (self->jobject) {
369     gst_amc_jni_object_unref (env, self->jobject);
370   }
371
372   G_OBJECT_CLASS (gst_amc_surface_texture_jni_parent_class)->dispose (object);
373 }
374
375 static void
376 gst_amc_surface_texture_jni_class_init (GstAmcSurfaceTextureJNIClass * klass)
377 {
378   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
379   GstAmcSurfaceTextureClass *surface_texture_class =
380       GST_AMC_SURFACE_TEXTURE_CLASS (klass);
381
382   gobject_class->dispose = gst_amc_surface_texture_jni_dispose;
383
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;
397 }
398
399 static void
400 gst_amc_surface_texture_jni_init (GstAmcSurfaceTextureJNI * self)
401 {
402 }
403
404 GstAmcSurfaceTextureJNI *
405 gst_amc_surface_texture_jni_new (GError ** err)
406 {
407   GstAmcSurfaceTextureJNI *self = NULL;
408   JNIEnv *env;
409
410   self = g_object_new (GST_TYPE_AMC_SURFACE_TEXTURE_JNI, NULL);
411   env = gst_amc_jni_get_env ();
412
413   self->texture_id = 0;
414
415   self->jobject =
416       gst_amc_jni_new_object (env, err, TRUE, surface_texture.jklass,
417       surface_texture.constructor, self->texture_id);
418   if (self->jobject == NULL) {
419     goto error;
420   }
421
422   if (!gst_amc_surface_texture_jni_detach_from_gl_context ((GstAmcSurfaceTexture
423               *) self, err)) {
424     goto error;
425   }
426
427   return self;
428
429 error:
430   if (self)
431     g_object_unref (self);
432   return NULL;
433 }
434
435 jobject
436 gst_amc_surface_texture_jni_get_jobject (GstAmcSurfaceTextureJNI * self)
437 {
438   return self->jobject;
439 }