3 * Copyright (C) 2009 Julien Isorce <julien.isorce@gmail.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
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 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 * SECTION:element-glvideomixer
23 * @title: glvideomixer
25 * Composites a number of streams into a single output scene using OpenGL in
26 * a similar fashion to compositor and videomixer. See the compositor plugin
27 * for documentation about the #GstGLVideoMixerPad properties.
31 * gst-launch-1.0 glvideomixer name=m ! glimagesink \
32 * videotestsrc ! video/x-raw, format=YUY2 ! glupload ! glcolorconvert ! m. \
33 * videotestsrc pattern=12 ! video/x-raw, format=I420, framerate=5/1, width=100, height=200 ! queue ! \
34 * glupload ! glcolorconvert ! m. \
35 * videotestsrc ! glupload ! gleffects effect=2 ! queue ! m. \
36 * videotestsrc ! glupload ! glfiltercube ! queue ! m. \
37 * videotestsrc ! glupload ! gleffects effect=6 ! queue ! m.
47 #include <gst/controller/gstproxycontrolbinding.h>
48 #include <gst/gl/gstglfuncs.h>
49 #include <gst/video/gstvideoaffinetransformationmeta.h>
51 #include "gstglvideomixer.h"
53 #include "gstglmixerbin.h"
54 #include "gstglutils.h"
56 #define GST_CAT_DEFAULT gst_gl_video_mixer_debug
57 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
59 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%u",
62 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
63 (GST_CAPS_FEATURE_MEMORY_GL_MEMORY,
67 #define GST_TYPE_GL_VIDEO_MIXER_BACKGROUND (gst_gl_video_mixer_background_get_type())
69 gst_gl_video_mixer_background_get_type (void)
71 static GType mixer_background_type = 0;
73 static const GEnumValue mixer_background[] = {
74 {GST_GL_VIDEO_MIXER_BACKGROUND_CHECKER, "Checker pattern", "checker"},
75 {GST_GL_VIDEO_MIXER_BACKGROUND_BLACK, "Black", "black"},
76 {GST_GL_VIDEO_MIXER_BACKGROUND_WHITE, "White", "white"},
77 {GST_GL_VIDEO_MIXER_BACKGROUND_TRANSPARENT,
78 "Transparent Background to enable further compositing", "transparent"},
82 if (!mixer_background_type) {
83 mixer_background_type =
84 g_enum_register_static ("GstGLVideoMixerBackground", mixer_background);
86 return mixer_background_type;
89 #define GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION (gst_gl_video_mixer_blend_equation_get_type())
91 gst_gl_video_mixer_blend_equation_get_type (void)
93 static GType mixer_blend_equation_type = 0;
95 static const GEnumValue mixer_blend_equations[] = {
96 {GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD, "Add", "add"},
97 {GST_GL_VIDEO_MIXER_BLEND_EQUATION_SUBTRACT, "Subtract", "subtract"},
98 {GST_GL_VIDEO_MIXER_BLEND_EQUATION_REVERSE_SUBTRACT, "Reverse Subtract",
103 if (!mixer_blend_equation_type) {
104 mixer_blend_equation_type =
105 g_enum_register_static ("GstGLVideoMixerBlendEquation",
106 mixer_blend_equations);
108 return mixer_blend_equation_type;
111 #define GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION (gst_gl_video_mixer_blend_function_get_type())
113 gst_gl_video_mixer_blend_function_get_type (void)
115 static GType mixer_blend_function_type = 0;
117 static const GEnumValue mixer_blend_funcs[] = {
118 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ZERO, "Zero", "zero"},
119 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE, "One", "one"},
120 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_COLOR, "Source Color", "src-color"},
121 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_COLOR,
122 "One Minus Source Color", "one-minus-src-color"},
123 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_COLOR, "Destination Color",
125 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_COLOR,
126 "One Minus Destination Color", "one-minus-dst-color"},
127 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA, "Source Alpha", "src-alpha"},
128 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA,
129 "One Minus Source Alpha", "one-minus-src-alpha"},
130 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_ALPHA, "Destination Alpha",
132 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_ALPHA,
133 "One Minus Destination Alpha", "one-minus-dst-alpha"},
134 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_COLOR, "Constant Color",
136 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_COLOR,
137 "One Minus Constant Color", "one-minus-contant-color"},
138 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_ALPHA, "Constant Alpha",
140 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_ALPHA,
141 "One Minus Constant Alpha", "one-minus-contant-alpha"},
142 {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE,
143 "Source Alpha Saturate", "src-alpha-saturate"},
147 if (!mixer_blend_function_type) {
148 mixer_blend_function_type =
149 g_enum_register_static ("GstGLVideoMixerBlendFunction",
152 return mixer_blend_function_type;
155 #define DEFAULT_PAD_XPOS 0
156 #define DEFAULT_PAD_YPOS 0
157 #define DEFAULT_PAD_WIDTH 0
158 #define DEFAULT_PAD_HEIGHT 0
159 #define DEFAULT_PAD_ALPHA 1.0
160 #define DEFAULT_PAD_ZORDER 0
161 #define DEFAULT_PAD_REPEAT_AFTER_EOS FALSE
162 #define DEFAULT_PAD_BLEND_EQUATION_RGB GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD
163 #define DEFAULT_PAD_BLEND_EQUATION_ALPHA GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD
164 #define DEFAULT_PAD_BLEND_FUNCTION_SRC_RGB GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA
165 #define DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE
166 #define DEFAULT_PAD_BLEND_FUNCTION_DST_RGB GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA
167 #define DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA
177 PROP_INPUT_BLEND_EQUATION_RGB,
178 PROP_INPUT_BLEND_EQUATION_ALPHA,
179 PROP_INPUT_BLEND_FUNCTION_SRC_RGB,
180 PROP_INPUT_BLEND_FUNCTION_SRC_ALPHA,
181 PROP_INPUT_BLEND_FUNCTION_DST_RGB,
182 PROP_INPUT_BLEND_FUNCTION_DST_ALPHA,
183 PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_RED,
184 PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_GREEN,
185 PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_BLUE,
186 PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA,
188 PROP_INPUT_REPEAT_AFTER_EOS,
191 static void gst_gl_video_mixer_input_get_property (GObject * object,
192 guint prop_id, GValue * value, GParamSpec * pspec);
193 static void gst_gl_video_mixer_input_set_property (GObject * object,
194 guint prop_id, const GValue * value, GParamSpec * pspec);
196 typedef struct _GstGLVideoMixerInput GstGLVideoMixerInput;
197 typedef GstGhostPadClass GstGLVideoMixerInputClass;
199 struct _GstGLVideoMixerInput
208 GType gst_gl_video_mixer_input_get_type (void);
209 G_DEFINE_TYPE (GstGLVideoMixerInput, gst_gl_video_mixer_input,
213 gst_gl_video_mixer_input_init (GstGLVideoMixerInput * self)
218 gst_gl_video_mixer_input_class_init (GstGLVideoMixerInputClass * klass)
220 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
222 gobject_class->set_property = gst_gl_video_mixer_input_set_property;
223 gobject_class->get_property = gst_gl_video_mixer_input_get_property;
225 g_object_class_install_property (gobject_class, PROP_INPUT_ZORDER,
226 g_param_spec_uint ("zorder", "Z-Order", "Z Order of the picture",
227 0, 10000, DEFAULT_PAD_ZORDER,
228 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
229 g_object_class_install_property (gobject_class, PROP_INPUT_REPEAT_AFTER_EOS,
230 g_param_spec_boolean ("repeat-after-eos", "Repeat After EOS",
231 "Aggregate the last "
232 "frame on pads that are EOS till they are released",
233 DEFAULT_PAD_REPEAT_AFTER_EOS,
234 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
235 g_object_class_install_property (gobject_class, PROP_INPUT_XPOS,
236 g_param_spec_int ("xpos", "X Position", "X Position of the picture",
237 G_MININT, G_MAXINT, DEFAULT_PAD_XPOS,
238 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
239 g_object_class_install_property (gobject_class, PROP_INPUT_YPOS,
240 g_param_spec_int ("ypos", "Y Position", "Y Position of the picture",
241 G_MININT, G_MAXINT, DEFAULT_PAD_YPOS,
242 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
243 g_object_class_install_property (gobject_class, PROP_INPUT_WIDTH,
244 g_param_spec_int ("width", "Width", "Width of the picture", G_MININT,
245 G_MAXINT, DEFAULT_PAD_WIDTH,
246 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
247 g_object_class_install_property (gobject_class, PROP_INPUT_HEIGHT,
248 g_param_spec_int ("height", "Height", "Height of the picture", G_MININT,
249 G_MAXINT, DEFAULT_PAD_HEIGHT,
250 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
251 g_object_class_install_property (gobject_class, PROP_INPUT_ALPHA,
252 g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0,
254 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
255 g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_EQUATION_RGB,
256 g_param_spec_enum ("blend-equation-rgb", "Blend Equation RGB",
257 "Blend Equation for RGB", GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION,
258 DEFAULT_PAD_BLEND_EQUATION_RGB,
259 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
260 g_object_class_install_property (gobject_class,
261 PROP_INPUT_BLEND_EQUATION_ALPHA,
262 g_param_spec_enum ("blend-equation-alpha", "Blend Equation Alpha",
263 "Blend Equation for Alpha", GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION,
264 DEFAULT_PAD_BLEND_EQUATION_ALPHA,
265 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
266 g_object_class_install_property (gobject_class,
267 PROP_INPUT_BLEND_FUNCTION_SRC_RGB,
268 g_param_spec_enum ("blend-function-src-rgb", "Blend Function Source RGB",
269 "Blend Function for Source RGB",
270 GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
271 DEFAULT_PAD_BLEND_FUNCTION_SRC_RGB,
272 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
273 g_object_class_install_property (gobject_class,
274 PROP_INPUT_BLEND_FUNCTION_SRC_ALPHA,
275 g_param_spec_enum ("blend-function-src-alpha",
276 "Blend Function Source Alpha", "Blend Function for Source Alpha",
277 GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
278 DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA,
279 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
280 g_object_class_install_property (gobject_class,
281 PROP_INPUT_BLEND_FUNCTION_DST_RGB,
282 g_param_spec_enum ("blend-function-dst-rgb",
283 "Blend Function Destination RGB",
284 "Blend Function for Destination RGB",
285 GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
286 DEFAULT_PAD_BLEND_FUNCTION_DST_RGB,
287 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
288 g_object_class_install_property (gobject_class,
289 PROP_INPUT_BLEND_FUNCTION_DST_ALPHA,
290 g_param_spec_enum ("blend-function-dst-alpha",
291 "Blend Function Destination Alpha",
292 "Blend Function for Destination Alpha",
293 GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
294 DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA,
295 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
296 g_object_class_install_property (gobject_class,
297 PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_RED,
298 g_param_spec_double ("blend-constant-color-red",
299 "Blend Constant Color Red", "Blend Constant Color Red", 0.0, 1.0, 0.0,
300 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
301 g_object_class_install_property (gobject_class,
302 PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_GREEN,
303 g_param_spec_double ("blend-constant-color-green",
304 "Blend Constant Color Green", "Blend Constant Color Green", 0.0, 1.0,
306 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
307 g_object_class_install_property (gobject_class,
308 PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_BLUE,
309 g_param_spec_double ("blend-constant-color-blue",
310 "Blend Constant Color Green", "Blend Constant Color Green", 0.0, 1.0,
312 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
313 g_object_class_install_property (gobject_class,
314 PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA,
315 g_param_spec_double ("blend-constant-color-alpha",
316 "Blend Constant Color Alpha", "Blend Constant Color Alpha", 0.0, 1.0,
318 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
322 gst_gl_video_mixer_input_get_property (GObject * object, guint prop_id,
323 GValue * value, GParamSpec * pspec)
325 GstGLVideoMixerInput *self = (GstGLVideoMixerInput *) object;
328 g_object_get_property (G_OBJECT (self->mixer_pad), pspec->name, value);
332 gst_gl_video_mixer_input_set_property (GObject * object, guint prop_id,
333 const GValue * value, GParamSpec * pspec)
335 GstGLVideoMixerInput *self = (GstGLVideoMixerInput *) object;
338 g_object_set_property (G_OBJECT (self->mixer_pad), pspec->name, value);
342 _create_video_mixer_input (GstGLMixerBin * self, GstPad * mixer_pad)
344 GstGLVideoMixerInput *input =
345 g_object_new (gst_gl_video_mixer_input_get_type (), "name",
346 GST_OBJECT_NAME (mixer_pad), "direction", GST_PAD_DIRECTION (mixer_pad),
349 if (!gst_ghost_pad_construct (GST_GHOST_PAD (input))) {
350 gst_object_unref (input);
353 #define ADD_BINDING(obj,ref,prop) \
354 gst_object_add_control_binding (GST_OBJECT (obj), \
355 gst_proxy_control_binding_new (GST_OBJECT (obj), prop, \
356 GST_OBJECT (ref), prop));
357 ADD_BINDING (mixer_pad, input, "zorder");
358 ADD_BINDING (mixer_pad, input, "xpos");
359 ADD_BINDING (mixer_pad, input, "ypos");
360 ADD_BINDING (mixer_pad, input, "width");
361 ADD_BINDING (mixer_pad, input, "height");
362 ADD_BINDING (mixer_pad, input, "alpha");
363 ADD_BINDING (mixer_pad, input, "blend-equation-rgb");
364 ADD_BINDING (mixer_pad, input, "blend-equation-alpha");
365 ADD_BINDING (mixer_pad, input, "blend-function-src-rgb");
366 ADD_BINDING (mixer_pad, input, "blend-function-src-alpha");
367 ADD_BINDING (mixer_pad, input, "blend-function-dst-rgb");
368 ADD_BINDING (mixer_pad, input, "blend-function-dst-alpha");
369 ADD_BINDING (mixer_pad, input, "blend-constant-color-red");
370 ADD_BINDING (mixer_pad, input, "blend-constant-color-green");
371 ADD_BINDING (mixer_pad, input, "blend-constant-color-blue");
372 ADD_BINDING (mixer_pad, input, "blend-constant-color-alpha");
375 input->mixer_pad = mixer_pad;
377 return GST_GHOST_PAD (input);
385 #define DEFAULT_BACKGROUND GST_GL_VIDEO_MIXER_BACKGROUND_CHECKER
387 static void gst_gl_video_mixer_bin_get_property (GObject * object,
388 guint prop_id, GValue * value, GParamSpec * pspec);
389 static void gst_gl_video_mixer_bin_set_property (GObject * object,
390 guint prop_id, const GValue * value, GParamSpec * pspec);
392 typedef GstGLMixerBin GstGLVideoMixerBin;
393 typedef GstGLMixerBinClass GstGLVideoMixerBinClass;
395 G_DEFINE_TYPE (GstGLVideoMixerBin, gst_gl_video_mixer_bin,
396 GST_TYPE_GL_MIXER_BIN);
399 gst_gl_video_mixer_bin_init (GstGLVideoMixerBin * self)
401 GstGLMixerBin *mix_bin = GST_GL_MIXER_BIN (self);
403 gst_gl_mixer_bin_finish_init_with_element (mix_bin,
404 g_object_new (GST_TYPE_GL_VIDEO_MIXER, NULL));
408 gst_gl_video_mixer_bin_class_init (GstGLVideoMixerBinClass * klass)
410 GstGLMixerBinClass *mixer_class = GST_GL_MIXER_BIN_CLASS (klass);
411 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
412 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
414 mixer_class->create_input_pad = _create_video_mixer_input;
416 gobject_class->set_property = gst_gl_video_mixer_bin_set_property;
417 gobject_class->get_property = gst_gl_video_mixer_bin_get_property;
419 g_object_class_install_property (gobject_class, PROP_BIN_BACKGROUND,
420 g_param_spec_enum ("background", "Background", "Background type",
421 GST_TYPE_GL_VIDEO_MIXER_BACKGROUND,
422 DEFAULT_BACKGROUND, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
424 gst_element_class_set_metadata (element_class, "OpenGL video_mixer bin",
425 "Bin/Filter/Effect/Video/Compositor", "OpenGL video_mixer bin",
426 "Matthew Waters <matthew@centricular.com>");
430 gst_gl_video_mixer_bin_get_property (GObject * object, guint prop_id,
431 GValue * value, GParamSpec * pspec)
433 GstGLMixerBin *self = GST_GL_MIXER_BIN (object);
436 g_object_get_property (G_OBJECT (self->mixer), pspec->name, value);
440 gst_gl_video_mixer_bin_set_property (GObject * object, guint prop_id,
441 const GValue * value, GParamSpec * pspec)
443 GstGLMixerBin *self = GST_GL_MIXER_BIN (object);
446 g_object_set_property (G_OBJECT (self->mixer), pspec->name, value);
455 static void gst_gl_video_mixer_child_proxy_init (gpointer g_iface,
456 gpointer iface_data);
459 GST_DEBUG_CATEGORY_INIT (gst_gl_video_mixer_debug, "glvideomixer", 0, "glvideomixer element");
461 #define gst_gl_video_mixer_parent_class parent_class
462 G_DEFINE_TYPE_WITH_CODE (GstGLVideoMixer, gst_gl_video_mixer, GST_TYPE_GL_MIXER,
463 G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY,
464 gst_gl_video_mixer_child_proxy_init); DEBUG_INIT);
466 static void gst_gl_video_mixer_set_property (GObject * object, guint prop_id,
467 const GValue * value, GParamSpec * pspec);
468 static void gst_gl_video_mixer_get_property (GObject * object, guint prop_id,
469 GValue * value, GParamSpec * pspec);
471 static GstCaps *_update_caps (GstVideoAggregator * vagg, GstCaps * caps);
472 static GstCaps *_fixate_caps (GstAggregator * agg, GstCaps * caps);
473 static gboolean gst_gl_video_mixer_propose_allocation (GstAggregator *
474 agg, GstAggregatorPad * agg_pad, GstQuery * decide_query, GstQuery * query);
475 static gboolean gst_gl_video_mixer_gl_start (GstGLBaseMixer * base_mix);
476 static void gst_gl_video_mixer_gl_stop (GstGLBaseMixer * base_mix);
477 static gboolean gst_gl_video_mixer_set_caps (GstGLMixer * mixer,
480 static gboolean gst_gl_video_mixer_process_textures (GstGLMixer * mixer,
481 GstGLMemory * out_tex);
482 static gboolean gst_gl_video_mixer_callback (gpointer stuff);
486 /* fragment source */
487 static const gchar *video_mixer_f_src =
488 "uniform sampler2D texture; \n"
489 "uniform float alpha;\n"
490 "varying vec2 v_texcoord; \n"
493 " vec4 rgba = texture2D(texture, v_texcoord);\n"
494 " gl_FragColor = vec4(rgba.rgb, rgba.a * alpha);\n"
497 /* checker vertex source */
498 static const gchar *checker_v_src =
499 "attribute vec4 a_position;\n"
502 " gl_Position = a_position;\n"
505 /* checker fragment source */
506 static const gchar *checker_f_src =
507 "const float blocksize = 8.0;\n"
510 " vec4 high = vec4(0.667, 0.667, 0.667, 1.0);\n"
511 " vec4 low = vec4(0.333, 0.333, 0.333, 1.0);\n"
512 " if (mod(gl_FragCoord.x, blocksize * 2.0) >= blocksize) {\n"
513 " if (mod(gl_FragCoord.y, blocksize * 2.0) >= blocksize)\n"
514 " gl_FragColor = low;\n"
516 " gl_FragColor = high;\n"
518 " if (mod(gl_FragCoord.y, blocksize * 2.0) < blocksize)\n"
519 " gl_FragColor = low;\n"
521 " gl_FragColor = high;\n"
526 #define GST_TYPE_GL_VIDEO_MIXER_PAD (gst_gl_video_mixer_pad_get_type())
527 #define GST_GL_VIDEO_MIXER_PAD(obj) \
528 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_VIDEO_MIXER_PAD, GstGLVideoMixerPad))
529 #define GST_GL_VIDEO_MIXER_PAD_CLASS(klass) \
530 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_VIDEO_MIXER_PAD, GstGLVideoMixerPadClass))
531 #define GST_IS_GL_VIDEO_MIXER_PAD(obj) \
532 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_VIDEO_MIXER_PAD))
533 #define GST_IS_GL_VIDEO_MIXER_PAD_CLASS(klass) \
534 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_VIDEO_MIXER_PAD))
536 typedef struct _GstGLVideoMixerPad GstGLVideoMixerPad;
537 typedef struct _GstGLVideoMixerPadClass GstGLVideoMixerPadClass;
538 typedef struct _GstGLVideoMixerCollect GstGLVideoMixerCollect;
541 * GstGLVideoMixerPad:
543 * The opaque #GstGLVideoMixerPad structure.
545 struct _GstGLVideoMixerPad
547 GstGLMixerPad parent;
554 GstGLVideoMixerBlendEquation blend_equation_rgb;
555 GstGLVideoMixerBlendEquation blend_equation_alpha;
556 GstGLVideoMixerBlendFunction blend_function_src_rgb;
557 GstGLVideoMixerBlendFunction blend_function_src_alpha;
558 GstGLVideoMixerBlendFunction blend_function_dst_rgb;
559 GstGLVideoMixerBlendFunction blend_function_dst_alpha;
560 gdouble blend_constant_color_red;
561 gdouble blend_constant_color_green;
562 gdouble blend_constant_color_blue;
563 gdouble blend_constant_color_alpha;
565 gboolean geometry_change;
566 GLuint vertex_buffer;
570 struct _GstGLVideoMixerPadClass
572 GstGLMixerPadClass parent_class;
575 GType gst_gl_video_mixer_pad_get_type (void);
576 G_DEFINE_TYPE (GstGLVideoMixerPad, gst_gl_video_mixer_pad,
577 GST_TYPE_GL_MIXER_PAD);
579 static void gst_gl_video_mixer_pad_set_property (GObject * object,
580 guint prop_id, const GValue * value, GParamSpec * pspec);
581 static void gst_gl_video_mixer_pad_get_property (GObject * object,
582 guint prop_id, GValue * value, GParamSpec * pspec);
592 PROP_PAD_BLEND_EQUATION_RGB,
593 PROP_PAD_BLEND_EQUATION_ALPHA,
594 PROP_PAD_BLEND_FUNCTION_SRC_RGB,
595 PROP_PAD_BLEND_FUNCTION_SRC_ALPHA,
596 PROP_PAD_BLEND_FUNCTION_DST_RGB,
597 PROP_PAD_BLEND_FUNCTION_DST_ALPHA,
598 PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_RED,
599 PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_GREEN,
600 PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_BLUE,
601 PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA,
605 gst_gl_video_mixer_pad_init (GstGLVideoMixerPad * pad)
607 pad->alpha = DEFAULT_PAD_ALPHA;
608 pad->blend_equation_rgb = DEFAULT_PAD_BLEND_EQUATION_RGB;
609 pad->blend_equation_alpha = DEFAULT_PAD_BLEND_EQUATION_ALPHA;
610 pad->blend_function_src_rgb = DEFAULT_PAD_BLEND_FUNCTION_SRC_RGB;
611 pad->blend_function_src_alpha = DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA;
612 pad->blend_function_dst_rgb = DEFAULT_PAD_BLEND_FUNCTION_DST_RGB;
613 pad->blend_function_dst_alpha = DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA;
614 memset (pad->m_matrix, 0, sizeof (gfloat) * 4 * 4);
615 pad->m_matrix[0] = 1.0;
616 pad->m_matrix[5] = 1.0;
617 pad->m_matrix[10] = 1.0;
618 pad->m_matrix[15] = 1.0;
622 gst_gl_video_mixer_pad_class_init (GstGLVideoMixerPadClass * klass)
624 GObjectClass *gobject_class = (GObjectClass *) klass;
626 gobject_class->set_property = gst_gl_video_mixer_pad_set_property;
627 gobject_class->get_property = gst_gl_video_mixer_pad_get_property;
629 g_object_class_install_property (gobject_class, PROP_PAD_XPOS,
630 g_param_spec_int ("xpos", "X Position", "X Position of the picture",
631 G_MININT, G_MAXINT, DEFAULT_PAD_XPOS,
632 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
633 g_object_class_install_property (gobject_class, PROP_PAD_YPOS,
634 g_param_spec_int ("ypos", "Y Position", "Y Position of the picture",
635 G_MININT, G_MAXINT, DEFAULT_PAD_YPOS,
636 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
637 g_object_class_install_property (gobject_class, PROP_PAD_WIDTH,
638 g_param_spec_int ("width", "Width", "Width of the picture",
639 G_MININT, G_MAXINT, DEFAULT_PAD_WIDTH,
640 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
641 g_object_class_install_property (gobject_class, PROP_PAD_HEIGHT,
642 g_param_spec_int ("height", "Height", "Height of the picture",
643 G_MININT, G_MAXINT, DEFAULT_PAD_HEIGHT,
644 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
645 g_object_class_install_property (gobject_class, PROP_PAD_ALPHA,
646 g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0,
648 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
649 g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_EQUATION_RGB,
650 g_param_spec_enum ("blend-equation-rgb", "Blend Equation RGB",
651 "Blend Equation for RGB",
652 GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION,
653 DEFAULT_PAD_BLEND_EQUATION_RGB,
654 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
655 g_object_class_install_property (gobject_class,
656 PROP_INPUT_BLEND_EQUATION_ALPHA,
657 g_param_spec_enum ("blend-equation-alpha", "Blend Equation Alpha",
658 "Blend Equation for Alpha", GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION,
659 DEFAULT_PAD_BLEND_EQUATION_ALPHA,
660 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
661 g_object_class_install_property (gobject_class,
662 PROP_INPUT_BLEND_FUNCTION_SRC_RGB,
663 g_param_spec_enum ("blend-function-src-rgb", "Blend Function Source RGB",
664 "Blend Function for Source RGB",
665 GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
666 DEFAULT_PAD_BLEND_FUNCTION_SRC_RGB,
667 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
668 g_object_class_install_property (gobject_class,
669 PROP_INPUT_BLEND_FUNCTION_SRC_ALPHA,
670 g_param_spec_enum ("blend-function-src-alpha",
671 "Blend Function Source Alpha", "Blend Function for Source Alpha",
672 GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
673 DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA,
674 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
675 g_object_class_install_property (gobject_class,
676 PROP_INPUT_BLEND_FUNCTION_DST_RGB,
677 g_param_spec_enum ("blend-function-dst-rgb",
678 "Blend Function Destination RGB",
679 "Blend Function for Destination RGB",
680 GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
681 DEFAULT_PAD_BLEND_FUNCTION_DST_RGB,
682 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
683 g_object_class_install_property (gobject_class,
684 PROP_INPUT_BLEND_FUNCTION_DST_ALPHA,
685 g_param_spec_enum ("blend-function-dst-alpha",
686 "Blend Function Destination Alpha",
687 "Blend Function for Destination Alpha",
688 GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
689 DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA,
690 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
691 g_object_class_install_property (gobject_class,
692 PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_RED,
693 g_param_spec_double ("blend-constant-color-red",
694 "Blend Constant Color Red", "Blend Constant Color Red", 0.0, 1.0, 0.0,
695 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
696 g_object_class_install_property (gobject_class,
697 PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_GREEN,
698 g_param_spec_double ("blend-constant-color-green",
699 "Blend Constant Color Green", "Blend Constant Color Green", 0.0, 1.0,
701 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
702 g_object_class_install_property (gobject_class,
703 PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_BLUE,
704 g_param_spec_double ("blend-constant-color-blue",
705 "Blend Constant Color Green", "Blend Constant Color Green", 0.0, 1.0,
707 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
708 g_object_class_install_property (gobject_class,
709 PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA,
710 g_param_spec_double ("blend-constant-color-alpha",
711 "Blend Constant Color Alpha", "Blend Constant Color Alpha", 0.0, 1.0,
713 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
717 gst_gl_video_mixer_pad_get_property (GObject * object, guint prop_id,
718 GValue * value, GParamSpec * pspec)
720 GstGLVideoMixerPad *pad = GST_GL_VIDEO_MIXER_PAD (object);
724 g_value_set_int (value, pad->xpos);
727 g_value_set_int (value, pad->ypos);
730 g_value_set_int (value, pad->width);
732 case PROP_PAD_HEIGHT:
733 g_value_set_int (value, pad->height);
736 g_value_set_double (value, pad->alpha);
738 case PROP_PAD_BLEND_EQUATION_RGB:
739 g_value_set_enum (value, pad->blend_equation_rgb);
741 case PROP_PAD_BLEND_EQUATION_ALPHA:
742 g_value_set_enum (value, pad->blend_equation_alpha);
744 case PROP_PAD_BLEND_FUNCTION_SRC_RGB:
745 g_value_set_enum (value, pad->blend_function_src_rgb);
747 case PROP_PAD_BLEND_FUNCTION_SRC_ALPHA:
748 g_value_set_enum (value, pad->blend_function_src_alpha);
750 case PROP_PAD_BLEND_FUNCTION_DST_RGB:
751 g_value_set_enum (value, pad->blend_function_dst_rgb);
753 case PROP_PAD_BLEND_FUNCTION_DST_ALPHA:
754 g_value_set_enum (value, pad->blend_function_dst_alpha);
756 case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_RED:
757 g_value_set_double (value, pad->blend_constant_color_red);
759 case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_GREEN:
760 g_value_set_double (value, pad->blend_constant_color_green);
762 case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_BLUE:
763 g_value_set_double (value, pad->blend_constant_color_blue);
765 case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA:
766 g_value_set_double (value, pad->blend_constant_color_alpha);
769 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
775 gst_gl_video_mixer_pad_set_property (GObject * object, guint prop_id,
776 const GValue * value, GParamSpec * pspec)
778 GstGLVideoMixerPad *pad = GST_GL_VIDEO_MIXER_PAD (object);
779 GstGLMixer *mix = GST_GL_MIXER (gst_pad_get_parent (GST_PAD (pad)));
783 pad->xpos = g_value_get_int (value);
784 pad->geometry_change = TRUE;
787 pad->ypos = g_value_get_int (value);
788 pad->geometry_change = TRUE;
791 pad->width = g_value_get_int (value);
792 pad->geometry_change = TRUE;
794 case PROP_PAD_HEIGHT:
795 pad->height = g_value_get_int (value);
796 pad->geometry_change = TRUE;
799 pad->alpha = g_value_get_double (value);
801 case PROP_PAD_BLEND_EQUATION_RGB:
802 pad->blend_equation_rgb = g_value_get_enum (value);
804 case PROP_PAD_BLEND_EQUATION_ALPHA:
805 pad->blend_equation_alpha = g_value_get_enum (value);
807 case PROP_PAD_BLEND_FUNCTION_SRC_RGB:
808 pad->blend_function_src_rgb = g_value_get_enum (value);
810 case PROP_PAD_BLEND_FUNCTION_SRC_ALPHA:
811 pad->blend_function_src_alpha = g_value_get_enum (value);
813 case PROP_PAD_BLEND_FUNCTION_DST_RGB:
814 pad->blend_function_dst_rgb = g_value_get_enum (value);
816 case PROP_PAD_BLEND_FUNCTION_DST_ALPHA:
817 pad->blend_function_dst_alpha = g_value_get_enum (value);
819 case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_RED:
820 pad->blend_constant_color_red = g_value_get_double (value);
822 case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_GREEN:
823 pad->blend_constant_color_green = g_value_get_double (value);
825 case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_BLUE:
826 pad->blend_constant_color_blue = g_value_get_double (value);
828 case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA:
829 pad->blend_constant_color_alpha = g_value_get_double (value);
832 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
836 gst_object_unref (mix);
840 _del_buffer (GstGLContext * context, GLuint * pBuffer)
842 context->gl_vtable->DeleteBuffers (1, pBuffer);
846 gst_gl_video_mixer_request_new_pad (GstElement * element,
847 GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
852 GST_ELEMENT_CLASS (parent_class)->request_new_pad (element,
853 templ, req_name, caps);
856 goto could_not_create;
858 gst_child_proxy_child_added (GST_CHILD_PROXY (element), G_OBJECT (newpad),
859 GST_OBJECT_NAME (newpad));
865 GST_DEBUG_OBJECT (element, "could not create/add pad");
871 gst_gl_video_mixer_release_pad (GstElement * element, GstPad * p)
873 GstGLVideoMixerPad *pad = GST_GL_VIDEO_MIXER_PAD (p);
875 gst_child_proxy_child_removed (GST_CHILD_PROXY (element), G_OBJECT (pad),
876 GST_OBJECT_NAME (pad));
878 /* we call the base class first as this will remove the pad from
879 * the aggregator, thus stopping misc callbacks from being called,
880 * one of which (process_textures) will recreate the vertex_buffer
881 * if it is destroyed */
882 GST_ELEMENT_CLASS (g_type_class_peek_parent (G_OBJECT_GET_CLASS (element)))
883 ->release_pad (element, p);
885 if (pad->vertex_buffer) {
886 GstGLBaseMixer *mix = GST_GL_BASE_MIXER (element);
887 gst_gl_context_thread_add (mix->context, (GstGLContextThreadFunc)
888 _del_buffer, &pad->vertex_buffer);
889 pad->vertex_buffer = 0;
894 gst_gl_video_mixer_class_init (GstGLVideoMixerClass * klass)
896 GObjectClass *gobject_class;
897 GstElementClass *element_class;
898 GstAggregatorClass *agg_class = (GstAggregatorClass *) klass;
899 GstVideoAggregatorClass *vagg_class = (GstVideoAggregatorClass *) klass;
901 gobject_class = (GObjectClass *) klass;
902 element_class = GST_ELEMENT_CLASS (klass);
903 element_class->request_new_pad = gst_gl_video_mixer_request_new_pad;
904 element_class->release_pad = gst_gl_video_mixer_release_pad;
906 gobject_class->set_property = gst_gl_video_mixer_set_property;
907 gobject_class->get_property = gst_gl_video_mixer_get_property;
909 gst_element_class_set_metadata (element_class, "OpenGL video_mixer",
910 "Filter/Effect/Video/Compositor", "OpenGL video_mixer",
911 "Matthew Waters <matthew@centricular.com>");
913 gst_element_class_add_static_pad_template_with_gtype (element_class,
914 &sink_factory, GST_TYPE_GL_VIDEO_MIXER_PAD);
916 g_object_class_install_property (gobject_class, PROP_BACKGROUND,
917 g_param_spec_enum ("background", "Background", "Background type",
918 GST_TYPE_GL_VIDEO_MIXER_BACKGROUND,
919 DEFAULT_BACKGROUND, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
921 GST_GL_MIXER_CLASS (klass)->set_caps = gst_gl_video_mixer_set_caps;
922 GST_GL_MIXER_CLASS (klass)->process_textures =
923 gst_gl_video_mixer_process_textures;
925 GST_GL_BASE_MIXER_CLASS (klass)->gl_stop = gst_gl_video_mixer_gl_stop;
926 GST_GL_BASE_MIXER_CLASS (klass)->gl_start = gst_gl_video_mixer_gl_start;
928 vagg_class->update_caps = _update_caps;
930 agg_class->fixate_src_caps = _fixate_caps;
931 agg_class->propose_allocation = gst_gl_video_mixer_propose_allocation;
933 GST_GL_BASE_MIXER_CLASS (klass)->supported_gl_api =
934 GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2;
936 gst_type_mark_as_plugin_api (GST_TYPE_GL_VIDEO_MIXER_BACKGROUND, 0);
937 gst_type_mark_as_plugin_api (GST_TYPE_GL_VIDEO_MIXER_PAD, 0);
938 gst_type_mark_as_plugin_api (GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION, 0);
939 gst_type_mark_as_plugin_api (GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION, 0);
943 gst_gl_video_mixer_init (GstGLVideoMixer * video_mixer)
945 video_mixer->background = DEFAULT_BACKGROUND;
946 video_mixer->shader = NULL;
950 gst_gl_video_mixer_set_property (GObject * object, guint prop_id,
951 const GValue * value, GParamSpec * pspec)
953 GstGLVideoMixer *mixer = GST_GL_VIDEO_MIXER (object);
956 case PROP_BACKGROUND:
957 mixer->background = g_value_get_enum (value);
960 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
966 gst_gl_video_mixer_get_property (GObject * object, guint prop_id,
967 GValue * value, GParamSpec * pspec)
969 GstGLVideoMixer *mixer = GST_GL_VIDEO_MIXER (object);
972 case PROP_BACKGROUND:
973 g_value_set_enum (value, mixer->background);
976 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
982 gst_gl_video_mixer_propose_allocation (GstAggregator * agg,
983 GstAggregatorPad * agg_pad, GstQuery * decide_query, GstQuery * query)
985 if (!GST_AGGREGATOR_CLASS (parent_class)->propose_allocation (agg,
986 agg_pad, decide_query, query))
989 gst_query_add_allocation_meta (query,
990 GST_VIDEO_AFFINE_TRANSFORMATION_META_API_TYPE, 0);
996 _mixer_pad_get_output_size (GstGLVideoMixer * mix,
997 GstGLVideoMixerPad * mix_pad, gint out_par_n, gint out_par_d, gint * width,
1000 GstVideoAggregatorPad *vagg_pad = GST_VIDEO_AGGREGATOR_PAD (mix_pad);
1001 gint pad_width, pad_height;
1004 /* FIXME: Anything better we can do here? */
1005 if (!vagg_pad->info.finfo
1006 || vagg_pad->info.finfo->format == GST_VIDEO_FORMAT_UNKNOWN) {
1007 GST_DEBUG_OBJECT (mix_pad, "Have no caps yet");
1015 0 ? GST_VIDEO_INFO_WIDTH (&vagg_pad->info) : mix_pad->width;
1018 0 ? GST_VIDEO_INFO_HEIGHT (&vagg_pad->info) : mix_pad->height;
1020 if (!gst_video_calculate_display_ratio (&dar_n, &dar_d, pad_width, pad_height,
1021 GST_VIDEO_INFO_PAR_N (&vagg_pad->info),
1022 GST_VIDEO_INFO_PAR_D (&vagg_pad->info), out_par_n, out_par_d)) {
1023 GST_WARNING_OBJECT (mix_pad, "Cannot calculate display aspect ratio");
1024 *width = *height = 0;
1027 GST_LOG_OBJECT (mix_pad, "scaling %ux%u by %u/%u (%u/%u / %u/%u)", pad_width,
1028 pad_height, dar_n, dar_d, GST_VIDEO_INFO_PAR_N (&vagg_pad->info),
1029 GST_VIDEO_INFO_PAR_D (&vagg_pad->info), out_par_n, out_par_d);
1031 if (pad_height % dar_n == 0) {
1032 pad_width = gst_util_uint64_scale_int (pad_height, dar_n, dar_d);
1033 } else if (pad_width % dar_d == 0) {
1034 pad_height = gst_util_uint64_scale_int (pad_width, dar_d, dar_n);
1036 pad_width = gst_util_uint64_scale_int (pad_height, dar_n, dar_d);
1040 *height = pad_height;
1044 _update_caps (GstVideoAggregator * vagg, GstCaps * caps)
1046 GstCaps *template_caps, *ret;
1049 GST_OBJECT_LOCK (vagg);
1050 for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) {
1051 GstVideoAggregatorPad *vaggpad = l->data;
1053 if (!vaggpad->info.finfo)
1056 if (GST_VIDEO_INFO_FORMAT (&vaggpad->info) == GST_VIDEO_FORMAT_UNKNOWN)
1059 if (GST_VIDEO_INFO_MULTIVIEW_MODE (&vaggpad->info) !=
1060 GST_VIDEO_MULTIVIEW_MODE_NONE
1061 && GST_VIDEO_INFO_MULTIVIEW_MODE (&vaggpad->info) !=
1062 GST_VIDEO_MULTIVIEW_MODE_MONO) {
1063 GST_FIXME_OBJECT (vaggpad, "Multiview support is not implemented yet");
1064 GST_OBJECT_UNLOCK (vagg);
1069 GST_OBJECT_UNLOCK (vagg);
1071 template_caps = gst_pad_get_pad_template_caps (GST_AGGREGATOR_SRC_PAD (vagg));
1072 ret = gst_caps_intersect (caps, template_caps);
1078 _fixate_caps (GstAggregator * agg, GstCaps * caps)
1080 GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg);
1081 GstGLVideoMixer *mix = GST_GL_VIDEO_MIXER (vagg);
1082 gint best_width = 0, best_height = 0;
1083 gint best_fps_n = 0, best_fps_d = 0;
1085 gdouble best_fps = 0.;
1086 GstCaps *ret = NULL;
1090 ret = gst_caps_make_writable (caps);
1092 /* we need this to calculate how large to make the output frame */
1093 s = gst_caps_get_structure (ret, 0);
1094 if (!gst_structure_has_field (s, "pixel-aspect-ratio")) {
1095 gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
1097 gst_structure_fixate_field_nearest_fraction (s, "pixel-aspect-ratio", 1, 1);
1098 gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d);
1100 GST_OBJECT_LOCK (vagg);
1101 for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) {
1102 GstVideoAggregatorPad *vaggpad = l->data;
1103 GstGLVideoMixerPad *mixer_pad = GST_GL_VIDEO_MIXER_PAD (vaggpad);
1104 gint this_width, this_height;
1109 fps_n = GST_VIDEO_INFO_FPS_N (&vaggpad->info);
1110 fps_d = GST_VIDEO_INFO_FPS_D (&vaggpad->info);
1111 _mixer_pad_get_output_size (mix, mixer_pad, par_n, par_d, &width, &height);
1113 if (width == 0 || height == 0)
1116 this_width = width + MAX (mixer_pad->xpos, 0);
1117 this_height = height + MAX (mixer_pad->ypos, 0);
1119 if (best_width < this_width)
1120 best_width = this_width;
1121 if (best_height < this_height)
1122 best_height = this_height;
1127 gst_util_fraction_to_double (fps_n, fps_d, &cur_fps);
1129 if (best_fps < cur_fps) {
1135 GST_OBJECT_UNLOCK (vagg);
1137 if (best_fps_n <= 0 || best_fps_d <= 0 || best_fps == 0.0) {
1143 s = gst_caps_get_structure (ret, 0);
1144 gst_structure_fixate_field_nearest_int (s, "width", best_width);
1145 gst_structure_fixate_field_nearest_int (s, "height", best_height);
1146 gst_structure_fixate_field_nearest_fraction (s, "framerate", best_fps_n,
1148 ret = gst_caps_fixate (ret);
1154 _reset_pad_gl (GstElement * agg, GstPad * aggpad, gpointer udata)
1156 const GstGLFuncs *gl = GST_GL_BASE_MIXER (agg)->context->gl_vtable;
1157 GstGLVideoMixerPad *pad = GST_GL_VIDEO_MIXER_PAD (aggpad);
1159 if (pad->vertex_buffer) {
1160 gl->DeleteBuffers (1, &pad->vertex_buffer);
1161 pad->vertex_buffer = 0;
1168 _reset_gl (GstGLContext * context, GstGLVideoMixer * video_mixer)
1170 const GstGLFuncs *gl = GST_GL_BASE_MIXER (video_mixer)->context->gl_vtable;
1172 if (video_mixer->vao) {
1173 gl->DeleteVertexArrays (1, &video_mixer->vao);
1174 video_mixer->vao = 0;
1177 if (video_mixer->vbo_indices) {
1178 gl->DeleteBuffers (1, &video_mixer->vbo_indices);
1179 video_mixer->vbo_indices = 0;
1182 if (video_mixer->checker_vbo) {
1183 gl->DeleteBuffers (1, &video_mixer->checker_vbo);
1184 video_mixer->checker_vbo = 0;
1187 gst_element_foreach_sink_pad (GST_ELEMENT (video_mixer), _reset_pad_gl, NULL);
1191 gst_gl_video_mixer_set_caps (GstGLMixer * mixer, GstCaps * outcaps)
1193 GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mixer);
1195 /* need reconfigure output geometry */
1196 video_mixer->output_geo_change = TRUE;
1202 gst_gl_video_mixer_gl_stop (GstGLBaseMixer * base_mix)
1204 GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (base_mix);
1206 gst_clear_object (&video_mixer->shader);
1207 gst_clear_object (&video_mixer->checker);
1209 _reset_gl (base_mix->context, video_mixer);
1211 GST_GL_BASE_MIXER_CLASS (parent_class)->gl_stop (base_mix);
1215 gst_gl_video_mixer_gl_start (GstGLBaseMixer * base_mix)
1217 GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (base_mix);
1219 if (!video_mixer->shader) {
1220 gchar *frag_str = g_strdup_printf ("%s%s",
1221 gst_gl_shader_string_get_highest_precision (base_mix->context,
1222 GST_GLSL_VERSION_NONE,
1223 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY),
1226 gst_gl_context_gen_shader (base_mix->context,
1227 gst_gl_shader_string_vertex_mat4_vertex_transform,
1228 frag_str, &video_mixer->shader);
1232 return GST_GL_BASE_MIXER_CLASS (parent_class)->gl_start (base_mix);
1236 _video_mixer_process_gl (GstGLContext * context, GstGLVideoMixer * video_mixer)
1238 GstGLMixer *mixer = GST_GL_MIXER (video_mixer);
1240 gst_gl_framebuffer_draw_to_texture (mixer->fbo, video_mixer->out_tex,
1241 gst_gl_video_mixer_callback, video_mixer);
1245 gst_gl_video_mixer_process_textures (GstGLMixer * mix, GstGLMemory * out_tex)
1247 GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mix);
1248 GstGLContext *context = GST_GL_BASE_MIXER (mix)->context;
1250 video_mixer->out_tex = out_tex;
1252 gst_gl_context_thread_add (context,
1253 (GstGLContextThreadFunc) _video_mixer_process_gl, video_mixer);
1258 static const GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
1261 _init_vbo_indices (GstGLVideoMixer * mixer)
1263 const GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable;
1265 if (!mixer->vbo_indices) {
1266 gl->GenBuffers (1, &mixer->vbo_indices);
1267 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, mixer->vbo_indices);
1268 gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indices), indices,
1274 _draw_checker_background (GstGLVideoMixer * video_mixer)
1276 GstGLMixer *mixer = GST_GL_MIXER (video_mixer);
1277 const GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable;
1278 gint attr_position_loc = 0;
1281 gfloat v_vertices[] = {
1289 if (!video_mixer->checker) {
1293 g_strdup_printf ("%s%s",
1294 gst_gl_shader_string_get_highest_precision (GST_GL_BASE_MIXER
1295 (mixer)->context, GST_GLSL_VERSION_NONE,
1296 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY),
1299 if (!gst_gl_context_gen_shader (GST_GL_BASE_MIXER (mixer)->context,
1300 checker_v_src, frag_str, &video_mixer->checker)) {
1307 gst_gl_shader_use (video_mixer->checker);
1309 gst_gl_shader_get_attribute_location (video_mixer->checker, "a_position");
1311 _init_vbo_indices (video_mixer);
1313 if (!video_mixer->checker_vbo) {
1314 gl->GenBuffers (1, &video_mixer->checker_vbo);
1315 gl->BindBuffer (GL_ARRAY_BUFFER, video_mixer->checker_vbo);
1316 gl->BufferData (GL_ARRAY_BUFFER, 4 * 3 * sizeof (GLfloat), v_vertices,
1319 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, video_mixer->vbo_indices);
1320 gl->BindBuffer (GL_ARRAY_BUFFER, video_mixer->checker_vbo);
1323 gl->VertexAttribPointer (attr_position_loc, 3, GL_FLOAT,
1324 GL_FALSE, 3 * sizeof (GLfloat), (void *) 0);
1326 gl->EnableVertexAttribArray (attr_position_loc);
1328 gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
1330 gl->DisableVertexAttribArray (attr_position_loc);
1331 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
1332 gl->BindBuffer (GL_ARRAY_BUFFER, 0);
1338 _draw_background (GstGLVideoMixer * video_mixer)
1340 GstGLMixer *mixer = GST_GL_MIXER (video_mixer);
1341 const GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable;
1343 switch (video_mixer->background) {
1344 case GST_GL_VIDEO_MIXER_BACKGROUND_BLACK:
1345 gl->ClearColor (0.0, 0.0, 0.0, 1.0);
1346 gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1348 case GST_GL_VIDEO_MIXER_BACKGROUND_WHITE:
1349 gl->ClearColor (1.0, 1.0, 1.0, 1.0);
1350 gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1352 case GST_GL_VIDEO_MIXER_BACKGROUND_TRANSPARENT:
1353 gl->ClearColor (0.0, 0.0, 0.0, 0.0);
1354 gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1356 case GST_GL_VIDEO_MIXER_BACKGROUND_CHECKER:
1357 return _draw_checker_background (video_mixer);
1367 _blend_equation_to_gl (GstGLVideoMixerBlendEquation equation)
1370 case GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD:
1372 case GST_GL_VIDEO_MIXER_BLEND_EQUATION_SUBTRACT:
1373 return GL_FUNC_SUBTRACT;
1374 case GST_GL_VIDEO_MIXER_BLEND_EQUATION_REVERSE_SUBTRACT:
1375 return GL_FUNC_REVERSE_SUBTRACT;
1377 g_assert_not_reached ();
1383 _blend_function_to_gl (GstGLVideoMixerBlendFunction equation)
1386 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ZERO:
1388 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE:
1390 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_COLOR:
1391 return GL_SRC_COLOR;
1392 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_COLOR:
1393 return GL_ONE_MINUS_SRC_COLOR;
1394 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_COLOR:
1395 return GL_DST_COLOR;
1396 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_COLOR:
1397 return GL_ONE_MINUS_DST_COLOR;
1398 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA:
1399 return GL_SRC_ALPHA;
1400 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA:
1401 return GL_ONE_MINUS_SRC_ALPHA;
1402 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_ALPHA:
1403 return GL_DST_ALPHA;
1404 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_ALPHA:
1405 return GL_ONE_MINUS_DST_ALPHA;
1406 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_COLOR:
1407 return GL_CONSTANT_COLOR;
1408 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_COLOR:
1409 return GL_ONE_MINUS_CONSTANT_COLOR;
1410 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_ALPHA:
1411 return GL_CONSTANT_ALPHA;
1412 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_ALPHA:
1413 return GL_ONE_MINUS_CONSTANT_ALPHA;
1414 case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE:
1415 return GL_SRC_ALPHA_SATURATE;
1417 g_assert_not_reached ();
1423 _set_blend_state (GstGLVideoMixer * video_mixer, GstGLVideoMixerPad * mix_pad)
1425 const GstGLFuncs *gl = GST_GL_BASE_MIXER (video_mixer)->context->gl_vtable;
1426 gboolean require_separate = FALSE;
1427 guint gl_func_src_rgb, gl_func_src_alpha, gl_func_dst_rgb, gl_func_dst_alpha;
1428 guint gl_equation_rgb, gl_equation_alpha;
1431 mix_pad->blend_equation_rgb != mix_pad->blend_equation_alpha
1432 || mix_pad->blend_function_src_rgb != mix_pad->blend_function_src_alpha
1433 || mix_pad->blend_function_dst_rgb != mix_pad->blend_function_dst_alpha;
1435 if (require_separate && (!gl->BlendFuncSeparate
1436 || !gl->BlendEquationSeparate)) {
1437 GST_ERROR_OBJECT (mix_pad,
1438 "separated blend equations/functions requested however "
1439 "glBlendFuncSeparate or glBlendEquationSeparate not available");
1443 if (mix_pad->blend_function_dst_rgb ==
1444 GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE) {
1445 GST_ERROR_OBJECT (mix_pad,
1446 "Destination RGB blend function cannot be \'SRC_ALPHA_SATURATE\'");
1450 if (mix_pad->blend_function_dst_alpha ==
1451 GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE) {
1452 GST_ERROR_OBJECT (mix_pad,
1453 "Destination alpha blend function cannot be \'SRC_ALPHA_SATURATE\'");
1457 gl_equation_rgb = _blend_equation_to_gl (mix_pad->blend_equation_rgb);
1458 gl_equation_alpha = _blend_equation_to_gl (mix_pad->blend_equation_alpha);
1460 gl_func_src_rgb = _blend_function_to_gl (mix_pad->blend_function_src_rgb);
1461 gl_func_src_alpha = _blend_function_to_gl (mix_pad->blend_function_src_alpha);
1462 gl_func_dst_rgb = _blend_function_to_gl (mix_pad->blend_function_dst_rgb);
1463 gl_func_dst_alpha = _blend_function_to_gl (mix_pad->blend_function_dst_alpha);
1465 if (gl->BlendEquationSeparate)
1466 gl->BlendEquationSeparate (gl_equation_rgb, gl_equation_alpha);
1468 gl->BlendEquation (gl_equation_rgb);
1470 if (gl->BlendFuncSeparate)
1471 gl->BlendFuncSeparate (gl_func_src_rgb, gl_func_dst_rgb, gl_func_src_alpha,
1474 gl->BlendFunc (gl_func_src_rgb, gl_func_dst_rgb);
1476 gl->BlendColor (mix_pad->blend_constant_color_red,
1477 mix_pad->blend_constant_color_green, mix_pad->blend_constant_color_blue,
1478 mix_pad->blend_constant_color_alpha);
1483 /* opengl scene, params: input texture (not the output mixer->texture) */
1485 gst_gl_video_mixer_callback (gpointer stuff)
1487 GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (stuff);
1488 GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (stuff);
1489 GstGLMixer *mixer = GST_GL_MIXER (video_mixer);
1490 GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable;
1491 GLint attr_position_loc = 0;
1492 GLint attr_texture_loc = 0;
1493 guint out_width, out_height;
1496 out_width = GST_VIDEO_INFO_WIDTH (&vagg->info);
1497 out_height = GST_VIDEO_INFO_HEIGHT (&vagg->info);
1499 gst_gl_context_clear_shader (GST_GL_BASE_MIXER (mixer)->context);
1500 gl->BindTexture (GL_TEXTURE_2D, 0);
1502 gl->Disable (GL_DEPTH_TEST);
1503 gl->Disable (GL_CULL_FACE);
1505 if (gl->GenVertexArrays) {
1506 if (!video_mixer->vao)
1507 gl->GenVertexArrays (1, &video_mixer->vao);
1508 gl->BindVertexArray (video_mixer->vao);
1511 if (!_draw_background (video_mixer))
1514 gst_gl_shader_use (video_mixer->shader);
1517 gst_gl_shader_get_attribute_location (video_mixer->shader, "a_position");
1519 gst_gl_shader_get_attribute_location (video_mixer->shader, "a_texcoord");
1521 gl->Enable (GL_BLEND);
1523 GST_OBJECT_LOCK (video_mixer);
1524 walk = GST_ELEMENT (video_mixer)->sinkpads;
1526 GstGLMixerPad *mix_pad = walk->data;
1527 GstGLVideoMixerPad *pad = walk->data;
1528 GstVideoAggregatorPad *vagg_pad = walk->data;
1529 GstVideoInfo *v_info;
1531 guint in_width, in_height;
1534 gfloat v_vertices[] = {
1535 -1.0,-1.0, 0.0f, 0.0f, 0.0f,
1536 1.0,-1.0, 0.0f, 1.0f, 0.0f,
1537 1.0, 1.0, 0.0f, 1.0f, 1.0f,
1538 -1.0, 1.0, 0.0f, 0.0f, 1.0f,
1542 v_info = &GST_VIDEO_AGGREGATOR_PAD (pad)->info;
1543 in_width = GST_VIDEO_INFO_WIDTH (v_info);
1544 in_height = GST_VIDEO_INFO_HEIGHT (v_info);
1546 if (!mix_pad->current_texture || in_width <= 0 || in_height <= 0
1547 || pad->alpha == 0.0f) {
1548 GST_DEBUG ("skipping texture:%u pad:%p width:%u height:%u alpha:%f",
1549 mix_pad->current_texture, pad, in_width, in_height, pad->alpha);
1550 walk = g_list_next (walk);
1554 if (!_set_blend_state (video_mixer, pad)) {
1555 GST_FIXME_OBJECT (pad, "skipping due to incorrect blend parameters");
1556 walk = g_list_next (walk);
1560 in_tex = mix_pad->current_texture;
1562 _init_vbo_indices (video_mixer);
1564 if (video_mixer->output_geo_change
1565 || pad->geometry_change || !pad->vertex_buffer) {
1566 gint pad_width, pad_height;
1569 _mixer_pad_get_output_size (video_mixer, pad,
1570 GST_VIDEO_INFO_PAR_N (&vagg->info),
1571 GST_VIDEO_INFO_PAR_D (&vagg->info), &pad_width, &pad_height);
1573 w = ((gfloat) pad_width / (gfloat) out_width);
1574 h = ((gfloat) pad_height / (gfloat) out_height);
1576 pad->m_matrix[0] = w;
1577 pad->m_matrix[5] = h;
1579 2. * (gfloat) pad->xpos / (gfloat) out_width - (1. - w);
1581 2. * (gfloat) pad->ypos / (gfloat) out_height - (1. - h);
1583 GST_TRACE ("processing texture:%u dimensions:%ux%u, at %f,%f %fx%f with "
1584 "alpha:%f", in_tex, in_width, in_height, pad->m_matrix[12],
1585 pad->m_matrix[13], pad->m_matrix[0], pad->m_matrix[5], pad->alpha);
1587 if (!pad->vertex_buffer)
1588 gl->GenBuffers (1, &pad->vertex_buffer);
1590 gl->BindBuffer (GL_ARRAY_BUFFER, pad->vertex_buffer);
1591 gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), v_vertices,
1594 pad->geometry_change = FALSE;
1596 gl->BindBuffer (GL_ARRAY_BUFFER, pad->vertex_buffer);
1598 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, video_mixer->vbo_indices);
1600 gl->ActiveTexture (GL_TEXTURE0);
1601 gl->BindTexture (GL_TEXTURE_2D, in_tex);
1602 gst_gl_shader_set_uniform_1i (video_mixer->shader, "texture", 0);
1603 gst_gl_shader_set_uniform_1f (video_mixer->shader, "alpha", pad->alpha);
1606 GstVideoAffineTransformationMeta *af_meta;
1608 gfloat af_matrix[16];
1610 gst_video_aggregator_pad_get_current_buffer (vagg_pad);
1612 af_meta = gst_buffer_get_video_affine_transformation_meta (buffer);
1613 gst_gl_get_affine_transformation_meta_as_ndc_ext (af_meta, af_matrix);
1614 gst_gl_multiply_matrix4 (af_matrix, pad->m_matrix, matrix);
1615 gst_gl_shader_set_uniform_matrix_4fv (video_mixer->shader,
1616 "u_transformation", 1, FALSE, matrix);
1619 gl->EnableVertexAttribArray (attr_position_loc);
1620 gl->EnableVertexAttribArray (attr_texture_loc);
1622 gl->VertexAttribPointer (attr_position_loc, 3, GL_FLOAT,
1623 GL_FALSE, 5 * sizeof (GLfloat), (void *) 0);
1625 gl->VertexAttribPointer (attr_texture_loc, 2, GL_FLOAT,
1626 GL_FALSE, 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat)));
1628 gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
1630 walk = g_list_next (walk);
1633 video_mixer->output_geo_change = FALSE;
1634 GST_OBJECT_UNLOCK (video_mixer);
1636 if (gl->GenVertexArrays) {
1637 gl->BindVertexArray (0);
1639 gl->DisableVertexAttribArray (attr_position_loc);
1640 gl->DisableVertexAttribArray (attr_texture_loc);
1642 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
1643 gl->BindBuffer (GL_ARRAY_BUFFER, 0);
1644 gl->BindTexture (GL_TEXTURE_2D, 0);
1647 gl->Disable (GL_BLEND);
1649 gst_gl_context_clear_shader (GST_GL_BASE_MIXER (mixer)->context);
1654 /* GstChildProxy implementation */
1656 gst_gl_video_mixer_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
1659 GstGLVideoMixer *gl_video_mixer = GST_GL_VIDEO_MIXER (child_proxy);
1660 GObject *obj = NULL;
1662 GST_OBJECT_LOCK (gl_video_mixer);
1663 obj = g_list_nth_data (GST_ELEMENT_CAST (gl_video_mixer)->sinkpads, index);
1665 gst_object_ref (obj);
1666 GST_OBJECT_UNLOCK (gl_video_mixer);
1672 gst_gl_video_mixer_child_proxy_get_children_count (GstChildProxy * child_proxy)
1675 GstGLVideoMixer *gl_video_mixer = GST_GL_VIDEO_MIXER (child_proxy);
1677 GST_OBJECT_LOCK (gl_video_mixer);
1678 count = GST_ELEMENT_CAST (gl_video_mixer)->numsinkpads;
1679 GST_OBJECT_UNLOCK (gl_video_mixer);
1680 GST_INFO_OBJECT (gl_video_mixer, "Children Count: %d", count);
1686 gst_gl_video_mixer_child_proxy_init (gpointer g_iface, gpointer iface_data)
1688 GstChildProxyInterface *iface = g_iface;
1690 iface->get_child_by_index = gst_gl_video_mixer_child_proxy_get_child_by_index;
1691 iface->get_children_count = gst_gl_video_mixer_child_proxy_get_children_count;