1 /*
2 * Copyright (C) 2013, Fluendo S.A.
3 * Author: Andoni Morales <amorales@fluendo.com>
4 *
5 * Copyright (C) 2014, 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.h"
30
31 G_DEFINE_TYPE (GstAmcSurfaceTexture, gst_amc_surface_texture, G_TYPE_OBJECT);
32
33 static gpointer parent_class = NULL;
34 static void gst_amc_surface_texture_dispose (GObject * object);
35
36 static gboolean
_cache_java_class(GstAmcSurfaceTextureClass * klass,GError ** err)37 _cache_java_class (GstAmcSurfaceTextureClass * klass, GError ** err)
38 {
39 JNIEnv *env;
40
41 gst_amc_jni_initialize ();
42 env = gst_amc_jni_get_env ();
43
44 klass->jklass =
45 gst_amc_jni_get_class (env, err, "android/graphics/SurfaceTexture");
46 if (!klass->jklass) {
47 return FALSE;
48 }
49
50 klass->constructor =
51 gst_amc_jni_get_method_id (env, err, klass->jklass, "<init>", "(I)V");
52 if (!klass->constructor) {
53 goto error;
54 }
55
56 klass->set_on_frame_available_listener =
57 gst_amc_jni_get_method_id (env, err, klass->jklass,
58 "setOnFrameAvailableListener",
59 "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V");
60
61 klass->set_default_buffer_size =
62 gst_amc_jni_get_method_id (env, err, klass->jklass,
63 "setDefaultBufferSize", "(II)V");
64 if (!klass->set_default_buffer_size) {
65 goto error;
66 }
67
68 klass->update_tex_image =
69 gst_amc_jni_get_method_id (env, err, klass->jklass, "updateTexImage",
70 "()V");
71 if (!klass->update_tex_image) {
72 goto error;
73 }
74
75 klass->detach_from_gl_context =
76 gst_amc_jni_get_method_id (env, err, klass->jklass, "detachFromGLContext",
77 "()V");
78 if (!klass->detach_from_gl_context) {
79 goto error;
80 }
81
82 klass->attach_to_gl_context =
83 gst_amc_jni_get_method_id (env, err, klass->jklass, "attachToGLContext",
84 "(I)V");
85 if (!klass->attach_to_gl_context) {
86 goto error;
87 }
88
89 klass->get_transform_matrix =
90 gst_amc_jni_get_method_id (env, err, klass->jklass, "getTransformMatrix",
91 "([F)V");
92 if (!klass->get_transform_matrix) {
93 goto error;
94 }
95
96 klass->get_timestamp =
97 gst_amc_jni_get_method_id (env, err, klass->jklass, "getTimestamp",
98 "()J");
99 if (!klass->get_timestamp) {
100 goto error;
101 }
102
103 klass->release =
104 gst_amc_jni_get_method_id (env, err, klass->jklass, "release", "()V");
105 if (!klass->release) {
106 goto error;
107 }
108
109 return TRUE;
110
111 error:
112 gst_amc_jni_object_unref (env, klass->constructor);
113 return FALSE;
114 }
115
116 static void
gst_amc_surface_texture_init(GstAmcSurfaceTexture * self)117 gst_amc_surface_texture_init (GstAmcSurfaceTexture * self)
118 {
119 }
120
121 static void
gst_amc_surface_texture_class_init(GstAmcSurfaceTextureClass * klass)122 gst_amc_surface_texture_class_init (GstAmcSurfaceTextureClass * klass)
123 {
124 GError *err = NULL;
125 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
126
127 parent_class = g_type_class_peek_parent (klass);
128 gobject_class->dispose = gst_amc_surface_texture_dispose;
129
130 if (!_cache_java_class (klass, &err)) {
131 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
132 "Could not cache java class android/graphics/SurfaceTexture: %s",
133 err->message);
134 g_clear_error (&err);
135 }
136 }
137
138 static void
gst_amc_surface_texture_dispose(GObject * object)139 gst_amc_surface_texture_dispose (GObject * object)
140 {
141 GstAmcSurfaceTexture *self;
142 JNIEnv *env;
143 GError *err = NULL;
144
145 self = GST_AMC_SURFACE_TEXTURE (object);
146 env = gst_amc_jni_get_env ();
147
148 if (!gst_amc_surface_texture_release (self, &err)) {
149 GST_ERROR ("Could not release surface texture: %s", err->message);
150 g_clear_error (&err);
151 }
152
153 if (self->jobject) {
154 gst_amc_jni_object_unref (env, self->jobject);
155 }
156 G_OBJECT_CLASS (parent_class)->dispose (object);
157 }
158
159 GstAmcSurfaceTexture *
gst_amc_surface_texture_new(GError ** err)160 gst_amc_surface_texture_new (GError ** err)
161 {
162 GstAmcSurfaceTexture *texture = NULL;
163 GstAmcSurfaceTextureClass *klass;
164 JNIEnv *env;
165
166 texture = g_object_new (GST_TYPE_AMC_SURFACE_TEXTURE, NULL);
167 klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (texture);
168 env = gst_amc_jni_get_env ();
169
170 texture->texture_id = 0;
171
172 texture->jobject = gst_amc_jni_new_object (env, err, TRUE, klass->jklass,
173 klass->constructor, texture->texture_id);
174 if (texture->jobject == NULL) {
175 goto error;
176 }
177
178 if (!gst_amc_surface_texture_detach_from_gl_context (texture, err)) {
179 goto error;
180 }
181
182 return texture;
183
184 error:
185 if (texture)
186 g_object_unref (texture);
187 return NULL;
188 }
189
190 gboolean
gst_amc_surface_texture_set_default_buffer_size(GstAmcSurfaceTexture * self,gint width,gint height,GError ** err)191 gst_amc_surface_texture_set_default_buffer_size (GstAmcSurfaceTexture * self,
192 gint width, gint height, GError ** err)
193 {
194 JNIEnv *env;
195 GstAmcSurfaceTextureClass *klass;
196
197 env = gst_amc_jni_get_env ();
198 klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self);
199
200 return gst_amc_jni_call_void_method (env, err, self->jobject,
201 klass->set_default_buffer_size, width, height);
202 }
203
204 gboolean
gst_amc_surface_texture_update_tex_image(GstAmcSurfaceTexture * self,GError ** err)205 gst_amc_surface_texture_update_tex_image (GstAmcSurfaceTexture * self,
206 GError ** err)
207 {
208 JNIEnv *env;
209 GstAmcSurfaceTextureClass *klass;
210
211 env = gst_amc_jni_get_env ();
212 klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self);
213
214 return gst_amc_jni_call_void_method (env, err, self->jobject,
215 klass->update_tex_image);
216 }
217
218 gboolean
gst_amc_surface_texture_detach_from_gl_context(GstAmcSurfaceTexture * self,GError ** err)219 gst_amc_surface_texture_detach_from_gl_context (GstAmcSurfaceTexture * self,
220 GError ** err)
221 {
222 JNIEnv *env;
223 gboolean ret;
224 GstAmcSurfaceTextureClass *klass;
225
226 env = gst_amc_jni_get_env ();
227 klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self);
228
229 ret =
230 gst_amc_jni_call_void_method (env, err, self->jobject,
231 klass->detach_from_gl_context);
232 self->texture_id = 0;
233 return ret;
234 }
235
236 gboolean
gst_amc_surface_texture_attach_to_gl_context(GstAmcSurfaceTexture * self,gint texture_id,GError ** err)237 gst_amc_surface_texture_attach_to_gl_context (GstAmcSurfaceTexture * self,
238 gint texture_id, GError ** err)
239 {
240 JNIEnv *env;
241 gboolean ret;
242 GstAmcSurfaceTextureClass *klass;
243
244 env = gst_amc_jni_get_env ();
245 klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self);
246
247 ret =
248 gst_amc_jni_call_void_method (env, err, self->jobject,
249 klass->attach_to_gl_context, texture_id);
250 self->texture_id = texture_id;
251 return ret;
252 }
253
254 gboolean
gst_amc_surface_texture_get_transform_matrix(GstAmcSurfaceTexture * self,const gfloat * matrix,GError ** err)255 gst_amc_surface_texture_get_transform_matrix (GstAmcSurfaceTexture * self,
256 const gfloat * matrix, GError ** err)
257 {
258 JNIEnv *env;
259 gboolean ret;
260 GstAmcSurfaceTextureClass *klass;
261 /* 4x4 Matrix */
262 jsize size = 16;
263 jfloatArray floatarray;
264
265 env = gst_amc_jni_get_env ();
266 klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self);
267
268 floatarray = (*env)->NewFloatArray (env, size);
269 ret =
270 gst_amc_jni_call_void_method (env, err, self->jobject,
271 klass->get_transform_matrix, floatarray);
272 if (ret) {
273 (*env)->GetFloatArrayRegion (env, floatarray, 0, size, (jfloat *) matrix);
274 (*env)->DeleteLocalRef (env, floatarray);
275 }
276
277 return ret;
278 }
279
280 gboolean
gst_amc_surface_texture_get_timestamp(GstAmcSurfaceTexture * self,gint64 * result,GError ** err)281 gst_amc_surface_texture_get_timestamp (GstAmcSurfaceTexture * self,
282 gint64 * result, GError ** err)
283 {
284 JNIEnv *env;
285 GstAmcSurfaceTextureClass *klass;
286
287 env = gst_amc_jni_get_env ();
288 klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self);
289
290 return gst_amc_jni_call_long_method (env, err, self->jobject,
291 klass->get_timestamp, result);
292 }
293
294 gboolean
gst_amc_surface_texture_release(GstAmcSurfaceTexture * self,GError ** err)295 gst_amc_surface_texture_release (GstAmcSurfaceTexture * self, GError ** err)
296 {
297 JNIEnv *env;
298 GstAmcSurfaceTextureClass *klass;
299
300 env = gst_amc_jni_get_env ();
301 klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self);
302
303 return gst_amc_jni_call_void_method (env, err, self->jobject, klass->release);
304 }
305
306 gboolean
gst_amc_surface_texture_set_on_frame_available_listener(GstAmcSurfaceTexture * self,jobject listener,GError ** err)307 gst_amc_surface_texture_set_on_frame_available_listener (GstAmcSurfaceTexture *
308 self, jobject listener, GError ** err)
309 {
310 JNIEnv *env;
311 GstAmcSurfaceTextureClass *klass;
312
313 env = gst_amc_jni_get_env ();
314 klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self);
315
316 return gst_amc_jni_call_void_method (env, err, self->jobject,
317 klass->set_on_frame_available_listener, listener);
318 }
319