1 /*
2 * Copyright (C) 2018 Collabora Ltd.
3 * Author: Xavier Claessens <xavier.claessens@collabora.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation
8 * version 2.1 of the License.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "gstamc-surfacetexture-ml.h"
26
27 #include <gst/gst.h>
28 #include <ml_media_surface_texture.h>
29
30 struct _GstAmcSurfaceTextureML
31 {
32 GObject parent;
33
34 MLHandle handle;
35 GstAmcSurfaceTextureOnFrameAvailableCallback callback;
36 gpointer user_data;
37 };
38
39 G_DEFINE_TYPE (GstAmcSurfaceTextureML, gst_amc_surface_texture_ml,
40 GST_TYPE_AMC_SURFACE_TEXTURE);
41
42 gboolean
gst_amc_surface_texture_static_init(void)43 gst_amc_surface_texture_static_init (void)
44 {
45 return TRUE;
46 }
47
48 static gboolean
gst_amc_surface_texture_ml_update_tex_image(GstAmcSurfaceTexture * base,GError ** err)49 gst_amc_surface_texture_ml_update_tex_image (GstAmcSurfaceTexture * base,
50 GError ** err)
51 {
52 GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base);
53 MLResult result;
54
55 result = MLMediaSurfaceTextureUpdateTexImage (self->handle);
56 if (result != MLResult_Ok) {
57 g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
58 "Failed to update tex image: %d", result);
59 return FALSE;
60 }
61
62 return TRUE;
63 }
64
65 static gboolean
gst_amc_surface_texture_ml_detach_from_gl_context(GstAmcSurfaceTexture * base,GError ** err)66 gst_amc_surface_texture_ml_detach_from_gl_context (GstAmcSurfaceTexture * base,
67 GError ** err)
68 {
69 GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base);
70 MLResult result;
71
72 result = MLMediaSurfaceTextureDetachFromGLContext (self->handle);
73 if (result != MLResult_Ok) {
74 g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
75 "Failed to detach from gl context: %d", result);
76 return FALSE;
77 }
78
79 return TRUE;
80 }
81
82 static gboolean
gst_amc_surface_texture_ml_attach_to_gl_context(GstAmcSurfaceTexture * base,gint texture_id,GError ** err)83 gst_amc_surface_texture_ml_attach_to_gl_context (GstAmcSurfaceTexture * base,
84 gint texture_id, GError ** err)
85 {
86 GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base);
87 MLResult result;
88
89 result = MLMediaSurfaceTextureAttachToGLContext (self->handle, texture_id);
90 if (result != MLResult_Ok) {
91 g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
92 "Failed to attach to gl context: %d", result);
93 return FALSE;
94 }
95
96 return TRUE;
97 }
98
99 static gboolean
gst_amc_surface_texture_ml_get_transform_matrix(GstAmcSurfaceTexture * base,gfloat * matrix,GError ** err)100 gst_amc_surface_texture_ml_get_transform_matrix (GstAmcSurfaceTexture * base,
101 gfloat * matrix, GError ** err)
102 {
103 GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base);
104 MLResult result;
105
106 result = MLMediaSurfaceTextureGetTransformationMatrix (self->handle, matrix);
107 if (result != MLResult_Ok) {
108 g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
109 "Failed to get transformation matrix: %d", result);
110 return FALSE;
111 }
112
113 return TRUE;
114 }
115
116 static gboolean
gst_amc_surface_texture_ml_get_timestamp(GstAmcSurfaceTexture * base,gint64 * timestamp,GError ** err)117 gst_amc_surface_texture_ml_get_timestamp (GstAmcSurfaceTexture * base,
118 gint64 * timestamp, GError ** err)
119 {
120 GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base);
121 MLResult result;
122
123 result = MLMediaSurfaceTextureGetTimestamp (self->handle, timestamp);
124 if (result != MLResult_Ok) {
125 g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
126 "Failed to get timestamp: %d", result);
127 return FALSE;
128 }
129
130 return TRUE;
131 }
132
133 static gboolean
gst_amc_surface_texture_ml_release(GstAmcSurfaceTexture * base,GError ** err)134 gst_amc_surface_texture_ml_release (GstAmcSurfaceTexture * base, GError ** err)
135 {
136 /* Nothing to do here, resources will be released when this object gets
137 * destroyed. */
138 return TRUE;
139 }
140
141 static gboolean
gst_amc_surface_texture_ml_set_on_frame_available_callback(GstAmcSurfaceTexture * base,GstAmcSurfaceTextureOnFrameAvailableCallback callback,gpointer user_data,GError ** err)142 gst_amc_surface_texture_ml_set_on_frame_available_callback
143 (GstAmcSurfaceTexture * base,
144 GstAmcSurfaceTextureOnFrameAvailableCallback callback, gpointer user_data,
145 GError ** err)
146 {
147 GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (base);
148
149 self->callback = callback;
150 self->user_data = user_data;
151 return TRUE;
152 }
153
154 static void
gst_amc_surface_texture_ml_dispose(GObject * object)155 gst_amc_surface_texture_ml_dispose (GObject * object)
156 {
157 GstAmcSurfaceTextureML *self = GST_AMC_SURFACE_TEXTURE_ML (object);
158
159 MLMediaSurfaceTextureSetOnFrameAvailableCallback (self->handle, NULL, NULL);
160 MLMediaSurfaceTextureDestroy (&self->handle);
161
162 G_OBJECT_CLASS (gst_amc_surface_texture_ml_parent_class)->dispose (object);
163 }
164
165 static void
gst_amc_surface_texture_ml_class_init(GstAmcSurfaceTextureMLClass * klass)166 gst_amc_surface_texture_ml_class_init (GstAmcSurfaceTextureMLClass * klass)
167 {
168 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
169 GstAmcSurfaceTextureClass *surface_texture_class =
170 GST_AMC_SURFACE_TEXTURE_CLASS (klass);
171
172 gobject_class->dispose = gst_amc_surface_texture_ml_dispose;
173
174 surface_texture_class->update_tex_image =
175 gst_amc_surface_texture_ml_update_tex_image;
176 surface_texture_class->detach_from_gl_context =
177 gst_amc_surface_texture_ml_detach_from_gl_context;
178 surface_texture_class->attach_to_gl_context =
179 gst_amc_surface_texture_ml_attach_to_gl_context;
180 surface_texture_class->get_transform_matrix =
181 gst_amc_surface_texture_ml_get_transform_matrix;
182 surface_texture_class->get_timestamp =
183 gst_amc_surface_texture_ml_get_timestamp;
184 surface_texture_class->release = gst_amc_surface_texture_ml_release;
185 surface_texture_class->set_on_frame_available_callback =
186 gst_amc_surface_texture_ml_set_on_frame_available_callback;
187 }
188
189 static void
on_frame_available_cb(MLHandle handle,gpointer user_data)190 on_frame_available_cb (MLHandle handle, gpointer user_data)
191 {
192 GstAmcSurfaceTextureML *self = user_data;
193
194 if (self->callback != NULL)
195 self->callback (GST_AMC_SURFACE_TEXTURE (self), self->user_data);
196 }
197
198 static void
gst_amc_surface_texture_ml_init(GstAmcSurfaceTextureML * self)199 gst_amc_surface_texture_ml_init (GstAmcSurfaceTextureML * self)
200 {
201 MLResult result;
202
203 result =
204 MLMediaSurfaceTextureCreate (MLMediaSurfaceTextureBackend_OpenGL,
205 &self->handle);
206 if (result != MLResult_Ok) {
207 GST_ERROR ("MLMediaSurfaceTextureCreate returned error: %d", result);
208 return;
209 }
210
211 result =
212 MLMediaSurfaceTextureSetOnFrameAvailableCallback (self->handle,
213 on_frame_available_cb, self);
214 if (result != MLResult_Ok) {
215 GST_ERROR
216 ("MLMediaSurfaceTextureSetOnFrameAvailableCallback returned error: %d",
217 result);
218 return;
219 }
220 }
221
222 GstAmcSurfaceTextureML *
gst_amc_surface_texture_ml_new(GError ** err)223 gst_amc_surface_texture_ml_new (GError ** err)
224 {
225 return g_object_new (GST_TYPE_AMC_SURFACE_TEXTURE_ML, NULL);
226 }
227
228 MLHandle
gst_amc_surface_texture_ml_get_handle(GstAmcSurfaceTextureML * self)229 gst_amc_surface_texture_ml_get_handle (GstAmcSurfaceTextureML * self)
230 {
231 return self->handle;
232 }
233