/* * Copyright (C) 2018 Collabora Ltd. * Author: Xavier Claessens * * 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 "gstamc-surfacetexture-ml.h" #include #include struct _GstAmcSurfaceTextureML { GObject parent; MLHandle handle; GstAmcSurfaceTextureOnFrameAvailableCallback callback; gpointer user_data; }; G_DEFINE_TYPE (GstAmcSurfaceTextureML, gst_amc_surface_texture_ml, GST_TYPE_AMC_SURFACE_TEXTURE); gboolean gst_amc_surface_texture_static_init (void) { return TRUE; } static gboolean gst_amc_surface_texture_ml_update_tex_image (GstAmcSurfaceTexture * base, GError ** err) { GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base); MLResult result; result = MLMediaSurfaceTextureUpdateTexImage (self->handle); if (result != MLResult_Ok) { g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, "Failed to update tex image: %d", result); return FALSE; } return TRUE; } static gboolean gst_amc_surface_texture_ml_detach_from_gl_context (GstAmcSurfaceTexture * base, GError ** err) { GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base); MLResult result; result = MLMediaSurfaceTextureDetachFromGLContext (self->handle); if (result != MLResult_Ok) { g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, "Failed to detach from gl context: %d", result); return FALSE; } return TRUE; } static gboolean gst_amc_surface_texture_ml_attach_to_gl_context (GstAmcSurfaceTexture * base, gint texture_id, GError ** err) { GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base); MLResult result; result = MLMediaSurfaceTextureAttachToGLContext (self->handle, texture_id); if (result != MLResult_Ok) { g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, "Failed to attach to gl context: %d", result); return FALSE; } return TRUE; } static gboolean gst_amc_surface_texture_ml_get_transform_matrix (GstAmcSurfaceTexture * base, gfloat * matrix, GError ** err) { GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base); MLResult result; result = MLMediaSurfaceTextureGetTransformationMatrix (self->handle, matrix); if (result != MLResult_Ok) { g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, "Failed to get transformation matrix: %d", result); return FALSE; } return TRUE; } static gboolean gst_amc_surface_texture_ml_get_timestamp (GstAmcSurfaceTexture * base, gint64 * timestamp, GError ** err) { GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base); MLResult result; result = MLMediaSurfaceTextureGetTimestamp (self->handle, timestamp); if (result != MLResult_Ok) { g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, "Failed to get timestamp: %d", result); return FALSE; } return TRUE; } static gboolean gst_amc_surface_texture_ml_release (GstAmcSurfaceTexture * base, GError ** err) { /* Nothing to do here, resources will be released when this object gets * destroyed. */ return TRUE; } static gboolean gst_amc_surface_texture_ml_set_on_frame_available_callback (GstAmcSurfaceTexture * base, GstAmcSurfaceTextureOnFrameAvailableCallback callback, gpointer user_data, GError ** err) { GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base); self->callback = callback; self->user_data = user_data; return TRUE; } static void gst_amc_surface_texture_ml_dispose (GObject * object) { GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (object); MLMediaSurfaceTextureSetOnFrameAvailableCallback (self->handle, NULL, NULL); MLMediaSurfaceTextureDestroy (&self->handle); G_OBJECT_CLASS (gst_amc_surface_texture_ml_parent_class)->dispose (object); } static void gst_amc_surface_texture_ml_class_init (GstAmcSurfaceTextureMLClass * 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_ml_dispose; surface_texture_class->update_tex_image = gst_amc_surface_texture_ml_update_tex_image; surface_texture_class->detach_from_gl_context = gst_amc_surface_texture_ml_detach_from_gl_context; surface_texture_class->attach_to_gl_context = gst_amc_surface_texture_ml_attach_to_gl_context; surface_texture_class->get_transform_matrix = gst_amc_surface_texture_ml_get_transform_matrix; surface_texture_class->get_timestamp = gst_amc_surface_texture_ml_get_timestamp; surface_texture_class->release = gst_amc_surface_texture_ml_release; surface_texture_class->set_on_frame_available_callback = gst_amc_surface_texture_ml_set_on_frame_available_callback; } static void on_frame_available_cb (MLHandle handle, gpointer user_data) { GstAmcSurfaceTextureML *self = user_data; if (self->callback != NULL) self->callback (GST_AMC_SURFACE_TEXTURE (self), self->user_data); } static void gst_amc_surface_texture_ml_init (GstAmcSurfaceTextureML * self) { MLResult result; result = MLMediaSurfaceTextureCreate (MLMediaSurfaceTextureBackend_OpenGL, &self->handle); if (result != MLResult_Ok) { GST_ERROR ("MLMediaSurfaceTextureCreate returned error: %d", result); return; } result = MLMediaSurfaceTextureSetOnFrameAvailableCallback (self->handle, on_frame_available_cb, self); if (result != MLResult_Ok) { GST_ERROR ("MLMediaSurfaceTextureSetOnFrameAvailableCallback returned error: %d", result); return; } } GstAmcSurfaceTextureML * gst_amc_surface_texture_ml_new (GError ** err) { return g_object_new (GST_TYPE_AMC_SURFACE_TEXTURE_ML, NULL); } MLHandle gst_amc_surface_texture_ml_get_handle (GstAmcSurfaceTextureML * self) { return self->handle; }