mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
amc: Turn GstAmcSurfaceTexture into a base class with JNI implementation
This commit is contained in:
parent
29ef89983c
commit
7fcf3ebf07
17 changed files with 647 additions and 410 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -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, "<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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -26,51 +26,51 @@
|
|||
|
||||
#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;
|
||||
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
|
||||
|
|
|
@ -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) {
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -29,6 +29,14 @@
|
|||
#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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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,
|
462
sys/androidmedia/jni/gstamcsurfacetexture-jni.c
Normal file
462
sys/androidmedia/jni/gstamcsurfacetexture-jni.c
Normal file
|
@ -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;
|
||||
}
|
40
sys/androidmedia/jni/gstamcsurfacetexture-jni.h
Normal file
40
sys/androidmedia/jni/gstamcsurfacetexture-jni.h
Normal file
|
@ -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
|
|
@ -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 = [
|
||||
|
|
Loading…
Reference in a new issue