From: Seungha Yang Date: Sat, 18 Jun 2022 11:14:22 +0000 (+0900) Subject: d3d11compositor: Performance optimization X-Git-Tag: 1.22.0~1415 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a0404506850cf7b968ee6c5f08816173e452ad1b;p=platform%2Fupstream%2Fgstreamer.git d3d11compositor: Performance optimization Removing glvideomixer-like nuance (it was initially referenced) and rewriting element since it's not an optimal design at all from performance point of view. * Remove wrapper bin (and internal conversion/upload/download elements) which will waste CPU/GPU resources. Conversion/blending can be done by the d3d11compositor element at once. * Add support YUV blending without RGB conversion. The RGB <-> YUV conversion is completely unnecessary since YUV textures support blending as well. * Remove complicated blending operation properties since it's hard to use from application point of view. Instead, adding "operator" property like what compositor element does. Part-of: --- diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp index 6fcf7ea..0e89ca5 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp @@ -23,11 +23,17 @@ */ /** - * SECTION:element-d3d11compositorelement - * @title: d3d11compositorelement + * SECTION:element-d3d11compositor + * @title: d3d11compositor * * A Direct3D11 based video compositing element. * + * ## Example launch line + * ``` + * gst-launch-1.0 d3d11compositor name=c ! d3d11videosink \ + * videotestsrc ! video/x-raw,width=320,height=240 ! c. \ + * videotestsrc pattern=ball ! video/x-raw,width=100,height=100 ! c. + * * Since: 1.20 * */ @@ -40,283 +46,27 @@ #include "gstd3d11converter.h" #include "gstd3d11shader.h" #include "gstd3d11pluginutils.h" +#include "gstd3d11videoprocessor.h" #include #include -GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_compositor_debug); +GST_DEBUG_CATEGORY_STATIC (gst_d3d11_compositor_debug); #define GST_CAT_DEFAULT gst_d3d11_compositor_debug /* *INDENT-OFF* */ using namespace Microsoft::WRL; /* *INDENT-ON* */ -/** - * GstD3D11CompositorBlendOperation: - * @GST_D3D11_COMPOSITOR_BLEND_OP_ADD: - * Add source 1 and source 2 - * @GST_D3D11_COMPOSITOR_BLEND_OP_SUBTRACT: - * Subtract source 1 from source 2 - * @GST_D3D11_COMPOSITOR_BLEND_OP_REV_SUBTRACT: - * Subtract source 2 from source 1 - * @GST_D3D11_COMPOSITOR_BLEND_OP_MIN: - * Find the minimum of source 1 and source 2 - * @GST_D3D11_COMPOSITOR_BLEND_OP_MAX: - * Find the maximum of source 1 and source 2 - * - * Since: 1.20 - */ -GType -gst_d3d11_compositor_blend_operation_get_type (void) -{ - static GType blend_operation_type = 0; - - static const GEnumValue blend_operator[] = { - {GST_D3D11_COMPOSITOR_BLEND_OP_ADD, "Add source and background", - "add"}, - {GST_D3D11_COMPOSITOR_BLEND_OP_SUBTRACT, - "Subtract source from background", - "subtract"}, - {GST_D3D11_COMPOSITOR_BLEND_OP_REV_SUBTRACT, - "Subtract background from source", - "rev-subtract"}, - {GST_D3D11_COMPOSITOR_BLEND_OP_MIN, - "Minimum of source and background", "min"}, - {GST_D3D11_COMPOSITOR_BLEND_OP_MAX, - "Maximum of source and background", "max"}, - {0, NULL, NULL}, - }; - - if (!blend_operation_type) { - blend_operation_type = - g_enum_register_static ("GstD3D11CompositorBlendOperation", - blend_operator); - } - return blend_operation_type; -} - -static GstD3D11CompositorBlendOperation -gst_d3d11_compositor_blend_operation_from_native (D3D11_BLEND_OP blend_op) -{ - switch (blend_op) { - case D3D11_BLEND_OP_ADD: - return GST_D3D11_COMPOSITOR_BLEND_OP_ADD; - case D3D11_BLEND_OP_SUBTRACT: - return GST_D3D11_COMPOSITOR_BLEND_OP_SUBTRACT; - case D3D11_BLEND_OP_REV_SUBTRACT: - return GST_D3D11_COMPOSITOR_BLEND_OP_REV_SUBTRACT; - case D3D11_BLEND_OP_MIN: - return GST_D3D11_COMPOSITOR_BLEND_OP_MIN; - case D3D11_BLEND_OP_MAX: - return GST_D3D11_COMPOSITOR_BLEND_OP_MAX; - default: - g_assert_not_reached (); - break; - } - - return GST_D3D11_COMPOSITOR_BLEND_OP_ADD; -} - -static D3D11_BLEND_OP -gst_d3d11_compositor_blend_operation_to_native (GstD3D11CompositorBlendOperation - op) +typedef enum { - switch (op) { - case GST_D3D11_COMPOSITOR_BLEND_OP_ADD: - return D3D11_BLEND_OP_ADD; - case GST_D3D11_COMPOSITOR_BLEND_OP_SUBTRACT: - return D3D11_BLEND_OP_SUBTRACT; - case GST_D3D11_COMPOSITOR_BLEND_OP_REV_SUBTRACT: - return D3D11_BLEND_OP_REV_SUBTRACT; - case GST_D3D11_COMPOSITOR_BLEND_OP_MIN: - return D3D11_BLEND_OP_MIN; - case GST_D3D11_COMPOSITOR_BLEND_OP_MAX: - return D3D11_BLEND_OP_MAX; - default: - g_assert_not_reached (); - break; - } - - return D3D11_BLEND_OP_ADD; -} - -/** - * GstD3D11CompositorBlend: - * @GST_D3D11_COMPOSITOR_BLEND_ZERO: - * The blend factor is (0, 0, 0, 0). No pre-blend operation. - * @GST_D3D11_COMPOSITOR_BLEND_ONE: - * The blend factor is (1, 1, 1, 1). No pre-blend operation. - * @GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR: - * The blend factor is (Rs, Gs, Bs, As), - * that is color data (RGB) from a pixel shader. No pre-blend operation. - * @GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR: - * The blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As), - * that is color data (RGB) from a pixel shader. - * The pre-blend operation inverts the data, generating 1 - RGB. - * @GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA: - * The blend factor is (As, As, As, As), - * that is alpha data (A) from a pixel shader. No pre-blend operation. - * @GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA: - * The blend factor is ( 1 - As, 1 - As, 1 - As, 1 - As), - * that is alpha data (A) from a pixel shader. - * The pre-blend operation inverts the data, generating 1 - A. - * @GST_D3D11_COMPOSITOR_BLEND_DEST_ALPHA: - * The blend factor is (Ad, Ad, Ad, Ad), - * that is alpha data from a render target. No pre-blend operation. - * @GST_D3D11_COMPOSITOR_BLEND_INV_DEST_ALPHA: - * The blend factor is (1 - Ad, 1 - Ad, 1 - Ad, 1 - Ad), - * that is alpha data from a render target. - * The pre-blend operation inverts the data, generating 1 - A. - * @GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR: - * The blend factor is (Rd, Gd, Bd, Ad), - * that is color data from a render target. No pre-blend operation. - * @GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR: - * The blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad), - * that is color data from a render target. - * The pre-blend operation inverts the data, generating 1 - RGB. - * @GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA_SAT: - * The blend factor is (f, f, f, 1); where f = min(As, 1 - Ad). - * The pre-blend operation clamps the data to 1 or less. - * @GST_D3D11_COMPOSITOR_BLEND_BLEND_FACTOR: - * The blend factor is the blend factor set with - * ID3D11DeviceContext::OMSetBlendState. No pre-blend operation. - * @GST_D3D11_COMPOSITOR_BLEND_INV_BLEND_FACTOR: - * The blend factor is the blend factor set with - * ID3D11DeviceContext::OMSetBlendState. - * The pre-blend operation inverts the blend factor, - * generating 1 - blend_factor. - * - * Since: 1.20 - */ -GType -gst_d3d11_compositor_blend_get_type (void) -{ - static GType blend_type = 0; - - static const GEnumValue blend[] = { - {GST_D3D11_COMPOSITOR_BLEND_ZERO, - "The blend factor is (0, 0, 0, 0)", "zero"}, - {GST_D3D11_COMPOSITOR_BLEND_ONE, - "The blend factor is (1, 1, 1, 1)", "one"}, - {GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR, - "The blend factor is (Rs, Gs, Bs, As)", "src-color"}, - {GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR, - "The blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As)", - "inv-src-color"}, - {GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA, - "The blend factor is (As, As, As, As)", "src-alpha"}, - {GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA, - "The blend factor is (1 - As, 1 - As, 1 - As, 1 - As)", - "inv-src-alpha"}, - {GST_D3D11_COMPOSITOR_BLEND_DEST_ALPHA, - "The blend factor is (Ad, Ad, Ad, Ad)", "dest-alpha"}, - {GST_D3D11_COMPOSITOR_BLEND_INV_DEST_ALPHA, - "The blend factor is (1 - Ad, 1 - Ad, 1 - Ad, 1 - Ad)", - "inv-dest-alpha"}, - {GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR, - "The blend factor is (Rd, Gd, Bd, Ad)", "dest-color"}, - {GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR, - "The blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad)", - "inv-dest-color"}, - {GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA_SAT, - "The blend factor is (f, f, f, 1); where f = min(As, 1 - Ad)", - "src-alpha-sat"}, - {GST_D3D11_COMPOSITOR_BLEND_BLEND_FACTOR, - "User defined blend factor", "blend-factor"}, - {GST_D3D11_COMPOSITOR_BLEND_INV_BLEND_FACTOR, - "Inverse of user defined blend factor", "inv-blend-factor"}, - {0, NULL, NULL}, - }; - - if (!blend_type) { - blend_type = g_enum_register_static ("GstD3D11CompositorBlend", blend); - } - return blend_type; -} - -static GstD3D11CompositorBlend -gst_d3d11_compositor_blend_from_native (D3D11_BLEND blend) -{ - switch (blend) { - case D3D11_BLEND_ZERO: - return GST_D3D11_COMPOSITOR_BLEND_ZERO; - case D3D11_BLEND_ONE: - return GST_D3D11_COMPOSITOR_BLEND_ONE; - case D3D11_BLEND_SRC_COLOR: - return GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR; - case D3D11_BLEND_INV_SRC_COLOR: - return GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR; - case D3D11_BLEND_SRC_ALPHA: - return GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA; - case D3D11_BLEND_INV_SRC_ALPHA: - return GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA; - case D3D11_BLEND_DEST_ALPHA: - return GST_D3D11_COMPOSITOR_BLEND_DEST_ALPHA; - case D3D11_BLEND_INV_DEST_ALPHA: - return GST_D3D11_COMPOSITOR_BLEND_INV_DEST_ALPHA; - case D3D11_BLEND_DEST_COLOR: - return GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR; - case D3D11_BLEND_INV_DEST_COLOR: - return GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR; - case D3D11_BLEND_SRC_ALPHA_SAT: - return GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA_SAT; - case D3D11_BLEND_BLEND_FACTOR: - return GST_D3D11_COMPOSITOR_BLEND_BLEND_FACTOR; - case D3D11_BLEND_INV_BLEND_FACTOR: - return GST_D3D11_COMPOSITOR_BLEND_INV_BLEND_FACTOR; - default: - g_assert_not_reached (); - break; - } - - return GST_D3D11_COMPOSITOR_BLEND_ZERO; -} - -static D3D11_BLEND -gst_d3d11_compositor_blend_to_native (GstD3D11CompositorBlend blend) -{ - switch (blend) { - case GST_D3D11_COMPOSITOR_BLEND_ZERO: - return D3D11_BLEND_ZERO; - case GST_D3D11_COMPOSITOR_BLEND_ONE: - return D3D11_BLEND_ONE; - case GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR: - return D3D11_BLEND_SRC_COLOR; - case GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR: - return D3D11_BLEND_INV_SRC_COLOR; - case GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA: - return D3D11_BLEND_SRC_ALPHA; - case GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA: - return D3D11_BLEND_INV_SRC_ALPHA; - case GST_D3D11_COMPOSITOR_BLEND_DEST_ALPHA: - return D3D11_BLEND_DEST_ALPHA; - case GST_D3D11_COMPOSITOR_BLEND_INV_DEST_ALPHA: - return D3D11_BLEND_INV_DEST_ALPHA; - case GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR: - return D3D11_BLEND_DEST_COLOR; - case GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR: - return D3D11_BLEND_INV_DEST_COLOR; - case GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA_SAT: - return D3D11_BLEND_SRC_ALPHA_SAT; - case GST_D3D11_COMPOSITOR_BLEND_BLEND_FACTOR: - return D3D11_BLEND_BLEND_FACTOR; - case GST_D3D11_COMPOSITOR_BLEND_INV_BLEND_FACTOR: - return D3D11_BLEND_INV_BLEND_FACTOR; - default: - g_assert_not_reached (); - break; - } - - return D3D11_BLEND_ZERO; -} - -/** - * GstD3D11CompositorBackground: - * - * Background mode - * - * Since: 1.20 - */ -GType + GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER, + GST_D3D11_COMPOSITOR_BACKGROUND_BLACK, + GST_D3D11_COMPOSITOR_BACKGROUND_WHITE, + GST_D3D11_COMPOSITOR_BACKGROUND_TRANSPARENT, +} GstD3D11CompositorBackground; + +#define GST_TYPE_D3D11_COMPOSITOR_BACKGROUND (gst_d3d11_compositor_background_get_type()) +static GType gst_d3d11_compositor_background_get_type (void) { static GType compositor_background_type = 0; @@ -327,7 +77,7 @@ gst_d3d11_compositor_background_get_type (void) {GST_D3D11_COMPOSITOR_BACKGROUND_WHITE, "White", "white"}, {GST_D3D11_COMPOSITOR_BACKGROUND_TRANSPARENT, "Transparent Background to enable further compositing", "transparent"}, - {0, NULL, NULL}, + {0, nullptr, nullptr}, }; if (!compositor_background_type) { @@ -338,14 +88,40 @@ gst_d3d11_compositor_background_get_type (void) return compositor_background_type; } -/** - * GstD3D11CompositorSizingPolicy: - * - * Sizing policy - * - * Since: 1.20 - */ -GType +typedef enum +{ + GST_D3D11_COMPOSITOR_OPERATOR_SOURCE, + GST_D3D11_COMPOSITOR_OPERATOR_OVER, +} GstD3D11CompositorOperator; + +#define GST_TYPE_D3D11_COMPOSITOR_OPERATOR (gst_d3d11_compositor_operator_get_type()) +static GType +gst_d3d11_compositor_operator_get_type (void) +{ + static GType compositor_operator_type = 0; + + static const GEnumValue compositor_operator[] = { + {GST_D3D11_COMPOSITOR_OPERATOR_SOURCE, "Source", "source"}, + {GST_D3D11_COMPOSITOR_OPERATOR_OVER, "Over", "over"}, + {0, nullptr, nullptr}, + }; + + if (!compositor_operator_type) { + compositor_operator_type = + g_enum_register_static ("GstD3D11CompositorOperator", + compositor_operator); + } + return compositor_operator_type; +} + +typedef enum +{ + GST_D3D11_COMPOSITOR_SIZING_POLICY_NONE, + GST_D3D11_COMPOSITOR_SIZING_POLICY_KEEP_ASPECT_RATIO, +} GstD3D11CompositorSizingPolicy; + +#define GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY (gst_d3d11_compositor_sizing_policy_get_type()) +static GType gst_d3d11_compositor_sizing_policy_get_type (void) { static GType sizing_policy_type = 0; @@ -360,7 +136,7 @@ gst_d3d11_compositor_sizing_policy_get_type (void) "with preserved aspect ratio. Resulting image will be centered in " "the destination rectangle with padding if necessary", "keep-aspect-ratio"}, - {0, NULL, NULL}, + {0, nullptr, nullptr}, }; if (!sizing_policy_type) { @@ -388,7 +164,7 @@ static const gchar checker_vs_src[] = " return input;\n" "}\n"; -static const gchar checker_ps_src[] = +static const gchar checker_ps_src_rgb[] = "static const float blocksize = 8.0;\n" "static const float4 high = float4(0.667, 0.667, 0.667, 1.0);\n" "static const float4 low = float4(0.333, 0.333, 0.333, 1.0);\n" @@ -416,20 +192,90 @@ static const gchar checker_ps_src[] = " }\n" " return output;\n" "}\n"; + +static const gchar checker_ps_src_vuya[] = + "static const float blocksize = 8.0;\n" + "static const float4 high = float4(0.5, 0.5, 0.667, 1.0);\n" + "static const float4 low = float4(0.5, 0.5, 0.333, 1.0);\n" + "struct PS_INPUT\n" + "{\n" + " float4 Position: SV_POSITION;\n" + "};\n" + "struct PS_OUTPUT\n" + "{\n" + " float4 Plane: SV_TARGET;\n" + "};\n" + "PS_OUTPUT main(PS_INPUT input)\n" + "{\n" + " PS_OUTPUT output;\n" + " if ((input.Position.x % (blocksize * 2.0)) >= blocksize) {\n" + " if ((input.Position.y % (blocksize * 2.0)) >= blocksize)\n" + " output.Plane = low;\n" + " else\n" + " output.Plane = high;\n" + " } else {\n" + " if ((input.Position.y % (blocksize * 2.0)) < blocksize)\n" + " output.Plane = low;\n" + " else\n" + " output.Plane = high;\n" + " }\n" + " return output;\n" + "}\n"; + +static const gchar checker_ps_src_luma[] = + "static const float blocksize = 8.0;\n" + "static const float4 high = float4(0.667, 0.0, 0.0, 1.0);\n" + "static const float4 low = float4(0.333, 0.0, 0.0, 1.0);\n" + "struct PS_INPUT\n" + "{\n" + " float4 Position: SV_POSITION;\n" + "};\n" + "struct PS_OUTPUT\n" + "{\n" + " float4 Plane: SV_TARGET;\n" + "};\n" + "PS_OUTPUT main(PS_INPUT input)\n" + "{\n" + " PS_OUTPUT output;\n" + " if ((input.Position.x % (blocksize * 2.0)) >= blocksize) {\n" + " if ((input.Position.y % (blocksize * 2.0)) >= blocksize)\n" + " output.Plane = low;\n" + " else\n" + " output.Plane = high;\n" + " } else {\n" + " if ((input.Position.y % (blocksize * 2.0)) < blocksize)\n" + " output.Plane = low;\n" + " else\n" + " output.Plane = high;\n" + " }\n" + " return output;\n" + "}\n"; + +static D3D11_RENDER_TARGET_BLEND_DESC blend_templ[] = { + /* SOURCE */ + { + TRUE, + D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, + D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, + D3D11_COLOR_WRITE_ENABLE_ALL + }, + /* OVER */ + { + TRUE, + D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, + D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, + D3D11_COLOR_WRITE_ENABLE_ALL, + }, +}; /* *INDENT-ON* */ -/** - * GstD3D11CompositorPad: - * - * Since: 1.20 - */ struct _GstD3D11CompositorPad { GstVideoAggregatorConvertPad parent; GstD3D11Converter *convert; + GstD3D11VideoProcessor *processor; - GstBufferPool *fallback_pool; GstBuffer *fallback_buf; gboolean position_updated; @@ -437,14 +283,22 @@ struct _GstD3D11CompositorPad gboolean blend_desc_updated; ID3D11BlendState *blend; + D3D11_RENDER_TARGET_BLEND_DESC desc; + + /* per frame update */ + ID3D11VideoProcessorInputView *piv; + + /* rectangle for video processor */ + RECT src_rect; + RECT dest_rect; + /* properties */ gint xpos; gint ypos; gint width; gint height; gdouble alpha; - D3D11_RENDER_TARGET_BLEND_DESC desc; - gfloat blend_factor[4]; + GstD3D11CompositorOperator op; GstD3D11CompositorSizingPolicy sizing_policy; }; @@ -458,18 +312,25 @@ typedef struct D3D11_VIEWPORT viewport; } GstD3D11CompositorQuad; +typedef struct +{ + /* [rtv][colors] */ + FLOAT color[4][4]; +} GstD3D11CompositorClearColor; + struct _GstD3D11Compositor { GstVideoAggregator parent; GstD3D11Device *device; - GstBufferPool *fallback_pool; GstBuffer *fallback_buf; GstD3D11CompositorQuad *checker_background; + /* black/white/transparent */ + GstD3D11CompositorClearColor clear_color[3]; - gboolean reconfigured; + gboolean downstream_supports_d3d11; /* properties */ gint adapter; @@ -484,16 +345,7 @@ enum PROP_PAD_WIDTH, PROP_PAD_HEIGHT, PROP_PAD_ALPHA, - PROP_PAD_BLEND_OP_RGB, - PROP_PAD_BLEND_OP_ALPHA, - PROP_PAD_BLEND_SRC_RGB, - PROP_PAD_BLEND_SRC_ALPHA, - PROP_PAD_BLEND_DEST_RGB, - PROP_PAD_BLEND_DEST_ALPHA, - PROP_PAD_BLEND_FACTOR_RED, - PROP_PAD_BLEND_FACTOR_GREEN, - PROP_PAD_BLEND_FACTOR_BLUE, - PROP_PAD_BLEND_FACTOR_ALPHA, + PROP_PAD_OPERATOR, PROP_PAD_SIZING_POLICY, }; @@ -502,12 +354,7 @@ enum #define DEFAULT_PAD_WIDTH 0 #define DEFAULT_PAD_HEIGHT 0 #define DEFAULT_PAD_ALPHA 1.0 -#define DEFAULT_PAD_BLEND_OP_RGB GST_D3D11_COMPOSITOR_BLEND_OP_ADD -#define DEFAULT_PAD_BLEND_OP_ALPHA GST_D3D11_COMPOSITOR_BLEND_OP_ADD -#define DEFAULT_PAD_BLEND_SRC_RGB GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA -#define DEFAULT_PAD_BLEND_SRC_ALPHA GST_D3D11_COMPOSITOR_BLEND_ONE -#define DEFAULT_PAD_BLEND_DEST_RGB GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA -#define DEFAULT_PAD_BLEND_DEST_ALPHA GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA +#define DEFAULT_PAD_OPERATOR GST_D3D11_COMPOSITOR_OPERATOR_OVER #define DEFAULT_PAD_SIZING_POLICY GST_D3D11_COMPOSITOR_SIZING_POLICY_NONE static void gst_d3d11_compositor_pad_set_property (GObject * object, @@ -518,11 +365,6 @@ static gboolean gst_d3d11_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad, GstVideoAggregator * vagg, GstBuffer * buffer, GstVideoFrame * prepared_frame); -static void -gst_d3d11_compositor_pad_clean_frame (GstVideoAggregatorPad * pad, - GstVideoAggregator * vagg, GstVideoFrame * prepared_frame); -static void -gst_d3d11_compositor_pad_init_blend_options (GstD3D11CompositorPad * pad); #define gst_d3d11_compositor_pad_parent_class parent_pad_class G_DEFINE_TYPE (GstD3D11CompositorPad, gst_d3d11_compositor_pad, @@ -531,144 +373,45 @@ G_DEFINE_TYPE (GstD3D11CompositorPad, gst_d3d11_compositor_pad, static void gst_d3d11_compositor_pad_class_init (GstD3D11CompositorPadClass * klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstVideoAggregatorPadClass *vaggpadclass = + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstVideoAggregatorPadClass *vagg_pad_class = GST_VIDEO_AGGREGATOR_PAD_CLASS (klass); + GParamFlags param_flags = (GParamFlags) + (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS); - gobject_class->set_property = gst_d3d11_compositor_pad_set_property; - gobject_class->get_property = gst_d3d11_compositor_pad_get_property; + object_class->set_property = gst_d3d11_compositor_pad_set_property; + object_class->get_property = gst_d3d11_compositor_pad_get_property; - g_object_class_install_property (gobject_class, PROP_PAD_XPOS, + g_object_class_install_property (object_class, PROP_PAD_XPOS, g_param_spec_int ("xpos", "X Position", "X position of the picture", - G_MININT, G_MAXINT, DEFAULT_PAD_XPOS, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_YPOS, + G_MININT, G_MAXINT, DEFAULT_PAD_XPOS, param_flags)); + g_object_class_install_property (object_class, PROP_PAD_YPOS, g_param_spec_int ("ypos", "Y Position", "Y position of the picture", - G_MININT, G_MAXINT, DEFAULT_PAD_YPOS, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_WIDTH, + G_MININT, G_MAXINT, DEFAULT_PAD_YPOS, param_flags)); + g_object_class_install_property (object_class, PROP_PAD_WIDTH, g_param_spec_int ("width", "Width", "Width of the picture", - G_MININT, G_MAXINT, DEFAULT_PAD_WIDTH, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_HEIGHT, + G_MININT, G_MAXINT, DEFAULT_PAD_WIDTH, param_flags)); + g_object_class_install_property (object_class, PROP_PAD_HEIGHT, g_param_spec_int ("height", "Height", "Height of the picture", - G_MININT, G_MAXINT, DEFAULT_PAD_HEIGHT, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_ALPHA, + G_MININT, G_MAXINT, DEFAULT_PAD_HEIGHT, param_flags)); + g_object_class_install_property (object_class, PROP_PAD_ALPHA, g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0, - DEFAULT_PAD_ALPHA, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_BLEND_OP_RGB, - g_param_spec_enum ("blend-op-rgb", "Blend Operation RGB", - "Blend equation for RGB", GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION, - DEFAULT_PAD_BLEND_OP_RGB, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_BLEND_OP_ALPHA, - g_param_spec_enum ("blend-op-alpha", "Blend Operation Alpha", - "Blend equation for alpha", GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION, - DEFAULT_PAD_BLEND_OP_ALPHA, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, - PROP_PAD_BLEND_SRC_RGB, - g_param_spec_enum ("blend-src-rgb", "Blend Source RGB", - "Blend factor for source RGB", - GST_TYPE_D3D11_COMPOSITOR_BLEND, - DEFAULT_PAD_BLEND_SRC_RGB, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, - PROP_PAD_BLEND_SRC_ALPHA, - g_param_spec_enum ("blend-src-alpha", - "Blend Source Alpha", - "Blend factor for source alpha, \"*-color\" values are not allowed", - GST_TYPE_D3D11_COMPOSITOR_BLEND, - DEFAULT_PAD_BLEND_SRC_ALPHA, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, - PROP_PAD_BLEND_DEST_RGB, - g_param_spec_enum ("blend-dest-rgb", - "Blend Destination RGB", - "Blend factor for destination RGB", - GST_TYPE_D3D11_COMPOSITOR_BLEND, - DEFAULT_PAD_BLEND_DEST_RGB, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, - PROP_PAD_BLEND_DEST_ALPHA, - g_param_spec_enum ("blend-dest-alpha", - "Blend Destination Alpha", - "Blend factor for destination alpha, " - "\"*-color\" values are not allowed", - GST_TYPE_D3D11_COMPOSITOR_BLEND, - DEFAULT_PAD_BLEND_DEST_ALPHA, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_BLEND_FACTOR_RED, - g_param_spec_float ("blend-factor-red", "Blend Factor Red", - "Blend factor for red component " - "when blend type is \"blend-factor\" or \"inv-blend-factor\"", - 0.0, 1.0, 1.0, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_BLEND_FACTOR_GREEN, - g_param_spec_float ("blend-factor-green", "Blend Factor Green", - "Blend factor for green component " - "when blend type is \"blend-factor\" or \"inv-blend-factor\"", - 0.0, 1.0, 1.0, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_BLEND_FACTOR_BLUE, - g_param_spec_float ("blend-factor-blue", "Blend Factor Blue", - "Blend factor for blue component " - "when blend type is \"blend-factor\" or \"inv-blend-factor\"", - 0.0, 1.0, 1.0, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_BLEND_FACTOR_ALPHA, - g_param_spec_float ("blend-factor-alpha", "Blend Factor Alpha", - "Blend factor for alpha component " - "when blend type is \"blend-factor\" or \"inv-blend-factor\"", - 0.0, 1.0, 1.0, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_PAD_SIZING_POLICY, + DEFAULT_PAD_ALPHA, param_flags)); + g_object_class_install_property (object_class, PROP_PAD_OPERATOR, + g_param_spec_enum ("operator", "Operator", + "Blending operator to use for blending this pad over the previous ones", + GST_TYPE_D3D11_COMPOSITOR_OPERATOR, DEFAULT_PAD_OPERATOR, + param_flags)); + g_object_class_install_property (object_class, PROP_PAD_SIZING_POLICY, g_param_spec_enum ("sizing-policy", "Sizing policy", "Sizing policy to use for image scaling", GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY, DEFAULT_PAD_SIZING_POLICY, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); + param_flags)); - vaggpadclass->prepare_frame = + vagg_pad_class->prepare_frame = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_pad_prepare_frame); - vaggpadclass->clean_frame = - GST_DEBUG_FUNCPTR (gst_d3d11_compositor_pad_clean_frame); - gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_BLEND, - (GstPluginAPIFlags) 0); - gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION, + gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_OPERATOR, (GstPluginAPIFlags) 0); gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY, (GstPluginAPIFlags) 0); @@ -682,36 +425,21 @@ gst_d3d11_compositor_pad_init (GstD3D11CompositorPad * pad) pad->width = DEFAULT_PAD_WIDTH; pad->height = DEFAULT_PAD_HEIGHT; pad->alpha = DEFAULT_PAD_ALPHA; + pad->op = DEFAULT_PAD_OPERATOR; pad->sizing_policy = DEFAULT_PAD_SIZING_POLICY; - - gst_d3d11_compositor_pad_init_blend_options (pad); + pad->desc = blend_templ[DEFAULT_PAD_OPERATOR]; } static void -gst_d3d11_compositor_pad_update_blend_function (GstD3D11CompositorPad * pad, - D3D11_BLEND * value, GstD3D11CompositorBlend new_value) +gst_d3d11_compositor_pad_update_position (GstD3D11CompositorPad * self, + gint * old, const GValue * value) { - D3D11_BLEND temp = gst_d3d11_compositor_blend_to_native (new_value); - - if (temp == *value) - return; - - *value = temp; - pad->blend_desc_updated = TRUE; -} - -static void -gst_d3d11_compositor_pad_update_blend_equation (GstD3D11CompositorPad * pad, - D3D11_BLEND_OP * value, GstD3D11CompositorBlendOperation new_value) -{ - D3D11_BLEND_OP temp = - gst_d3d11_compositor_blend_operation_to_native (new_value); - - if (temp == *value) - return; + gint tmp = g_value_get_int (value); - *value = temp; - pad->blend_desc_updated = TRUE; + if (*old != tmp) { + *old = tmp; + self->position_updated = TRUE; + } } static void @@ -722,23 +450,18 @@ gst_d3d11_compositor_pad_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_PAD_XPOS: - pad->xpos = g_value_get_int (value); - pad->position_updated = TRUE; + gst_d3d11_compositor_pad_update_position (pad, &pad->xpos, value); break; case PROP_PAD_YPOS: - pad->ypos = g_value_get_int (value); - pad->position_updated = TRUE; + gst_d3d11_compositor_pad_update_position (pad, &pad->ypos, value); break; case PROP_PAD_WIDTH: - pad->width = g_value_get_int (value); - pad->position_updated = TRUE; + gst_d3d11_compositor_pad_update_position (pad, &pad->width, value); break; case PROP_PAD_HEIGHT: - pad->height = g_value_get_int (value); - pad->position_updated = TRUE; + gst_d3d11_compositor_pad_update_position (pad, &pad->height, value); break; - case PROP_PAD_ALPHA: - { + case PROP_PAD_ALPHA:{ gdouble alpha = g_value_get_double (value); if (pad->alpha != alpha) { pad->alpha_updated = TRUE; @@ -746,70 +469,25 @@ gst_d3d11_compositor_pad_set_property (GObject * object, guint prop_id, } break; } - case PROP_PAD_BLEND_OP_RGB: - gst_d3d11_compositor_pad_update_blend_equation (pad, &pad->desc.BlendOp, - (GstD3D11CompositorBlendOperation) g_value_get_enum (value)); - break; - case PROP_PAD_BLEND_OP_ALPHA: - gst_d3d11_compositor_pad_update_blend_equation (pad, - &pad->desc.BlendOpAlpha, - (GstD3D11CompositorBlendOperation) g_value_get_enum (value)); - break; - case PROP_PAD_BLEND_SRC_RGB: - gst_d3d11_compositor_pad_update_blend_function (pad, &pad->desc.SrcBlend, - (GstD3D11CompositorBlend) g_value_get_enum (value)); - break; - case PROP_PAD_BLEND_SRC_ALPHA: - { - GstD3D11CompositorBlend blend = - (GstD3D11CompositorBlend) g_value_get_enum (value); - if (blend == GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR || - blend == GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR || - blend == GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR || - blend == GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR) { - g_warning ("%d is not allowed for %s", blend, pspec->name); - } else { - gst_d3d11_compositor_pad_update_blend_function (pad, - &pad->desc.SrcBlendAlpha, blend); + case PROP_PAD_OPERATOR:{ + GstD3D11CompositorOperator op = + (GstD3D11CompositorOperator) g_value_get_enum (value); + if (op != pad->op) { + pad->op = op; + pad->desc = blend_templ[op]; + pad->blend_desc_updated = TRUE; } break; } - case PROP_PAD_BLEND_DEST_RGB: - gst_d3d11_compositor_pad_update_blend_function (pad, &pad->desc.DestBlend, - (GstD3D11CompositorBlend) g_value_get_enum (value)); - break; - case PROP_PAD_BLEND_DEST_ALPHA: - { - GstD3D11CompositorBlend blend = - (GstD3D11CompositorBlend) g_value_get_enum (value); - if (blend == GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR || - blend == GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR || - blend == GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR || - blend == GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR) { - g_warning ("%d is not allowed for %s", blend, pspec->name); - } else { - gst_d3d11_compositor_pad_update_blend_function (pad, - &pad->desc.DestBlendAlpha, blend); + case PROP_PAD_SIZING_POLICY:{ + GstD3D11CompositorSizingPolicy policy = + (GstD3D11CompositorSizingPolicy) g_value_get_enum (value); + if (pad->sizing_policy != policy) { + pad->sizing_policy = policy; + pad->position_updated = TRUE; } break; } - case PROP_PAD_BLEND_FACTOR_RED: - pad->blend_factor[0] = g_value_get_float (value); - break; - case PROP_PAD_BLEND_FACTOR_GREEN: - pad->blend_factor[1] = g_value_get_float (value); - break; - case PROP_PAD_BLEND_FACTOR_BLUE: - pad->blend_factor[2] = g_value_get_float (value); - break; - case PROP_PAD_BLEND_FACTOR_ALPHA: - pad->blend_factor[3] = g_value_get_float (value); - break; - case PROP_PAD_SIZING_POLICY: - pad->sizing_policy = - (GstD3D11CompositorSizingPolicy) g_value_get_enum (value); - pad->position_updated = TRUE; - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -838,42 +516,8 @@ gst_d3d11_compositor_pad_get_property (GObject * object, guint prop_id, case PROP_PAD_ALPHA: g_value_set_double (value, pad->alpha); break; - case PROP_PAD_BLEND_OP_RGB: - g_value_set_enum (value, - gst_d3d11_compositor_blend_operation_from_native (pad->desc.BlendOp)); - break; - case PROP_PAD_BLEND_OP_ALPHA: - g_value_set_enum (value, - gst_d3d11_compositor_blend_operation_from_native (pad-> - desc.BlendOpAlpha)); - break; - case PROP_PAD_BLEND_SRC_RGB: - g_value_set_enum (value, - gst_d3d11_compositor_blend_from_native (pad->desc.SrcBlend)); - break; - case PROP_PAD_BLEND_SRC_ALPHA: - g_value_set_enum (value, - gst_d3d11_compositor_blend_from_native (pad->desc.SrcBlendAlpha)); - break; - case PROP_PAD_BLEND_DEST_RGB: - g_value_set_enum (value, - gst_d3d11_compositor_blend_from_native (pad->desc.DestBlend)); - break; - case PROP_PAD_BLEND_DEST_ALPHA: - g_value_set_enum (value, - gst_d3d11_compositor_blend_from_native (pad->desc.DestBlendAlpha)); - break; - case PROP_PAD_BLEND_FACTOR_RED: - g_value_set_float (value, pad->blend_factor[0]); - break; - case PROP_PAD_BLEND_FACTOR_GREEN: - g_value_set_float (value, pad->blend_factor[1]); - break; - case PROP_PAD_BLEND_FACTOR_BLUE: - g_value_set_float (value, pad->blend_factor[2]); - break; - case PROP_PAD_BLEND_FACTOR_ALPHA: - g_value_set_float (value, pad->blend_factor[3]); + case PROP_PAD_OPERATOR: + g_value_set_enum (value, pad->op); break; case PROP_PAD_SIZING_POLICY: g_value_set_enum (value, pad->sizing_policy); @@ -885,200 +529,6 @@ gst_d3d11_compositor_pad_get_property (GObject * object, guint prop_id, } static void -gst_d3d11_compositor_pad_init_blend_options (GstD3D11CompositorPad * pad) -{ - guint i; - - pad->desc.BlendEnable = TRUE; - pad->desc.SrcBlend = - gst_d3d11_compositor_blend_to_native (DEFAULT_PAD_BLEND_SRC_RGB); - pad->desc.DestBlend = - gst_d3d11_compositor_blend_to_native (DEFAULT_PAD_BLEND_DEST_RGB); - pad->desc.BlendOp = - gst_d3d11_compositor_blend_operation_to_native (DEFAULT_PAD_BLEND_OP_RGB); - pad->desc.SrcBlendAlpha = - gst_d3d11_compositor_blend_to_native (DEFAULT_PAD_BLEND_SRC_ALPHA); - pad->desc.DestBlendAlpha = - gst_d3d11_compositor_blend_to_native (DEFAULT_PAD_BLEND_DEST_ALPHA); - pad->desc.BlendOpAlpha = - gst_d3d11_compositor_blend_operation_to_native - (DEFAULT_PAD_BLEND_OP_ALPHA); - pad->desc.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - - for (i = 0; i < G_N_ELEMENTS (pad->blend_factor); i++) - pad->blend_factor[i] = 1.0f; -} - -static gboolean -gst_d3d11_compositor_configure_fallback_pool (GstD3D11Compositor * self, - GstVideoInfo * info, gint bind_flags, GstBufferPool ** pool) -{ - GstD3D11AllocationParams *d3d11_params; - GstBufferPool *new_pool; - GstCaps *caps; - - if (*pool) { - gst_buffer_pool_set_active (*pool, FALSE); - gst_clear_object (pool); - } - - caps = gst_video_info_to_caps (info); - if (!caps) { - GST_ERROR_OBJECT (self, "Couldn't create caps from info"); - return FALSE; - } - - d3d11_params = gst_d3d11_allocation_params_new (self->device, - info, (GstD3D11AllocationFlags) 0, bind_flags); - - new_pool = gst_d3d11_buffer_pool_new_with_options (self->device, - caps, d3d11_params, 0, 0); - gst_caps_unref (caps); - gst_d3d11_allocation_params_free (d3d11_params); - - if (!new_pool) { - GST_ERROR_OBJECT (self, "Failed to configure fallback pool"); - return FALSE; - } - - gst_buffer_pool_set_active (new_pool, TRUE); - *pool = new_pool; - - return TRUE; -} - -static gboolean -gst_d3d11_compsitor_prepare_fallback_buffer (GstD3D11Compositor * self, - GstVideoInfo * info, gboolean is_input, GstBufferPool ** pool, - GstBuffer ** fallback_buffer) -{ - GstBuffer *new_buf = NULL; - gint bind_flags = D3D11_BIND_SHADER_RESOURCE; - guint i; - - gst_clear_buffer (fallback_buffer); - - if (!is_input) - bind_flags = D3D11_BIND_RENDER_TARGET; - - if (*pool == NULL && - !gst_d3d11_compositor_configure_fallback_pool (self, info, - bind_flags, pool)) { - GST_ERROR_OBJECT (self, "Couldn't configure fallback buffer pool"); - return FALSE; - } - - if (gst_buffer_pool_acquire_buffer (*pool, &new_buf, NULL) - != GST_FLOW_OK) { - GST_ERROR_OBJECT (self, "Couldn't get fallback buffer from pool"); - return FALSE; - } - - for (i = 0; i < gst_buffer_n_memory (new_buf); i++) { - GstD3D11Memory *new_mem = - (GstD3D11Memory *) gst_buffer_peek_memory (new_buf, i); - - if (is_input && !gst_d3d11_memory_get_shader_resource_view_size (new_mem)) { - GST_ERROR_OBJECT (self, "Couldn't prepare shader resource view"); - gst_buffer_unref (new_buf); - return FALSE; - } else if (!is_input && - !gst_d3d11_memory_get_render_target_view_size (new_mem)) { - GST_ERROR_OBJECT (self, "Couldn't prepare render target view"); - gst_buffer_unref (new_buf); - return FALSE; - } - } - - *fallback_buffer = new_buf; - - return TRUE; -} - -static gboolean -gst_d3d11_compositor_copy_buffer (GstD3D11Compositor * self, - GstVideoInfo * info, GstBuffer * src_buf, GstBuffer * dest_buf, - gboolean do_device_copy) -{ - guint i; - - if (do_device_copy) { - return gst_d3d11_buffer_copy_into (dest_buf, src_buf, info); - } else { - GstVideoFrame src_frame, dest_frame; - - if (!gst_video_frame_map (&src_frame, info, src_buf, - (GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) { - GST_ERROR_OBJECT (self, "Couldn't map input buffer"); - return FALSE; - } - - if (!gst_video_frame_map (&dest_frame, info, dest_buf, - (GstMapFlags) (GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) { - GST_ERROR_OBJECT (self, "Couldn't fallback buffer"); - gst_video_frame_unmap (&src_frame); - return FALSE; - } - - for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (&src_frame); i++) { - if (!gst_video_frame_copy_plane (&dest_frame, &src_frame, i)) { - GST_ERROR_OBJECT (self, "Couldn't copy %dth plane", i); - - gst_video_frame_unmap (&dest_frame); - gst_video_frame_unmap (&src_frame); - - return FALSE; - } - } - - gst_video_frame_unmap (&dest_frame); - gst_video_frame_unmap (&src_frame); - } - - return TRUE; -} - -static gboolean -gst_d3d11_compositor_check_d3d11_memory (GstD3D11Compositor * self, - GstBuffer * buffer, gboolean is_input, gboolean * view_available) -{ - guint i; - gboolean ret = TRUE; - - *view_available = TRUE; - - for (i = 0; i < gst_buffer_n_memory (buffer); i++) { - GstMemory *mem = gst_buffer_peek_memory (buffer, i); - GstD3D11Memory *dmem; - - if (!gst_is_d3d11_memory (mem)) { - ret = FALSE; - goto done; - } - - dmem = (GstD3D11Memory *) mem; - if (dmem->device != self->device) { - ret = FALSE; - goto done; - } - - if (is_input) { - if (!gst_d3d11_memory_get_shader_resource_view_size (dmem)) - *view_available = FALSE; - } else { - if (!gst_d3d11_memory_get_render_target_view_size (dmem)) - *view_available = FALSE; - } - } - -done: - if (!ret) - *view_available = FALSE; - - return ret; -} - -static void gst_d3d11_compositor_pad_get_output_size (GstD3D11CompositorPad * comp_pad, gint out_par_n, gint out_par_d, gint * width, gint * height, gint * x_offset, gint * y_offset) @@ -1134,8 +584,7 @@ gst_d3d11_compositor_pad_get_output_size (GstD3D11CompositorPad * comp_pad, pad_width = gst_util_uint64_scale_int (pad_height, dar_n, dar_d); } break; - case GST_D3D11_COMPOSITOR_SIZING_POLICY_KEEP_ASPECT_RATIO: - { + case GST_D3D11_COMPOSITOR_SIZING_POLICY_KEEP_ASPECT_RATIO:{ gint from_dar_n, from_dar_d, to_dar_n, to_dar_d, num, den; /* Calculate DAR again with actual video size */ @@ -1234,28 +683,141 @@ gst_d3d11_compositor_pad_check_frame_obscured (GstVideoAggregatorPad * pad, GstVideoRectangle frame_rect; gint x_offset, y_offset; - /* There's three types of width/height here: - * 1. GST_VIDEO_FRAME_WIDTH/HEIGHT: - * The frame width/height (same as pad->info.height/width; - * see gst_video_frame_map()) - * 2. cpad->width/height: - * The optional pad property for scaling the frame (if zero, the video is - * left unscaled) - */ + /* There's three types of width/height here: + * 1. GST_VIDEO_FRAME_WIDTH/HEIGHT: + * The frame width/height (same as pad->info.height/width; + * see gst_video_frame_map()) + * 2. cpad->width/height: + * The optional pad property for scaling the frame (if zero, the video is + * left unscaled) + */ + + gst_d3d11_compositor_pad_get_output_size (cpad, GST_VIDEO_INFO_PAR_N (info), + GST_VIDEO_INFO_PAR_D (info), &width, &height, &x_offset, &y_offset); + + frame_rect = clamp_rectangle (cpad->xpos + x_offset, cpad->ypos + y_offset, + width, height, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info)); + + if (frame_rect.w == 0 || frame_rect.h == 0) { + GST_DEBUG_OBJECT (pad, "Resulting frame is zero-width or zero-height " + "(w: %i, h: %i), skipping", frame_rect.w, frame_rect.h); + return TRUE; + } + + return FALSE; +} + +static gboolean +gst_d3d11_compositor_pad_ensure_fallback_buffer (GstD3D11Compositor * self, + GstD3D11CompositorPad * pad, GstVideoInfo * info) +{ + GstD3D11AllocationParams *d3d11_params; + GstBufferPool *pool; + GstCaps *caps; + GstFlowReturn flow_ret; + + if (pad->fallback_buf) + return TRUE; + + caps = gst_video_info_to_caps (info); + if (!caps) { + GST_ERROR_OBJECT (pad, "Failed to create caps"); + return FALSE; + } + + d3d11_params = gst_d3d11_allocation_params_new (self->device, + info, (GstD3D11AllocationFlags) 0, D3D11_BIND_SHADER_RESOURCE); + + pool = gst_d3d11_buffer_pool_new_with_options (self->device, + caps, d3d11_params, 0, 0); + gst_caps_unref (caps); + gst_d3d11_allocation_params_free (d3d11_params); + + if (!pool) { + GST_ERROR_OBJECT (self, "Failed to create pool"); + return FALSE; + } + + if (!gst_buffer_pool_set_active (pool, TRUE)) { + GST_ERROR_OBJECT (self, "Failed to set active"); + gst_object_unref (pool); + return FALSE; + } + + flow_ret = gst_buffer_pool_acquire_buffer (pool, &pad->fallback_buf, nullptr); + if (flow_ret != GST_FLOW_OK) { + GST_ERROR_OBJECT (pad, "Failed to acquire buffer"); + gst_object_unref (pool); + return FALSE; + } + + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); + + return TRUE; +} + +static GstBuffer * +gst_d3d11_compositor_upload_buffer (GstD3D11Compositor * self, + GstD3D11CompositorPad * pad, GstBuffer * buffer, + ID3D11VideoProcessorInputView ** piv) +{ + GstVideoAggregatorPad *vagg_pad = GST_VIDEO_AGGREGATOR_PAD_CAST (pad); + GstVideoInfo *info; + GstD3D11Device *device = self->device; + guint n_memory = gst_buffer_n_memory (buffer); + + *piv = nullptr; + + for (guint i = 0; i < n_memory; i++) { + GstMemory *mem = gst_buffer_peek_memory (buffer, i); + GstD3D11Memory *dmem; + D3D11_TEXTURE2D_DESC desc; + gboolean srv_available = FALSE; + + if (!gst_is_d3d11_memory (mem)) + goto do_copy; + + dmem = GST_D3D11_MEMORY_CAST (mem); + if (dmem->device != device) + goto do_copy; + + gst_d3d11_memory_get_texture_desc (dmem, &desc); + + if ((desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) == + D3D11_BIND_SHADER_RESOURCE) { + srv_available = TRUE; + } - gst_d3d11_compositor_pad_get_output_size (cpad, GST_VIDEO_INFO_PAR_N (info), - GST_VIDEO_INFO_PAR_D (info), &width, &height, &x_offset, &y_offset); + if (pad->processor && pad->alpha == 1.0 && n_memory == 1 + && desc.Usage == D3D11_USAGE_DEFAULT && !srv_available && + gst_d3d11_video_processor_check_bind_flags_for_input_view + (desc.BindFlags)) { + *piv = gst_d3d11_video_processor_get_input_view (pad->processor, dmem); + if (*piv) + return buffer; + } - frame_rect = clamp_rectangle (cpad->xpos + x_offset, cpad->ypos + y_offset, - width, height, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info)); + if (desc.ArraySize != 1 || desc.Usage != D3D11_USAGE_DEFAULT || + !srv_available) { + goto do_copy; + } + } - if (frame_rect.w == 0 || frame_rect.h == 0) { - GST_DEBUG_OBJECT (pad, "Resulting frame is zero-width or zero-height " - "(w: %i, h: %i), skipping", frame_rect.w, frame_rect.h); - return TRUE; + return buffer; + +do_copy: + info = &vagg_pad->info; + + if (!gst_d3d11_compositor_pad_ensure_fallback_buffer (self, pad, info)) + return nullptr; + + if (!gst_d3d11_buffer_copy_into (pad->fallback_buf, buffer, info)) { + GST_ERROR_OBJECT (pad, "Failed to copy into fallback buffer"); + return nullptr; } - return FALSE; + return pad->fallback_buf; } static gboolean @@ -1265,37 +827,18 @@ gst_d3d11_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad, { GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (vagg); GstD3D11CompositorPad *cpad = GST_D3D11_COMPOSITOR_PAD (pad); - GstBuffer *target_buf = buffer; - gboolean do_device_copy = FALSE; + GstBuffer *upload_buf; /* Skip this frame */ if (gst_d3d11_compositor_pad_check_frame_obscured (pad, vagg)) return TRUE; - /* Use fallback buffer when input buffer is: - * - non-d3d11 memory - * - or, from different d3d11 device - * - or not bound to shader resource - */ - if (!gst_d3d11_compositor_check_d3d11_memory (self, - buffer, TRUE, &do_device_copy) || !do_device_copy) { - if (!gst_d3d11_compsitor_prepare_fallback_buffer (self, &pad->info, TRUE, - &cpad->fallback_pool, &cpad->fallback_buf)) { - GST_ERROR_OBJECT (self, "Couldn't prepare fallback buffer"); - return FALSE; - } - - if (!gst_d3d11_compositor_copy_buffer (self, &pad->info, buffer, - cpad->fallback_buf, do_device_copy)) { - GST_ERROR_OBJECT (self, "Couldn't copy input buffer to fallback buffer"); - gst_clear_buffer (&cpad->fallback_buf); - return FALSE; - } - - target_buf = cpad->fallback_buf; - } + upload_buf = gst_d3d11_compositor_upload_buffer (self, + cpad, buffer, &cpad->piv); + if (!upload_buf) + return FALSE; - if (!gst_video_frame_map (prepared_frame, &pad->info, target_buf, + if (!gst_video_frame_map (prepared_frame, &pad->info, upload_buf, (GstMapFlags) (GST_MAP_READ | GST_MAP_D3D11))) { GST_WARNING_OBJECT (pad, "Couldn't map input buffer"); return FALSE; @@ -1304,18 +847,6 @@ gst_d3d11_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad, return TRUE; } -static void -gst_d3d11_compositor_pad_clean_frame (GstVideoAggregatorPad * pad, - GstVideoAggregator * vagg, GstVideoFrame * prepared_frame) -{ - GstD3D11CompositorPad *cpad = GST_D3D11_COMPOSITOR_PAD (pad); - - GST_VIDEO_AGGREGATOR_PAD_CLASS (parent_pad_class)->clean_frame (pad, - vagg, prepared_frame); - - gst_clear_buffer (&cpad->fallback_buf); -} - static gboolean gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, GstVideoAggregator * vagg) @@ -1326,41 +857,120 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, GstVideoInfo *info = &vagg->info; GstVideoRectangle frame_rect; gboolean is_first = FALSE; + gboolean output_has_alpha_comp = FALSE; gint x_offset, y_offset; #ifndef GST_DISABLE_GST_DEBUG guint zorder = 0; #endif + static const D3D11_RENDER_TARGET_BLEND_DESC blend_over_no_alpha = { + TRUE, + D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_OP_ADD, + D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_OP_ADD, + D3D11_COLOR_WRITE_ENABLE_ALL, + }; + + if (GST_VIDEO_INFO_HAS_ALPHA (info) || + GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_BGRx || + GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_RGBx) { + output_has_alpha_comp = TRUE; + } - if (!cpad->convert || self->reconfigured) { - gst_clear_object (&cpad->convert); + if (!cpad->convert) { + GstD3D11Format in_format, out_format; - cpad->convert = - gst_d3d11_converter_new (self->device, &pad->info, &vagg->info); + cpad->convert = gst_d3d11_converter_new (self->device, &pad->info, info); if (!cpad->convert) { GST_ERROR_OBJECT (pad, "Couldn't create converter"); return FALSE; } - g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr); + if (output_has_alpha_comp) + g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr); is_first = TRUE; - } else if (cpad->alpha_updated) { - g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr); + + cpad->src_rect.left = 0; + cpad->src_rect.top = 0; + cpad->src_rect.right = pad->info.width; + cpad->src_rect.bottom = pad->info.height; + + /* Will use videoprocessor when input has no alpha channel and + * alpha == 1.0, mainly for decoder output texture which could not be + * bound to shader resource */ + if (GST_VIDEO_INFO_IS_YUV (&pad->info) && + !GST_VIDEO_INFO_HAS_ALPHA (&pad->info) && + gst_d3d11_device_get_format (self->device, + GST_VIDEO_INFO_FORMAT (&pad->info), &in_format) && + in_format.dxgi_format != DXGI_FORMAT_UNKNOWN && + gst_d3d11_device_get_format (self->device, + GST_VIDEO_INFO_FORMAT (info), &out_format) && + out_format.dxgi_format != DXGI_FORMAT_UNKNOWN) { + const GstDxgiColorSpace *in_space; + const GstDxgiColorSpace *out_space; + + in_space = gst_d3d11_video_info_to_dxgi_color_space (&pad->info); + out_space = gst_d3d11_video_info_to_dxgi_color_space (info); + + if (in_space && out_space) { + GstD3D11VideoProcessor *processor = + gst_d3d11_video_processor_new (self->device, + pad->info.width, pad->info.height, info->width, + info->height); + + if (processor) { + if (gst_d3d11_video_processor_check_format_conversion (processor, + in_format.dxgi_format, + (DXGI_COLOR_SPACE_TYPE) in_space->dxgi_color_space_type, + in_format.dxgi_format, + (DXGI_COLOR_SPACE_TYPE) out_space->dxgi_color_space_type) && + gst_d3d11_video_processor_set_input_dxgi_color_space (processor, + (DXGI_COLOR_SPACE_TYPE) in_space->dxgi_color_space_type) && + gst_d3d11_video_processor_set_output_dxgi_color_space (processor, + (DXGI_COLOR_SPACE_TYPE) out_space->dxgi_color_space_type)) { + cpad->processor = processor; + GST_DEBUG_OBJECT (pad, "Video processor is available"); + } else { + gst_d3d11_video_processor_free (processor); + } + } + } + } + } + + if (cpad->alpha_updated) { + if (output_has_alpha_comp) { + g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr); + } else { + gfloat blend_factor = cpad->alpha; + + g_object_set (cpad->convert, + "blend-factor-red", blend_factor, + "blend-factor-green", blend_factor, + "blend-factor-blue", blend_factor, + "blend-factor-alpha", blend_factor, nullptr); + } + cpad->alpha_updated = FALSE; } if (!cpad->blend || cpad->blend_desc_updated) { HRESULT hr; D3D11_BLEND_DESC desc = { 0, }; - ID3D11BlendState *blend = NULL; + ID3D11BlendState *blend = nullptr; ID3D11Device *device_handle = gst_d3d11_device_get_device_handle (self->device); + gfloat blend_factor = 1.0f; GST_D3D11_CLEAR_COM (cpad->blend); desc.AlphaToCoverageEnable = FALSE; desc.IndependentBlendEnable = FALSE; desc.RenderTarget[0] = cpad->desc; + if (!output_has_alpha_comp && + cpad->op == GST_D3D11_COMPOSITOR_OPERATOR_OVER) { + desc.RenderTarget[0] = blend_over_no_alpha; + blend_factor = cpad->alpha; + } hr = device_handle->CreateBlendState (&desc, &blend); if (!gst_d3d11_result (hr, self->device)) { @@ -1371,11 +981,12 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, cpad->blend = blend; g_object_set (cpad->convert, "blend-state", blend, - "blend-factor-red", cpad->blend_factor[0], - "blend-factor-green", cpad->blend_factor[1], - "blend-factor-blue", cpad->blend_factor[2], - "blend-factor-alpha", cpad->blend_factor[3], - "blend-sample-mask", 0xffffffff, nullptr); + "blend-factor-red", blend_factor, + "blend-factor-green", blend_factor, + "blend-factor-blue", blend_factor, + "blend-factor-alpha", blend_factor, nullptr); + + cpad->blend_desc_updated = FALSE; } if (!is_first && !cpad->position_updated) @@ -1388,7 +999,7 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, width, height, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info)); #ifndef GST_DISABLE_GST_DEBUG - g_object_get (pad, "zorder", &zorder, NULL); + g_object_get (pad, "zorder", &zorder, nullptr); GST_LOG_OBJECT (pad, "Update position, pad-xpos %d, pad-ypos %d, " "pad-zorder %d, pad-width %d, pad-height %d, in-resolution %dx%d, " @@ -1401,6 +1012,12 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, cpad->position_updated = FALSE; + /* rectangle stored for video processor */ + cpad->dest_rect.left = frame_rect.x; + cpad->dest_rect.top = frame_rect.y; + cpad->dest_rect.right = frame_rect.x + frame_rect.w; + cpad->dest_rect.bottom = frame_rect.y + frame_rect.h; + g_object_set (cpad->convert, "dest-x", frame_rect.x, "dest-y", frame_rect.y, "dest-width", frame_rect.w, "dest-height", frame_rect.h, nullptr); @@ -1408,9 +1025,23 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad, return TRUE; } -static GstStaticCaps pad_template_caps = -GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES - (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, "{ RGBA, BGRA }")); +static GstStaticCaps sink_pad_template_caps = + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES + (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_SINK_FORMATS) "; " + GST_VIDEO_CAPS_MAKE (GST_D3D11_SINK_FORMATS)); + +/* formats we can output without conversion. + * Excludes 10/12 bits planar YUV (needs bitshift) and + * AYUV/AYUV64 (d3d11 runtime does not understand the ayuv order) */ +#define COMPOSITOR_SRC_FORMATS \ + "{ RGBA64_LE, RGB10A2_LE, BGRA, RGBA, BGRx, RGBx, VUYA, NV12, NV21, " \ + "P010_10LE, P012_LE, P016_LE, I420, YV12, Y42B, Y444, Y444_16LE, " \ + "GRAY8, GRAY16_LE }" + +static GstStaticCaps src_pad_template_caps = + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES + (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, COMPOSITOR_SRC_FORMATS) "; " + GST_VIDEO_CAPS_MAKE (COMPOSITOR_SRC_FORMATS)); enum { @@ -1437,19 +1068,21 @@ static void gst_d3d11_compositor_release_pad (GstElement * element, static void gst_d3d11_compositor_set_context (GstElement * element, GstContext * context); -static gboolean gst_d3d11_compositor_start (GstAggregator * aggregator); -static gboolean gst_d3d11_compositor_stop (GstAggregator * aggregator); -static gboolean gst_d3d11_compositor_sink_query (GstAggregator * aggregator, +static gboolean gst_d3d11_compositor_start (GstAggregator * agg); +static gboolean gst_d3d11_compositor_stop (GstAggregator * agg); +static gboolean gst_d3d11_compositor_sink_query (GstAggregator * agg, GstAggregatorPad * pad, GstQuery * query); -static gboolean gst_d3d11_compositor_src_query (GstAggregator * aggregator, +static gboolean gst_d3d11_compositor_src_query (GstAggregator * agg, GstQuery * query); -static GstCaps *gst_d3d11_compositor_fixate_src_caps (GstAggregator * - aggregator, GstCaps * caps); -static gboolean gst_d3d11_compositor_propose_allocation (GstAggregator * - aggregator, GstAggregatorPad * pad, GstQuery * decide_query, +static GstCaps *gst_d3d11_compositor_fixate_src_caps (GstAggregator * agg, + GstCaps * caps); +static gboolean gst_d3d11_compositor_negotiated_src_caps (GstAggregator * agg, + GstCaps * caps); +static gboolean +gst_d3d11_compositor_propose_allocation (GstAggregator * agg, + GstAggregatorPad * pad, GstQuery * decide_query, GstQuery * query); +static gboolean gst_d3d11_compositor_decide_allocation (GstAggregator * agg, GstQuery * query); -static gboolean gst_d3d11_compositor_decide_allocation (GstAggregator * - aggregator, GstQuery * query); static GstFlowReturn gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf); @@ -1466,24 +1099,24 @@ G_DEFINE_TYPE_WITH_CODE (GstD3D11Compositor, gst_d3d11_compositor, static void gst_d3d11_compositor_class_init (GstD3D11CompositorClass * klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - GstAggregatorClass *aggregator_class = GST_AGGREGATOR_CLASS (klass); + GstAggregatorClass *agg_class = GST_AGGREGATOR_CLASS (klass); GstVideoAggregatorClass *vagg_class = GST_VIDEO_AGGREGATOR_CLASS (klass); GstCaps *caps; - gobject_class->dispose = gst_d3d11_compositor_dispose; - gobject_class->set_property = gst_d3d11_compositor_set_property; - gobject_class->get_property = gst_d3d11_compositor_get_property; + object_class->dispose = gst_d3d11_compositor_dispose; + object_class->set_property = gst_d3d11_compositor_set_property; + object_class->get_property = gst_d3d11_compositor_get_property; - g_object_class_install_property (gobject_class, PROP_ADAPTER, + g_object_class_install_property (object_class, PROP_ADAPTER, g_param_spec_int ("adapter", "Adapter", "Adapter index for creating device (-1 for default)", -1, G_MAXINT32, DEFAULT_ADAPTER, (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS))); - g_object_class_install_property (gobject_class, PROP_BACKGROUND, + g_object_class_install_property (object_class, PROP_BACKGROUND, g_param_spec_enum ("background", "Background", "Background type", GST_TYPE_D3D11_COMPOSITOR_BACKGROUND, DEFAULT_BACKGROUND, @@ -1496,17 +1129,17 @@ gst_d3d11_compositor_class_init (GstD3D11CompositorClass * klass) element_class->set_context = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_set_context); - aggregator_class->start = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_start); - aggregator_class->stop = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_stop); - aggregator_class->sink_query = - GST_DEBUG_FUNCPTR (gst_d3d11_compositor_sink_query); - aggregator_class->src_query = - GST_DEBUG_FUNCPTR (gst_d3d11_compositor_src_query); - aggregator_class->fixate_src_caps = + agg_class->start = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_start); + agg_class->stop = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_stop); + agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_sink_query); + agg_class->src_query = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_src_query); + agg_class->fixate_src_caps = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_fixate_src_caps); - aggregator_class->propose_allocation = + agg_class->negotiated_src_caps = + GST_DEBUG_FUNCPTR (gst_d3d11_compositor_negotiated_src_caps); + agg_class->propose_allocation = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_propose_allocation); - aggregator_class->decide_allocation = + agg_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_decide_allocation); vagg_class->aggregate_frames = @@ -1514,24 +1147,29 @@ gst_d3d11_compositor_class_init (GstD3D11CompositorClass * klass) vagg_class->create_output_buffer = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_create_output_buffer); - caps = gst_d3d11_get_updated_template_caps (&pad_template_caps); + caps = gst_d3d11_get_updated_template_caps (&sink_pad_template_caps); gst_element_class_add_pad_template (element_class, gst_pad_template_new_with_gtype ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, caps, GST_TYPE_D3D11_COMPOSITOR_PAD)); + gst_caps_unref (caps); + caps = gst_d3d11_get_updated_template_caps (&src_pad_template_caps); gst_element_class_add_pad_template (element_class, gst_pad_template_new_with_gtype ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps, GST_TYPE_AGGREGATOR_PAD)); gst_caps_unref (caps); gst_element_class_set_static_metadata (element_class, "Direct3D11 Compositor", - "Filter/Editor/Video/Compositor", - "A Direct3D11 compositor", "Seungha Yang "); + "Filter/Editor/Video/Compositor", "A Direct3D11 compositor", + "Seungha Yang "); gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_BACKGROUND, (GstPluginAPIFlags) 0); gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_PAD, (GstPluginAPIFlags) 0); + + GST_DEBUG_CATEGORY_INIT (gst_d3d11_compositor_debug, + "d3d11compositor", 0, "d3d11compositor element"); } static void @@ -1548,7 +1186,6 @@ gst_d3d11_compositor_dispose (GObject * object) gst_clear_object (&self->device); gst_clear_buffer (&self->fallback_buf); - gst_clear_object (&self->fallback_pool); g_clear_pointer (&self->checker_background, gst_d3d11_compositor_quad_free); G_OBJECT_CLASS (parent_class)->dispose (object); @@ -1598,7 +1235,7 @@ gst_d3d11_compositor_child_proxy_get_child_by_index (GstChildProxy * proxy, guint index) { GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (proxy); - GObject *obj = NULL; + GObject *obj = nullptr; GST_OBJECT_LOCK (self); obj = (GObject *) g_list_nth_data (GST_ELEMENT_CAST (self)->sinkpads, index); @@ -1643,8 +1280,10 @@ gst_d3d11_compositor_request_new_pad (GstElement * element, pad = GST_ELEMENT_CLASS (parent_class)->request_new_pad (element, templ, name, caps); - if (pad == NULL) - goto could_not_create; + if (!pad) { + GST_DEBUG_OBJECT (element, "could not create/add pad"); + return nullptr; + } gst_child_proxy_child_added (GST_CHILD_PROXY (element), G_OBJECT (pad), GST_OBJECT_NAME (pad)); @@ -1652,12 +1291,6 @@ gst_d3d11_compositor_request_new_pad (GstElement * element, GST_DEBUG_OBJECT (element, "Created new pad %s:%s", GST_DEBUG_PAD_NAME (pad)); return pad; - -could_not_create: - { - GST_DEBUG_OBJECT (element, "could not create/add pad"); - return NULL; - } } static gboolean @@ -1665,11 +1298,8 @@ gst_d3d11_compositor_pad_clear_resource (GstD3D11Compositor * self, GstD3D11CompositorPad * cpad, gpointer user_data) { gst_clear_buffer (&cpad->fallback_buf); - if (cpad->fallback_pool) { - gst_buffer_pool_set_active (cpad->fallback_pool, FALSE); - gst_clear_object (&cpad->fallback_pool); - } gst_clear_object (&cpad->convert); + g_clear_pointer (&cpad->processor, gst_d3d11_video_processor_free); GST_D3D11_CLEAR_COM (cpad->blend); return TRUE; @@ -1686,7 +1316,7 @@ gst_d3d11_compositor_release_pad (GstElement * element, GstPad * pad) gst_child_proxy_child_removed (GST_CHILD_PROXY (self), G_OBJECT (pad), GST_OBJECT_NAME (pad)); - gst_d3d11_compositor_pad_clear_resource (self, cpad, NULL); + gst_d3d11_compositor_pad_clear_resource (self, cpad, nullptr); GST_ELEMENT_CLASS (parent_class)->release_pad (element, pad); } @@ -1702,9 +1332,9 @@ gst_d3d11_compositor_set_context (GstElement * element, GstContext * context) } static gboolean -gst_d3d11_compositor_start (GstAggregator * aggregator) +gst_d3d11_compositor_start (GstAggregator * agg) { - GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator); + GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg); if (!gst_d3d11_ensure_element_data (GST_ELEMENT_CAST (self), self->adapter, &self->device)) { @@ -1712,18 +1342,18 @@ gst_d3d11_compositor_start (GstAggregator * aggregator) return FALSE; } - return GST_AGGREGATOR_CLASS (parent_class)->start (aggregator); + return GST_AGGREGATOR_CLASS (parent_class)->start (agg); } static gboolean -gst_d3d11_compositor_stop (GstAggregator * aggregator) +gst_d3d11_compositor_stop (GstAggregator * agg) { - GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator); + GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg); g_clear_pointer (&self->checker_background, gst_d3d11_compositor_quad_free); gst_clear_object (&self->device); - return GST_AGGREGATOR_CLASS (parent_class)->stop (aggregator); + return GST_AGGREGATOR_CLASS (parent_class)->stop (agg); } static GstCaps * @@ -1737,7 +1367,7 @@ gst_d3d11_compositor_sink_getcaps (GstPad * pad, GstCaps * filter) template_caps = gst_pad_get_pad_template_caps (pad); sinkcaps = gst_pad_get_current_caps (pad); - if (sinkcaps == NULL) { + if (sinkcaps == nullptr) { sinkcaps = gst_caps_ref (template_caps); } else { sinkcaps = gst_caps_merge (sinkcaps, gst_caps_ref (template_caps)); @@ -1780,23 +1410,19 @@ gst_d3d11_compositor_sink_acceptcaps (GstPad * pad, GstCaps * caps) } static gboolean -gst_d3d11_compositor_sink_query (GstAggregator * aggregator, +gst_d3d11_compositor_sink_query (GstAggregator * agg, GstAggregatorPad * pad, GstQuery * query) { - GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator); + GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONTEXT: - { - gboolean ret; - ret = gst_d3d11_handle_context_query (GST_ELEMENT (aggregator), query, - self->device); - if (ret) + if (gst_d3d11_handle_context_query (GST_ELEMENT (agg), query, + self->device)) { return TRUE; + } break; - } - case GST_QUERY_CAPS: - { + case GST_QUERY_CAPS:{ GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); @@ -1805,8 +1431,7 @@ gst_d3d11_compositor_sink_query (GstAggregator * aggregator, gst_caps_unref (caps); return TRUE; } - case GST_QUERY_ACCEPT_CAPS: - { + case GST_QUERY_ACCEPT_CAPS:{ GstCaps *caps; gboolean ret; @@ -1819,43 +1444,38 @@ gst_d3d11_compositor_sink_query (GstAggregator * aggregator, break; } - return GST_AGGREGATOR_CLASS (parent_class)->sink_query (aggregator, - pad, query); + return GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, pad, query); } static gboolean -gst_d3d11_compositor_src_query (GstAggregator * aggregator, GstQuery * query) +gst_d3d11_compositor_src_query (GstAggregator * agg, GstQuery * query) { - GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator); + GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONTEXT: - { - gboolean ret; - ret = gst_d3d11_handle_context_query (GST_ELEMENT (aggregator), query, - self->device); - if (ret) + if (gst_d3d11_handle_context_query (GST_ELEMENT (agg), query, + self->device)) { return TRUE; + } break; - } default: break; } - return GST_AGGREGATOR_CLASS (parent_class)->src_query (aggregator, query); + return GST_AGGREGATOR_CLASS (parent_class)->src_query (agg, query); } static GstCaps * -gst_d3d11_compositor_fixate_src_caps (GstAggregator * aggregator, - GstCaps * caps) +gst_d3d11_compositor_fixate_src_caps (GstAggregator * agg, GstCaps * caps) { - GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (aggregator); + GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg); GList *l; gint best_width = -1, best_height = -1; gint best_fps_n = -1, best_fps_d = -1; gint par_n, par_d; gdouble best_fps = 0.; - GstCaps *ret = NULL; + GstCaps *ret = nullptr; GstStructure *s; ret = gst_caps_make_writable (caps); @@ -1924,45 +1544,302 @@ gst_d3d11_compositor_fixate_src_caps (GstAggregator * aggregator, best_fps_d); ret = gst_caps_fixate (ret); - GST_LOG_OBJECT (aggregator, "Fixated caps %" GST_PTR_FORMAT, ret); + GST_LOG_OBJECT (agg, "Fixated caps %" GST_PTR_FORMAT, ret); return ret; } +static void +convert_info_gray_to_yuv (const GstVideoInfo * gray, GstVideoInfo * yuv) +{ + GstVideoInfo tmp; + + if (GST_VIDEO_INFO_IS_YUV (gray)) { + *yuv = *gray; + return; + } + + if (gray->finfo->depth[0] == 8) { + gst_video_info_set_format (&tmp, + GST_VIDEO_FORMAT_Y444, gray->width, gray->height); + } else { + gst_video_info_set_format (&tmp, + GST_VIDEO_FORMAT_Y444_16LE, gray->width, gray->height); + } + + tmp.colorimetry.range = gray->colorimetry.range; + if (tmp.colorimetry.range == GST_VIDEO_COLOR_RANGE_UNKNOWN) + tmp.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; + + tmp.colorimetry.primaries = gray->colorimetry.primaries; + if (tmp.colorimetry.primaries == GST_VIDEO_COLOR_PRIMARIES_UNKNOWN) + tmp.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709; + + tmp.colorimetry.transfer = gray->colorimetry.transfer; + if (tmp.colorimetry.transfer == GST_VIDEO_TRANSFER_UNKNOWN) + tmp.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709; + + tmp.colorimetry.matrix = gray->colorimetry.matrix; + if (tmp.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN) + tmp.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; + + *yuv = tmp; +} + +static void +gst_d3d11_compositor_calculate_background_color (GstD3D11Compositor * self, + const GstVideoInfo * info) +{ + GstD3D11ColorMatrix clear_color_matrix; + gdouble rgb[3]; + gdouble converted[3]; + GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info); + + if (GST_VIDEO_INFO_IS_RGB (info)) { + GstVideoInfo rgb_info = *info; + rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; + + gst_d3d11_color_range_adjust_matrix_unorm (&rgb_info, info, + &clear_color_matrix); + } else { + GstVideoInfo rgb_info; + GstVideoInfo yuv_info; + + gst_video_info_set_format (&rgb_info, GST_VIDEO_FORMAT_RGBA64_LE, + info->width, info->height); + convert_info_gray_to_yuv (info, &yuv_info); + + if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || + yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { + GST_WARNING_OBJECT (self, "Invalid matrix is detected"); + yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; + } + + gst_d3d11_rgb_to_yuv_matrix_unorm (&rgb_info, + &yuv_info, &clear_color_matrix); + } + + /* Calculate black and white color values */ + for (guint i = 0; i < 2; i++) { + GstD3D11CompositorClearColor *clear_color = &self->clear_color[i]; + rgb[0] = rgb[1] = rgb[2] = (gdouble) i; + + for (guint j = 0; j < 3; j++) { + converted[j] = 0; + for (guint k = 0; k < 3; k++) { + converted[j] += clear_color_matrix.matrix[j][k] * rgb[k]; + } + converted[j] += clear_color_matrix.offset[j]; + converted[j] = CLAMP (converted[j], + clear_color_matrix.min[j], clear_color_matrix.max[j]); + } + + GST_DEBUG_OBJECT (self, "Calculated background color RGB: %f, %f, %f", + converted[0], converted[1], converted[2]); + + if (GST_VIDEO_INFO_IS_RGB (info) || GST_VIDEO_INFO_IS_GRAY (info)) { + for (guint j = 0; j < 3; j++) + clear_color->color[0][j] = converted[j]; + clear_color->color[0][3] = 1.0; + } else { + switch (format) { + case GST_VIDEO_FORMAT_VUYA: + clear_color->color[0][0] = converted[2]; + clear_color->color[0][1] = converted[1]; + clear_color->color[0][2] = converted[0]; + clear_color->color[0][3] = 1.0; + break; + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + case GST_VIDEO_FORMAT_P010_10LE: + case GST_VIDEO_FORMAT_P012_LE: + case GST_VIDEO_FORMAT_P016_LE: + clear_color->color[0][0] = converted[0]; + clear_color->color[0][1] = 0; + clear_color->color[0][2] = 0; + clear_color->color[0][3] = 1.0; + if (format == GST_VIDEO_FORMAT_NV21) { + clear_color->color[1][0] = converted[2]; + clear_color->color[1][1] = converted[1]; + } else { + clear_color->color[1][0] = converted[1]; + clear_color->color[1][1] = converted[2]; + } + clear_color->color[1][2] = 0; + clear_color->color[1][3] = 1.0; + break; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_I420_10LE: + case GST_VIDEO_FORMAT_I420_12LE: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_I422_10LE: + case GST_VIDEO_FORMAT_I422_12LE: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y444_10LE: + case GST_VIDEO_FORMAT_Y444_12LE: + case GST_VIDEO_FORMAT_Y444_16LE: + clear_color->color[0][0] = converted[0]; + clear_color->color[0][1] = 0; + clear_color->color[0][2] = 0; + clear_color->color[0][3] = 1.0; + if (format == GST_VIDEO_FORMAT_YV12) { + clear_color->color[1][0] = converted[2]; + clear_color->color[2][0] = converted[1]; + } else { + clear_color->color[1][0] = converted[1]; + clear_color->color[2][0] = converted[2]; + } + clear_color->color[1][1] = 0; + clear_color->color[1][2] = 0; + clear_color->color[1][3] = 1.0; + clear_color->color[2][1] = 0; + clear_color->color[2][2] = 0; + clear_color->color[2][3] = 1.0; + break; + default: + g_assert_not_reached (); + break; + } + } + } +} + +static gboolean +gst_d3d11_compositor_negotiated_src_caps (GstAggregator * agg, GstCaps * caps) +{ + GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg); + GstCapsFeatures *features; + GstVideoInfo info; + + if (!gst_video_info_from_caps (&info, caps)) { + GST_ERROR_OBJECT (self, "Failed to convert caps to info"); + return FALSE; + } + + features = gst_caps_get_features (caps, 0); + if (features + && gst_caps_features_contains (features, + GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) { + GST_DEBUG_OBJECT (self, "Negotiated with D3D11 memory caps"); + self->downstream_supports_d3d11 = TRUE; + } else { + GST_DEBUG_OBJECT (self, "Negotiated with system memory caps"); + self->downstream_supports_d3d11 = FALSE; + } + + gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self), + (GstElementForeachPadFunc) gst_d3d11_compositor_pad_clear_resource, + nullptr); + + gst_clear_buffer (&self->fallback_buf); + g_clear_pointer (&self->checker_background, gst_d3d11_compositor_quad_free); + + gst_d3d11_compositor_calculate_background_color (self, &info); + + if (!self->downstream_supports_d3d11) { + GstD3D11AllocationParams *d3d11_params; + GstBufferPool *pool; + GstFlowReturn flow_ret; + + d3d11_params = gst_d3d11_allocation_params_new (self->device, + &info, (GstD3D11AllocationFlags) 0, + D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET); + + pool = gst_d3d11_buffer_pool_new_with_options (self->device, + caps, d3d11_params, 0, 0); + gst_d3d11_allocation_params_free (d3d11_params); + + if (!pool) { + GST_ERROR_OBJECT (self, "Failed to create pool"); + return FALSE; + } + + if (!gst_buffer_pool_set_active (pool, TRUE)) { + GST_ERROR_OBJECT (self, "Failed to set active"); + gst_object_unref (pool); + return FALSE; + } + + flow_ret = gst_buffer_pool_acquire_buffer (pool, &self->fallback_buf, + nullptr); + if (flow_ret != GST_FLOW_OK) { + GST_ERROR_OBJECT (self, "Failed to acquire buffer"); + gst_object_unref (pool); + return FALSE; + } + + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); + } + + return GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps); +} + static gboolean -gst_d3d11_compositor_propose_allocation (GstAggregator * aggregator, +gst_d3d11_compositor_propose_allocation (GstAggregator * agg, GstAggregatorPad * pad, GstQuery * decide_query, GstQuery * query) { - GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator); + GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg); GstVideoInfo info; GstBufferPool *pool; GstCaps *caps; guint size; - gst_query_parse_allocation (query, &caps, NULL); + gst_query_parse_allocation (query, &caps, nullptr); - if (caps == NULL) + if (caps == nullptr) return FALSE; if (!gst_video_info_from_caps (&info, caps)) return FALSE; if (gst_query_get_n_allocation_pools (query) == 0) { - GstD3D11AllocationParams *d3d11_params; + GstCapsFeatures *features; GstStructure *config; - - d3d11_params = gst_d3d11_allocation_params_new (self->device, &info, - (GstD3D11AllocationFlags) 0, D3D11_BIND_SHADER_RESOURCE); - - pool = gst_d3d11_buffer_pool_new_with_options (self->device, - caps, d3d11_params, 0, 0); - gst_d3d11_allocation_params_free (d3d11_params); + gboolean is_d3d11 = FALSE; + + features = gst_caps_get_features (caps, 0); + if (features + && gst_caps_features_contains (features, + GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) { + GST_DEBUG_OBJECT (pad, "upstream support d3d11 memory"); + pool = gst_d3d11_buffer_pool_new (self->device); + is_d3d11 = TRUE; + } else { + pool = gst_d3d11_staging_buffer_pool_new (self->device); + } if (!pool) { GST_ERROR_OBJECT (self, "Failed to create buffer pool"); return FALSE; } + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_add_option (config, + GST_BUFFER_POOL_OPTION_VIDEO_META); + + size = GST_VIDEO_INFO_SIZE (&info); + if (is_d3d11) { + GstD3D11AllocationParams *d3d11_params; + + d3d11_params = + gst_d3d11_allocation_params_new (self->device, + &info, (GstD3D11AllocationFlags) 0, D3D11_BIND_SHADER_RESOURCE); + + gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params); + gst_d3d11_allocation_params_free (d3d11_params); + } + + gst_buffer_pool_config_set_params (config, caps, (guint) size, 0, 0); + + if (!gst_buffer_pool_set_config (pool, config)) { + GST_ERROR_OBJECT (pool, "Couldn't set config"); + gst_object_unref (pool); + + return FALSE; + } + /* d3d11 buffer pool will update buffer size based on allocated texture, * get size from config again */ config = gst_buffer_pool_get_config (pool); @@ -1974,71 +1851,99 @@ gst_d3d11_compositor_propose_allocation (GstAggregator * aggregator, gst_object_unref (pool); } - gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, nullptr); return TRUE; } static gboolean -gst_d3d11_compositor_decide_allocation (GstAggregator * aggregator, - GstQuery * query) +gst_d3d11_compositor_decide_allocation (GstAggregator * agg, GstQuery * query) { - GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator); + GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg); GstCaps *caps; - GstBufferPool *pool = NULL; + GstBufferPool *pool = nullptr; guint n, size, min, max; GstVideoInfo info; GstStructure *config; - GstD3D11AllocationParams *d3d11_params; + gboolean use_d3d11_pool; + gboolean has_videometa; - gst_query_parse_allocation (query, &caps, NULL); + gst_query_parse_allocation (query, &caps, nullptr); if (!caps) { GST_DEBUG_OBJECT (self, "No output caps"); return FALSE; } - gst_video_info_from_caps (&info, caps); + if (!gst_video_info_from_caps (&info, caps)) { + GST_ERROR_OBJECT (self, "Invalid caps"); + return FALSE; + } + + has_videometa = gst_query_find_allocation_meta (query, + GST_VIDEO_META_API_TYPE, nullptr); + use_d3d11_pool = self->downstream_supports_d3d11; + n = gst_query_get_n_allocation_pools (query); if (n > 0) gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); /* create our own pool */ if (pool) { - if (!GST_IS_D3D11_BUFFER_POOL (pool)) { - gst_clear_object (&pool); - } else { - GstD3D11BufferPool *dpool = GST_D3D11_BUFFER_POOL (pool); - if (dpool->device != self->device) + if (use_d3d11_pool) { + if (!GST_IS_D3D11_BUFFER_POOL (pool)) { + GST_DEBUG_OBJECT (self, + "Downstream pool is not d3d11, will create new one"); gst_clear_object (&pool); + } else { + GstD3D11BufferPool *dpool = GST_D3D11_BUFFER_POOL (pool); + if (dpool->device != self->device) { + GST_DEBUG_OBJECT (self, "Different device, will create new one"); + gst_clear_object (&pool); + } + } + } else if (has_videometa) { + /* We will use d3d11 staging buffer pool */ + gst_clear_object (&pool); } } + size = (guint) info.size; + if (!pool) { - pool = gst_d3d11_buffer_pool_new (self->device); + if (use_d3d11_pool) + pool = gst_d3d11_buffer_pool_new (self->device); + else if (has_videometa) + pool = gst_d3d11_staging_buffer_pool_new (self->device); + else + pool = gst_video_buffer_pool_new (); - min = max = 0; - size = (guint) info.size; + min = 0; + max = 0; } config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, min, max); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); - d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config); - if (!d3d11_params) { - d3d11_params = gst_d3d11_allocation_params_new (self->device, - &info, (GstD3D11AllocationFlags) 0, D3D11_BIND_RENDER_TARGET); - } else { - guint i; + if (use_d3d11_pool) { + GstD3D11AllocationParams *d3d11_params; + + d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config); + if (!d3d11_params) { + d3d11_params = gst_d3d11_allocation_params_new (self->device, + &info, (GstD3D11AllocationFlags) 0, D3D11_BIND_RENDER_TARGET); + } else { + guint i; - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) { - d3d11_params->desc[i].BindFlags |= D3D11_BIND_RENDER_TARGET; + for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) { + d3d11_params->desc[i].BindFlags |= D3D11_BIND_RENDER_TARGET; + } } - } - gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params); - gst_d3d11_allocation_params_free (d3d11_params); + gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params); + gst_d3d11_allocation_params_free (d3d11_params); + } gst_buffer_pool_set_config (pool, config); @@ -2054,8 +1959,6 @@ gst_d3d11_compositor_decide_allocation (GstAggregator * aggregator, gst_query_add_allocation_pool (query, pool, size, min, max); gst_object_unref (pool); - self->reconfigured = TRUE; - return TRUE; } @@ -2092,13 +1995,22 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self, ComPtr < ID3D11VertexShader > vs; ComPtr < ID3D11InputLayout > layout; HRESULT hr; + const gchar *ps_src; device_handle = gst_d3d11_device_get_device_handle (self->device); context_handle = gst_d3d11_device_get_device_context_handle (self->device); - if (!gst_d3d11_create_pixel_shader (self->device, checker_ps_src, &ps)) { + if (GST_VIDEO_INFO_IS_RGB (info)) { + ps_src = checker_ps_src_rgb; + } else if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_VUYA) { + ps_src = checker_ps_src_vuya; + } else { + ps_src = checker_ps_src_luma; + } + + if (!gst_d3d11_create_pixel_shader (self->device, ps_src, &ps)) { GST_ERROR_OBJECT (self, "Couldn't setup pixel shader"); - return NULL; + return nullptr; } memset (&input_desc, 0, sizeof (D3D11_INPUT_ELEMENT_DESC)); @@ -2113,7 +2025,7 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self, if (!gst_d3d11_create_vertex_shader (self->device, checker_vs_src, &input_desc, 1, &vs, &layout)) { GST_ERROR_OBJECT (self, "Couldn't setup vertex shader"); - return NULL; + return nullptr; } memset (&buffer_desc, 0, sizeof (D3D11_BUFFER_DESC)); @@ -2122,11 +2034,11 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self, buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - hr = device_handle->CreateBuffer (&buffer_desc, NULL, &vertex_buffer); + hr = device_handle->CreateBuffer (&buffer_desc, nullptr, &vertex_buffer); if (!gst_d3d11_result (hr, self->device)) { GST_ERROR_OBJECT (self, "Couldn't create vertex buffer, hr: 0x%x", (guint) hr); - return NULL; + return nullptr; } hr = context_handle->Map (vertex_buffer.Get (), @@ -2134,12 +2046,11 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self, if (!gst_d3d11_result (hr, self->device)) { GST_ERROR_OBJECT (self, "Couldn't map vertex buffer, hr: 0x%x", (guint) hr); - return NULL; + return nullptr; } vertex_data = (VertexData *) map.pData; /* bottom left */ - /* bottom left */ vertex_data[0].position.x = -1.0f; vertex_data[0].position.y = -1.0f; vertex_data[0].position.z = 0.0f; @@ -2174,11 +2085,11 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self, buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - hr = device_handle->CreateBuffer (&buffer_desc, NULL, &index_buffer); + hr = device_handle->CreateBuffer (&buffer_desc, nullptr, &index_buffer); if (!gst_d3d11_result (hr, self->device)) { GST_ERROR_OBJECT (self, "Couldn't create index buffer, hr: 0x%x", (guint) hr); - return NULL; + return nullptr; } hr = context_handle->Map (index_buffer.Get (), @@ -2186,7 +2097,7 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self, if (!gst_d3d11_result (hr, self->device)) { GST_ERROR_OBJECT (self, "Couldn't map index buffer, hr: 0x%x", (guint) hr); - return NULL; + return nullptr; } indices = (WORD *) map.pData; @@ -2271,32 +2182,40 @@ gst_d3d11_compositor_draw_background_checker (GstD3D11Compositor * self, /* Must be called with d3d11 device lock */ static gboolean gst_d3d11_compositor_draw_background (GstD3D11Compositor * self, - ID3D11RenderTargetView * rtv) + ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES], guint num_rtv) { ID3D11DeviceContext *context = gst_d3d11_device_get_device_context_handle (self->device); - FLOAT rgba[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + GstD3D11CompositorClearColor *color = &self->clear_color[0]; + + if (self->background == GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER) { + if (!gst_d3d11_compositor_draw_background_checker (self, rtv[0])) + return FALSE; + + /* clear U and V components if needed */ + for (guint i = 1; i < num_rtv; i++) + context->ClearRenderTargetView (rtv[i], color->color[i]); + + return TRUE; + } switch (self->background) { - case GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER: - return gst_d3d11_compositor_draw_background_checker (self, rtv); case GST_D3D11_COMPOSITOR_BACKGROUND_BLACK: - /* {0, 0, 0, 1} */ + color = &self->clear_color[0]; break; case GST_D3D11_COMPOSITOR_BACKGROUND_WHITE: - rgba[0] = 1.0f; - rgba[1] = 1.0f; - rgba[2] = 1.0f; + color = &self->clear_color[1]; break; case GST_D3D11_COMPOSITOR_BACKGROUND_TRANSPARENT: - rgba[3] = 0.0f; + color = &self->clear_color[2]; break; default: g_assert_not_reached (); return FALSE; } - context->ClearRenderTargetView (rtv, rgba); + for (guint i = 0; i < num_rtv; i++) + context->ClearRenderTargetView (rtv[i], color->color[i]); return TRUE; } @@ -2308,79 +2227,42 @@ gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg, GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (vagg); GList *iter; GstBuffer *target_buf = outbuf; - gboolean need_copy = FALSE; - gboolean do_device_copy = FALSE; GstFlowReturn ret = GST_FLOW_OK; - ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES] = { NULL, }; - guint i, j; - gint view_idx; - - /* Use fallback buffer when output buffer is: - * - non-d3d11 memory - * - or, from different d3d11 device - * - or not bound to render target - */ - if (!gst_d3d11_compositor_check_d3d11_memory (self, - outbuf, FALSE, &do_device_copy) || !do_device_copy) { - if (!gst_d3d11_compsitor_prepare_fallback_buffer (self, &vagg->info, FALSE, - &self->fallback_pool, &self->fallback_buf)) { - GST_ERROR_OBJECT (self, "Couldn't prepare fallback buffer"); - return GST_FLOW_ERROR; - } - - GST_TRACE_OBJECT (self, "Will draw on fallback texture"); + ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES] = { nullptr, }; + GstVideoFrame target_frame; + guint num_rtv = GST_VIDEO_INFO_N_PLANES (&vagg->info); + ID3D11VideoProcessorOutputView *pov = nullptr; - need_copy = TRUE; + if (!self->downstream_supports_d3d11) target_buf = self->fallback_buf; - } - - view_idx = 0; - for (i = 0; i < gst_buffer_n_memory (target_buf); i++) { - GstMemory *mem = gst_buffer_peek_memory (target_buf, i); - GstD3D11Memory *dmem; - guint rtv_size; - - if (!gst_is_d3d11_memory (mem)) { - GST_ERROR_OBJECT (self, "Invalid output memory"); - return GST_FLOW_ERROR; - } - - dmem = (GstD3D11Memory *) mem; - rtv_size = gst_d3d11_memory_get_render_target_view_size (dmem); - if (!rtv_size) { - GST_ERROR_OBJECT (self, "Render target view is unavailable"); - return GST_FLOW_ERROR; - } - - for (j = 0; j < rtv_size; j++) { - g_assert (view_idx < GST_VIDEO_MAX_PLANES); - rtv[view_idx] = gst_d3d11_memory_get_render_target_view (dmem, j); - view_idx++; - } + if (!gst_video_frame_map (&target_frame, &vagg->info, target_buf, + (GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) { + GST_ERROR_OBJECT (self, "Failed to map render target frame"); + return GST_FLOW_ERROR; + } - /* Mark need-download for fallback buffer use case */ - GST_MINI_OBJECT_FLAG_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); + if (!gst_d3d11_buffer_get_render_target_view (target_buf, rtv)) { + GST_ERROR_OBJECT (self, "RTV is unavailable"); + gst_video_frame_unmap (&target_frame); + return GST_FLOW_ERROR; } gst_d3d11_device_lock (self->device); - /* XXX: the number of render target view must be one here, since we support - * only RGBA or BGRA */ - if (!gst_d3d11_compositor_draw_background (self, rtv[0])) { + if (!gst_d3d11_compositor_draw_background (self, rtv, num_rtv)) { GST_ERROR_OBJECT (self, "Couldn't draw background"); gst_d3d11_device_unlock (self->device); - ret = GST_FLOW_ERROR; - goto done; + gst_video_frame_unmap (&target_frame); + return GST_FLOW_ERROR; } GST_OBJECT_LOCK (self); - for (iter = GST_ELEMENT (vagg)->sinkpads; iter; iter = g_list_next (iter)) { GstVideoAggregatorPad *pad = GST_VIDEO_AGGREGATOR_PAD (iter->data); GstD3D11CompositorPad *cpad = GST_D3D11_COMPOSITOR_PAD (pad); GstVideoFrame *prepared_frame = gst_video_aggregator_pad_get_prepared_frame (pad); - ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES] = { NULL, }; + ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES] = { nullptr, }; GstBuffer *buffer; if (!prepared_frame) @@ -2393,45 +2275,58 @@ gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg, } buffer = prepared_frame->buffer; + if (cpad->piv) { + if (!pov) { + GstD3D11Memory *dmem = + (GstD3D11Memory *) gst_buffer_peek_memory (target_buf, 0); + pov = gst_d3d11_video_processor_get_output_view (cpad->processor, dmem); + } - view_idx = 0; - for (i = 0; i < gst_buffer_n_memory (buffer); i++) { - GstD3D11Memory *dmem = - (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i); - guint srv_size = gst_d3d11_memory_get_shader_resource_view_size (dmem); + if (!pov) { + GST_ERROR_OBJECT (self, "POV is unavailable"); + ret = GST_FLOW_ERROR; + break; + } - for (j = 0; j < srv_size; j++) { - g_assert (view_idx < GST_VIDEO_MAX_PLANES); + if (!gst_d3d11_video_processor_render_unlocked (cpad->processor, + &cpad->src_rect, cpad->piv, &cpad->dest_rect, pov)) { + GST_ERROR_OBJECT (self, "Failed to convert using processor"); + ret = GST_FLOW_ERROR; + break; + } - srv[view_idx] = gst_d3d11_memory_get_shader_resource_view (dmem, j); - view_idx++; + GST_TRACE_OBJECT (pad, "Blended using processor"); + } else { + if (!gst_d3d11_buffer_get_shader_resource_view (buffer, srv)) { + GST_ERROR_OBJECT (pad, "SRV is unavailable"); + ret = GST_FLOW_ERROR; + break; } - } - if (!gst_d3d11_converter_convert_unlocked (cpad->convert, srv, rtv)) { - GST_ERROR_OBJECT (self, "Couldn't convert frame"); - ret = GST_FLOW_ERROR; - break; + if (!gst_d3d11_converter_convert_unlocked (cpad->convert, srv, rtv)) { + GST_ERROR_OBJECT (self, "Couldn't convert frame"); + ret = GST_FLOW_ERROR; + break; + } + + GST_TRACE_OBJECT (pad, "Blended using converter"); } } - - self->reconfigured = FALSE; GST_OBJECT_UNLOCK (self); gst_d3d11_device_unlock (self->device); + gst_video_frame_unmap (&target_frame); if (ret != GST_FLOW_OK) - goto done; + return ret; - if (need_copy && !gst_d3d11_compositor_copy_buffer (self, &vagg->info, - target_buf, outbuf, do_device_copy)) { - GST_ERROR_OBJECT (self, "Couldn't copy input buffer to fallback buffer"); - ret = GST_FLOW_ERROR; + if (!self->downstream_supports_d3d11) { + if (!gst_d3d11_buffer_copy_into (outbuf, self->fallback_buf, &vagg->info)) { + GST_ERROR_OBJECT (self, "Couldn't copy input buffer to fallback buffer"); + return GST_FLOW_ERROR; + } } -done: - gst_clear_buffer (&self->fallback_buf); - - return ret; + return GST_FLOW_OK; } typedef struct @@ -2462,13 +2357,8 @@ gst_d3d11_compositor_check_device_update (GstElement * agg, } mem = gst_buffer_peek_memory (buf, 0); - /* FIXME: we should be able to accept non-d3d11 memory later once - * we remove intermediate elements (d3d11upload and d3d11colorconvert) - */ - if (!gst_is_d3d11_memory (mem)) { - GST_ELEMENT_ERROR (agg, CORE, FAILED, (NULL), ("Invalid memory")); - return FALSE; - } + if (!gst_is_d3d11_memory (mem)) + return TRUE; dmem = GST_D3D11_MEMORY_CAST (mem); @@ -2483,7 +2373,7 @@ gst_d3d11_compositor_check_device_update (GstElement * agg, } else { guint adapter = 0; - g_object_get (dmem->device, "adapter", &adapter, NULL); + g_object_get (dmem->device, "adapter", &adapter, nullptr); /* The same GPU as what user wanted, update */ if (adapter == (guint) self->adapter) update_device = TRUE; @@ -2508,25 +2398,25 @@ gst_d3d11_compositor_create_output_buffer (GstVideoAggregator * vagg, /* Check whether there is at least one sinkpad which holds d3d11 buffer * with compatible device, and if not, update our device */ - data.other_device = NULL; + data.other_device = nullptr; data.have_same_device = FALSE; gst_element_foreach_sink_pad (GST_ELEMENT_CAST (vagg), (GstElementForeachPadFunc) gst_d3d11_compositor_check_device_update, &data); - if (data.have_same_device || !data.other_device) - goto done; + if (data.have_same_device || !data.other_device) { + return + GST_VIDEO_AGGREGATOR_CLASS (parent_class)->create_output_buffer (vagg, + outbuffer); + } /* Clear all device dependent resources */ gst_element_foreach_sink_pad (GST_ELEMENT_CAST (vagg), - (GstElementForeachPadFunc) gst_d3d11_compositor_pad_clear_resource, NULL); + (GstElementForeachPadFunc) gst_d3d11_compositor_pad_clear_resource, + nullptr); gst_clear_buffer (&self->fallback_buf); - if (self->fallback_pool) { - gst_buffer_pool_set_active (self->fallback_pool, FALSE); - gst_clear_object (&self->fallback_pool); - } g_clear_pointer (&self->checker_background, gst_d3d11_compositor_quad_free); GST_INFO_OBJECT (self, "Updating device %" GST_PTR_FORMAT " -> %" @@ -2540,8 +2430,4 @@ gst_d3d11_compositor_create_output_buffer (GstVideoAggregator * vagg, gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (vagg)); return GST_AGGREGATOR_FLOW_NEED_DATA; - -done: - return GST_VIDEO_AGGREGATOR_CLASS (parent_class)->create_output_buffer (vagg, - outbuffer); } diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.h b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.h index 78a79ab..ed084a0 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.h +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.h @@ -1,6 +1,6 @@ /* * GStreamer - * Copyright (C) 2020 Seungha Yang + * Copyright (C) 2022 Seungha Yang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -18,8 +18,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __GST_D3D11_COMPOSITOR_H__ -#define __GST_D3D11_COMPOSITOR_H__ +#pragma once #include #include @@ -36,58 +35,5 @@ G_DECLARE_FINAL_TYPE (GstD3D11CompositorPad, gst_d3d11_compositor_pad, G_DECLARE_FINAL_TYPE (GstD3D11Compositor, gst_d3d11_compositor, GST, D3D11_COMPOSITOR, GstVideoAggregator) -typedef enum -{ - GST_D3D11_COMPOSITOR_BLEND_OP_ADD, - GST_D3D11_COMPOSITOR_BLEND_OP_SUBTRACT, - GST_D3D11_COMPOSITOR_BLEND_OP_REV_SUBTRACT, - GST_D3D11_COMPOSITOR_BLEND_OP_MIN, - GST_D3D11_COMPOSITOR_BLEND_OP_MAX -} GstD3D11CompositorBlendOperation; - -#define GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION (gst_d3d11_compositor_blend_operation_get_type()) -GType gst_d3d11_compositor_blend_operation_get_type (void); - -typedef enum -{ - GST_D3D11_COMPOSITOR_BLEND_ZERO, - GST_D3D11_COMPOSITOR_BLEND_ONE, - GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR, - GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR, - GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA, - GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA, - GST_D3D11_COMPOSITOR_BLEND_DEST_ALPHA, - GST_D3D11_COMPOSITOR_BLEND_INV_DEST_ALPHA, - GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR, - GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR, - GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA_SAT, - GST_D3D11_COMPOSITOR_BLEND_BLEND_FACTOR, - GST_D3D11_COMPOSITOR_BLEND_INV_BLEND_FACTOR, -} GstD3D11CompositorBlend; - -#define GST_TYPE_D3D11_COMPOSITOR_BLEND (gst_d3d11_compositor_blend_get_type()) -GType gst_d3d11_compositor_blend_get_type (void); - -typedef enum -{ - GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER, - GST_D3D11_COMPOSITOR_BACKGROUND_BLACK, - GST_D3D11_COMPOSITOR_BACKGROUND_WHITE, - GST_D3D11_COMPOSITOR_BACKGROUND_TRANSPARENT, -} GstD3D11CompositorBackground; - -#define GST_TYPE_D3D11_COMPOSITOR_BACKGROUND (gst_d3d11_compositor_background_get_type()) -GType gst_d3d11_compositor_background_get_type (void); - -typedef enum -{ - GST_D3D11_COMPOSITOR_SIZING_POLICY_NONE, - GST_D3D11_COMPOSITOR_SIZING_POLICY_KEEP_ASPECT_RATIO, -} GstD3D11CompositorSizingPolicy; - -#define GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY (gst_d3d11_compositor_sizing_policy_get_type()) -GType gst_d3d11_compositor_sizing_policy_get_type (void); - G_END_DECLS -#endif /* __GST_D3D11_COMPOSITOR_H__ */ diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.cpp deleted file mode 100644 index 1e60797..0000000 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.cpp +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters - * Copyright (C) 2020 Seungha Yang - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-d3d11compositor - * @title: d3d11compositor - * - * A convenient bin which wraps #d3d11compositorelement for video composition - * with other helper elements to handle color conversion and memory transfer - * between Direct3D11 and system memory space. - * - * ## Example launch line - * ``` - * gst-launch-1.0 d3d11compositor name=c ! d3d11videosink \ - * videotestsrc ! video/x-raw,width=320,height=240 ! c. \ - * videotestsrc pattern=ball ! video/x-raw,width=100,height=100 ! c. - * ``` - * - * Since: 1.20 - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "gstd3d11compositorbin.h" -#include "gstd3d11compositor.h" -#include "gstd3d11pluginutils.h" - -GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_compositor_debug); -#define GST_CAT_DEFAULT gst_d3d11_compositor_debug - -/**************************** - * GstD3D11CompositorBinPad * - ****************************/ - -enum -{ - PROP_PAD_0, - /* GstAggregatorPad */ - PROP_PAD_EMIT_SIGNALS, -}; - -/* GstAggregatorPad */ -#define DEFAULT_PAD_EMIT_SIGNALS FALSE - -enum -{ - /* GstAggregatorPad */ - SIGNAL_PAD_BUFFER_CONSUMED = 0, - SIGNAL_PAD_LAST, -}; - -static guint gst_d3d11_compositor_bin_pad_signals[SIGNAL_PAD_LAST] = { 0 }; - -/** - * GstD3D11CompositorBinPad: - * - * Since: 1.20 - */ -struct _GstD3D11CompositorBinPad -{ - GstGhostPad parent; - - /* Holds ref */ - GstPad *target; - gulong sig_id; -}; - -static void gst_d3d11_compositor_bin_pad_dispose (GObject * object); -static void gst_d3d11_compositor_bin_pad_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_d3d11_compositor_bin_pad_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); -static void -gst_d3d11_compositor_bin_pad_set_target_default (GstD3D11CompositorBinPad * pad, - GstPad * target); - -G_DEFINE_TYPE (GstD3D11CompositorBinPad, gst_d3d11_compositor_bin_pad, - GST_TYPE_GHOST_PAD); - -static void -gst_d3d11_compositor_bin_pad_class_init (GstD3D11CompositorBinPadClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->dispose = gst_d3d11_compositor_bin_pad_dispose; - gobject_class->set_property = gst_d3d11_compositor_bin_pad_set_property; - gobject_class->get_property = gst_d3d11_compositor_bin_pad_get_property; - - /* GstAggregatorPad */ - g_object_class_install_property (gobject_class, PROP_PAD_EMIT_SIGNALS, - g_param_spec_boolean ("emit-signals", "Emit signals", - "Send signals to signal data consumption", - DEFAULT_PAD_EMIT_SIGNALS, - (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - gst_d3d11_compositor_bin_pad_signals[SIGNAL_PAD_BUFFER_CONSUMED] = - g_signal_new ("buffer-consumed", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_BUFFER); - - klass->set_target = - GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_pad_set_target_default); -} - -static void -gst_d3d11_compositor_bin_pad_init (GstD3D11CompositorBinPad * self) -{ -} - -static void -gst_d3d11_compositor_bin_pad_dispose (GObject * object) -{ - GstD3D11CompositorBinPad *self = GST_D3D11_COMPOSITOR_BIN_PAD (object); - - gst_clear_object (&self->target); - - G_OBJECT_CLASS (gst_d3d11_compositor_bin_pad_parent_class)->dispose (object); -} - -static void -gst_d3d11_compositor_bin_pad_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec) -{ - GstD3D11CompositorBinPad *self = GST_D3D11_COMPOSITOR_BIN_PAD (object); - - if (self->target) - g_object_set_property (G_OBJECT (self->target), pspec->name, value); -} - -static void -gst_d3d11_compositor_bin_pad_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - GstD3D11CompositorBinPad *self = GST_D3D11_COMPOSITOR_BIN_PAD (object); - - if (self->target) - g_object_get_property (G_OBJECT (self->target), pspec->name, value); -} - -static void -gst_d3d11_compositor_bin_pad_on_buffer_consumed (GstAggregatorPad * pad, - GstBuffer * buffer, GstD3D11CompositorBinPad * self) -{ - g_signal_emit (self, - gst_d3d11_compositor_bin_pad_signals[SIGNAL_PAD_BUFFER_CONSUMED], - 0, buffer); -} - -/** - * gst_d3d11_compositor_bin_pad_set_target: - * @self: a #GstD3D11CompositorBinPad - * @target: (transfer full): a #GstAggregatorPad - */ -static void -gst_d3d11_compositor_bin_pad_set_target (GstD3D11CompositorBinPad * pad, - GstPad * target) -{ - GstD3D11CompositorBinPadClass *klass = - GST_D3D11_COMPOSITOR_BIN_PAD_GET_CLASS (pad); - - klass->set_target (pad, target); -} - -static void -gst_d3d11_compositor_bin_pad_set_target_default (GstD3D11CompositorBinPad * pad, - GstPad * target) -{ - pad->target = target; - pad->sig_id = g_signal_connect (target, "buffer-consumed", - G_CALLBACK (gst_d3d11_compositor_bin_pad_on_buffer_consumed), pad); -} - -static void -gst_d3d11_compositor_bin_pad_unset_target (GstD3D11CompositorBinPad * self) -{ - if (!self->target) - return; - - if (self->sig_id) - g_signal_handler_disconnect (self->target, self->sig_id); - self->sig_id = 0; - gst_clear_object (&self->target); -} - -/****************************** - * GstD3D11CompositorBinInput * - ******************************/ - -enum -{ - PROP_INPUT_0, - /* GstVideoAggregatorPad */ - PROP_INPUT_ZORDER, - PROP_INPUT_REPEAT_AFTER_EOS, - PROP_INPUT_MAX_LAST_BUFFER_REPEAT, - /* GstD3D11CompositorPad */ - PROP_INPUT_XPOS, - PROP_INPUT_YPOS, - PROP_INPUT_WIDTH, - PROP_INPUT_HEIGHT, - PROP_INPUT_ALPHA, - PROP_INPUT_BLEND_OP_RGB, - PROP_INPUT_BLEND_OP_ALPHA, - PROP_INPUT_BLEND_SRC_RGB, - PROP_INPUT_BLEND_SRC_ALPHA, - PROP_INPUT_BLEND_DEST_RGB, - PROP_INPUT_BLEND_DEST_ALPHA, - PROP_INPUT_BLEND_FACTOR_RED, - PROP_INPUT_BLEND_FACTOR_GREEN, - PROP_INPUT_BLEND_FACTOR_BLUE, - PROP_INPUT_BLEND_FACTOR_ALPHA, - PROP_INPUT_SIZING_POLICY, -}; - -/* GstVideoAggregatorPad */ -#define DEFAULT_INPUT_ZORDER 0 -#define DEFAULT_INPUT_REPEAT_AFTER_EOS FALSE -#define DEFAULT_INPUT_MAX_LAST_BUFFER_REPEAT GST_CLOCK_TIME_NONE -/* GstD3D11CompositorPad */ -#define DEFAULT_INPUT_XPOS 0 -#define DEFAULT_INPUT_YPOS 0 -#define DEFAULT_INPUT_WIDTH 0 -#define DEFAULT_INPUT_HEIGHT 0 -#define DEFAULT_INPUT_ALPHA 1.0 -#define DEFAULT_INPUT_BLEND_OP_RGB GST_D3D11_COMPOSITOR_BLEND_OP_ADD -#define DEFAULT_INPUT_BLEND_OP_ALPHA GST_D3D11_COMPOSITOR_BLEND_OP_ADD -#define DEFAULT_INPUT_BLEND_SRC_RGB GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA -#define DEFAULT_INPUT_BLEND_SRC_ALPHA GST_D3D11_COMPOSITOR_BLEND_ONE -#define DEFAULT_INPUT_BLEND_DEST_RGB GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA -#define DEFAULT_INPUT_BLEND_DEST_ALPHA GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA -#define DEFAULT_INPUT_SIZING_POLICY GST_D3D11_COMPOSITOR_SIZING_POLICY_NONE - -/** - * GstD3D11CompositorBinInput: - * - * Since: 1.20 - */ -struct _GstD3D11CompositorBinInput -{ - GstD3D11CompositorBinPad parent; -}; - -static void gst_d3d11_compositor_bin_input_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_d3d11_compositor_bin_input_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); -static void -gst_d3d11_compositor_bin_input_set_target (GstD3D11CompositorBinPad * pad, - GstPad * target); - -#define gst_d3d11_compositor_bin_input_parent_class input_parent_class -G_DEFINE_TYPE (GstD3D11CompositorBinInput, gst_d3d11_compositor_bin_input, - GST_TYPE_D3D11_COMPOSITOR_BIN_PAD); - -static void -gst_d3d11_compositor_bin_input_class_init (GstD3D11CompositorBinInputClass * - klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstD3D11CompositorBinPadClass *pad_class = - GST_D3D11_COMPOSITOR_BIN_PAD_CLASS (klass); - - gobject_class->set_property = gst_d3d11_compositor_bin_input_set_property; - gobject_class->get_property = gst_d3d11_compositor_bin_input_get_property; - - /* GstVideoAggregatorPad */ - g_object_class_install_property (gobject_class, PROP_INPUT_ZORDER, - g_param_spec_uint ("zorder", "Z-Order", "Z Order of the picture", - 0, G_MAXUINT, DEFAULT_INPUT_ZORDER, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_REPEAT_AFTER_EOS, - g_param_spec_boolean ("repeat-after-eos", "Repeat After EOS", - "Repeat the " "last frame after EOS until all pads are EOS", - DEFAULT_INPUT_REPEAT_AFTER_EOS, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, - PROP_INPUT_MAX_LAST_BUFFER_REPEAT, - g_param_spec_uint64 ("max-last-buffer-repeat", "Max Last Buffer Repeat", - "Repeat last buffer for time (in ns, -1=until EOS), " - "behaviour on EOS is not affected", 0, G_MAXUINT64, - DEFAULT_INPUT_MAX_LAST_BUFFER_REPEAT, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | - G_PARAM_STATIC_STRINGS))); - - /* GstD3D11CompositorPad */ - g_object_class_install_property (gobject_class, PROP_INPUT_XPOS, - g_param_spec_int ("xpos", "X Position", "X position of the picture", - G_MININT, G_MAXINT, DEFAULT_INPUT_XPOS, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_YPOS, - g_param_spec_int ("ypos", "Y Position", "Y position of the picture", - G_MININT, G_MAXINT, DEFAULT_INPUT_YPOS, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_WIDTH, - g_param_spec_int ("width", "Width", "Width of the picture", - G_MININT, G_MAXINT, DEFAULT_INPUT_WIDTH, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_HEIGHT, - g_param_spec_int ("height", "Height", "Height of the picture", - G_MININT, G_MAXINT, DEFAULT_INPUT_HEIGHT, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_ALPHA, - g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0, - DEFAULT_INPUT_ALPHA, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_OP_RGB, - g_param_spec_enum ("blend-op-rgb", "Blend Operation RGB", - "Blend equation for RGB", GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION, - DEFAULT_INPUT_BLEND_OP_RGB, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_OP_ALPHA, - g_param_spec_enum ("blend-op-alpha", "Blend Operation Alpha", - "Blend equation for alpha", GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION, - DEFAULT_INPUT_BLEND_OP_ALPHA, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, - PROP_INPUT_BLEND_SRC_RGB, - g_param_spec_enum ("blend-src-rgb", "Blend Source RGB", - "Blend factor for source RGB", - GST_TYPE_D3D11_COMPOSITOR_BLEND, - DEFAULT_INPUT_BLEND_SRC_RGB, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, - PROP_INPUT_BLEND_SRC_ALPHA, - g_param_spec_enum ("blend-src-alpha", - "Blend Source Alpha", - "Blend factor for source alpha, \"*-color\" values are not allowed", - GST_TYPE_D3D11_COMPOSITOR_BLEND, - DEFAULT_INPUT_BLEND_SRC_ALPHA, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, - PROP_INPUT_BLEND_DEST_RGB, - g_param_spec_enum ("blend-dest-rgb", - "Blend Destination RGB", - "Blend factor for destination RGB", - GST_TYPE_D3D11_COMPOSITOR_BLEND, - DEFAULT_INPUT_BLEND_DEST_RGB, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, - PROP_INPUT_BLEND_DEST_ALPHA, - g_param_spec_enum ("blend-dest-alpha", - "Blend Destination Alpha", - "Blend factor for destination alpha, " - "\"*-color\" values are not allowed", - GST_TYPE_D3D11_COMPOSITOR_BLEND, - DEFAULT_INPUT_BLEND_DEST_ALPHA, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_FACTOR_RED, - g_param_spec_float ("blend-factor-red", "Blend Factor Red", - "Blend factor for red component " - "when blend type is \"blend-factor\" or \"inv-blend-factor\"", - 0.0, 1.0, 1.0, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_FACTOR_GREEN, - g_param_spec_float ("blend-factor-green", "Blend Factor Green", - "Blend factor for green component " - "when blend type is \"blend-factor\" or \"inv-blend-factor\"", - 0.0, 1.0, 1.0, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_FACTOR_BLUE, - g_param_spec_float ("blend-factor-blue", "Blend Factor Blue", - "Blend factor for blue component " - "when blend type is \"blend-factor\" or \"inv-blend-factor\"", - 0.0, 1.0, 1.0, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_FACTOR_ALPHA, - g_param_spec_float ("blend-factor-alpha", "Blend Factor Alpha", - "Blend factor for alpha component " - "when blend type is \"blend-factor\" or \"inv-blend-factor\"", - 0.0, 1.0, 1.0, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_INPUT_SIZING_POLICY, - g_param_spec_enum ("sizing-policy", "Sizing policy", - "Sizing policy to use for image scaling", - GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY, DEFAULT_INPUT_SIZING_POLICY, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | - G_PARAM_STATIC_STRINGS))); - - pad_class->set_target = - GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_input_set_target); -} - -static void -gst_d3d11_compositor_bin_input_init (GstD3D11CompositorBinInput * self) -{ -} - -static void -gst_d3d11_compositor_bin_input_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec) -{ - GstD3D11CompositorBinPad *pad = GST_D3D11_COMPOSITOR_BIN_PAD (object); - - if (pad->target) - g_object_set_property (G_OBJECT (pad->target), pspec->name, value); -} - -static void -gst_d3d11_compositor_bin_input_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - GstD3D11CompositorBinPad *pad = GST_D3D11_COMPOSITOR_BIN_PAD (object); - - if (pad->target) - g_object_get_property (G_OBJECT (pad->target), pspec->name, value); -} - -static void -gst_d3d11_compositor_bin_input_set_target (GstD3D11CompositorBinPad * pad, - GstPad * target) -{ - GST_D3D11_COMPOSITOR_BIN_PAD_CLASS (input_parent_class)->set_target (pad, - target); - -#define ADD_BINDING(obj,ref,prop) \ - gst_object_add_control_binding (GST_OBJECT (obj), \ - gst_proxy_control_binding_new (GST_OBJECT (obj), prop, \ - GST_OBJECT (ref), prop)); - /* GstVideoAggregatorPad */ - ADD_BINDING (target, pad, "zorder"); - ADD_BINDING (target, pad, "repeat-after-eos"); - /* GstD3D11CompositorPad */ - ADD_BINDING (target, pad, "xpos"); - ADD_BINDING (target, pad, "ypos"); - ADD_BINDING (target, pad, "width"); - ADD_BINDING (target, pad, "height"); - ADD_BINDING (target, pad, "alpha"); - ADD_BINDING (target, pad, "blend-op-rgb"); - ADD_BINDING (target, pad, "blend-op-alpha"); - ADD_BINDING (target, pad, "blend-src-rgb"); - ADD_BINDING (target, pad, "blend-src-alpha"); - ADD_BINDING (target, pad, "blend-dest-rgb"); - ADD_BINDING (target, pad, "blend-dest-alpha"); - ADD_BINDING (target, pad, "blend-factor-red"); - ADD_BINDING (target, pad, "blend-factor-green"); - ADD_BINDING (target, pad, "blend-factor-blue"); - ADD_BINDING (target, pad, "blend-factor-alpha"); - ADD_BINDING (target, pad, "sizing-policy"); -#undef ADD_BINDING -} - -/************************* - * GstD3D11CompositorBin * - *************************/ - -static GstStaticCaps sink_template_caps = - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES - (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_SINK_FORMATS) ";" - GST_VIDEO_CAPS_MAKE (GST_D3D11_SINK_FORMATS)); - -static GstStaticCaps src_template_caps = - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES - (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_SRC_FORMATS) ";" - GST_VIDEO_CAPS_MAKE (GST_D3D11_SRC_FORMATS)); - -enum -{ - PROP_0, - PROP_MIXER, - /* GstAggregator */ - PROP_LATENCY, - PROP_MIN_UPSTREAM_LATENCY, - PROP_START_TIME_SELECTION, - PROP_START_TIME, - PROP_EMIT_SIGNALS, - /* GstD3D11Compositor */ - PROP_ADAPTER, - PROP_BACKGROUND, - PROP_LAST -}; - -/* GstAggregator */ -#define DEFAULT_LATENCY 0 -#define DEFAULT_MIN_UPSTREAM_LATENCY 0 -#define DEFAULT_START_TIME_SELECTION GST_AGGREGATOR_START_TIME_SELECTION_ZERO -#define DEFAULT_START_TIME (-1) -#define DEFAULT_EMIT_SIGNALS FALSE - -/* GstD3D11Compositor */ -#define DEFAULT_ADAPTER -1 -#define DEFAULT_BACKGROUND GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER - -typedef struct _GstD3D11CompositorBinChain -{ - /* without ref */ - GstD3D11CompositorBin *self; - GstD3D11CompositorBinPad *ghost_pad; - GstElement *upload; - GstElement *convert; - - gulong probe_id; -} GstD3D11CompositorBinChain; - -struct _GstD3D11CompositorBin -{ - GstBin parent; - - GstElement *compositor; - - GList *input_chains; - gboolean running; - - gint adapter; -}; - -static void gst_d3d11_compositor_bin_child_proxy_init (gpointer g_iface, - gpointer iface_data); -static void gst_d3d11_compositor_bin_dispose (GObject * object); -static void gst_d3d11_compositor_bin_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_d3d11_compositor_bin_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn -gst_d3d11_compositor_bin_change_state (GstElement * element, - GstStateChange transition); -static GstPad *gst_d3d11_compositor_bin_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * name, const GstCaps * caps); -static void gst_d3d11_compositor_bin_release_pad (GstElement * element, - GstPad * pad); - -#define gst_d3d11_compositor_bin_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstD3D11CompositorBin, gst_d3d11_compositor_bin, - GST_TYPE_BIN, G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY, - gst_d3d11_compositor_bin_child_proxy_init)); - -static void -gst_d3d11_compositor_bin_class_init (GstD3D11CompositorBinClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - GstCaps *caps; - - gobject_class->dispose = gst_d3d11_compositor_bin_dispose; - gobject_class->set_property = gst_d3d11_compositor_bin_set_property; - gobject_class->get_property = gst_d3d11_compositor_bin_get_property; - - element_class->change_state = - GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_change_state); - element_class->request_new_pad = - GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_request_new_pad); - element_class->release_pad = - GST_DEBUG_FUNCPTR (gst_d3d11_compositor_bin_release_pad); - - gst_element_class_set_static_metadata (element_class, - "Direct3D11 Compositor Bin", - "Filter/Editor/Video/Compositor", - "A Direct3D11 compositor bin", "Seungha Yang "); - - caps = gst_d3d11_get_updated_template_caps (&sink_template_caps); - gst_element_class_add_pad_template (element_class, - gst_pad_template_new_with_gtype ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, - caps, GST_TYPE_D3D11_COMPOSITOR_BIN_INPUT)); - gst_caps_unref (caps); - - caps = gst_d3d11_get_updated_template_caps (&src_template_caps); - gst_element_class_add_pad_template (element_class, - gst_pad_template_new_with_gtype ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - caps, GST_TYPE_D3D11_COMPOSITOR_BIN_PAD)); - gst_caps_unref (caps); - - g_object_class_install_property (gobject_class, PROP_MIXER, - g_param_spec_object ("mixer", "D3D11 mixer element", - "The d3d11 mixer chain to use", - GST_TYPE_ELEMENT, - (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); - - /*GstAggregator */ - g_object_class_install_property (gobject_class, PROP_LATENCY, - g_param_spec_uint64 ("latency", "Buffer latency", - "Additional latency in live mode to allow upstream " - "to take longer to produce buffers for the current " - "position (in nanoseconds)", 0, G_MAXUINT64, - DEFAULT_LATENCY, - (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_MIN_UPSTREAM_LATENCY, - g_param_spec_uint64 ("min-upstream-latency", "Buffer latency", - "When sources with a higher latency are expected to be plugged " - "in dynamically after the aggregator has started playing, " - "this allows overriding the minimum latency reported by the " - "initial source(s). This is only taken into account when larger " - "than the actually reported minimum latency. (nanoseconds)", - 0, G_MAXUINT64, - DEFAULT_LATENCY, - (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_START_TIME_SELECTION, - g_param_spec_enum ("start-time-selection", "Start Time Selection", - "Decides which start time is output", - gst_aggregator_start_time_selection_get_type (), - DEFAULT_START_TIME_SELECTION, - (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_START_TIME, - g_param_spec_uint64 ("start-time", "Start Time", - "Start time to use if start-time-selection=set", 0, - G_MAXUINT64, - DEFAULT_START_TIME, - (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS, - g_param_spec_boolean ("emit-signals", "Emit signals", - "Send signals", DEFAULT_EMIT_SIGNALS, - (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - /* GstD3D11Compositor */ - g_object_class_install_property (gobject_class, PROP_ADAPTER, - g_param_spec_int ("adapter", "Adapter", - "Adapter index for creating device (-1 for default)", - -1, G_MAXINT32, DEFAULT_ADAPTER, - (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY | - G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (gobject_class, PROP_BACKGROUND, - g_param_spec_enum ("background", "Background", "Background type", - GST_TYPE_D3D11_COMPOSITOR_BACKGROUND, - DEFAULT_BACKGROUND, - (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_BIN_PAD, - (GstPluginAPIFlags) 0); - gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_BIN_INPUT, - (GstPluginAPIFlags) 0); -} - -static void -gst_d3d11_compositor_bin_init (GstD3D11CompositorBin * self) -{ - GstPad *pad; - GstPad *gpad; - GstElement *out_convert, *download; - - self->compositor = gst_element_factory_make ("d3d11compositorelement", NULL); - out_convert = gst_element_factory_make ("d3d11colorconvert", NULL); - download = gst_element_factory_make ("d3d11download", NULL); - - gst_bin_add_many (GST_BIN (self), - self->compositor, out_convert, download, NULL); - gst_element_link_many (self->compositor, out_convert, download, NULL); - - gpad = (GstPad *) g_object_new (GST_TYPE_D3D11_COMPOSITOR_BIN_PAD, - "name", "src", "direction", GST_PAD_SRC, NULL); - pad = gst_element_get_static_pad (self->compositor, "src"); - /* GstD3D11CompositorBinPad will hold reference of this compositor srcpad */ - gst_d3d11_compositor_bin_pad_set_target ((GstD3D11CompositorBinPad *) gpad, - pad); - - pad = gst_element_get_static_pad (download, "src"); - gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (gpad), pad); - gst_object_unref (pad); - - gst_element_add_pad (GST_ELEMENT_CAST (self), gpad); -} - -static void -gst_d3d11_compositor_bin_dispose (GObject * object) -{ - GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (object); - GList *iter; - - for (iter = self->input_chains; iter; iter = g_list_next (iter)) { - GstD3D11CompositorBinChain *chain = - (GstD3D11CompositorBinChain *) iter->data; - - if (self->compositor && chain->ghost_pad && chain->ghost_pad->target) { - gst_element_release_request_pad (GST_ELEMENT_CAST (self->compositor), - chain->ghost_pad->target); - gst_d3d11_compositor_bin_pad_unset_target (chain->ghost_pad); - } - } - - if (self->input_chains) - g_list_free_full (self->input_chains, (GDestroyNotify) g_free); - self->input_chains = NULL; - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -gst_d3d11_compositor_bin_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec) -{ - GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (object); - - switch (prop_id) { - case PROP_ADAPTER: - self->adapter = g_value_get_int (value); - /* fallthrough */ - default: - g_object_set_property (G_OBJECT (self->compositor), pspec->name, value); - break; - } -} - -static void -gst_d3d11_compositor_bin_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (object); - - switch (prop_id) { - case PROP_MIXER: - g_value_set_object (value, self->compositor); - break; - case PROP_ADAPTER: - g_value_set_int (value, self->adapter); - break; - default: - g_object_get_property (G_OBJECT (self->compositor), pspec->name, value); - break; - } -} - -static GstStateChangeReturn -gst_d3d11_compositor_bin_change_state (GstElement * element, - GstStateChange transition) -{ - GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (element); - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - GST_OBJECT_LOCK (element); - self->running = TRUE; - GST_OBJECT_UNLOCK (element); - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - GST_OBJECT_LOCK (self); - self->running = FALSE; - GST_OBJECT_UNLOCK (self); - default: - break; - } - - return ret; -} - -static GstD3D11CompositorBinChain * -gst_d3d11_compositor_bin_input_chain_new (GstD3D11CompositorBin * self, - GstPad * compositor_pad) -{ - GstD3D11CompositorBinChain *chain; - GstPad *pad; - - chain = g_new0 (GstD3D11CompositorBinChain, 1); - - chain->self = self; - - chain->upload = gst_element_factory_make ("d3d11upload", NULL); - chain->convert = gst_element_factory_make ("d3d11colorconvert", NULL); - - /* 1. Create child elements and like */ - gst_bin_add_many (GST_BIN (self), chain->upload, chain->convert, NULL); - - gst_element_link (chain->upload, chain->convert); - pad = gst_element_get_static_pad (chain->convert, "src"); - gst_pad_link (pad, compositor_pad); - gst_object_unref (pad); - - chain->ghost_pad = (GstD3D11CompositorBinPad *) - g_object_new (GST_TYPE_D3D11_COMPOSITOR_BIN_INPUT, "name", - GST_OBJECT_NAME (compositor_pad), "direction", GST_PAD_SINK, NULL); - - /* transfer ownership of compositor pad */ - gst_d3d11_compositor_bin_pad_set_target (chain->ghost_pad, compositor_pad); - - pad = gst_element_get_static_pad (chain->upload, "sink"); - gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->ghost_pad), pad); - gst_object_unref (pad); - - GST_OBJECT_LOCK (self); - if (self->running) - gst_pad_set_active (GST_PAD (chain->ghost_pad), TRUE); - GST_OBJECT_UNLOCK (self); - - gst_element_add_pad (GST_ELEMENT_CAST (self), - GST_PAD_CAST (chain->ghost_pad)); - - gst_element_sync_state_with_parent (chain->upload); - gst_element_sync_state_with_parent (chain->convert); - - return chain; -} - -static void -gst_d3d11_compositor_bin_input_chain_free (GstD3D11CompositorBinChain * chain) -{ - if (!chain) - return; - - if (chain->ghost_pad && chain->probe_id) { - gst_pad_remove_probe (GST_PAD_CAST (chain->ghost_pad), chain->probe_id); - chain->probe_id = 0; - } - - if (chain->upload) { - gst_element_set_state (chain->upload, GST_STATE_NULL); - gst_bin_remove (GST_BIN_CAST (chain->self), chain->upload); - } - - if (chain->convert) { - gst_element_set_state (chain->convert, GST_STATE_NULL); - gst_bin_remove (GST_BIN_CAST (chain->self), chain->convert); - } - - if (chain->ghost_pad && chain->ghost_pad->target) { - gst_element_release_request_pad (chain->self->compositor, - chain->ghost_pad->target); - gst_d3d11_compositor_bin_pad_unset_target (chain->ghost_pad); - } - - g_free (chain); -} - -static GstPad * -gst_d3d11_compositor_bin_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * name, const GstCaps * caps) -{ - GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (element); - GstElementClass *compositor_class = GST_ELEMENT_GET_CLASS (self->compositor); - GstPad *compositor_pad; - GstD3D11CompositorBinChain *chain; - GstPadTemplate *compositor_templ = NULL; - GList *templ_list; - GList *iter; - - templ_list = gst_element_class_get_pad_template_list (compositor_class); - for (iter = templ_list; iter; iter = g_list_next (iter)) { - GstPadTemplate *t = (GstPadTemplate *) iter->data; - if (GST_PAD_TEMPLATE_DIRECTION (t) != GST_PAD_SINK || - GST_PAD_TEMPLATE_PRESENCE (t) != GST_PAD_REQUEST) - continue; - - compositor_templ = t; - break; - } - - g_assert (compositor_templ); - - compositor_pad = - gst_element_request_pad (self->compositor, compositor_templ, name, caps); - if (!compositor_pad) { - GST_WARNING_OBJECT (self, "Failed to request pad"); - return NULL; - } - - chain = gst_d3d11_compositor_bin_input_chain_new (self, compositor_pad); - g_assert (chain); - - GST_OBJECT_LOCK (self); - self->input_chains = g_list_append (self->input_chains, chain); - GST_OBJECT_UNLOCK (self); - - gst_child_proxy_child_added (GST_CHILD_PROXY (self), - G_OBJECT (chain->ghost_pad), GST_OBJECT_NAME (chain->ghost_pad)); - - GST_DEBUG_OBJECT (element, "Created new pad %s:%s", - GST_DEBUG_PAD_NAME (chain->ghost_pad)); - - return GST_PAD_CAST (chain->ghost_pad); -} - -static void -gst_d3d11_compositor_bin_release_pad (GstElement * element, GstPad * pad) -{ - GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (element); - GList *iter; - gboolean found = FALSE; - - GST_DEBUG_OBJECT (self, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); - - GST_OBJECT_LOCK (self); - for (iter = self->input_chains; iter; iter = g_list_next (iter)) { - GstD3D11CompositorBinChain *chain = - (GstD3D11CompositorBinChain *) iter->data; - - if (pad == GST_PAD_CAST (chain->ghost_pad)) { - self->input_chains = g_list_delete_link (self->input_chains, iter); - GST_OBJECT_UNLOCK (self); - - gst_d3d11_compositor_bin_input_chain_free (chain); - found = TRUE; - break; - } - } - - if (!found) { - GST_OBJECT_UNLOCK (self); - GST_WARNING_OBJECT (self, "Unknown pad to release %s:%s", - GST_DEBUG_PAD_NAME (pad)); - } - - gst_element_remove_pad (element, pad); -} - -static GObject * -gst_d3d11_compositor_bin_child_proxy_get_child_by_index (GstChildProxy * proxy, - guint index) -{ - GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (proxy); - GstBin *bin = GST_BIN_CAST (proxy); - GObject *res = NULL; - - GST_OBJECT_LOCK (self); - /* XXX: not exactly thread safe with ordering */ - if (index < (guint) bin->numchildren) { - if ((res = (GObject *) g_list_nth_data (bin->children, index))) - gst_object_ref (res); - } else { - GstD3D11CompositorBinChain *chain; - if ((chain = - (GstD3D11CompositorBinChain *) g_list_nth_data (self->input_chains, - index - bin->numchildren))) { - res = (GObject *) gst_object_ref (chain->ghost_pad); - } - } - GST_OBJECT_UNLOCK (self); - - return res; -} - -static guint -gst_d3d11_compositor_bin_child_proxy_get_children_count (GstChildProxy * proxy) -{ - GstD3D11CompositorBin *self = GST_D3D11_COMPOSITOR_BIN (proxy); - guint count = 0; - - GST_OBJECT_LOCK (self); - count = GST_BIN_CAST (self)->numchildren + g_list_length (self->input_chains); - GST_OBJECT_UNLOCK (self); - GST_INFO_OBJECT (self, "Children Count: %d", count); - - return count; -} - -static void -gst_d3d11_compositor_bin_child_proxy_init (gpointer g_iface, - gpointer iface_data) -{ - GstChildProxyInterface *iface = (GstChildProxyInterface *) g_iface; - - iface->get_child_by_index = - gst_d3d11_compositor_bin_child_proxy_get_child_by_index; - iface->get_children_count = - gst_d3d11_compositor_bin_child_proxy_get_children_count; -} diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.h b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.h deleted file mode 100644 index bf58670..0000000 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2020 Seungha Yang - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_D3D11_COMPOSITOR_BIN_H__ -#define __GST_D3D11_COMPOSITOR_BIN_H__ - -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define GST_TYPE_D3D11_COMPOSITOR_BIN_PAD (gst_d3d11_compositor_bin_pad_get_type()) -#define GST_D3D11_COMPOSITOR_BIN_PAD(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD, GstD3D11CompositorBinPad)) -#define GST_D3D11_COMPOSITOR_BIN_PAD_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD, GstD3D11CompositorBinPadClass)) -#define GST_IS_D3D11_COMPOSITOR_BIN_PAD(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD)) -#define GST_IS_D3D11_COMPOSITOR_BIN_PAD_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD)) -#define GST_D3D11_COMPOSITOR_BIN_PAD_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD,GstD3D11CompositorBinPadClass)) - -typedef struct _GstD3D11CompositorBinPad GstD3D11CompositorBinPad; -typedef struct _GstD3D11CompositorBinPadClass GstD3D11CompositorBinPadClass; - -struct _GstD3D11CompositorBinPadClass -{ - GstGhostPadClass parent_class; - - void (*set_target) (GstD3D11CompositorBinPad * pad, GstPad * target); -}; - -GType gst_d3d11_compositor_bin_pad_get_type (void); -G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstD3D11CompositorBinPad, gst_object_unref) - -#define GST_TYPE_D3D11_COMPOSITOR_BIN_INPUT (gst_d3d11_compositor_bin_input_get_type()) -G_DECLARE_FINAL_TYPE (GstD3D11CompositorBinInput, gst_d3d11_compositor_bin_input, - GST, D3D11_COMPOSITOR_BIN_INPUT, GstD3D11CompositorBinPad); - -#define GST_TYPE_D3D11_COMPOSITOR_BIN (gst_d3d11_compositor_bin_get_type()) -G_DECLARE_FINAL_TYPE (GstD3D11CompositorBin, gst_d3d11_compositor_bin, - GST, D3D11_COMPOSITOR_BIN, GstBin) - -G_END_DECLS - -#endif /* __GST_D3D11_COMPOSITOR_BIN_H__ */ diff --git a/subprojects/gst-plugins-bad/sys/d3d11/meson.build b/subprojects/gst-plugins-bad/sys/d3d11/meson.build index e9a8262..39b1977 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/meson.build +++ b/subprojects/gst-plugins-bad/sys/d3d11/meson.build @@ -2,7 +2,6 @@ d3d11_sources = [ 'gstd3d11av1dec.cpp', 'gstd3d11basefilter.cpp', 'gstd3d11compositor.cpp', - 'gstd3d11compositorbin.cpp', 'gstd3d11convert.cpp', 'gstd3d11converter.cpp', 'gstd3d11decoder.cpp', diff --git a/subprojects/gst-plugins-bad/sys/d3d11/plugin.cpp b/subprojects/gst-plugins-bad/sys/d3d11/plugin.cpp index 6a19f12..279ee28 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/plugin.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/plugin.cpp @@ -68,7 +68,6 @@ #include "gstd3d11convert.h" #include "gstd3d11shader.h" #include "gstd3d11compositor.h" -#include "gstd3d11compositorbin.h" #include "gstd3d11h264dec.h" #include "gstd3d11h265dec.h" #include "gstd3d11vp9dec.h" @@ -91,7 +90,6 @@ GST_DEBUG_CATEGORY (gst_d3d11_device_debug); GST_DEBUG_CATEGORY (gst_d3d11_overlay_compositor_debug); GST_DEBUG_CATEGORY (gst_d3d11_window_debug); GST_DEBUG_CATEGORY (gst_d3d11_video_processor_debug); -GST_DEBUG_CATEGORY (gst_d3d11_compositor_debug); GST_DEBUG_CATEGORY (gst_d3d11_decoder_debug); GST_DEBUG_CATEGORY (gst_d3d11_h264_dec_debug); GST_DEBUG_CATEGORY (gst_d3d11_h265_dec_debug); @@ -126,8 +124,6 @@ plugin_init (GstPlugin * plugin) "d3d11window", 0, "d3d11window"); GST_DEBUG_CATEGORY_INIT (gst_d3d11_video_processor_debug, "d3d11videoprocessor", 0, "d3d11videoprocessor"); - GST_DEBUG_CATEGORY_INIT (gst_d3d11_compositor_debug, - "d3d11compositor", 0, "d3d11compositor element"); if (!gst_d3d11_shader_init ()) { GST_WARNING ("Cannot initialize d3d11 shader"); @@ -223,9 +219,7 @@ plugin_init (GstPlugin * plugin) "d3d11videosink", video_sink_rank, GST_TYPE_D3D11_VIDEO_SINK); gst_element_register (plugin, - "d3d11compositorelement", GST_RANK_NONE, GST_TYPE_D3D11_COMPOSITOR); - gst_element_register (plugin, - "d3d11compositor", GST_RANK_SECONDARY, GST_TYPE_D3D11_COMPOSITOR_BIN); + "d3d11compositor", GST_RANK_SECONDARY, GST_TYPE_D3D11_COMPOSITOR); gst_element_register (plugin, "d3d11testsrc", GST_RANK_NONE, GST_TYPE_D3D11_TEST_SRC);