amc: Turn GstAmcSurfaceTexture into a base class with JNI implementation
authorXavier Claessens <xavier.claessens@collabora.com>
Mon, 12 Nov 2018 19:02:37 +0000 (14:02 -0500)
committerXavier Claessens <xavier.claessens@collabora.com>
Tue, 20 Aug 2019 12:53:55 +0000 (08:53 -0400)
17 files changed:
sys/androidmedia/gst-android-hardware-camera.c
sys/androidmedia/gst-android-hardware-camera.h
sys/androidmedia/gstahcsrc.c
sys/androidmedia/gstahcsrc.h
sys/androidmedia/gstamc-codec.h
sys/androidmedia/gstamc.c
sys/androidmedia/gstamcsurfacetexture.c
sys/androidmedia/gstamcsurfacetexture.h
sys/androidmedia/gstamcvideodec.c
sys/androidmedia/gstamcvideodec.h
sys/androidmedia/gstjniutils.h
sys/androidmedia/jni/gstamc-codec-jni.c
sys/androidmedia/jni/gstamcsurface.c [moved from sys/androidmedia/gstamcsurface.c with 96% similarity]
sys/androidmedia/jni/gstamcsurface.h [moved from sys/androidmedia/gstamcsurface.h with 96% similarity]
sys/androidmedia/jni/gstamcsurfacetexture-jni.c [new file with mode: 0644]
sys/androidmedia/jni/gstamcsurfacetexture-jni.h [new file with mode: 0644]
sys/androidmedia/meson.build

index 614dc86..a47ea77 100644 (file)
@@ -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);
index ab2e25a..9eeadc0 100644 (file)
@@ -29,7 +29,7 @@
 #include <jni.h>
 
 #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);
index d77c3ce..7c6d7b1 100644 (file)
@@ -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);
   }
 
index dc80beb..8c9a17f 100644 (file)
@@ -30,7 +30,7 @@
 #include <gst/base/gstdataqueue.h>
 
 #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;
index 442451a..984dcc5 100644 (file)
@@ -24,6 +24,7 @@
 #include <gst/gst.h>
 
 #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__ */
index 1ea4a82..b2818e2 100644 (file)
@@ -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
index 43c3142..9c7d286 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2013, Fluendo S.A.
  *   Author: Andoni Morales <amorales@fluendo.com>
  *
- * Copyright (C) 2014, Collabora Ltd.
+ * Copyright (C) 2014,2018 Collabora Ltd.
  *   Author: Matthieu Bouron <matthieu.bouron@collabora.com>
  *
  * This library is free software; you can redistribute it and/or
 #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, "<init>", "(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);
 }
index 0d6ebf1..dd250b0 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2013, Fluendo S.A.
  *   Author: Andoni Morales <amorales@fluendo.com>
  *
- * Copyright (C) 2014, Collabora Ltd.
+ * Copyright (C) 2014,2018 Collabora Ltd.
  *   Author: Matthieu Bouron <matthieu.bouron@collabora.com>
  *
  * This library is free software; you can redistribute it and/or
 
 #include <glib.h>
 #include <glib-object.h>
-#include <jni.h>
 
 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;
-
-  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 (* set_default_buffer_size) (GstAmcSurfaceTexture *texture,
+                                        gint width,
+                                        gint height,
+                                        GError ** err);
+
+  gboolean (* update_tex_image)        (GstAmcSurfaceTexture *texture,
+                                        GError ** err);
+
+  gboolean (* detach_from_gl_context)  (GstAmcSurfaceTexture *texture,
+                                        GError ** err);
 
-GType gst_amc_surface_texture_get_type                   (void);
+  gboolean (* attach_to_gl_context)    (GstAmcSurfaceTexture *texture,
+                                        gint index,
+                                        GError ** err);
 
-GstAmcSurfaceTexture * gst_amc_surface_texture_new       (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);
+};
+
+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
index 6ca6dd2..2865c5b 100644 (file)
@@ -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, "<init>", "()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) {
-      ret = FALSE;
-      goto done;
-    }
-
-    if (!gst_amc_surface_texture_set_on_frame_available_listener
-        (surface_texture, self->listener, &err)) {
+    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;
     }
 
-    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)
index 039a785..af3e000 100644 (file)
@@ -27,7 +27,7 @@
 #include <gst/video/gstvideodecoder.h>
 
 #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;
index 1d30edc..98c932c 100644 (file)
 #include <glib.h>
 #include <gst/gst.h>
 
+#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);
index f6fa010..b1752b5 100644 (file)
@@ -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);
+}
similarity index 96%
rename from sys/androidmedia/gstamcsurface.c
rename to sys/androidmedia/jni/gstamcsurface.c
index 33dc6a7..f851e17 100644 (file)
@@ -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;
similarity index 96%
rename from sys/androidmedia/gstamcsurface.h
rename to sys/androidmedia/jni/gstamcsurface.h
index 21f9969..01c67ac 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <glib-object.h>
 #include <jni.h>
-#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 (file)
index 0000000..4c479c6
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2013, Fluendo S.A.
+ *   Author: Andoni Morales <amorales@fluendo.com>
+ *
+ * Copyright (C) 2014,2018 Collabora Ltd.
+ *   Author: Matthieu Bouron <matthieu.bouron@collabora.com>
+ *
+ * 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, "<init>",
+      "(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, "<init>", "()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 (file)
index 0000000..21a6fb7
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013, Fluendo S.A.
+ *   Author: Andoni Morales <amorales@fluendo.com>
+ *
+ * Copyright (C) 2014,2018 Collabora Ltd.
+ *   Author: Matthieu Bouron <matthieu.bouron@collabora.com>
+ *
+ * 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
index 994faf7..3e9622a 100644 (file)
@@ -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 = [