1 /*
2 * GStreamer
3 * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
4 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 /**
23 * SECTION:element-d3d11compositor
24 * @title: d3d11compositor
25 *
26 * A convenient bin which wraps #d3d11compositorelement for video composition
27 * with other helper elements to handle color conversion and memory transfer
28 * between Direct3D11 and system memory space.
29 *
30 * ## Example launch line
31 * ```
32 * gst-launch-1.0 d3d11compositor name=c ! d3d11videosink \
33 * videotestsrc ! video/x-raw,width=320,height=240 ! c. \
34 * videotestsrc pattern=ball ! video/x-raw,width=100,height=100 ! c.
35 * ```
36 *
37 * Since: 1.20
38 *
39 */
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 #include <gst/controller/gstproxycontrolbinding.h>
46 #include "gstd3d11compositorbin.h"
47 #include "gstd3d11compositor.h"
48 #include "gstd3d11pluginutils.h"
49
50 GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_compositor_debug);
51 #define GST_CAT_DEFAULT gst_d3d11_compositor_debug
52
53 /****************************
54 * GstD3D11CompositorBinPad *
55 ****************************/
56
57 enum
58 {
59 PROP_PAD_0,
60 /* GstAggregatorPad */
61 PROP_PAD_EMIT_SIGNALS,
62 };
63
64 /* GstAggregatorPad */
65 #define DEFAULT_PAD_EMIT_SIGNALS FALSE
66
67 enum
68 {
69 /* GstAggregatorPad */
70 SIGNAL_PAD_BUFFER_CONSUMED = 0,
71 SIGNAL_PAD_LAST,
72 };
73
74 static guint gst_d3d11_compositor_bin_pad_signals[SIGNAL_PAD_LAST] = { 0 };
75
76 /**
77 * GstD3D11CompositorBinPad:
78 *
79 * Since: 1.20
80 */
81 struct _GstD3D11CompositorBinPad
82 {
83 GstGhostPad parent;
84
85 /* Holds ref */
86 GstPad *target;
87 gulong sig_id;
88 };
89
90 static void gst_d3d11_compositor_bin_pad_dispose (GObject * object);
91 static void gst_d3d11_compositor_bin_pad_set_property (GObject * object,
92 guint prop_id, const GValue * value, GParamSpec * pspec);
93 static void gst_d3d11_compositor_bin_pad_get_property (GObject * object,
94 guint prop_id, GValue * value, GParamSpec * pspec);
95 static void
96 gst_d3d11_compositor_bin_pad_set_target_default (GstD3D11CompositorBinPad * pad,
97 GstPad * target);
98
99 G_DEFINE_TYPE (GstD3D11CompositorBinPad, gst_d3d11_compositor_bin_pad,
100 GST_TYPE_GHOST_PAD);
101
102 static void
gst_d3d11_compositor_bin_pad_class_init(GstD3D11CompositorBinPadClass * klass)103 gst_d3d11_compositor_bin_pad_class_init (GstD3D11CompositorBinPadClass * klass)
104 {
105 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
106
107 gobject_class->dispose = gst_d3d11_compositor_bin_pad_dispose;
108 gobject_class->set_property = gst_d3d11_compositor_bin_pad_set_property;
109 gobject_class->get_property = gst_d3d11_compositor_bin_pad_get_property;
110
111 /* GstAggregatorPad */
112 g_object_class_install_property (gobject_class, PROP_PAD_EMIT_SIGNALS,
113 g_param_spec_boolean ("emit-signals", "Emit signals",
114 "Send signals to signal data consumption",
115 DEFAULT_PAD_EMIT_SIGNALS,
116 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
117
118 gst_d3d11_compositor_bin_pad_signals[SIGNAL_PAD_BUFFER_CONSUMED] =
119 g_signal_new ("buffer-consumed", G_TYPE_FROM_CLASS (klass),
120 G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_BUFFER);
121
122 klass->set_target =
123 GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_pad_set_target_default);
124 }
125
126 static void
gst_d3d11_compositor_bin_pad_init(GstD3D11CompositorBinPad * self)127 gst_d3d11_compositor_bin_pad_init (GstD3D11CompositorBinPad * self)
128 {
129 }
130
131 static void
gst_d3d11_compositor_bin_pad_dispose(GObject * object)132 gst_d3d11_compositor_bin_pad_dispose (GObject * object)
133 {
134 GstD3D11CompositorBinPad *self = GST_D3D11_COMPOSITOR_BIN_PAD (object);
135
136 gst_clear_object (&self->target);
137
138 G_OBJECT_CLASS (gst_d3d11_compositor_bin_pad_parent_class)->dispose (object);
139 }
140
141 static void
gst_d3d11_compositor_bin_pad_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)142 gst_d3d11_compositor_bin_pad_set_property (GObject * object,
143 guint prop_id, const GValue * value, GParamSpec * pspec)
144 {
145 GstD3D11CompositorBinPad *self = GST_D3D11_COMPOSITOR_BIN_PAD (object);
146
147 if (self->target)
148 g_object_set_property (G_OBJECT (self->target), pspec->name, value);
149 }
150
151 static void
gst_d3d11_compositor_bin_pad_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)152 gst_d3d11_compositor_bin_pad_get_property (GObject * object,
153 guint prop_id, GValue * value, GParamSpec * pspec)
154 {
155 GstD3D11CompositorBinPad *self = GST_D3D11_COMPOSITOR_BIN_PAD (object);
156
157 if (self->target)
158 g_object_get_property (G_OBJECT (self->target), pspec->name, value);
159 }
160
161 static void
gst_d3d11_compositor_bin_pad_on_buffer_consumed(GstAggregatorPad * pad,GstBuffer * buffer,GstD3D11CompositorBinPad * self)162 gst_d3d11_compositor_bin_pad_on_buffer_consumed (GstAggregatorPad * pad,
163 GstBuffer * buffer, GstD3D11CompositorBinPad * self)
164 {
165 g_signal_emit (self,
166 gst_d3d11_compositor_bin_pad_signals[SIGNAL_PAD_BUFFER_CONSUMED],
167 0, buffer);
168 }
169
170 /**
171 * gst_d3d11_compositor_bin_pad_set_target:
172 * @self: a #GstD3D11CompositorBinPad
173 * @target: (transfer full): a #GstAggregatorPad
174 */
175 static void
gst_d3d11_compositor_bin_pad_set_target(GstD3D11CompositorBinPad * pad,GstPad * target)176 gst_d3d11_compositor_bin_pad_set_target (GstD3D11CompositorBinPad * pad,
177 GstPad * target)
178 {
179 GstD3D11CompositorBinPadClass *klass =
180 GST_D3D11_COMPOSITOR_BIN_PAD_GET_CLASS (pad);
181
182 klass->set_target (pad, target);
183 }
184
185 static void
gst_d3d11_compositor_bin_pad_set_target_default(GstD3D11CompositorBinPad * pad,GstPad * target)186 gst_d3d11_compositor_bin_pad_set_target_default (GstD3D11CompositorBinPad * pad,
187 GstPad * target)
188 {
189 pad->target = target;
190 pad->sig_id = g_signal_connect (target, "buffer-consumed",
191 G_CALLBACK (gst_d3d11_compositor_bin_pad_on_buffer_consumed), pad);
192 }
193
194 static void
gst_d3d11_compositor_bin_pad_unset_target(GstD3D11CompositorBinPad * self)195 gst_d3d11_compositor_bin_pad_unset_target (GstD3D11CompositorBinPad * self)
196 {
197 if (!self->target)
198 return;
199
200 if (self->sig_id)
201 g_signal_handler_disconnect (self->target, self->sig_id);
202 self->sig_id = 0;
203 gst_clear_object (&self->target);
204 }
205
206 /******************************
207 * GstD3D11CompositorBinInput *
208 ******************************/
209
210 enum
211 {
212 PROP_INPUT_0,
213 /* GstVideoAggregatorPad */
214 PROP_INPUT_ZORDER,
215 PROP_INPUT_REPEAT_AFTER_EOS,
216 PROP_INPUT_MAX_LAST_BUFFER_REPEAT,
217 /* GstD3D11CompositorPad */
218 PROP_INPUT_XPOS,
219 PROP_INPUT_YPOS,
220 PROP_INPUT_WIDTH,
221 PROP_INPUT_HEIGHT,
222 PROP_INPUT_ALPHA,
223 PROP_INPUT_BLEND_OP_RGB,
224 PROP_INPUT_BLEND_OP_ALPHA,
225 PROP_INPUT_BLEND_SRC_RGB,
226 PROP_INPUT_BLEND_SRC_ALPHA,
227 PROP_INPUT_BLEND_DEST_RGB,
228 PROP_INPUT_BLEND_DEST_ALPHA,
229 PROP_INPUT_BLEND_FACTOR_RED,
230 PROP_INPUT_BLEND_FACTOR_GREEN,
231 PROP_INPUT_BLEND_FACTOR_BLUE,
232 PROP_INPUT_BLEND_FACTOR_ALPHA,
233 PROP_INPUT_SIZING_POLICY,
234 };
235
236 /* GstVideoAggregatorPad */
237 #define DEFAULT_INPUT_ZORDER 0
238 #define DEFAULT_INPUT_REPEAT_AFTER_EOS FALSE
239 #define DEFAULT_INPUT_MAX_LAST_BUFFER_REPEAT GST_CLOCK_TIME_NONE
240 /* GstD3D11CompositorPad */
241 #define DEFAULT_INPUT_XPOS 0
242 #define DEFAULT_INPUT_YPOS 0
243 #define DEFAULT_INPUT_WIDTH 0
244 #define DEFAULT_INPUT_HEIGHT 0
245 #define DEFAULT_INPUT_ALPHA 1.0
246 #define DEFAULT_INPUT_BLEND_OP_RGB GST_D3D11_COMPOSITOR_BLEND_OP_ADD
247 #define DEFAULT_INPUT_BLEND_OP_ALPHA GST_D3D11_COMPOSITOR_BLEND_OP_ADD
248 #define DEFAULT_INPUT_BLEND_SRC_RGB GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA
249 #define DEFAULT_INPUT_BLEND_SRC_ALPHA GST_D3D11_COMPOSITOR_BLEND_ONE
250 #define DEFAULT_INPUT_BLEND_DEST_RGB GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA
251 #define DEFAULT_INPUT_BLEND_DEST_ALPHA GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA
252 #define DEFAULT_INPUT_SIZING_POLICY GST_D3D11_COMPOSITOR_SIZING_POLICY_NONE
253
254 /**
255 * GstD3D11CompositorBinInput:
256 *
257 * Since: 1.20
258 */
259 struct _GstD3D11CompositorBinInput
260 {
261 GstD3D11CompositorBinPad parent;
262 };
263
264 static void gst_d3d11_compositor_bin_input_set_property (GObject * object,
265 guint prop_id, const GValue * value, GParamSpec * pspec);
266 static void gst_d3d11_compositor_bin_input_get_property (GObject * object,
267 guint prop_id, GValue * value, GParamSpec * pspec);
268 static void
269 gst_d3d11_compositor_bin_input_set_target (GstD3D11CompositorBinPad * pad,
270 GstPad * target);
271
272 #define gst_d3d11_compositor_bin_input_parent_class input_parent_class
273 G_DEFINE_TYPE (GstD3D11CompositorBinInput, gst_d3d11_compositor_bin_input,
274 GST_TYPE_D3D11_COMPOSITOR_BIN_PAD);
275
276 static void
gst_d3d11_compositor_bin_input_class_init(GstD3D11CompositorBinInputClass * klass)277 gst_d3d11_compositor_bin_input_class_init (GstD3D11CompositorBinInputClass *
278 klass)
279 {
280 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
281 GstD3D11CompositorBinPadClass *pad_class =
282 GST_D3D11_COMPOSITOR_BIN_PAD_CLASS (klass);
283
284 gobject_class->set_property = gst_d3d11_compositor_bin_input_set_property;
285 gobject_class->get_property = gst_d3d11_compositor_bin_input_get_property;
286
287 /* GstVideoAggregatorPad */
288 g_object_class_install_property (gobject_class, PROP_INPUT_ZORDER,
289 g_param_spec_uint ("zorder", "Z-Order", "Z Order of the picture",
290 0, G_MAXUINT, DEFAULT_INPUT_ZORDER,
291 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
292 G_PARAM_STATIC_STRINGS)));
293
294 g_object_class_install_property (gobject_class, PROP_INPUT_REPEAT_AFTER_EOS,
295 g_param_spec_boolean ("repeat-after-eos", "Repeat After EOS",
296 "Repeat the " "last frame after EOS until all pads are EOS",
297 DEFAULT_INPUT_REPEAT_AFTER_EOS,
298 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
299 G_PARAM_STATIC_STRINGS)));
300
301 g_object_class_install_property (gobject_class,
302 PROP_INPUT_MAX_LAST_BUFFER_REPEAT,
303 g_param_spec_uint64 ("max-last-buffer-repeat", "Max Last Buffer Repeat",
304 "Repeat last buffer for time (in ns, -1=until EOS), "
305 "behaviour on EOS is not affected", 0, G_MAXUINT64,
306 DEFAULT_INPUT_MAX_LAST_BUFFER_REPEAT,
307 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
308 G_PARAM_STATIC_STRINGS)));
309
310 /* GstD3D11CompositorPad */
311 g_object_class_install_property (gobject_class, PROP_INPUT_XPOS,
312 g_param_spec_int ("xpos", "X Position", "X position of the picture",
313 G_MININT, G_MAXINT, DEFAULT_INPUT_XPOS,
314 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
315 G_PARAM_STATIC_STRINGS)));
316
317 g_object_class_install_property (gobject_class, PROP_INPUT_YPOS,
318 g_param_spec_int ("ypos", "Y Position", "Y position of the picture",
319 G_MININT, G_MAXINT, DEFAULT_INPUT_YPOS,
320 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
321 G_PARAM_STATIC_STRINGS)));
322
323 g_object_class_install_property (gobject_class, PROP_INPUT_WIDTH,
324 g_param_spec_int ("width", "Width", "Width of the picture",
325 G_MININT, G_MAXINT, DEFAULT_INPUT_WIDTH,
326 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
327 G_PARAM_STATIC_STRINGS)));
328
329 g_object_class_install_property (gobject_class, PROP_INPUT_HEIGHT,
330 g_param_spec_int ("height", "Height", "Height of the picture",
331 G_MININT, G_MAXINT, DEFAULT_INPUT_HEIGHT,
332 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
333 G_PARAM_STATIC_STRINGS)));
334
335 g_object_class_install_property (gobject_class, PROP_INPUT_ALPHA,
336 g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0,
337 DEFAULT_INPUT_ALPHA,
338 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
339 G_PARAM_STATIC_STRINGS)));
340
341 g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_OP_RGB,
342 g_param_spec_enum ("blend-op-rgb", "Blend Operation RGB",
343 "Blend equation for RGB", GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION,
344 DEFAULT_INPUT_BLEND_OP_RGB,
345 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
346 G_PARAM_STATIC_STRINGS)));
347
348 g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_OP_ALPHA,
349 g_param_spec_enum ("blend-op-alpha", "Blend Operation Alpha",
350 "Blend equation for alpha", GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION,
351 DEFAULT_INPUT_BLEND_OP_ALPHA,
352 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
353 G_PARAM_STATIC_STRINGS)));
354
355 g_object_class_install_property (gobject_class,
356 PROP_INPUT_BLEND_SRC_RGB,
357 g_param_spec_enum ("blend-src-rgb", "Blend Source RGB",
358 "Blend factor for source RGB",
359 GST_TYPE_D3D11_COMPOSITOR_BLEND,
360 DEFAULT_INPUT_BLEND_SRC_RGB,
361 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
362 G_PARAM_STATIC_STRINGS)));
363
364 g_object_class_install_property (gobject_class,
365 PROP_INPUT_BLEND_SRC_ALPHA,
366 g_param_spec_enum ("blend-src-alpha",
367 "Blend Source Alpha",
368 "Blend factor for source alpha, \"*-color\" values are not allowed",
369 GST_TYPE_D3D11_COMPOSITOR_BLEND,
370 DEFAULT_INPUT_BLEND_SRC_ALPHA,
371 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
372 G_PARAM_STATIC_STRINGS)));
373
374 g_object_class_install_property (gobject_class,
375 PROP_INPUT_BLEND_DEST_RGB,
376 g_param_spec_enum ("blend-dest-rgb",
377 "Blend Destination RGB",
378 "Blend factor for destination RGB",
379 GST_TYPE_D3D11_COMPOSITOR_BLEND,
380 DEFAULT_INPUT_BLEND_DEST_RGB,
381 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
382 G_PARAM_STATIC_STRINGS)));
383
384 g_object_class_install_property (gobject_class,
385 PROP_INPUT_BLEND_DEST_ALPHA,
386 g_param_spec_enum ("blend-dest-alpha",
387 "Blend Destination Alpha",
388 "Blend factor for destination alpha, "
389 "\"*-color\" values are not allowed",
390 GST_TYPE_D3D11_COMPOSITOR_BLEND,
391 DEFAULT_INPUT_BLEND_DEST_ALPHA,
392 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
393 G_PARAM_STATIC_STRINGS)));
394
395 g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_FACTOR_RED,
396 g_param_spec_float ("blend-factor-red", "Blend Factor Red",
397 "Blend factor for red component "
398 "when blend type is \"blend-factor\" or \"inv-blend-factor\"",
399 0.0, 1.0, 1.0,
400 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
401 G_PARAM_STATIC_STRINGS)));
402
403 g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_FACTOR_GREEN,
404 g_param_spec_float ("blend-factor-green", "Blend Factor Green",
405 "Blend factor for green component "
406 "when blend type is \"blend-factor\" or \"inv-blend-factor\"",
407 0.0, 1.0, 1.0,
408 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
409 G_PARAM_STATIC_STRINGS)));
410
411 g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_FACTOR_BLUE,
412 g_param_spec_float ("blend-factor-blue", "Blend Factor Blue",
413 "Blend factor for blue component "
414 "when blend type is \"blend-factor\" or \"inv-blend-factor\"",
415 0.0, 1.0, 1.0,
416 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
417 G_PARAM_STATIC_STRINGS)));
418
419 g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_FACTOR_ALPHA,
420 g_param_spec_float ("blend-factor-alpha", "Blend Factor Alpha",
421 "Blend factor for alpha component "
422 "when blend type is \"blend-factor\" or \"inv-blend-factor\"",
423 0.0, 1.0, 1.0,
424 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
425 G_PARAM_STATIC_STRINGS)));
426
427 g_object_class_install_property (gobject_class, PROP_INPUT_SIZING_POLICY,
428 g_param_spec_enum ("sizing-policy", "Sizing policy",
429 "Sizing policy to use for image scaling",
430 GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY, DEFAULT_INPUT_SIZING_POLICY,
431 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
432 G_PARAM_STATIC_STRINGS)));
433
434 pad_class->set_target =
435 GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_input_set_target);
436 }
437
438 static void
gst_d3d11_compositor_bin_input_init(GstD3D11CompositorBinInput * self)439 gst_d3d11_compositor_bin_input_init (GstD3D11CompositorBinInput * self)
440 {
441 }
442
443 static void
gst_d3d11_compositor_bin_input_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)444 gst_d3d11_compositor_bin_input_set_property (GObject * object,
445 guint prop_id, const GValue * value, GParamSpec * pspec)
446 {
447 GstD3D11CompositorBinPad *pad = GST_D3D11_COMPOSITOR_BIN_PAD (object);
448
449 if (pad->target)
450 g_object_set_property (G_OBJECT (pad->target), pspec->name, value);
451 }
452
453 static void
gst_d3d11_compositor_bin_input_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)454 gst_d3d11_compositor_bin_input_get_property (GObject * object,
455 guint prop_id, GValue * value, GParamSpec * pspec)
456 {
457 GstD3D11CompositorBinPad *pad = GST_D3D11_COMPOSITOR_BIN_PAD (object);
458
459 if (pad->target)
460 g_object_get_property (G_OBJECT (pad->target), pspec->name, value);
461 }
462
463 static void
gst_d3d11_compositor_bin_input_set_target(GstD3D11CompositorBinPad * pad,GstPad * target)464 gst_d3d11_compositor_bin_input_set_target (GstD3D11CompositorBinPad * pad,
465 GstPad * target)
466 {
467 GST_D3D11_COMPOSITOR_BIN_PAD_CLASS (input_parent_class)->set_target (pad,
468 target);
469
470 #define ADD_BINDING(obj,ref,prop) \
471 gst_object_add_control_binding (GST_OBJECT (obj), \
472 gst_proxy_control_binding_new (GST_OBJECT (obj), prop, \
473 GST_OBJECT (ref), prop));
474 /* GstVideoAggregatorPad */
475 ADD_BINDING (target, pad, "zorder");
476 ADD_BINDING (target, pad, "repeat-after-eos");
477 /* GstD3D11CompositorPad */
478 ADD_BINDING (target, pad, "xpos");
479 ADD_BINDING (target, pad, "ypos");
480 ADD_BINDING (target, pad, "width");
481 ADD_BINDING (target, pad, "height");
482 ADD_BINDING (target, pad, "alpha");
483 ADD_BINDING (target, pad, "blend-op-rgb");
484 ADD_BINDING (target, pad, "blend-op-alpha");
485 ADD_BINDING (target, pad, "blend-src-rgb");
486 ADD_BINDING (target, pad, "blend-src-alpha");
487 ADD_BINDING (target, pad, "blend-dest-rgb");
488 ADD_BINDING (target, pad, "blend-dest-alpha");
489 ADD_BINDING (target, pad, "blend-factor-red");
490 ADD_BINDING (target, pad, "blend-factor-green");
491 ADD_BINDING (target, pad, "blend-factor-blue");
492 ADD_BINDING (target, pad, "blend-factor-alpha");
493 ADD_BINDING (target, pad, "sizing-policy");
494 #undef ADD_BINDING
495 }
496
497 /*************************
498 * GstD3D11CompositorBin *
499 *************************/
500
501 static GstStaticCaps sink_template_caps =
502 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
503 (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_SINK_FORMATS) ";"
504 GST_VIDEO_CAPS_MAKE (GST_D3D11_SINK_FORMATS));
505
506 static GstStaticCaps src_template_caps =
507 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
508 (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_SRC_FORMATS) ";"
509 GST_VIDEO_CAPS_MAKE (GST_D3D11_SRC_FORMATS));
510
511 enum
512 {
513 PROP_0,
514 PROP_MIXER,
515 /* GstAggregator */
516 PROP_LATENCY,
517 PROP_MIN_UPSTREAM_LATENCY,
518 PROP_START_TIME_SELECTION,
519 PROP_START_TIME,
520 PROP_EMIT_SIGNALS,
521 /* GstD3D11Compositor */
522 PROP_ADAPTER,
523 PROP_BACKGROUND,
524 PROP_LAST
525 };
526
527 /* GstAggregator */
528 #define DEFAULT_LATENCY 0
529 #define DEFAULT_MIN_UPSTREAM_LATENCY 0
530 #define DEFAULT_START_TIME_SELECTION GST_AGGREGATOR_START_TIME_SELECTION_ZERO
531 #define DEFAULT_START_TIME (-1)
532 #define DEFAULT_EMIT_SIGNALS FALSE
533
534 /* GstD3D11Compositor */
535 #define DEFAULT_ADAPTER -1
536 #define DEFAULT_BACKGROUND GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER
537
538 typedef struct _GstD3D11CompositorBinChain
539 {
540 /* without ref */
541 GstD3D11CompositorBin *self;
542 GstD3D11CompositorBinPad *ghost_pad;
543 GstElement *upload;
544 GstElement *convert;
545
546 gulong probe_id;
547 } GstD3D11CompositorBinChain;
548
549 struct _GstD3D11CompositorBin
550 {
551 GstBin parent;
552
553 GstElement *compositor;
554
555 GList *input_chains;
556 gboolean running;
557
558 gint adapter;
559 };
560
561 static void gst_d3d11_compositor_bin_child_proxy_init (gpointer g_iface,
562 gpointer iface_data);
563 static void gst_d3d11_compositor_bin_dispose (GObject * object);
564 static void gst_d3d11_compositor_bin_set_property (GObject * object,
565 guint prop_id, const GValue * value, GParamSpec * pspec);
566 static void gst_d3d11_compositor_bin_get_property (GObject * object,
567 guint prop_id, GValue * value, GParamSpec * pspec);
568
569 static GstStateChangeReturn
570 gst_d3d11_compositor_bin_change_state (GstElement * element,
571 GstStateChange transition);
572 static GstPad *gst_d3d11_compositor_bin_request_new_pad (GstElement * element,
573 GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
574 static void gst_d3d11_compositor_bin_release_pad (GstElement * element,
575 GstPad * pad);
576
577 #define gst_d3d11_compositor_bin_parent_class parent_class
578 G_DEFINE_TYPE_WITH_CODE (GstD3D11CompositorBin, gst_d3d11_compositor_bin,
579 GST_TYPE_BIN, G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY,
580 gst_d3d11_compositor_bin_child_proxy_init));
581
582 static void
gst_d3d11_compositor_bin_class_init(GstD3D11CompositorBinClass * klass)583 gst_d3d11_compositor_bin_class_init (GstD3D11CompositorBinClass * klass)
584 {
585 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
586 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
587 GstCaps *caps;
588
589 gobject_class->dispose = gst_d3d11_compositor_bin_dispose;
590 gobject_class->set_property = gst_d3d11_compositor_bin_set_property;
591 gobject_class->get_property = gst_d3d11_compositor_bin_get_property;
592
593 element_class->change_state =
594 GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_change_state);
595 element_class->request_new_pad =
596 GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_request_new_pad);
597 element_class->release_pad =
598 GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_release_pad);
599
600 gst_element_class_set_static_metadata (element_class,
601 "Direct3D11 Compositor Bin",
602 "Filter/Editor/Video/Compositor",
603 "A Direct3D11 compositor bin", "Seungha Yang <seungha@centricular.com>");
604
605 caps = gst_d3d11_get_updated_template_caps (&sink_template_caps);
606 gst_element_class_add_pad_template (element_class,
607 gst_pad_template_new_with_gtype ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST,
608 caps, GST_TYPE_D3D11_COMPOSITOR_BIN_INPUT));
609 gst_caps_unref (caps);
610
611 caps = gst_d3d11_get_updated_template_caps (&src_template_caps);
612 gst_element_class_add_pad_template (element_class,
613 gst_pad_template_new_with_gtype ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
614 caps, GST_TYPE_D3D11_COMPOSITOR_BIN_PAD));
615 gst_caps_unref (caps);
616
617 g_object_class_install_property (gobject_class, PROP_MIXER,
618 g_param_spec_object ("mixer", "D3D11 mixer element",
619 "The d3d11 mixer chain to use",
620 GST_TYPE_ELEMENT,
621 (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
622
623 /*GstAggregator */
624 g_object_class_install_property (gobject_class, PROP_LATENCY,
625 g_param_spec_uint64 ("latency", "Buffer latency",
626 "Additional latency in live mode to allow upstream "
627 "to take longer to produce buffers for the current "
628 "position (in nanoseconds)", 0, G_MAXUINT64,
629 DEFAULT_LATENCY,
630 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
631
632 g_object_class_install_property (gobject_class, PROP_MIN_UPSTREAM_LATENCY,
633 g_param_spec_uint64 ("min-upstream-latency", "Buffer latency",
634 "When sources with a higher latency are expected to be plugged "
635 "in dynamically after the aggregator has started playing, "
636 "this allows overriding the minimum latency reported by the "
637 "initial source(s). This is only taken into account when larger "
638 "than the actually reported minimum latency. (nanoseconds)",
639 0, G_MAXUINT64,
640 DEFAULT_LATENCY,
641 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
642
643 g_object_class_install_property (gobject_class, PROP_START_TIME_SELECTION,
644 g_param_spec_enum ("start-time-selection", "Start Time Selection",
645 "Decides which start time is output",
646 gst_aggregator_start_time_selection_get_type (),
647 DEFAULT_START_TIME_SELECTION,
648 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
649
650 g_object_class_install_property (gobject_class, PROP_START_TIME,
651 g_param_spec_uint64 ("start-time", "Start Time",
652 "Start time to use if start-time-selection=set", 0,
653 G_MAXUINT64,
654 DEFAULT_START_TIME,
655 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
656
657 g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
658 g_param_spec_boolean ("emit-signals", "Emit signals",
659 "Send signals", DEFAULT_EMIT_SIGNALS,
660 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
661
662 /* GstD3D11Compositor */
663 g_object_class_install_property (gobject_class, PROP_ADAPTER,
664 g_param_spec_int ("adapter", "Adapter",
665 "Adapter index for creating device (-1 for default)",
666 -1, G_MAXINT32, DEFAULT_ADAPTER,
667 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY |
668 G_PARAM_STATIC_STRINGS)));
669
670 g_object_class_install_property (gobject_class, PROP_BACKGROUND,
671 g_param_spec_enum ("background", "Background", "Background type",
672 GST_TYPE_D3D11_COMPOSITOR_BACKGROUND,
673 DEFAULT_BACKGROUND,
674 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
675
676 gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_BIN_PAD,
677 (GstPluginAPIFlags) 0);
678 gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_BIN_INPUT,
679 (GstPluginAPIFlags) 0);
680 }
681
682 static void
gst_d3d11_compositor_bin_init(GstD3D11CompositorBin * self)683 gst_d3d11_compositor_bin_init (GstD3D11CompositorBin * self)
684 {
685 GstPad *pad;
686 GstPad *gpad;
687 GstElement *out_convert, *download;
688
689 self->compositor = gst_element_factory_make ("d3d11compositorelement", NULL);
690 out_convert = gst_element_factory_make ("d3d11colorconvert", NULL);
691 download = gst_element_factory_make ("d3d11download", NULL);
692
693 gst_bin_add_many (GST_BIN (self),
694 self->compositor, out_convert, download, NULL);
695 gst_element_link_many (self->compositor, out_convert, download, NULL);
696
697 gpad = (GstPad *) g_object_new (GST_TYPE_D3D11_COMPOSITOR_BIN_PAD,
698 "name", "src", "direction", GST_PAD_SRC, NULL);
699 pad = gst_element_get_static_pad (self->compositor, "src");
700 /* GstD3D11CompositorBinPad will hold reference of this compositor srcpad */
701 gst_d3d11_compositor_bin_pad_set_target ((GstD3D11CompositorBinPad *) gpad,
702 pad);
703
704 pad = gst_element_get_static_pad (download, "src");
705 gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (gpad), pad);
706 gst_object_unref (pad);
707
708 gst_element_add_pad (GST_ELEMENT_CAST (self), gpad);
709 }
710
711 static void
gst_d3d11_compositor_bin_dispose(GObject * object)712 gst_d3d11_compositor_bin_dispose (GObject * object)
713 {
714 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (object);
715 GList *iter;
716
717 for (iter = self->input_chains; iter; iter = g_list_next (iter)) {
718 GstD3D11CompositorBinChain *chain =
719 (GstD3D11CompositorBinChain *) iter->data;
720
721 if (self->compositor && chain->ghost_pad && chain->ghost_pad->target) {
722 gst_element_release_request_pad (GST_ELEMENT_CAST (self->compositor),
723 chain->ghost_pad->target);
724 gst_d3d11_compositor_bin_pad_unset_target (chain->ghost_pad);
725 }
726 }
727
728 if (self->input_chains)
729 g_list_free_full (self->input_chains, (GDestroyNotify) g_free);
730 self->input_chains = NULL;
731
732 G_OBJECT_CLASS (parent_class)->dispose (object);
733 }
734
735 static void
gst_d3d11_compositor_bin_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)736 gst_d3d11_compositor_bin_set_property (GObject * object,
737 guint prop_id, const GValue * value, GParamSpec * pspec)
738 {
739 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (object);
740
741 switch (prop_id) {
742 case PROP_ADAPTER:
743 self->adapter = g_value_get_int (value);
744 /* fallthrough */
745 default:
746 g_object_set_property (G_OBJECT (self->compositor), pspec->name, value);
747 break;
748 }
749 }
750
751 static void
gst_d3d11_compositor_bin_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)752 gst_d3d11_compositor_bin_get_property (GObject * object,
753 guint prop_id, GValue * value, GParamSpec * pspec)
754 {
755 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (object);
756
757 switch (prop_id) {
758 case PROP_MIXER:
759 g_value_set_object (value, self->compositor);
760 break;
761 case PROP_ADAPTER:
762 g_value_set_int (value, self->adapter);
763 break;
764 default:
765 g_object_get_property (G_OBJECT (self->compositor), pspec->name, value);
766 break;
767 }
768 }
769
770 static GstStateChangeReturn
gst_d3d11_compositor_bin_change_state(GstElement * element,GstStateChange transition)771 gst_d3d11_compositor_bin_change_state (GstElement * element,
772 GstStateChange transition)
773 {
774 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (element);
775 GstStateChangeReturn ret;
776
777 switch (transition) {
778 case GST_STATE_CHANGE_NULL_TO_READY:
779 GST_OBJECT_LOCK (element);
780 self->running = TRUE;
781 GST_OBJECT_UNLOCK (element);
782 break;
783 default:
784 break;
785 }
786
787 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
788 if (ret == GST_STATE_CHANGE_FAILURE)
789 return ret;
790
791 switch (transition) {
792 case GST_STATE_CHANGE_READY_TO_NULL:
793 GST_OBJECT_LOCK (self);
794 self->running = FALSE;
795 GST_OBJECT_UNLOCK (self);
796 default:
797 break;
798 }
799
800 return ret;
801 }
802
803 static GstD3D11CompositorBinChain *
gst_d3d11_compositor_bin_input_chain_new(GstD3D11CompositorBin * self,GstPad * compositor_pad)804 gst_d3d11_compositor_bin_input_chain_new (GstD3D11CompositorBin * self,
805 GstPad * compositor_pad)
806 {
807 GstD3D11CompositorBinChain *chain;
808 GstPad *pad;
809
810 chain = g_new0 (GstD3D11CompositorBinChain, 1);
811
812 chain->self = self;
813
814 chain->upload = gst_element_factory_make ("d3d11upload", NULL);
815 chain->convert = gst_element_factory_make ("d3d11colorconvert", NULL);
816
817 /* 1. Create child elements and like */
818 gst_bin_add_many (GST_BIN (self), chain->upload, chain->convert, NULL);
819
820 gst_element_link (chain->upload, chain->convert);
821 pad = gst_element_get_static_pad (chain->convert, "src");
822 gst_pad_link (pad, compositor_pad);
823 gst_object_unref (pad);
824
825 chain->ghost_pad = (GstD3D11CompositorBinPad *)
826 g_object_new (GST_TYPE_D3D11_COMPOSITOR_BIN_INPUT, "name",
827 GST_OBJECT_NAME (compositor_pad), "direction", GST_PAD_SINK, NULL);
828
829 /* transfer ownership of compositor pad */
830 gst_d3d11_compositor_bin_pad_set_target (chain->ghost_pad, compositor_pad);
831
832 pad = gst_element_get_static_pad (chain->upload, "sink");
833 gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->ghost_pad), pad);
834 gst_object_unref (pad);
835
836 GST_OBJECT_LOCK (self);
837 if (self->running)
838 gst_pad_set_active (GST_PAD (chain->ghost_pad), TRUE);
839 GST_OBJECT_UNLOCK (self);
840
841 gst_element_add_pad (GST_ELEMENT_CAST (self),
842 GST_PAD_CAST (chain->ghost_pad));
843
844 gst_element_sync_state_with_parent (chain->upload);
845 gst_element_sync_state_with_parent (chain->convert);
846
847 return chain;
848 }
849
850 static void
gst_d3d11_compositor_bin_input_chain_free(GstD3D11CompositorBinChain * chain)851 gst_d3d11_compositor_bin_input_chain_free (GstD3D11CompositorBinChain * chain)
852 {
853 if (!chain)
854 return;
855
856 if (chain->ghost_pad && chain->probe_id) {
857 gst_pad_remove_probe (GST_PAD_CAST (chain->ghost_pad), chain->probe_id);
858 chain->probe_id = 0;
859 }
860
861 if (chain->upload) {
862 gst_element_set_state (chain->upload, GST_STATE_NULL);
863 gst_bin_remove (GST_BIN_CAST (chain->self), chain->upload);
864 }
865
866 if (chain->convert) {
867 gst_element_set_state (chain->convert, GST_STATE_NULL);
868 gst_bin_remove (GST_BIN_CAST (chain->self), chain->convert);
869 }
870
871 if (chain->ghost_pad && chain->ghost_pad->target) {
872 gst_element_release_request_pad (chain->self->compositor,
873 chain->ghost_pad->target);
874 gst_d3d11_compositor_bin_pad_unset_target (chain->ghost_pad);
875 }
876
877 g_free (chain);
878 }
879
880 static GstPad *
gst_d3d11_compositor_bin_request_new_pad(GstElement * element,GstPadTemplate * templ,const gchar * name,const GstCaps * caps)881 gst_d3d11_compositor_bin_request_new_pad (GstElement * element,
882 GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
883 {
884 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (element);
885 GstElementClass *compositor_class = GST_ELEMENT_GET_CLASS (self->compositor);
886 GstPad *compositor_pad;
887 GstD3D11CompositorBinChain *chain;
888 GstPadTemplate *compositor_templ = NULL;
889 GList *templ_list;
890 GList *iter;
891
892 templ_list = gst_element_class_get_pad_template_list (compositor_class);
893 for (iter = templ_list; iter; iter = g_list_next (iter)) {
894 GstPadTemplate *t = (GstPadTemplate *) iter->data;
895 if (GST_PAD_TEMPLATE_DIRECTION (t) != GST_PAD_SINK ||
896 GST_PAD_TEMPLATE_PRESENCE (t) != GST_PAD_REQUEST)
897 continue;
898
899 compositor_templ = t;
900 break;
901 }
902
903 g_assert (compositor_templ);
904
905 compositor_pad =
906 gst_element_request_pad (self->compositor, compositor_templ, name, caps);
907 if (!compositor_pad) {
908 GST_WARNING_OBJECT (self, "Failed to request pad");
909 return NULL;
910 }
911
912 chain = gst_d3d11_compositor_bin_input_chain_new (self, compositor_pad);
913 g_assert (chain);
914
915 GST_OBJECT_LOCK (self);
916 self->input_chains = g_list_append (self->input_chains, chain);
917 GST_OBJECT_UNLOCK (self);
918
919 gst_child_proxy_child_added (GST_CHILD_PROXY (self),
920 G_OBJECT (chain->ghost_pad), GST_OBJECT_NAME (chain->ghost_pad));
921
922 GST_DEBUG_OBJECT (element, "Created new pad %s:%s",
923 GST_DEBUG_PAD_NAME (chain->ghost_pad));
924
925 return GST_PAD_CAST (chain->ghost_pad);
926 }
927
928 static void
gst_d3d11_compositor_bin_release_pad(GstElement * element,GstPad * pad)929 gst_d3d11_compositor_bin_release_pad (GstElement * element, GstPad * pad)
930 {
931 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (element);
932 GList *iter;
933 gboolean found = FALSE;
934
935 GST_DEBUG_OBJECT (self, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
936
937 GST_OBJECT_LOCK (self);
938 for (iter = self->input_chains; iter; iter = g_list_next (iter)) {
939 GstD3D11CompositorBinChain *chain =
940 (GstD3D11CompositorBinChain *) iter->data;
941
942 if (pad == GST_PAD_CAST (chain->ghost_pad)) {
943 self->input_chains = g_list_delete_link (self->input_chains, iter);
944 GST_OBJECT_UNLOCK (self);
945
946 gst_d3d11_compositor_bin_input_chain_free (chain);
947 found = TRUE;
948 break;
949 }
950 }
951
952 if (!found) {
953 GST_OBJECT_UNLOCK (self);
954 GST_WARNING_OBJECT (self, "Unknown pad to release %s:%s",
955 GST_DEBUG_PAD_NAME (pad));
956 }
957
958 gst_element_remove_pad (element, pad);
959 }
960
961 static GObject *
gst_d3d11_compositor_bin_child_proxy_get_child_by_index(GstChildProxy * proxy,guint index)962 gst_d3d11_compositor_bin_child_proxy_get_child_by_index (GstChildProxy * proxy,
963 guint index)
964 {
965 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (proxy);
966 GstBin *bin = GST_BIN_CAST (proxy);
967 GObject *res = NULL;
968
969 GST_OBJECT_LOCK (self);
970 /* XXX: not exactly thread safe with ordering */
971 if (index < (guint) bin->numchildren) {
972 if ((res = (GObject *) g_list_nth_data (bin->children, index)))
973 gst_object_ref (res);
974 } else {
975 GstD3D11CompositorBinChain *chain;
976 if ((chain =
977 (GstD3D11CompositorBinChain *) g_list_nth_data (self->input_chains,
978 index - bin->numchildren))) {
979 res = (GObject *) gst_object_ref (chain->ghost_pad);
980 }
981 }
982 GST_OBJECT_UNLOCK (self);
983
984 return res;
985 }
986
987 static guint
gst_d3d11_compositor_bin_child_proxy_get_children_count(GstChildProxy * proxy)988 gst_d3d11_compositor_bin_child_proxy_get_children_count (GstChildProxy * proxy)
989 {
990 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (proxy);
991 guint count = 0;
992
993 GST_OBJECT_LOCK (self);
994 count = GST_BIN_CAST (self)->numchildren + g_list_length (self->input_chains);
995 GST_OBJECT_UNLOCK (self);
996 GST_INFO_OBJECT (self, "Children Count: %d", count);
997
998 return count;
999 }
1000
1001 static void
gst_d3d11_compositor_bin_child_proxy_init(gpointer g_iface,gpointer iface_data)1002 gst_d3d11_compositor_bin_child_proxy_init (gpointer g_iface,
1003 gpointer iface_data)
1004 {
1005 GstChildProxyInterface *iface = (GstChildProxyInterface *) g_iface;
1006
1007 iface->get_child_by_index =
1008 gst_d3d11_compositor_bin_child_proxy_get_child_by_index;
1009 iface->get_children_count =
1010 gst_d3d11_compositor_bin_child_proxy_get_children_count;
1011 }
1012