3 * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
4 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
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.
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.
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.
23 * SECTION:element-d3d11compositor
24 * @title: d3d11compositor
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.
30 * ## Example launch line
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.
45 #include <gst/controller/gstproxycontrolbinding.h>
46 #include "gstd3d11compositorbin.h"
47 #include "gstd3d11compositor.h"
48 #include "gstd3d11pluginutils.h"
50 GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_compositor_debug);
51 #define GST_CAT_DEFAULT gst_d3d11_compositor_debug
53 /****************************
54 * GstD3D11CompositorBinPad *
55 ****************************/
60 /* GstAggregatorPad */
61 PROP_PAD_EMIT_SIGNALS,
64 /* GstAggregatorPad */
65 #define DEFAULT_PAD_EMIT_SIGNALS FALSE
69 /* GstAggregatorPad */
70 SIGNAL_PAD_BUFFER_CONSUMED = 0,
74 static guint gst_d3d11_compositor_bin_pad_signals[SIGNAL_PAD_LAST] = { 0 };
77 * GstD3D11CompositorBinPad:
81 struct _GstD3D11CompositorBinPad
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);
96 gst_d3d11_compositor_bin_pad_set_target_default (GstD3D11CompositorBinPad * pad,
99 G_DEFINE_TYPE (GstD3D11CompositorBinPad, gst_d3d11_compositor_bin_pad,
103 gst_d3d11_compositor_bin_pad_class_init (GstD3D11CompositorBinPadClass * klass)
105 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
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;
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)));
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);
123 GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_pad_set_target_default);
127 gst_d3d11_compositor_bin_pad_init (GstD3D11CompositorBinPad * self)
132 gst_d3d11_compositor_bin_pad_dispose (GObject * object)
134 GstD3D11CompositorBinPad *self = GST_D3D11_COMPOSITOR_BIN_PAD (object);
136 gst_clear_object (&self->target);
138 G_OBJECT_CLASS (gst_d3d11_compositor_bin_pad_parent_class)->dispose (object);
142 gst_d3d11_compositor_bin_pad_set_property (GObject * object,
143 guint prop_id, const GValue * value, GParamSpec * pspec)
145 GstD3D11CompositorBinPad *self = GST_D3D11_COMPOSITOR_BIN_PAD (object);
148 g_object_set_property (G_OBJECT (self->target), pspec->name, value);
152 gst_d3d11_compositor_bin_pad_get_property (GObject * object,
153 guint prop_id, GValue * value, GParamSpec * pspec)
155 GstD3D11CompositorBinPad *self = GST_D3D11_COMPOSITOR_BIN_PAD (object);
158 g_object_get_property (G_OBJECT (self->target), pspec->name, value);
162 gst_d3d11_compositor_bin_pad_on_buffer_consumed (GstAggregatorPad * pad,
163 GstBuffer * buffer, GstD3D11CompositorBinPad * self)
166 gst_d3d11_compositor_bin_pad_signals[SIGNAL_PAD_BUFFER_CONSUMED],
171 * gst_d3d11_compositor_bin_pad_set_target:
172 * @self: a #GstD3D11CompositorBinPad
173 * @target: (transfer full): a #GstAggregatorPad
176 gst_d3d11_compositor_bin_pad_set_target (GstD3D11CompositorBinPad * pad,
179 GstD3D11CompositorBinPadClass *klass =
180 GST_D3D11_COMPOSITOR_BIN_PAD_GET_CLASS (pad);
182 klass->set_target (pad, target);
186 gst_d3d11_compositor_bin_pad_set_target_default (GstD3D11CompositorBinPad * pad,
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);
195 gst_d3d11_compositor_bin_pad_unset_target (GstD3D11CompositorBinPad * self)
201 g_signal_handler_disconnect (self->target, self->sig_id);
203 gst_clear_object (&self->target);
206 /******************************
207 * GstD3D11CompositorBinInput *
208 ******************************/
213 /* GstVideoAggregatorPad */
215 PROP_INPUT_REPEAT_AFTER_EOS,
216 PROP_INPUT_MAX_LAST_BUFFER_REPEAT,
217 /* GstD3D11CompositorPad */
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,
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
255 * GstD3D11CompositorBinInput:
259 struct _GstD3D11CompositorBinInput
261 GstD3D11CompositorBinPad parent;
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);
269 gst_d3d11_compositor_bin_input_set_target (GstD3D11CompositorBinPad * pad,
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);
277 gst_d3d11_compositor_bin_input_class_init (GstD3D11CompositorBinInputClass *
280 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
281 GstD3D11CompositorBinPadClass *pad_class =
282 GST_D3D11_COMPOSITOR_BIN_PAD_CLASS (klass);
284 gobject_class->set_property = gst_d3d11_compositor_bin_input_set_property;
285 gobject_class->get_property = gst_d3d11_compositor_bin_input_get_property;
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)));
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)));
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)));
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)));
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)));
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)));
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)));
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,
338 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
339 G_PARAM_STATIC_STRINGS)));
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)));
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)));
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)));
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)));
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)));
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)));
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\"",
400 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
401 G_PARAM_STATIC_STRINGS)));
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\"",
408 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
409 G_PARAM_STATIC_STRINGS)));
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\"",
416 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
417 G_PARAM_STATIC_STRINGS)));
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\"",
424 (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
425 G_PARAM_STATIC_STRINGS)));
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)));
434 pad_class->set_target =
435 GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_input_set_target);
439 gst_d3d11_compositor_bin_input_init (GstD3D11CompositorBinInput * self)
444 gst_d3d11_compositor_bin_input_set_property (GObject * object,
445 guint prop_id, const GValue * value, GParamSpec * pspec)
447 GstD3D11CompositorBinPad *pad = GST_D3D11_COMPOSITOR_BIN_PAD (object);
450 g_object_set_property (G_OBJECT (pad->target), pspec->name, value);
454 gst_d3d11_compositor_bin_input_get_property (GObject * object,
455 guint prop_id, GValue * value, GParamSpec * pspec)
457 GstD3D11CompositorBinPad *pad = GST_D3D11_COMPOSITOR_BIN_PAD (object);
460 g_object_get_property (G_OBJECT (pad->target), pspec->name, value);
464 gst_d3d11_compositor_bin_input_set_target (GstD3D11CompositorBinPad * pad,
467 GST_D3D11_COMPOSITOR_BIN_PAD_CLASS (input_parent_class)->set_target (pad,
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");
497 /*************************
498 * GstD3D11CompositorBin *
499 *************************/
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));
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));
517 PROP_MIN_UPSTREAM_LATENCY,
518 PROP_START_TIME_SELECTION,
521 /* GstD3D11Compositor */
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
534 /* GstD3D11Compositor */
535 #define DEFAULT_ADAPTER -1
536 #define DEFAULT_BACKGROUND GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER
538 typedef struct _GstD3D11CompositorBinChain
541 GstD3D11CompositorBin *self;
542 GstD3D11CompositorBinPad *ghost_pad;
547 } GstD3D11CompositorBinChain;
549 struct _GstD3D11CompositorBin
553 GstElement *compositor;
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);
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,
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));
583 gst_d3d11_compositor_bin_class_init (GstD3D11CompositorBinClass * klass)
585 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
586 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
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;
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);
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>");
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);
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);
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",
621 (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
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,
630 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
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)",
641 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
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)));
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,
655 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
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)));
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)));
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,
674 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
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);
683 gst_d3d11_compositor_bin_init (GstD3D11CompositorBin * self)
687 GstElement *out_convert, *download;
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);
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);
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,
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);
708 gst_element_add_pad (GST_ELEMENT_CAST (self), gpad);
712 gst_d3d11_compositor_bin_dispose (GObject * object)
714 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (object);
717 for (iter = self->input_chains; iter; iter = g_list_next (iter)) {
718 GstD3D11CompositorBinChain *chain =
719 (GstD3D11CompositorBinChain *) iter->data;
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);
728 if (self->input_chains)
729 g_list_free_full (self->input_chains, (GDestroyNotify) g_free);
730 self->input_chains = NULL;
732 G_OBJECT_CLASS (parent_class)->dispose (object);
736 gst_d3d11_compositor_bin_set_property (GObject * object,
737 guint prop_id, const GValue * value, GParamSpec * pspec)
739 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (object);
743 self->adapter = g_value_get_int (value);
746 g_object_set_property (G_OBJECT (self->compositor), pspec->name, value);
752 gst_d3d11_compositor_bin_get_property (GObject * object,
753 guint prop_id, GValue * value, GParamSpec * pspec)
755 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (object);
759 g_value_set_object (value, self->compositor);
762 g_value_set_int (value, self->adapter);
765 g_object_get_property (G_OBJECT (self->compositor), pspec->name, value);
770 static GstStateChangeReturn
771 gst_d3d11_compositor_bin_change_state (GstElement * element,
772 GstStateChange transition)
774 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (element);
775 GstStateChangeReturn ret;
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);
787 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
788 if (ret == GST_STATE_CHANGE_FAILURE)
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);
803 static GstD3D11CompositorBinChain *
804 gst_d3d11_compositor_bin_input_chain_new (GstD3D11CompositorBin * self,
805 GstPad * compositor_pad)
807 GstD3D11CompositorBinChain *chain;
810 chain = g_new0 (GstD3D11CompositorBinChain, 1);
814 chain->upload = gst_element_factory_make ("d3d11upload", NULL);
815 chain->convert = gst_element_factory_make ("d3d11colorconvert", NULL);
817 /* 1. Create child elements and like */
818 gst_bin_add_many (GST_BIN (self), chain->upload, chain->convert, NULL);
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);
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);
829 /* transfer ownership of compositor pad */
830 gst_d3d11_compositor_bin_pad_set_target (chain->ghost_pad, compositor_pad);
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);
836 GST_OBJECT_LOCK (self);
838 gst_pad_set_active (GST_PAD (chain->ghost_pad), TRUE);
839 GST_OBJECT_UNLOCK (self);
841 gst_element_add_pad (GST_ELEMENT_CAST (self),
842 GST_PAD_CAST (chain->ghost_pad));
844 gst_element_sync_state_with_parent (chain->upload);
845 gst_element_sync_state_with_parent (chain->convert);
851 gst_d3d11_compositor_bin_input_chain_free (GstD3D11CompositorBinChain * chain)
856 if (chain->ghost_pad && chain->probe_id) {
857 gst_pad_remove_probe (GST_PAD_CAST (chain->ghost_pad), chain->probe_id);
862 gst_element_set_state (chain->upload, GST_STATE_NULL);
863 gst_bin_remove (GST_BIN_CAST (chain->self), chain->upload);
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);
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);
881 gst_d3d11_compositor_bin_request_new_pad (GstElement * element,
882 GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
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;
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)
899 compositor_templ = t;
903 g_assert (compositor_templ);
906 gst_element_request_pad (self->compositor, compositor_templ, name, caps);
907 if (!compositor_pad) {
908 GST_WARNING_OBJECT (self, "Failed to request pad");
912 chain = gst_d3d11_compositor_bin_input_chain_new (self, compositor_pad);
915 GST_OBJECT_LOCK (self);
916 self->input_chains = g_list_append (self->input_chains, chain);
917 GST_OBJECT_UNLOCK (self);
919 gst_child_proxy_child_added (GST_CHILD_PROXY (self),
920 G_OBJECT (chain->ghost_pad), GST_OBJECT_NAME (chain->ghost_pad));
922 GST_DEBUG_OBJECT (element, "Created new pad %s:%s",
923 GST_DEBUG_PAD_NAME (chain->ghost_pad));
925 return GST_PAD_CAST (chain->ghost_pad);
929 gst_d3d11_compositor_bin_release_pad (GstElement * element, GstPad * pad)
931 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (element);
933 gboolean found = FALSE;
935 GST_DEBUG_OBJECT (self, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
937 GST_OBJECT_LOCK (self);
938 for (iter = self->input_chains; iter; iter = g_list_next (iter)) {
939 GstD3D11CompositorBinChain *chain =
940 (GstD3D11CompositorBinChain *) iter->data;
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);
946 gst_d3d11_compositor_bin_input_chain_free (chain);
953 GST_OBJECT_UNLOCK (self);
954 GST_WARNING_OBJECT (self, "Unknown pad to release %s:%s",
955 GST_DEBUG_PAD_NAME (pad));
958 gst_element_remove_pad (element, pad);
962 gst_d3d11_compositor_bin_child_proxy_get_child_by_index (GstChildProxy * proxy,
965 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (proxy);
966 GstBin *bin = GST_BIN_CAST (proxy);
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);
975 GstD3D11CompositorBinChain *chain;
977 (GstD3D11CompositorBinChain *) g_list_nth_data (self->input_chains,
978 index - bin->numchildren))) {
979 res = (GObject *) gst_object_ref (chain->ghost_pad);
982 GST_OBJECT_UNLOCK (self);
988 gst_d3d11_compositor_bin_child_proxy_get_children_count (GstChildProxy * proxy)
990 GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (proxy);
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);
1002 gst_d3d11_compositor_bin_child_proxy_init (gpointer g_iface,
1003 gpointer iface_data)
1005 GstChildProxyInterface *iface = (GstChildProxyInterface *) g_iface;
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;