*/
/**
- * 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
*
*/
#include "gstd3d11converter.h"
#include "gstd3d11shader.h"
#include "gstd3d11pluginutils.h"
+#include "gstd3d11videoprocessor.h"
#include <string.h>
#include <wrl.h>
-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;
{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) {
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;
"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) {
" 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"
" }\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;
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;
};
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;
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,
};
#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,
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,
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);
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
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;
}
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;
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);
}
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)
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 */
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
{
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;
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)
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)) {
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)
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, "
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);
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
{
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);
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,
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 =
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 <seungha@centricular.com>");
+ "Filter/Editor/Video/Compositor", "A Direct3D11 compositor",
+ "Seungha Yang <seungha@centricular.com>");
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
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);
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);
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));
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
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;
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);
}
}
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)) {
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 *
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));
}
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);
gst_caps_unref (caps);
return TRUE;
}
- case GST_QUERY_ACCEPT_CAPS:
- {
+ case GST_QUERY_ACCEPT_CAPS:{
GstCaps *caps;
gboolean ret;
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);
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);
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);
gst_query_add_allocation_pool (query, pool, size, min, max);
gst_object_unref (pool);
- self->reconfigured = TRUE;
-
return TRUE;
}
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));
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));
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 (),
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;
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 (),
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;
/* 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;
}
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)
}
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
}
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);
} 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;
/* 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 " -> %"
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);
}
+++ /dev/null
-/*
- * GStreamer
- * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
- * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
- *
- * 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 <gst/controller/gstproxycontrolbinding.h>
-#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 <seungha@centricular.com>");
-
- 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;
-}