From 7fcf3ebf0731a023bb1c5a597e01d46d041219c6 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 12 Nov 2018 14:02:37 -0500 Subject: [PATCH] amc: Turn GstAmcSurfaceTexture into a base class with JNI implementation --- .../gst-android-hardware-camera.c | 5 +- .../gst-android-hardware-camera.h | 4 +- sys/androidmedia/gstahcsrc.c | 10 +- sys/androidmedia/gstahcsrc.h | 4 +- sys/androidmedia/gstamc-codec.h | 5 +- sys/androidmedia/gstamc.c | 3 + sys/androidmedia/gstamcsurfacetexture.c | 234 +-------- sys/androidmedia/gstamcsurfacetexture.h | 76 +-- sys/androidmedia/gstamcvideodec.c | 161 ++---- sys/androidmedia/gstamcvideodec.h | 7 +- sys/androidmedia/gstjniutils.h | 8 + sys/androidmedia/jni/gstamc-codec-jni.c | 25 +- sys/androidmedia/{ => jni}/gstamcsurface.c | 4 +- sys/androidmedia/{ => jni}/gstamcsurface.h | 6 +- .../jni/gstamcsurfacetexture-jni.c | 462 ++++++++++++++++++ .../jni/gstamcsurfacetexture-jni.h | 40 ++ sys/androidmedia/meson.build | 3 +- 17 files changed, 647 insertions(+), 410 deletions(-) rename sys/androidmedia/{ => jni}/gstamcsurface.c (96%) rename sys/androidmedia/{ => jni}/gstamcsurface.h (96%) create mode 100644 sys/androidmedia/jni/gstamcsurfacetexture-jni.c create mode 100644 sys/androidmedia/jni/gstamcsurfacetexture-jni.h diff --git a/sys/androidmedia/gst-android-hardware-camera.c b/sys/androidmedia/gst-android-hardware-camera.c index 614dc86eff..a47ea774f4 100644 --- a/sys/androidmedia/gst-android-hardware-camera.c +++ b/sys/androidmedia/gst-android-hardware-camera.c @@ -2503,13 +2503,14 @@ done: void gst_ah_camera_set_preview_texture (GstAHCamera * self, - GstAmcSurfaceTexture * surfaceTexture) + GstAmcSurfaceTextureJNI * surfaceTexture) { JNIEnv *env = gst_amc_jni_get_env (); GError *err = NULL; gst_amc_jni_call_void_method (env, &err, self->object, - android_hardware_camera.setPreviewTexture, surfaceTexture->jobject); + android_hardware_camera.setPreviewTexture, + gst_amc_surface_texture_jni_get_jobject (surfaceTexture)); if (err) { GST_ERROR ("Failed to call android.hardware.Camera.setPreviewTexture: %s", err->message); diff --git a/sys/androidmedia/gst-android-hardware-camera.h b/sys/androidmedia/gst-android-hardware-camera.h index ab2e25a737..9eeadc0fab 100644 --- a/sys/androidmedia/gst-android-hardware-camera.h +++ b/sys/androidmedia/gst-android-hardware-camera.h @@ -29,7 +29,7 @@ #include #include "gst-android-graphics-imageformat.h" -#include "gstamcsurfacetexture.h" +#include "jni/gstamcsurfacetexture-jni.h" G_BEGIN_DECLS @@ -150,7 +150,7 @@ gboolean gst_ah_camera_set_error_callback (GstAHCamera * self, gboolean gst_ah_camera_set_preview_callback_with_buffer (GstAHCamera * self, GstAHCPreviewCallback cb, gpointer user_data); void gst_ah_camera_set_preview_texture (GstAHCamera * self, - GstAmcSurfaceTexture * surfaceTexture); + GstAmcSurfaceTextureJNI * surfaceTexture); gboolean gst_ah_camera_start_preview (GstAHCamera * self); gboolean gst_ah_camera_start_smooth_zoom (GstAHCamera * self, gint value); gboolean gst_ah_camera_stop_preview (GstAHCamera * self); diff --git a/sys/androidmedia/gstahcsrc.c b/sys/androidmedia/gstahcsrc.c index d77c3ce570..7c6d7b1723 100644 --- a/sys/androidmedia/gstahcsrc.c +++ b/sys/androidmedia/gstahcsrc.c @@ -2176,7 +2176,7 @@ gst_ahc_src_open (GstAHCSrc * self) if (self->camera) { GST_DEBUG_OBJECT (self, "Opened camera"); - self->texture = gst_amc_surface_texture_new (&err); + self->texture = gst_amc_surface_texture_jni_new (&err); if (self->texture == NULL) { GST_ERROR_OBJECT (self, "Failed to create surface texture object: %s", err->message); @@ -2222,9 +2222,11 @@ gst_ahc_src_close (GstAHCSrc * self) } self->camera = NULL; - if (self->texture && !gst_amc_surface_texture_release (self->texture, &err)) { - GST_ERROR_OBJECT (self, - "Failed to release surface texture object: %s", err->message); + if (self->texture + && !gst_amc_surface_texture_release ((GstAmcSurfaceTexture *) + self->texture, &err)) { + GST_ERROR_OBJECT (self, "Failed to release surface texture object: %s", + err->message); g_clear_error (&err); } diff --git a/sys/androidmedia/gstahcsrc.h b/sys/androidmedia/gstahcsrc.h index dc80beba2a..8c9a17f878 100644 --- a/sys/androidmedia/gstahcsrc.h +++ b/sys/androidmedia/gstahcsrc.h @@ -30,7 +30,7 @@ #include #include "gst-android-hardware-camera.h" -#include "gstamcsurfacetexture.h" +#include "jni/gstamcsurfacetexture-jni.h" G_BEGIN_DECLS @@ -60,7 +60,7 @@ struct _GstAHCSrc GstPushSrc parent; GstAHCamera *camera; - GstAmcSurfaceTexture *texture; + GstAmcSurfaceTextureJNI *texture; GList *data; GstDataQueue *queue; gint buffer_size; diff --git a/sys/androidmedia/gstamc-codec.h b/sys/androidmedia/gstamc-codec.h index 442451aa1b..984dcc5151 100644 --- a/sys/androidmedia/gstamc-codec.h +++ b/sys/androidmedia/gstamc-codec.h @@ -24,6 +24,7 @@ #include #include "gstamc-format.h" +#include "gstamcsurfacetexture.h" G_BEGIN_DECLS @@ -52,7 +53,7 @@ gboolean gst_amc_buffer_set_position_and_limit (GstAmcBuffer * buffer, GError ** GstAmcCodec * gst_amc_codec_new (const gchar *name, GError **err); void gst_amc_codec_free (GstAmcCodec * codec); -gboolean gst_amc_codec_configure (GstAmcCodec * codec, GstAmcFormat * format, jobject surface, gint flags, GError **err); +gboolean gst_amc_codec_configure (GstAmcCodec * codec, GstAmcFormat * format, GstAmcSurfaceTexture * surface_texture, gint flags, GError **err); GstAmcFormat * gst_amc_codec_get_output_format (GstAmcCodec * codec, GError **err); gboolean gst_amc_codec_start (GstAmcCodec * codec, GError **err); @@ -69,6 +70,8 @@ gint gst_amc_codec_dequeue_output_buffer (GstAmcCodec * codec, GstAmcBufferInfo gboolean gst_amc_codec_queue_input_buffer (GstAmcCodec * codec, gint index, const GstAmcBufferInfo *info, GError **err); gboolean gst_amc_codec_release_output_buffer (GstAmcCodec * codec, gint index, gboolean render, GError **err); +GstAmcSurfaceTexture * gst_amc_codec_new_surface_texture (GError ** err); + G_END_DECLS #endif /* __GST_AMC_CODEC_H__ */ diff --git a/sys/androidmedia/gstamc.c b/sys/androidmedia/gstamc.c index 1ea4a82072..b2818e2493 100644 --- a/sys/androidmedia/gstamc.c +++ b/sys/androidmedia/gstamc.c @@ -1828,6 +1828,9 @@ amc_init (GstPlugin * plugin) if (!gst_amc_format_static_init ()) return FALSE; + if (!gst_amc_surface_texture_static_init ()) + return FALSE; + /* Set this to TRUE to allow registering decoders that have * any unknown color formats, or encoders that only have * unknown color formats diff --git a/sys/androidmedia/gstamcsurfacetexture.c b/sys/androidmedia/gstamcsurfacetexture.c index 43c3142a96..9c7d286c08 100644 --- a/sys/androidmedia/gstamcsurfacetexture.c +++ b/sys/androidmedia/gstamcsurfacetexture.c @@ -2,7 +2,7 @@ * Copyright (C) 2013, Fluendo S.A. * Author: Andoni Morales * - * Copyright (C) 2014, Collabora Ltd. + * Copyright (C) 2014,2018 Collabora Ltd. * Author: Matthieu Bouron * * This library is free software; you can redistribute it and/or @@ -25,93 +25,10 @@ #include "config.h" #endif -#include "gstjniutils.h" #include "gstamcsurfacetexture.h" -G_DEFINE_TYPE (GstAmcSurfaceTexture, gst_amc_surface_texture, G_TYPE_OBJECT); - -static gpointer parent_class = NULL; -static void gst_amc_surface_texture_dispose (GObject * object); - -static gboolean -_cache_java_class (GstAmcSurfaceTextureClass * klass, GError ** err) -{ - JNIEnv *env; - - gst_amc_jni_initialize (); - env = gst_amc_jni_get_env (); - - klass->jklass = - gst_amc_jni_get_class (env, err, "android/graphics/SurfaceTexture"); - if (!klass->jklass) { - return FALSE; - } - - klass->constructor = - gst_amc_jni_get_method_id (env, err, klass->jklass, "", "(I)V"); - if (!klass->constructor) { - goto error; - } - - klass->set_on_frame_available_listener = - gst_amc_jni_get_method_id (env, err, klass->jklass, - "setOnFrameAvailableListener", - "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V"); - - klass->set_default_buffer_size = - gst_amc_jni_get_method_id (env, err, klass->jklass, - "setDefaultBufferSize", "(II)V"); - if (!klass->set_default_buffer_size) { - goto error; - } - - klass->update_tex_image = - gst_amc_jni_get_method_id (env, err, klass->jklass, "updateTexImage", - "()V"); - if (!klass->update_tex_image) { - goto error; - } - - klass->detach_from_gl_context = - gst_amc_jni_get_method_id (env, err, klass->jklass, "detachFromGLContext", - "()V"); - if (!klass->detach_from_gl_context) { - goto error; - } - - klass->attach_to_gl_context = - gst_amc_jni_get_method_id (env, err, klass->jklass, "attachToGLContext", - "(I)V"); - if (!klass->attach_to_gl_context) { - goto error; - } - - klass->get_transform_matrix = - gst_amc_jni_get_method_id (env, err, klass->jklass, "getTransformMatrix", - "([F)V"); - if (!klass->get_transform_matrix) { - goto error; - } - - klass->get_timestamp = - gst_amc_jni_get_method_id (env, err, klass->jklass, "getTimestamp", - "()J"); - if (!klass->get_timestamp) { - goto error; - } - - klass->release = - gst_amc_jni_get_method_id (env, err, klass->jklass, "release", "()V"); - if (!klass->release) { - goto error; - } - - return TRUE; - -error: - gst_amc_jni_object_unref (env, klass->constructor); - return FALSE; -} +G_DEFINE_ABSTRACT_TYPE (GstAmcSurfaceTexture, gst_amc_surface_texture, + G_TYPE_OBJECT); static void gst_amc_surface_texture_init (GstAmcSurfaceTexture * self) @@ -121,198 +38,77 @@ gst_amc_surface_texture_init (GstAmcSurfaceTexture * self) static void gst_amc_surface_texture_class_init (GstAmcSurfaceTextureClass * klass) { - GError *err = NULL; - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - gobject_class->dispose = gst_amc_surface_texture_dispose; - - if (!_cache_java_class (klass, &err)) { - g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, - "Could not cache java class android/graphics/SurfaceTexture: %s", - err->message); - g_clear_error (&err); - } -} - -static void -gst_amc_surface_texture_dispose (GObject * object) -{ - GstAmcSurfaceTexture *self; - JNIEnv *env; - GError *err = NULL; - - self = GST_AMC_SURFACE_TEXTURE (object); - env = gst_amc_jni_get_env (); - - if (!gst_amc_surface_texture_release (self, &err)) { - GST_ERROR ("Could not release surface texture: %s", err->message); - g_clear_error (&err); - } - - if (self->jobject) { - gst_amc_jni_object_unref (env, self->jobject); - } - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -GstAmcSurfaceTexture * -gst_amc_surface_texture_new (GError ** err) -{ - GstAmcSurfaceTexture *texture = NULL; - GstAmcSurfaceTextureClass *klass; - JNIEnv *env; - - texture = g_object_new (GST_TYPE_AMC_SURFACE_TEXTURE, NULL); - klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (texture); - env = gst_amc_jni_get_env (); - - texture->texture_id = 0; - - texture->jobject = gst_amc_jni_new_object (env, err, TRUE, klass->jklass, - klass->constructor, texture->texture_id); - if (texture->jobject == NULL) { - goto error; - } - - if (!gst_amc_surface_texture_detach_from_gl_context (texture, err)) { - goto error; - } - - return texture; - -error: - if (texture) - g_object_unref (texture); - return NULL; } gboolean gst_amc_surface_texture_set_default_buffer_size (GstAmcSurfaceTexture * self, gint width, gint height, GError ** err) { - JNIEnv *env; GstAmcSurfaceTextureClass *klass; - - env = gst_amc_jni_get_env (); klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self); - - return gst_amc_jni_call_void_method (env, err, self->jobject, - klass->set_default_buffer_size, width, height); + return klass->set_default_buffer_size (self, width, height, err); } gboolean gst_amc_surface_texture_update_tex_image (GstAmcSurfaceTexture * self, GError ** err) { - JNIEnv *env; GstAmcSurfaceTextureClass *klass; - - env = gst_amc_jni_get_env (); klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self); - - return gst_amc_jni_call_void_method (env, err, self->jobject, - klass->update_tex_image); + return klass->update_tex_image (self, err); } gboolean gst_amc_surface_texture_detach_from_gl_context (GstAmcSurfaceTexture * self, GError ** err) { - JNIEnv *env; - gboolean ret; GstAmcSurfaceTextureClass *klass; - - env = gst_amc_jni_get_env (); klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self); - - ret = - gst_amc_jni_call_void_method (env, err, self->jobject, - klass->detach_from_gl_context); - self->texture_id = 0; - return ret; + return klass->detach_from_gl_context (self, err); } gboolean gst_amc_surface_texture_attach_to_gl_context (GstAmcSurfaceTexture * self, gint texture_id, GError ** err) { - JNIEnv *env; - gboolean ret; GstAmcSurfaceTextureClass *klass; - - env = gst_amc_jni_get_env (); klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self); - - ret = - gst_amc_jni_call_void_method (env, err, self->jobject, - klass->attach_to_gl_context, texture_id); - self->texture_id = texture_id; - return ret; + return klass->attach_to_gl_context (self, texture_id, err); } gboolean gst_amc_surface_texture_get_transform_matrix (GstAmcSurfaceTexture * self, const gfloat * matrix, GError ** err) { - JNIEnv *env; - gboolean ret; GstAmcSurfaceTextureClass *klass; - /* 4x4 Matrix */ - jsize size = 16; - jfloatArray floatarray; - - env = gst_amc_jni_get_env (); klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self); - - floatarray = (*env)->NewFloatArray (env, size); - ret = - gst_amc_jni_call_void_method (env, err, self->jobject, - klass->get_transform_matrix, floatarray); - if (ret) { - (*env)->GetFloatArrayRegion (env, floatarray, 0, size, (jfloat *) matrix); - (*env)->DeleteLocalRef (env, floatarray); - } - - return ret; + return klass->get_transform_matrix (self, matrix, err); } gboolean gst_amc_surface_texture_get_timestamp (GstAmcSurfaceTexture * self, gint64 * result, GError ** err) { - JNIEnv *env; GstAmcSurfaceTextureClass *klass; - - env = gst_amc_jni_get_env (); klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self); - - return gst_amc_jni_call_long_method (env, err, self->jobject, - klass->get_timestamp, result); + return klass->get_timestamp (self, result, err); } gboolean gst_amc_surface_texture_release (GstAmcSurfaceTexture * self, GError ** err) { - JNIEnv *env; GstAmcSurfaceTextureClass *klass; - - env = gst_amc_jni_get_env (); klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self); - - return gst_amc_jni_call_void_method (env, err, self->jobject, klass->release); + return klass->release (self, err); } gboolean -gst_amc_surface_texture_set_on_frame_available_listener (GstAmcSurfaceTexture * - self, jobject listener, GError ** err) +gst_amc_surface_texture_set_on_frame_available_callback (GstAmcSurfaceTexture * + self, GstAmcSurfaceTextureOnFrameAvailableCallback callback, + gpointer user_data, GError ** err) { - JNIEnv *env; GstAmcSurfaceTextureClass *klass; - - env = gst_amc_jni_get_env (); klass = GST_AMC_SURFACE_TEXTURE_GET_CLASS (self); - - return gst_amc_jni_call_void_method (env, err, self->jobject, - klass->set_on_frame_available_listener, listener); + return klass->set_on_frame_available_callback (self, callback, user_data, + err); } diff --git a/sys/androidmedia/gstamcsurfacetexture.h b/sys/androidmedia/gstamcsurfacetexture.h index 0d6ebf14eb..dd250b02e3 100644 --- a/sys/androidmedia/gstamcsurfacetexture.h +++ b/sys/androidmedia/gstamcsurfacetexture.h @@ -2,7 +2,7 @@ * Copyright (C) 2013, Fluendo S.A. * Author: Andoni Morales * - * Copyright (C) 2014, Collabora Ltd. + * Copyright (C) 2014,2018 Collabora Ltd. * Author: Matthieu Bouron * * This library is free software; you can redistribute it and/or @@ -26,51 +26,51 @@ #include #include -#include G_BEGIN_DECLS -#define GST_TYPE_AMC_SURFACE_TEXTURE (gst_amc_surface_texture_get_type ()) -#define GST_AMC_SURFACE_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_AMC_SURFACE_TEXTURE, GstAmcSurfaceTexture)) -#define GST_IS_AMC_SURFACE_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_AMC_SURFACE_TEXTURE)) -#define GST_AMC_SURFACE_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_AMC_SURFACE_TEXTURE, GstAmcSurfaceTextureClass)) -#define GST_IS_AMC_SURFACE_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_AMC_SURFACE_TEXTURE)) -#define GST_AMC_SURFACE_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AMC_SURFACE_TEXTURE, GstAmcSurfaceTextureClass)) +#define GST_TYPE_AMC_SURFACE_TEXTURE gst_amc_surface_texture_get_type () +G_DECLARE_DERIVABLE_TYPE (GstAmcSurfaceTexture, gst_amc_surface_texture, GST, AMC_SURFACE_TEXTURE, GObject) -typedef struct _GstAmcSurfaceTexture GstAmcSurfaceTexture; -typedef struct _GstAmcSurfaceTextureClass GstAmcSurfaceTextureClass; - -struct _GstAmcSurfaceTexture -{ - GObject parent_instance; - - /* instance members */ - gint texture_id; - jobject jobject; -}; +typedef void (* GstAmcSurfaceTextureOnFrameAvailableCallback) (GstAmcSurfaceTexture * self, gpointer user_data); struct _GstAmcSurfaceTextureClass { GObjectClass parent_class; - /* class members */ - gint texture_id; + gboolean (* set_default_buffer_size) (GstAmcSurfaceTexture *texture, + gint width, + gint height, + GError ** err); - jclass jklass; - jmethodID constructor; - jmethodID set_on_frame_available_listener; - jmethodID set_default_buffer_size; - jmethodID update_tex_image; - jmethodID detach_from_gl_context; - jmethodID attach_to_gl_context; - jmethodID get_transform_matrix; - jmethodID get_timestamp; - jmethodID release; + gboolean (* update_tex_image) (GstAmcSurfaceTexture *texture, + GError ** err); + + gboolean (* detach_from_gl_context) (GstAmcSurfaceTexture *texture, + GError ** err); + + gboolean (* attach_to_gl_context) (GstAmcSurfaceTexture *texture, + gint index, + GError ** err); + + gboolean (* get_transform_matrix) (GstAmcSurfaceTexture *texture, + const gfloat *matrix, + GError ** err); + + gboolean (* get_timestamp) (GstAmcSurfaceTexture *texture, + gint64 * result, + GError ** err); + + gboolean (* release) (GstAmcSurfaceTexture *texture, + GError ** err); + + gboolean (* set_on_frame_available_callback) (GstAmcSurfaceTexture * self, + GstAmcSurfaceTextureOnFrameAvailableCallback callback, + gpointer user_data, + GError ** err); }; -GType gst_amc_surface_texture_get_type (void); - -GstAmcSurfaceTexture * gst_amc_surface_texture_new (GError ** err); +gboolean gst_amc_surface_texture_static_init (void); gboolean gst_amc_surface_texture_set_default_buffer_size (GstAmcSurfaceTexture *texture, gint width, @@ -98,9 +98,11 @@ gboolean gst_amc_surface_texture_get_timestamp (GstAmcSurfaceTexture * gboolean gst_amc_surface_texture_release (GstAmcSurfaceTexture *texture, GError ** err); -gboolean gst_amc_surface_texture_set_on_frame_available_listener (GstAmcSurfaceTexture * self, - jobject listener, - GError ** err); +gboolean gst_amc_surface_texture_set_on_frame_available_callback (GstAmcSurfaceTexture * self, + GstAmcSurfaceTextureOnFrameAvailableCallback callback, + gpointer user_data, + GError ** err); G_END_DECLS + #endif diff --git a/sys/androidmedia/gstamcvideodec.c b/sys/androidmedia/gstamcvideodec.c index 6ca6dd2fda..2865c5b38c 100644 --- a/sys/androidmedia/gstamcvideodec.c +++ b/sys/androidmedia/gstamcvideodec.c @@ -68,14 +68,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_amc_video_dec_debug_category); g_clear_error (&err); \ } G_STMT_END -#if GLIB_SIZEOF_VOID_P == 8 -#define JLONG_TO_GST_AMC_VIDEO_DEC(value) (GstAmcVideoDec *)(value) -#define GST_AMC_VIDEO_DEC_TO_JLONG(value) (jlong)(value) -#else -#define JLONG_TO_GST_AMC_VIDEO_DEC(value) (GstAmcVideoDec *)(jint)(value) -#define GST_AMC_VIDEO_DEC_TO_JLONG(value) (jlong)(jint)(value) -#endif - typedef struct _BufferIdentification BufferIdentification; struct _BufferIdentification { @@ -123,7 +115,7 @@ struct gl_sync gint buffer_idx; /* idx of the AMC buffer we should render */ GstBuffer *buffer; /* back reference to the buffer */ GstGLMemory *oes_mem; /* where amc is rendering into. The same for every gl_sync */ - GstAmcSurface *surface; /* java wrapper for where amc is rendering into */ + GstAmcSurfaceTexture *surface; /* java wrapper for where amc is rendering into */ guint gl_frame_no; /* effectively the frame id */ gint64 released_ts; /* microseconds from g_get_monotonic_time() */ struct gl_sync_result *result; @@ -181,8 +173,8 @@ static void _attach_mem_to_context (GstGLContext * context, GstAmcVideoDec * self) { GST_TRACE_OBJECT (self, "attaching texture %p id %u to current context", - self->surface->texture, self->oes_mem->tex_id); - if (!gst_amc_surface_texture_attach_to_gl_context (self->surface->texture, + self->surface, self->oes_mem->tex_id); + if (!gst_amc_surface_texture_attach_to_gl_context (self->surface, self->oes_mem->tex_id, &self->gl_error)) { GST_ERROR_OBJECT (self, "Failed to attach texture to the GL context"); GST_ELEMENT_ERROR_FROM_ERROR (self, self->gl_error); @@ -198,9 +190,9 @@ _dettach_mem_from_context (GstGLContext * context, GstAmcVideoDec * self) guint tex_id = self->oes_mem ? self->oes_mem->tex_id : 0; GST_TRACE_OBJECT (self, "detaching texture %p id %u from current context", - self->surface->texture, tex_id); + self->surface, tex_id); - if (!gst_amc_surface_texture_detach_from_gl_context (self->surface->texture, + if (!gst_amc_surface_texture_detach_from_gl_context (self->surface, &self->gl_error)) { GST_ERROR_OBJECT (self, "Failed to attach texture to the GL context"); GST_ELEMENT_ERROR_FROM_ERROR (self, self->gl_error); @@ -252,8 +244,8 @@ static gboolean gst_amc_video_dec_src_query (GstVideoDecoder * bdec, static GstFlowReturn gst_amc_video_dec_drain (GstAmcVideoDec * self); static gboolean gst_amc_video_dec_check_codec_config (GstAmcVideoDec * self); static void -gst_amc_video_dec_on_frame_available (JNIEnv * env, jobject thiz, - long long context, jobject surfaceTexture); +gst_amc_video_dec_on_frame_available (GstAmcSurfaceTexture * texture, + gpointer user_data); enum { @@ -484,24 +476,19 @@ gst_amc_video_dec_close (GstVideoDecoder * decoder) self->gl_last_rendered_frame = 0; if (self->surface) { - gst_object_unref (self->surface); - self->surface = NULL; - } - - if (self->listener) { - JNIEnv *env = gst_amc_jni_get_env (); GError *err = NULL; - if (!gst_amc_jni_call_void_method (env, &err, self->listener, - self->set_context_id, GST_AMC_VIDEO_DEC_TO_JLONG (NULL))) { - GST_ERROR_OBJECT (self, "Failed to unset back pointer on the listener. " + if (!gst_amc_surface_texture_set_on_frame_available_callback (self->surface, + NULL, NULL, &err)) { + GST_ERROR_OBJECT (self, + "Failed to unset back pointer on the listener. " "crashes/hangs may ensue: %s", err ? err->message : "Unknown"); GST_ELEMENT_ERROR_FROM_ERROR (self, err); } - gst_amc_jni_object_unref (env, self->listener); + gst_object_unref (self->surface); + self->surface = NULL; } - self->listener = NULL; if (self->codec) { GError *err = NULL; @@ -1069,8 +1056,7 @@ _gl_sync_render_unlocked (struct gl_sync *sync) /* FIXME: if this ever starts returning valid values we should attempt * to use it */ - if (!gst_amc_surface_texture_get_timestamp (sync->surface->texture, &ts, - &error)) { + if (!gst_amc_surface_texture_get_timestamp (sync->surface, &ts, &error)) { GST_ERROR_OBJECT (sync->sink, "Failed to update texture image"); GST_ELEMENT_ERROR_FROM_ERROR (sync->sink, error); goto out; @@ -1079,8 +1065,7 @@ _gl_sync_render_unlocked (struct gl_sync *sync) sync, ts); GST_TRACE ("gl_sync %p update_tex_image", sync); - if (!gst_amc_surface_texture_update_tex_image (sync->surface->texture, - &error)) { + if (!gst_amc_surface_texture_update_tex_image (sync->surface, &error)) { GST_ERROR_OBJECT (sync->sink, "Failed to update texture image"); GST_ELEMENT_ERROR_FROM_ERROR (sync->sink, error); goto out; @@ -1089,8 +1074,7 @@ _gl_sync_render_unlocked (struct gl_sync *sync) sync->result->updated = TRUE; sync->sink->gl_last_rendered_frame = sync->gl_frame_no; - if (!gst_amc_surface_texture_get_timestamp (sync->surface->texture, &ts, - &error)) { + if (!gst_amc_surface_texture_get_timestamp (sync->surface, &ts, &error)) { GST_ERROR_OBJECT (sync->sink, "Failed to update texture image"); GST_ELEMENT_ERROR_FROM_ERROR (sync->sink, error); goto out; @@ -1102,8 +1086,8 @@ _gl_sync_render_unlocked (struct gl_sync *sync) if (!af_meta) { GST_WARNING ("Failed to retreive the transformation meta from the " "gl_sync %p buffer %p", sync, sync->buffer); - } else if (gst_amc_surface_texture_get_transform_matrix (sync->surface-> - texture, matrix, &error)) { + } else if (gst_amc_surface_texture_get_transform_matrix (sync->surface, + matrix, &error)) { gfloat inv_mat[16]; /* The transform from mediacodec applies to the texture coords, but @@ -1123,7 +1107,7 @@ _gl_sync_render_unlocked (struct gl_sync *sync) } GST_LOG ("gl_sync %p successfully updated SurfaceTexture %p into " - "OES texture %u", sync, sync->surface->texture, sync->oes_mem->tex_id); + "OES texture %u", sync, sync->surface, sync->oes_mem->tex_id); out: if (error) { @@ -1807,64 +1791,6 @@ gst_amc_video_dec_stop (GstVideoDecoder * decoder) return TRUE; } -static jobject -gst_amc_video_dec_new_on_frame_available_listener (GstAmcVideoDec * decoder, - JNIEnv * env, GError ** err) -{ - jobject listener = NULL; - jclass listener_cls = NULL; - jmethodID constructor_id = 0; - - JNINativeMethod amcOnFrameAvailableListener = { - "native_onFrameAvailable", - "(JLandroid/graphics/SurfaceTexture;)V", - (void *) gst_amc_video_dec_on_frame_available, - }; - - listener_cls = - gst_amc_jni_get_application_class (env, - "org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener", - err); - if (!listener_cls) { - return FALSE; - } - - (*env)->RegisterNatives (env, listener_cls, &amcOnFrameAvailableListener, 1); - if ((*env)->ExceptionCheck (env)) { - (*env)->ExceptionClear (env); - goto done; - } - - constructor_id = - gst_amc_jni_get_method_id (env, err, listener_cls, "", "()V"); - if (!constructor_id) { - goto done; - } - - decoder->set_context_id = - gst_amc_jni_get_method_id (env, err, listener_cls, "setContext", "(J)V"); - if (!decoder->set_context_id) { - goto done; - } - - listener = - gst_amc_jni_new_object (env, err, TRUE, listener_cls, constructor_id); - if (!listener) { - goto done; - } - - if (!gst_amc_jni_call_void_method (env, err, listener, - decoder->set_context_id, GST_AMC_VIDEO_DEC_TO_JLONG (decoder))) { - gst_amc_jni_object_unref (env, listener); - listener = NULL; - } - -done: - gst_amc_jni_object_unref (env, listener_cls); - - return listener; -} - static gboolean gst_amc_video_dec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state) @@ -1879,7 +1805,6 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder, guint8 *codec_data = NULL; gsize codec_data_size = 0; GError *err = NULL; - jobject jsurface = NULL; self = GST_AMC_VIDEO_DEC (decoder); klass = GST_AMC_VIDEO_DEC_GET_CLASS (self); @@ -2071,50 +1996,31 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder, } if (self->downstream_supports_gl && self->surface) { - jsurface = self->surface->jobject; + self->codec_config = AMC_CODEC_CONFIG_WITH_SURFACE; } else if (self->downstream_supports_gl && !self->surface) { int ret = TRUE; - JNIEnv *env = NULL; - GstAmcSurfaceTexture *surface_texture = NULL; - env = gst_amc_jni_get_env (); - surface_texture = gst_amc_surface_texture_new (&err); - if (!surface_texture) { + self->surface = gst_amc_codec_new_surface_texture (&err); + if (!self->surface) { GST_ELEMENT_ERROR_FROM_ERROR (self, err); return FALSE; } - if (self->listener) { - if (!gst_amc_jni_call_void_method (env, &err, self->listener, - self->set_context_id, GST_AMC_VIDEO_DEC_TO_JLONG (NULL))) { - ret = FALSE; - goto done; - } - - gst_amc_jni_object_unref (env, self->listener); - } - self->listener = - gst_amc_video_dec_new_on_frame_available_listener (self, env, &err); - if (!self->listener) { + if (!gst_amc_surface_texture_set_on_frame_available_callback + (self->surface, gst_amc_video_dec_on_frame_available, self, &err)) { ret = FALSE; goto done; } - if (!gst_amc_surface_texture_set_on_frame_available_listener - (surface_texture, self->listener, &err)) { - ret = FALSE; - goto done; - } - - self->surface = gst_amc_surface_new (surface_texture, &err); - jsurface = self->surface->jobject; + self->codec_config = AMC_CODEC_CONFIG_WITH_SURFACE; done: - g_object_unref (surface_texture); if (!ret) { GST_ELEMENT_ERROR_FROM_ERROR (self, err); return FALSE; } + } else { + self->codec_config = AMC_CODEC_CONFIG_WITHOUT_SURFACE; } format_string = gst_amc_format_to_string (format, &err); @@ -2124,16 +2030,11 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder, GST_STR_NULL (format_string)); g_free (format_string); - if (!gst_amc_codec_configure (self->codec, format, jsurface, 0, &err)) { + if (!gst_amc_codec_configure (self->codec, format, self->surface, 0, &err)) { GST_ERROR_OBJECT (self, "Failed to configure codec"); GST_ELEMENT_ERROR_FROM_ERROR (self, err); return FALSE; } - if (jsurface) { - self->codec_config = AMC_CODEC_CONFIG_WITH_SURFACE; - } else { - self->codec_config = AMC_CODEC_CONFIG_WITHOUT_SURFACE; - } gst_amc_format_free (format); @@ -2606,10 +2507,10 @@ context_error: } static void -gst_amc_video_dec_on_frame_available (JNIEnv * env, jobject thiz, - long long context, jobject surfaceTexture) +gst_amc_video_dec_on_frame_available (GstAmcSurfaceTexture * texture, + gpointer user_data) { - GstAmcVideoDec *self = JLONG_TO_GST_AMC_VIDEO_DEC (context); + GstAmcVideoDec *self = (GstAmcVideoDec *) user_data; /* apparently we can be called after the decoder has been closed */ if (!self) diff --git a/sys/androidmedia/gstamcvideodec.h b/sys/androidmedia/gstamcvideodec.h index 039a785e3e..af3e000992 100644 --- a/sys/androidmedia/gstamcvideodec.h +++ b/sys/androidmedia/gstamcvideodec.h @@ -27,7 +27,7 @@ #include #include "gstamc.h" -#include "gstamcsurface.h" +#include "gstamcsurfacetexture.h" G_BEGIN_DECLS @@ -91,7 +91,7 @@ struct _GstAmcVideoDec /* TRUE if the component is drained currently */ gboolean drained; - GstAmcSurface *surface; + GstAmcSurfaceTexture *surface; GstGLDisplay *gl_display; GstGLContext *gl_context; @@ -100,9 +100,6 @@ struct _GstAmcVideoDec gboolean downstream_supports_gl; GstFlowReturn downstream_flow_ret; - jobject listener; - jmethodID set_context_id; - gboolean gl_mem_attached; GstGLMemory *oes_mem; GError *gl_error; diff --git a/sys/androidmedia/gstjniutils.h b/sys/androidmedia/gstjniutils.h index 1d30edc43a..98c932c9d3 100644 --- a/sys/androidmedia/gstjniutils.h +++ b/sys/androidmedia/gstjniutils.h @@ -29,6 +29,14 @@ #include #include +#if GLIB_SIZEOF_VOID_P == 8 +#define JLONG_TO_GPOINTER(value) (gpointer)(value) +#define GPOINTER_TO_JLONG(value) (jlong)(value) +#else +#define JLONG_TO_GPOINTER(value) (gpointer)(jint)(value) +#define GPOINTER_TO_JLONG(value) (jlong)(jint)(value) +#endif + jclass gst_amc_jni_get_class (JNIEnv * env, GError ** err, const gchar * name); diff --git a/sys/androidmedia/jni/gstamc-codec-jni.c b/sys/androidmedia/jni/gstamc-codec-jni.c index f6fa010d77..b1752b5847 100644 --- a/sys/androidmedia/jni/gstamc-codec-jni.c +++ b/sys/androidmedia/jni/gstamc-codec-jni.c @@ -27,6 +27,8 @@ #include "../gstamc-codec.h" #include "../gstamc-constants.h" #include "gstamc-internal-jni.h" +#include "gstamcsurfacetexture-jni.h" +#include "gstamcsurface.h" struct _GstAmcCodec { @@ -34,6 +36,7 @@ struct _GstAmcCodec RealBuffer *input_buffers, *output_buffers; gsize n_input_buffers, n_output_buffers; + GstAmcSurface *surface; }; static struct @@ -503,22 +506,34 @@ gst_amc_codec_free (GstAmcCodec * codec) codec->output_buffers = NULL; codec->n_output_buffers = 0; + g_clear_object (&codec->surface); + gst_amc_jni_object_unref (env, codec->object); g_slice_free (GstAmcCodec, codec); } gboolean gst_amc_codec_configure (GstAmcCodec * codec, GstAmcFormat * format, - jobject surface, gint flags, GError ** err) + GstAmcSurfaceTexture * surface, gint flags, GError ** err) { JNIEnv *env; g_return_val_if_fail (codec != NULL, FALSE); g_return_val_if_fail (format != NULL, FALSE); + g_return_val_if_fail (GST_IS_AMC_SURFACE_TEXTURE_JNI (surface), FALSE); env = gst_amc_jni_get_env (); + + if (surface) { + g_object_unref (codec->surface); + codec->surface = + gst_amc_surface_new ((GstAmcSurfaceTextureJNI *) surface, err); + if (!codec->surface) + return FALSE; + } + return gst_amc_jni_call_void_method (env, err, codec->object, - media_codec.configure, format->object, surface, NULL, flags); + media_codec.configure, format->object, codec->surface, NULL, flags); } GstAmcFormat * @@ -934,3 +949,9 @@ gst_amc_codec_release_output_buffer (GstAmcCodec * codec, gint index, return gst_amc_jni_call_void_method (env, err, codec->object, media_codec.release_output_buffer, index, render); } + +GstAmcSurfaceTexture * +gst_amc_codec_new_surface_texture (GError ** err) +{ + return (GstAmcSurfaceTexture *) gst_amc_surface_texture_jni_new (err); +} diff --git a/sys/androidmedia/gstamcsurface.c b/sys/androidmedia/jni/gstamcsurface.c similarity index 96% rename from sys/androidmedia/gstamcsurface.c rename to sys/androidmedia/jni/gstamcsurface.c index 33dc6a7ce7..f851e176ce 100644 --- a/sys/androidmedia/gstamcsurface.c +++ b/sys/androidmedia/jni/gstamcsurface.c @@ -131,7 +131,7 @@ gst_amc_surface_dispose (GObject * object) } GstAmcSurface * -gst_amc_surface_new (GstAmcSurfaceTexture * texture, GError ** err) +gst_amc_surface_new (GstAmcSurfaceTextureJNI * texture, GError ** err) { GstAmcSurface *surface; GstAmcSurfaceClass *klass; @@ -142,7 +142,7 @@ gst_amc_surface_new (GstAmcSurfaceTexture * texture, GError ** err) klass = GST_AMC_SURFACE_GET_CLASS (surface); surface->jobject = gst_amc_jni_new_object (env, err, TRUE, klass->jklass, - klass->constructor, texture->jobject); + klass->constructor, gst_amc_surface_texture_jni_get_jobject (texture)); if (surface->jobject == NULL) { g_object_unref (surface); return NULL; diff --git a/sys/androidmedia/gstamcsurface.h b/sys/androidmedia/jni/gstamcsurface.h similarity index 96% rename from sys/androidmedia/gstamcsurface.h rename to sys/androidmedia/jni/gstamcsurface.h index 21f9969b25..01c67ac4f4 100644 --- a/sys/androidmedia/gstamcsurface.h +++ b/sys/androidmedia/jni/gstamcsurface.h @@ -26,7 +26,7 @@ #include #include -#include "gstamcsurfacetexture.h" +#include "jni/gstamcsurfacetexture-jni.h" G_BEGIN_DECLS @@ -46,7 +46,7 @@ struct _GstAmcSurface /* instance members */ jobject jobject; - GstAmcSurfaceTexture *texture; + GstAmcSurfaceTextureJNI *texture; }; struct _GstAmcSurfaceClass @@ -63,7 +63,7 @@ struct _GstAmcSurfaceClass GType gst_amc_surface_get_type (void); -GstAmcSurface * gst_amc_surface_new (GstAmcSurfaceTexture *texture, +GstAmcSurface * gst_amc_surface_new (GstAmcSurfaceTextureJNI *texture, GError ** err); gboolean gst_amc_surface_is_valid (GstAmcSurface *surface, diff --git a/sys/androidmedia/jni/gstamcsurfacetexture-jni.c b/sys/androidmedia/jni/gstamcsurfacetexture-jni.c new file mode 100644 index 0000000000..4c479c6671 --- /dev/null +++ b/sys/androidmedia/jni/gstamcsurfacetexture-jni.c @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2013, Fluendo S.A. + * Author: Andoni Morales + * + * Copyright (C) 2014,2018 Collabora Ltd. + * Author: Matthieu Bouron + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstjniutils.h" +#include "gstamcsurfacetexture-jni.h" + +struct _GstAmcSurfaceTextureJNI +{ + jobject jobject; + gint texture_id; + + jobject listener; + jmethodID set_context_id; + GstAmcSurfaceTextureOnFrameAvailableCallback callback; + gpointer user_data; +}; + +static struct +{ + jclass jklass; + jmethodID constructor; + jmethodID set_on_frame_available_listener; + jmethodID set_default_buffer_size; + jmethodID update_tex_image; + jmethodID detach_from_gl_context; + jmethodID attach_to_gl_context; + jmethodID get_transform_matrix; + jmethodID get_timestamp; + jmethodID release; +} surface_texture; + + +G_DEFINE_TYPE (GstAmcSurfaceTextureJNI, gst_amc_surface_texture_jni, + GST_TYPE_AMC_SURFACE_TEXTURE); + +gboolean +gst_amc_surface_texture_static_init (void) +{ + JNIEnv *env; + GError *err = NULL; + + env = gst_amc_jni_get_env (); + + surface_texture.jklass = gst_amc_jni_get_class (env, &err, + "android/graphics/SurfaceTexture"); + if (!surface_texture.jklass) { + GST_ERROR ("Failed to get android.graphics.SurfaceTexture class: %s", + err->message); + g_clear_error (&err); + return FALSE; + } + + surface_texture.constructor = + gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, "", + "(I)V"); + if (!surface_texture.constructor) { + goto error; + } + + surface_texture.set_on_frame_available_listener = + gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, + "setOnFrameAvailableListener", + "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V"); + if (!surface_texture.set_on_frame_available_listener) { + goto error; + } + + surface_texture.set_default_buffer_size = + gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, + "setDefaultBufferSize", "(II)V"); + if (!surface_texture.set_default_buffer_size) { + goto error; + } + + surface_texture.update_tex_image = + gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, + "updateTexImage", "()V"); + if (!surface_texture.update_tex_image) { + goto error; + } + + surface_texture.detach_from_gl_context = + gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, + "detachFromGLContext", "()V"); + if (!surface_texture.detach_from_gl_context) { + goto error; + } + + surface_texture.attach_to_gl_context = + gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, + "attachToGLContext", "(I)V"); + if (!surface_texture.attach_to_gl_context) { + goto error; + } + + surface_texture.get_transform_matrix = + gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, + "getTransformMatrix", "([F)V"); + if (!surface_texture.get_transform_matrix) { + goto error; + } + + surface_texture.get_timestamp = + gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, + "getTimestamp", "()J"); + if (!surface_texture.get_timestamp) { + goto error; + } + + surface_texture.release = + gst_amc_jni_get_method_id (env, &err, surface_texture.jklass, "release", + "()V"); + if (!surface_texture.release) { + goto error; + } + + return TRUE; + +error: + GST_ERROR ("Failed to get android.graphics.SurfaceTexture methods: %s", + err->message); + g_clear_error (&err); + gst_amc_jni_object_unref (env, surface_texture.constructor); + return FALSE; +} + +static gboolean +gst_amc_surface_texture_jni_set_default_buffer_size (GstAmcSurfaceTexture * + base, gint width, gint height, GError ** err) +{ + GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base); + JNIEnv *env; + + env = gst_amc_jni_get_env (); + + return gst_amc_jni_call_void_method (env, err, self->jobject, + surface_texture.set_default_buffer_size, width, height); +} + +static gboolean +gst_amc_surface_texture_jni_update_tex_image (GstAmcSurfaceTexture * base, + GError ** err) +{ + GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base); + JNIEnv *env; + + env = gst_amc_jni_get_env (); + + return gst_amc_jni_call_void_method (env, err, self->jobject, + surface_texture.update_tex_image); +} + +static gboolean +gst_amc_surface_texture_jni_detach_from_gl_context (GstAmcSurfaceTexture * base, + GError ** err) +{ + GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base); + JNIEnv *env; + gboolean ret; + + env = gst_amc_jni_get_env (); + + ret = + gst_amc_jni_call_void_method (env, err, self->jobject, + surface_texture.detach_from_gl_context); + self->texture_id = 0; + return ret; +} + +static gboolean +gst_amc_surface_texture_jni_attach_to_gl_context (GstAmcSurfaceTexture * base, + gint texture_id, GError ** err) +{ + GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base); + JNIEnv *env; + gboolean ret; + + env = gst_amc_jni_get_env (); + + ret = + gst_amc_jni_call_void_method (env, err, self->jobject, + surface_texture.attach_to_gl_context, texture_id); + self->texture_id = texture_id; + return ret; +} + +static gboolean +gst_amc_surface_texture_jni_get_transform_matrix (GstAmcSurfaceTexture * base, + const gfloat * matrix, GError ** err) +{ + GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base); + JNIEnv *env; + gboolean ret; + /* 4x4 Matrix */ + jsize size = 16; + jfloatArray floatarray; + + env = gst_amc_jni_get_env (); + + floatarray = (*env)->NewFloatArray (env, size); + ret = + gst_amc_jni_call_void_method (env, err, self->jobject, + surface_texture.get_transform_matrix, floatarray); + if (ret) { + (*env)->GetFloatArrayRegion (env, floatarray, 0, size, (jfloat *) matrix); + (*env)->DeleteLocalRef (env, floatarray); + } + + return ret; +} + +static gboolean +gst_amc_surface_texture_jni_get_timestamp (GstAmcSurfaceTexture * base, + gint64 * result, GError ** err) +{ + GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base); + JNIEnv *env; + + env = gst_amc_jni_get_env (); + + return gst_amc_jni_call_long_method (env, err, self->jobject, + surface_texture.get_timestamp, result); +} + +static gboolean +gst_amc_surface_texture_jni_release (GstAmcSurfaceTexture * base, GError ** err) +{ + GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base); + JNIEnv *env; + + env = gst_amc_jni_get_env (); + + return gst_amc_jni_call_void_method (env, err, self->jobject, + surface_texture.release); +} + +static void +on_frame_available_cb (JNIEnv * env, jobject thiz, + long long context, jobject surfaceTexture) +{ + GstAmcSurfaceTextureJNI *self = JLONG_TO_GPOINTER (context); + + self->callback (GST_AMC_SURFACE_TEXTURE (self), self->user_data); +} + +static gboolean +create_listener (GstAmcSurfaceTextureJNI * self, JNIEnv * env, GError ** err) +{ + jclass listener_cls = NULL; + jmethodID constructor_id = 0; + + JNINativeMethod amcOnFrameAvailableListener = { + "native_onFrameAvailable", + "(JLandroid/graphics/SurfaceTexture;)V", + (void *) on_frame_available_cb, + }; + + listener_cls = + gst_amc_jni_get_application_class (env, + "org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener", + err); + if (!listener_cls) { + return FALSE; + } + + (*env)->RegisterNatives (env, listener_cls, &amcOnFrameAvailableListener, 1); + if ((*env)->ExceptionCheck (env)) { + (*env)->ExceptionClear (env); + goto done; + } + + constructor_id = + gst_amc_jni_get_method_id (env, err, listener_cls, "", "()V"); + if (!constructor_id) { + goto done; + } + + self->set_context_id = + gst_amc_jni_get_method_id (env, err, listener_cls, "setContext", "(J)V"); + if (!self->set_context_id) { + goto done; + } + + self->listener = + gst_amc_jni_new_object (env, err, TRUE, listener_cls, constructor_id); + if (!self->listener) { + goto done; + } + + if (!gst_amc_jni_call_void_method (env, err, self->listener, + self->set_context_id, GPOINTER_TO_JLONG (self))) { + gst_amc_jni_object_unref (env, self->listener); + self->listener = NULL; + } + +done: + gst_amc_jni_object_unref (env, listener_cls); + + return self->listener != NULL; +} + +static gboolean +remove_listener (GstAmcSurfaceTextureJNI * self, JNIEnv * env, GError ** err) +{ + if (self->listener) { + if (!gst_amc_jni_call_void_method (env, err, self->listener, + self->set_context_id, GPOINTER_TO_JLONG (NULL))) + return FALSE; + + gst_amc_jni_object_unref (env, self->listener); + self->listener = NULL; + } + + return TRUE; +} + +static gboolean + gst_amc_surface_texture_jni_set_on_frame_available_callback + (GstAmcSurfaceTexture * base, + GstAmcSurfaceTextureOnFrameAvailableCallback callback, gpointer user_data, + GError ** err) +{ + GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (base); + JNIEnv *env; + + env = gst_amc_jni_get_env (); + + if (!remove_listener (self, env, err)) + return FALSE; + + self->callback = callback; + self->user_data = user_data; + if (callback == NULL) + return TRUE; + + if (!create_listener (self, env, err)) + return FALSE; + + if (!gst_amc_jni_call_void_method (env, err, self->jobject, + surface_texture.set_on_frame_available_listener, self->listener)) { + remove_listener (self, env, NULL); + return FALSE; + } + + return TRUE; +} + +static void +gst_amc_surface_texture_jni_dispose (GObject * object) +{ + GstAmcSurfaceTextureJNI *self = GST_AMC_SURFACE_TEXTURE_JNI (object); + JNIEnv *env; + GError *err = NULL; + + env = gst_amc_jni_get_env (); + + if (!gst_amc_surface_texture_jni_release (GST_AMC_SURFACE_TEXTURE (self), + &err)) { + GST_ERROR ("Could not release surface texture: %s", err->message); + g_clear_error (&err); + } + + remove_listener (self, env, NULL); + + if (self->jobject) { + gst_amc_jni_object_unref (env, self->jobject); + } + + G_OBJECT_CLASS (gst_amc_surface_texture_jni_parent_class)->dispose (object); +} + +static void +gst_amc_surface_texture_jni_class_init (GstAmcSurfaceTextureJNIClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstAmcSurfaceTextureClass *surface_texture_class = + GST_AMC_SURFACE_TEXTURE_CLASS (klass); + + gobject_class->dispose = gst_amc_surface_texture_jni_dispose; + + surface_texture_class->set_default_buffer_size = + gst_amc_surface_texture_jni_set_default_buffer_size; + surface_texture_class->update_tex_image = + gst_amc_surface_texture_jni_update_tex_image; + surface_texture_class->detach_from_gl_context = + gst_amc_surface_texture_jni_detach_from_gl_context; + surface_texture_class->attach_to_gl_context = + gst_amc_surface_texture_jni_attach_to_gl_context; + surface_texture_class->get_transform_matrix = + gst_amc_surface_texture_jni_get_transform_matrix; + surface_texture_class->get_timestamp = + gst_amc_surface_texture_jni_get_timestamp; + surface_texture_class->release = gst_amc_surface_texture_jni_release; + surface_texture_class->set_on_frame_available_callback = + gst_amc_surface_texture_jni_set_on_frame_available_callback; +} + +static void +gst_amc_surface_texture_jni_init (GstAmcSurfaceTextureJNI * self) +{ +} + +GstAmcSurfaceTextureJNI * +gst_amc_surface_texture_jni_new (GError ** err) +{ + GstAmcSurfaceTextureJNI *self = NULL; + JNIEnv *env; + + self = g_object_new (GST_TYPE_AMC_SURFACE_TEXTURE_JNI, NULL); + env = gst_amc_jni_get_env (); + + self->texture_id = 0; + + self->jobject = + gst_amc_jni_new_object (env, err, TRUE, surface_texture.jklass, + surface_texture.constructor, self->texture_id); + if (self->jobject == NULL) { + goto error; + } + + if (!gst_amc_surface_texture_jni_detach_from_gl_context ((GstAmcSurfaceTexture + *) self, err)) { + goto error; + } + + return self; + +error: + if (self) + g_object_unref (self); + return NULL; +} + +jobject +gst_amc_surface_texture_jni_get_jobject (GstAmcSurfaceTextureJNI * self) +{ + return self->jobject; +} diff --git a/sys/androidmedia/jni/gstamcsurfacetexture-jni.h b/sys/androidmedia/jni/gstamcsurfacetexture-jni.h new file mode 100644 index 0000000000..21a6fb7a4b --- /dev/null +++ b/sys/androidmedia/jni/gstamcsurfacetexture-jni.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013, Fluendo S.A. + * Author: Andoni Morales + * + * Copyright (C) 2014,2018 Collabora Ltd. + * Author: Matthieu Bouron + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __GST_AMC_SURFACE_TEXTURE_JNI_H__ +#define __GST_AMC_SURFACE_TEXTURE_JNI_H__ + +#include "../gstamcsurfacetexture.h" + +G_BEGIN_DECLS + +#define GST_TYPE_AMC_SURFACE_TEXTURE_JNI gst_amc_surface_texture_jni_get_type () +G_DECLARE_FINAL_TYPE (GstAmcSurfaceTextureJNI, gst_amc_surface_texture_jni, GST, AMC_SURFACE_TEXTURE_JNI, GstAmcSurfaceTexture) + +GstAmcSurfaceTextureJNI * gst_amc_surface_texture_jni_new (GError ** err); + +jobject gst_amc_surface_texture_jni_get_jobject (GstAmcSurfaceTextureJNI * self); + +G_END_DECLS + +#endif diff --git a/sys/androidmedia/meson.build b/sys/androidmedia/meson.build index 994faf79f2..3e9622a96e 100644 --- a/sys/androidmedia/meson.build +++ b/sys/androidmedia/meson.build @@ -3,7 +3,6 @@ androidmedia_sources = [ 'gstahssrc.c', 'gstamcaudiodec.c', 'gstamc.c', - 'gstamcsurface.c', 'gstamcsurfacetexture.c', 'gstamcvideodec.c', 'gstamcvideoenc.c', @@ -14,6 +13,8 @@ androidmedia_sources = [ 'jni/gstamc-codec-jni.c', 'jni/gstamc-codeclist-jni.c', 'jni/gstamc-format-jni.c', + 'jni/gstamcsurface.c', + 'jni/gstamcsurfacetexture-jni.c', ] androidmedia_java_sources = [