/
nemovideotexture.c
308 lines (273 loc) · 9.46 KB
/
nemovideotexture.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/*
* Copyright (C) 2013 Jolla LTD.
*
* Contact: Mohammed Hassan <mohammed.hassan@jollamobile.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; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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
*/
/**
* SECTION:nemo_gst_video_texture
* @short_description Interface for video rendering
*
* This is an interface which enables integrating video rendering into any OpenGL ES 2.0
* application.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "nemovideotexture.h"
enum
{
SIGNAL_FRAME_READY,
LAST_SIGNAL
};
static guint nemo_gst_video_texture_iface_signals[LAST_SIGNAL] = { 0 };
static void nemo_gst_video_texture_iface_base_init (NemoGstVideoTextureClass *
klass);
static void nemo_gst_video_texture_iface_class_init (NemoGstVideoTextureClass *
klass);
GType
nemo_gst_video_texture_get_type (void)
{
static GType nemo_gst_video_texture_type = 0;
if (!nemo_gst_video_texture_type) {
static const GTypeInfo nemo_gst_video_texture_info = {
sizeof (NemoGstVideoTextureClass),
(GBaseInitFunc) nemo_gst_video_texture_iface_base_init, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) nemo_gst_video_texture_iface_class_init, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL, /* instance_init */
};
nemo_gst_video_texture_type = g_type_register_static (G_TYPE_INTERFACE,
"NemoGstVideoTexture", &nemo_gst_video_texture_info, 0);
}
return nemo_gst_video_texture_type;
}
static void
nemo_gst_video_texture_iface_base_init (NemoGstVideoTextureClass * klass)
{
static gboolean initialized = FALSE;
if (!initialized) {
/**
* NemoGstVideoTextureClass::frame-ready
*
* Triggered when the sink element implementing this interface eith has
* a frame for the application to render or lost its frame.
* frame is an opaque frame identifier.
* frame will be -1 if the sink element has lost its frame
* or will be 0 or greater if there is a frame available for rendering.
*
* If frame is 0 or more, application should call nemo_gst_video_texture_acquire_frame()
* if its interested in rendering.
* If frame is -1 then application should release any acquired frames.
*/
nemo_gst_video_texture_iface_signals[SIGNAL_FRAME_READY] =
g_signal_new ("frame-ready",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
initialized = TRUE;
}
klass->acquire_frame = NULL;
klass->bind_frame = NULL;
klass->unbind_frame = NULL;
klass->release_frame = NULL;
}
static void
nemo_gst_video_texture_iface_class_init (NemoGstVideoTextureClass * klass)
{
/**
* NemoGstVideoTextureClass::egl-display
* EGL Display
* Application must provide a valid EGL display to the sink before attempting
* to call nemo_gst_video_texture_acquire_frame()
*/
g_object_interface_install_property (klass,
g_param_spec_pointer ("egl-display",
"EGL display ",
"The application provided EGL display to be used for creating EGLImageKHR objects.",
G_PARAM_READWRITE));
}
/**
* nemo_gst_video_texture_acquire_frame:
* @iface: #NemoGstVideoTexture of a GStreamer element
*
* Used to inform the sink that the application wants to render a frame.
* The sink should do any needed steps in order to prepare for rendering
*
* Returns: %TRUE on success and %FALSE on failure.
*/
gboolean
nemo_gst_video_texture_acquire_frame (NemoGstVideoTexture * iface)
{
NemoGstVideoTextureClass *klass = NEMO_GST_VIDEO_TEXTURE_GET_CLASS (iface);
if (klass->acquire_frame) {
return klass->acquire_frame (iface);
}
return FALSE;
}
/**
* nemo_gst_video_texture_bind_frame:
* @iface: #NemoGstVideoTexture of a GStreamer element
*
* The sink will acquire the needed EGLImageKHR corresponding to the
* latest available frame for rendering. If the function returns TRUE then
* @image will carry the address of the EGLImageKHR corresponding to the latest frame.
*
* The sink ensures that the pointer remains valid until the application unbinds the frame.
* The application ensures that only one EGLImageKHR will be bound at a time.
*
* Application might get a different EGLImageKHR everytime this function gets called.
* Application should not try to use the pointer address in a hash or something.
*
* The time between bind and unbind should be as minimal as possible. Ideally it should
* be done at vsync to minimize the time of acquisition.
*
* Returns: %TRUE on success and %FALSE on failure.
*/
gboolean
nemo_gst_video_texture_bind_frame (NemoGstVideoTexture * iface,
EGLImageKHR * image)
{
NemoGstVideoTextureClass *klass = NEMO_GST_VIDEO_TEXTURE_GET_CLASS (iface);
if (klass->bind_frame) {
return klass->bind_frame (iface, image);
}
return FALSE;
}
/**
* nemo_gst_video_texture_unbind_frame:
* @iface: #NemoGstVideoTexture of a GStreamer element
*
* This call is used to inform the sink that the application is not
* interested in using the EGLImageKHR obtained from calling nemo_gst_video_texture_bind_frame
* anymore.
* Application must not access the EGLImageKHR pointer obtained by calling
* nemo_gst_video_texture_bind_frame anymore. Failing to do so will result in a crash.
*/
void
nemo_gst_video_texture_unbind_frame (NemoGstVideoTexture * iface)
{
NemoGstVideoTextureClass *klass = NEMO_GST_VIDEO_TEXTURE_GET_CLASS (iface);
if (klass->unbind_frame) {
klass->unbind_frame (iface);
}
}
/**
* nemo_gst_video_texture_release_frame:
* @iface: #NemoGstVideoTexture of a GStreamer element
* @sync: an optional fence object
*
* Called by the application to release a frame after rendering
* it via the GPU.
* The application is expected to use the
* EGL_KHR_sync_fence extension to place a fence into the
* GPU command stream after the rendering commands
* accessing the video frame.
* This sync object should be given as @sync, and the sink
* assumes ownership of that sync object.
*
* If @sync is not %NULL, then the sink implementation
* asynchronously waits until the specified fence
* object is signalled before reusing the image.
*/
void
nemo_gst_video_texture_release_frame (NemoGstVideoTexture * iface,
EGLSyncKHR sync)
{
NemoGstVideoTextureClass *klass = NEMO_GST_VIDEO_TEXTURE_GET_CLASS (iface);
if (klass->release_frame) {
klass->release_frame (iface, sync);
}
}
/**
* nemo_gst_video_texture_get_frame_info:
* @iface: #NemoGstVideoTexture of a GStreamer element
* @info: A pointer to #NemoGstVideoTextureFrameInfo
*
* Called by the application to get information about the
* currently acquired frame
*
* Returns: %TRUE on success and %FALSE on failure.
*/
gboolean
nemo_gst_video_texture_get_frame_info (NemoGstVideoTexture *iface, NemoGstVideoTextureFrameInfo *info)
{
NemoGstVideoTextureClass *klass = NEMO_GST_VIDEO_TEXTURE_GET_CLASS (iface);
if (klass->get_frame_info) {
return klass->get_frame_info (iface, info);
}
return FALSE;
}
/**
* nemo_gst_video_texture_get_frame_qdata:
* @iface: #NemoGstVideoTexture of a GStreamer element
* @quark: name quark of data structure to find
*
* Called by the application to get metadata structure from the currently
* acquired frame.
* The GstStructure is guaranteed to be available until the application
* releases the frame.
*
* Returns: a GstStructure, or NULL if not found.
*/
const GstStructure *
nemo_gst_video_texture_get_frame_qdata (NemoGstVideoTexture *iface, const GQuark quark)
{
NemoGstVideoTextureClass *klass = NEMO_GST_VIDEO_TEXTURE_GET_CLASS (iface);
if (klass->get_frame_qdata) {
return klass->get_frame_qdata (iface, quark);
}
return NULL;
}
/**
* nemo_gst_video_texture_get_frame_meta:
* @iface: #NemoGstVideoTexture of a GStreamer element
* @api: the GType of an API
*
* Called by the application to get metadata for api on buffer.
* There must be a currently acquired frame
*
* Returns: the matadate for API on buffer or NULL
*/
GstMeta *
nemo_gst_video_texture_get_frame_meta (NemoGstVideoTexture *iface, GType api)
{
NemoGstVideoTextureClass *klass = NEMO_GST_VIDEO_TEXTURE_GET_CLASS (iface);
if (klass->get_frame_meta) {
return klass->get_frame_meta (iface, api);
}
return NULL;
}
/**
* nemo_gst_video_texture_frame_ready:
* @iface: #NemoGstVideoTexture of a GStreamer element
* @frame: frame number
*
* Called by the elements implementing the #NemoGstVideoTexture interface
* to trigger the frame-ready signal emission.
*/
void
nemo_gst_video_texture_frame_ready (NemoGstVideoTexture * iface, gint frame)
{
g_return_if_fail (NEMO_GST_IS_VIDEO_TEXTURE (iface));
g_signal_emit (G_OBJECT (iface),
nemo_gst_video_texture_iface_signals[SIGNAL_FRAME_READY], 0, frame);
}