d3d11compositor: Performance optimization
authorSeungha Yang <seungha@centricular.com>
Sat, 18 Jun 2022 11:14:22 +0000 (20:14 +0900)
committerSeungha Yang <seungha@centricular.com>
Mon, 20 Jun 2022 19:18:53 +0000 (19:18 +0000)
Removing glvideomixer-like nuance (it was initially referenced)
and rewriting element since it's not an optimal design at all
from performance point of view.

* Remove wrapper bin (and internal conversion/upload/download elements)
  which will waste CPU/GPU resources. Conversion/blending can be done by the
  d3d11compositor element at once.
* Add support YUV blending without RGB conversion.
  The RGB <-> YUV conversion is completely unnecessary since YUV textures
  support blending as well.
* Remove complicated blending operation properties since it's hard
  to use from application point of view. Instead, adding "operator" property
  like what compositor element does.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2631>

subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.h
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.cpp [deleted file]
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.h [deleted file]
subprojects/gst-plugins-bad/sys/d3d11/meson.build
subprojects/gst-plugins-bad/sys/d3d11/plugin.cpp

index 6fcf7ea..0e89ca5 100644 (file)
  */
 
 /**
- * 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;
@@ -327,7 +77,7 @@ gst_d3d11_compositor_background_get_type (void)
     {GST_D3D11_COMPOSITOR_BACKGROUND_WHITE, "White", "white"},
     {GST_D3D11_COMPOSITOR_BACKGROUND_TRANSPARENT,
         "Transparent Background to enable further compositing", "transparent"},
-    {0, NULL, NULL},
+    {0, nullptr, nullptr},
   };
 
   if (!compositor_background_type) {
@@ -338,14 +88,40 @@ gst_d3d11_compositor_background_get_type (void)
   return compositor_background_type;
 }
 
-/**
- * GstD3D11CompositorSizingPolicy:
- *
- * Sizing policy
- *
- * Since: 1.20
- */
-GType
+typedef enum
+{
+  GST_D3D11_COMPOSITOR_OPERATOR_SOURCE,
+  GST_D3D11_COMPOSITOR_OPERATOR_OVER,
+} GstD3D11CompositorOperator;
+
+#define GST_TYPE_D3D11_COMPOSITOR_OPERATOR (gst_d3d11_compositor_operator_get_type())
+static GType
+gst_d3d11_compositor_operator_get_type (void)
+{
+  static GType compositor_operator_type = 0;
+
+  static const GEnumValue compositor_operator[] = {
+    {GST_D3D11_COMPOSITOR_OPERATOR_SOURCE, "Source", "source"},
+    {GST_D3D11_COMPOSITOR_OPERATOR_OVER, "Over", "over"},
+    {0, nullptr, nullptr},
+  };
+
+  if (!compositor_operator_type) {
+    compositor_operator_type =
+        g_enum_register_static ("GstD3D11CompositorOperator",
+        compositor_operator);
+  }
+  return compositor_operator_type;
+}
+
+typedef enum
+{
+  GST_D3D11_COMPOSITOR_SIZING_POLICY_NONE,
+  GST_D3D11_COMPOSITOR_SIZING_POLICY_KEEP_ASPECT_RATIO,
+} GstD3D11CompositorSizingPolicy;
+
+#define GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY (gst_d3d11_compositor_sizing_policy_get_type())
+static GType
 gst_d3d11_compositor_sizing_policy_get_type (void)
 {
   static GType sizing_policy_type = 0;
@@ -360,7 +136,7 @@ gst_d3d11_compositor_sizing_policy_get_type (void)
           "with preserved aspect ratio. Resulting image will be centered in "
           "the destination rectangle with padding if necessary",
         "keep-aspect-ratio"},
-    {0, NULL, NULL},
+    {0, nullptr, nullptr},
   };
 
   if (!sizing_policy_type) {
@@ -388,7 +164,7 @@ static const gchar checker_vs_src[] =
     "  return input;\n"
     "}\n";
 
-static const gchar checker_ps_src[] =
+static const gchar checker_ps_src_rgb[] =
     "static const float blocksize = 8.0;\n"
     "static const float4 high = float4(0.667, 0.667, 0.667, 1.0);\n"
     "static const float4 low = float4(0.333, 0.333, 0.333, 1.0);\n"
@@ -416,20 +192,90 @@ static const gchar checker_ps_src[] =
     "  }\n"
     "  return output;\n"
     "}\n";
+
+static const gchar checker_ps_src_vuya[] =
+    "static const float blocksize = 8.0;\n"
+    "static const float4 high = float4(0.5, 0.5, 0.667, 1.0);\n"
+    "static const float4 low = float4(0.5, 0.5, 0.333, 1.0);\n"
+    "struct PS_INPUT\n"
+    "{\n"
+    "  float4 Position: SV_POSITION;\n"
+    "};\n"
+    "struct PS_OUTPUT\n"
+    "{\n"
+    "  float4 Plane: SV_TARGET;\n"
+    "};\n"
+    "PS_OUTPUT main(PS_INPUT input)\n"
+    "{\n"
+    "  PS_OUTPUT output;\n"
+    "  if ((input.Position.x % (blocksize * 2.0)) >= blocksize) {\n"
+    "    if ((input.Position.y % (blocksize * 2.0)) >= blocksize)\n"
+    "      output.Plane = low;\n"
+    "    else\n"
+    "      output.Plane = high;\n"
+    "  } else {\n"
+    "    if ((input.Position.y % (blocksize * 2.0)) < blocksize)\n"
+    "      output.Plane = low;\n"
+    "    else\n"
+    "      output.Plane = high;\n"
+    "  }\n"
+    "  return output;\n"
+    "}\n";
+
+static const gchar checker_ps_src_luma[] =
+    "static const float blocksize = 8.0;\n"
+    "static const float4 high = float4(0.667, 0.0, 0.0, 1.0);\n"
+    "static const float4 low = float4(0.333, 0.0, 0.0, 1.0);\n"
+    "struct PS_INPUT\n"
+    "{\n"
+    "  float4 Position: SV_POSITION;\n"
+    "};\n"
+    "struct PS_OUTPUT\n"
+    "{\n"
+    "  float4 Plane: SV_TARGET;\n"
+    "};\n"
+    "PS_OUTPUT main(PS_INPUT input)\n"
+    "{\n"
+    "  PS_OUTPUT output;\n"
+    "  if ((input.Position.x % (blocksize * 2.0)) >= blocksize) {\n"
+    "    if ((input.Position.y % (blocksize * 2.0)) >= blocksize)\n"
+    "      output.Plane = low;\n"
+    "    else\n"
+    "      output.Plane = high;\n"
+    "  } else {\n"
+    "    if ((input.Position.y % (blocksize * 2.0)) < blocksize)\n"
+    "      output.Plane = low;\n"
+    "    else\n"
+    "      output.Plane = high;\n"
+    "  }\n"
+    "  return output;\n"
+    "}\n";
+
+static D3D11_RENDER_TARGET_BLEND_DESC blend_templ[] = {
+  /* SOURCE */
+  {
+    TRUE,
+    D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD,
+    D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD,
+    D3D11_COLOR_WRITE_ENABLE_ALL
+  },
+  /* OVER */
+  {
+    TRUE,
+    D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
+    D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
+    D3D11_COLOR_WRITE_ENABLE_ALL,
+  },
+};
 /* *INDENT-ON* */
 
-/**
- * GstD3D11CompositorPad:
- *
- * Since: 1.20
- */
 struct _GstD3D11CompositorPad
 {
   GstVideoAggregatorConvertPad parent;
 
   GstD3D11Converter *convert;
+  GstD3D11VideoProcessor *processor;
 
-  GstBufferPool *fallback_pool;
   GstBuffer *fallback_buf;
 
   gboolean position_updated;
@@ -437,14 +283,22 @@ struct _GstD3D11CompositorPad
   gboolean blend_desc_updated;
   ID3D11BlendState *blend;
 
+  D3D11_RENDER_TARGET_BLEND_DESC desc;
+
+  /* per frame update */
+  ID3D11VideoProcessorInputView *piv;
+
+  /* rectangle for video processor */
+  RECT src_rect;
+  RECT dest_rect;
+
   /* properties */
   gint xpos;
   gint ypos;
   gint width;
   gint height;
   gdouble alpha;
-  D3D11_RENDER_TARGET_BLEND_DESC desc;
-  gfloat blend_factor[4];
+  GstD3D11CompositorOperator op;
   GstD3D11CompositorSizingPolicy sizing_policy;
 };
 
@@ -458,18 +312,25 @@ typedef struct
   D3D11_VIEWPORT viewport;
 } GstD3D11CompositorQuad;
 
+typedef struct
+{
+  /* [rtv][colors] */
+  FLOAT color[4][4];
+} GstD3D11CompositorClearColor;
+
 struct _GstD3D11Compositor
 {
   GstVideoAggregator parent;
 
   GstD3D11Device *device;
 
-  GstBufferPool *fallback_pool;
   GstBuffer *fallback_buf;
 
   GstD3D11CompositorQuad *checker_background;
+  /* black/white/transparent */
+  GstD3D11CompositorClearColor clear_color[3];
 
-  gboolean reconfigured;
+  gboolean downstream_supports_d3d11;
 
   /* properties */
   gint adapter;
@@ -484,16 +345,7 @@ enum
   PROP_PAD_WIDTH,
   PROP_PAD_HEIGHT,
   PROP_PAD_ALPHA,
-  PROP_PAD_BLEND_OP_RGB,
-  PROP_PAD_BLEND_OP_ALPHA,
-  PROP_PAD_BLEND_SRC_RGB,
-  PROP_PAD_BLEND_SRC_ALPHA,
-  PROP_PAD_BLEND_DEST_RGB,
-  PROP_PAD_BLEND_DEST_ALPHA,
-  PROP_PAD_BLEND_FACTOR_RED,
-  PROP_PAD_BLEND_FACTOR_GREEN,
-  PROP_PAD_BLEND_FACTOR_BLUE,
-  PROP_PAD_BLEND_FACTOR_ALPHA,
+  PROP_PAD_OPERATOR,
   PROP_PAD_SIZING_POLICY,
 };
 
@@ -502,12 +354,7 @@ enum
 #define DEFAULT_PAD_WIDTH  0
 #define DEFAULT_PAD_HEIGHT 0
 #define DEFAULT_PAD_ALPHA  1.0
-#define DEFAULT_PAD_BLEND_OP_RGB GST_D3D11_COMPOSITOR_BLEND_OP_ADD
-#define DEFAULT_PAD_BLEND_OP_ALPHA GST_D3D11_COMPOSITOR_BLEND_OP_ADD
-#define DEFAULT_PAD_BLEND_SRC_RGB GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA
-#define DEFAULT_PAD_BLEND_SRC_ALPHA GST_D3D11_COMPOSITOR_BLEND_ONE
-#define DEFAULT_PAD_BLEND_DEST_RGB GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA
-#define DEFAULT_PAD_BLEND_DEST_ALPHA GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA
+#define DEFAULT_PAD_OPERATOR GST_D3D11_COMPOSITOR_OPERATOR_OVER
 #define DEFAULT_PAD_SIZING_POLICY GST_D3D11_COMPOSITOR_SIZING_POLICY_NONE
 
 static void gst_d3d11_compositor_pad_set_property (GObject * object,
@@ -518,11 +365,6 @@ static gboolean
 gst_d3d11_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
     GstVideoAggregator * vagg, GstBuffer * buffer,
     GstVideoFrame * prepared_frame);
-static void
-gst_d3d11_compositor_pad_clean_frame (GstVideoAggregatorPad * pad,
-    GstVideoAggregator * vagg, GstVideoFrame * prepared_frame);
-static void
-gst_d3d11_compositor_pad_init_blend_options (GstD3D11CompositorPad * pad);
 
 #define gst_d3d11_compositor_pad_parent_class parent_pad_class
 G_DEFINE_TYPE (GstD3D11CompositorPad, gst_d3d11_compositor_pad,
@@ -531,144 +373,45 @@ G_DEFINE_TYPE (GstD3D11CompositorPad, gst_d3d11_compositor_pad,
 static void
 gst_d3d11_compositor_pad_class_init (GstD3D11CompositorPadClass * klass)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstVideoAggregatorPadClass *vaggpadclass =
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GstVideoAggregatorPadClass *vagg_pad_class =
       GST_VIDEO_AGGREGATOR_PAD_CLASS (klass);
+  GParamFlags param_flags = (GParamFlags)
+      (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS);
 
-  gobject_class->set_property = gst_d3d11_compositor_pad_set_property;
-  gobject_class->get_property = gst_d3d11_compositor_pad_get_property;
+  object_class->set_property = gst_d3d11_compositor_pad_set_property;
+  object_class->get_property = gst_d3d11_compositor_pad_get_property;
 
-  g_object_class_install_property (gobject_class, PROP_PAD_XPOS,
+  g_object_class_install_property (object_class, PROP_PAD_XPOS,
       g_param_spec_int ("xpos", "X Position", "X position of the picture",
-          G_MININT, G_MAXINT, DEFAULT_PAD_XPOS,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_YPOS,
+          G_MININT, G_MAXINT, DEFAULT_PAD_XPOS, param_flags));
+  g_object_class_install_property (object_class, PROP_PAD_YPOS,
       g_param_spec_int ("ypos", "Y Position", "Y position of the picture",
-          G_MININT, G_MAXINT, DEFAULT_PAD_YPOS,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_WIDTH,
+          G_MININT, G_MAXINT, DEFAULT_PAD_YPOS, param_flags));
+  g_object_class_install_property (object_class, PROP_PAD_WIDTH,
       g_param_spec_int ("width", "Width", "Width of the picture",
-          G_MININT, G_MAXINT, DEFAULT_PAD_WIDTH,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_HEIGHT,
+          G_MININT, G_MAXINT, DEFAULT_PAD_WIDTH, param_flags));
+  g_object_class_install_property (object_class, PROP_PAD_HEIGHT,
       g_param_spec_int ("height", "Height", "Height of the picture",
-          G_MININT, G_MAXINT, DEFAULT_PAD_HEIGHT,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_ALPHA,
+          G_MININT, G_MAXINT, DEFAULT_PAD_HEIGHT, param_flags));
+  g_object_class_install_property (object_class, PROP_PAD_ALPHA,
       g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0,
-          DEFAULT_PAD_ALPHA,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_BLEND_OP_RGB,
-      g_param_spec_enum ("blend-op-rgb", "Blend Operation RGB",
-          "Blend equation for RGB", GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION,
-          DEFAULT_PAD_BLEND_OP_RGB,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_BLEND_OP_ALPHA,
-      g_param_spec_enum ("blend-op-alpha", "Blend Operation Alpha",
-          "Blend equation for alpha", GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION,
-          DEFAULT_PAD_BLEND_OP_ALPHA,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class,
-      PROP_PAD_BLEND_SRC_RGB,
-      g_param_spec_enum ("blend-src-rgb", "Blend Source RGB",
-          "Blend factor for source RGB",
-          GST_TYPE_D3D11_COMPOSITOR_BLEND,
-          DEFAULT_PAD_BLEND_SRC_RGB,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class,
-      PROP_PAD_BLEND_SRC_ALPHA,
-      g_param_spec_enum ("blend-src-alpha",
-          "Blend Source Alpha",
-          "Blend factor for source alpha, \"*-color\" values are not allowed",
-          GST_TYPE_D3D11_COMPOSITOR_BLEND,
-          DEFAULT_PAD_BLEND_SRC_ALPHA,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class,
-      PROP_PAD_BLEND_DEST_RGB,
-      g_param_spec_enum ("blend-dest-rgb",
-          "Blend Destination RGB",
-          "Blend factor for destination RGB",
-          GST_TYPE_D3D11_COMPOSITOR_BLEND,
-          DEFAULT_PAD_BLEND_DEST_RGB,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class,
-      PROP_PAD_BLEND_DEST_ALPHA,
-      g_param_spec_enum ("blend-dest-alpha",
-          "Blend Destination Alpha",
-          "Blend factor for destination alpha, "
-          "\"*-color\" values are not allowed",
-          GST_TYPE_D3D11_COMPOSITOR_BLEND,
-          DEFAULT_PAD_BLEND_DEST_ALPHA,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_BLEND_FACTOR_RED,
-      g_param_spec_float ("blend-factor-red", "Blend Factor Red",
-          "Blend factor for red component "
-          "when blend type is \"blend-factor\" or \"inv-blend-factor\"",
-          0.0, 1.0, 1.0,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_BLEND_FACTOR_GREEN,
-      g_param_spec_float ("blend-factor-green", "Blend Factor Green",
-          "Blend factor for green component "
-          "when blend type is \"blend-factor\" or \"inv-blend-factor\"",
-          0.0, 1.0, 1.0,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_BLEND_FACTOR_BLUE,
-      g_param_spec_float ("blend-factor-blue", "Blend Factor Blue",
-          "Blend factor for blue component "
-          "when blend type is \"blend-factor\" or \"inv-blend-factor\"",
-          0.0, 1.0, 1.0,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_BLEND_FACTOR_ALPHA,
-      g_param_spec_float ("blend-factor-alpha", "Blend Factor Alpha",
-          "Blend factor for alpha component "
-          "when blend type is \"blend-factor\" or \"inv-blend-factor\"",
-          0.0, 1.0, 1.0,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
-
-  g_object_class_install_property (gobject_class, PROP_PAD_SIZING_POLICY,
+          DEFAULT_PAD_ALPHA, param_flags));
+  g_object_class_install_property (object_class, PROP_PAD_OPERATOR,
+      g_param_spec_enum ("operator", "Operator",
+          "Blending operator to use for blending this pad over the previous ones",
+          GST_TYPE_D3D11_COMPOSITOR_OPERATOR, DEFAULT_PAD_OPERATOR,
+          param_flags));
+  g_object_class_install_property (object_class, PROP_PAD_SIZING_POLICY,
       g_param_spec_enum ("sizing-policy", "Sizing policy",
           "Sizing policy to use for image scaling",
           GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY, DEFAULT_PAD_SIZING_POLICY,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
-              G_PARAM_STATIC_STRINGS)));
+          param_flags));
 
-  vaggpadclass->prepare_frame =
+  vagg_pad_class->prepare_frame =
       GST_DEBUG_FUNCPTR (gst_d3d11_compositor_pad_prepare_frame);
-  vaggpadclass->clean_frame =
-      GST_DEBUG_FUNCPTR (gst_d3d11_compositor_pad_clean_frame);
 
-  gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_BLEND,
-      (GstPluginAPIFlags) 0);
-  gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION,
+  gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_OPERATOR,
       (GstPluginAPIFlags) 0);
   gst_type_mark_as_plugin_api (GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY,
       (GstPluginAPIFlags) 0);
@@ -682,36 +425,21 @@ gst_d3d11_compositor_pad_init (GstD3D11CompositorPad * pad)
   pad->width = DEFAULT_PAD_WIDTH;
   pad->height = DEFAULT_PAD_HEIGHT;
   pad->alpha = DEFAULT_PAD_ALPHA;
+  pad->op = DEFAULT_PAD_OPERATOR;
   pad->sizing_policy = DEFAULT_PAD_SIZING_POLICY;
-
-  gst_d3d11_compositor_pad_init_blend_options (pad);
+  pad->desc = blend_templ[DEFAULT_PAD_OPERATOR];
 }
 
 static void
-gst_d3d11_compositor_pad_update_blend_function (GstD3D11CompositorPad * pad,
-    D3D11_BLEND * value, GstD3D11CompositorBlend new_value)
+gst_d3d11_compositor_pad_update_position (GstD3D11CompositorPad * self,
+    gint * old, const GValue * value)
 {
-  D3D11_BLEND temp = gst_d3d11_compositor_blend_to_native (new_value);
-
-  if (temp == *value)
-    return;
-
-  *value = temp;
-  pad->blend_desc_updated = TRUE;
-}
-
-static void
-gst_d3d11_compositor_pad_update_blend_equation (GstD3D11CompositorPad * pad,
-    D3D11_BLEND_OP * value, GstD3D11CompositorBlendOperation new_value)
-{
-  D3D11_BLEND_OP temp =
-      gst_d3d11_compositor_blend_operation_to_native (new_value);
-
-  if (temp == *value)
-    return;
+  gint tmp = g_value_get_int (value);
 
-  *value = temp;
-  pad->blend_desc_updated = TRUE;
+  if (*old != tmp) {
+    *old = tmp;
+    self->position_updated = TRUE;
+  }
 }
 
 static void
@@ -722,23 +450,18 @@ gst_d3d11_compositor_pad_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_PAD_XPOS:
-      pad->xpos = g_value_get_int (value);
-      pad->position_updated = TRUE;
+      gst_d3d11_compositor_pad_update_position (pad, &pad->xpos, value);
       break;
     case PROP_PAD_YPOS:
-      pad->ypos = g_value_get_int (value);
-      pad->position_updated = TRUE;
+      gst_d3d11_compositor_pad_update_position (pad, &pad->ypos, value);
       break;
     case PROP_PAD_WIDTH:
-      pad->width = g_value_get_int (value);
-      pad->position_updated = TRUE;
+      gst_d3d11_compositor_pad_update_position (pad, &pad->width, value);
       break;
     case PROP_PAD_HEIGHT:
-      pad->height = g_value_get_int (value);
-      pad->position_updated = TRUE;
+      gst_d3d11_compositor_pad_update_position (pad, &pad->height, value);
       break;
-    case PROP_PAD_ALPHA:
-    {
+    case PROP_PAD_ALPHA:{
       gdouble alpha = g_value_get_double (value);
       if (pad->alpha != alpha) {
         pad->alpha_updated = TRUE;
@@ -746,70 +469,25 @@ gst_d3d11_compositor_pad_set_property (GObject * object, guint prop_id,
       }
       break;
     }
-    case PROP_PAD_BLEND_OP_RGB:
-      gst_d3d11_compositor_pad_update_blend_equation (pad, &pad->desc.BlendOp,
-          (GstD3D11CompositorBlendOperation) g_value_get_enum (value));
-      break;
-    case PROP_PAD_BLEND_OP_ALPHA:
-      gst_d3d11_compositor_pad_update_blend_equation (pad,
-          &pad->desc.BlendOpAlpha,
-          (GstD3D11CompositorBlendOperation) g_value_get_enum (value));
-      break;
-    case PROP_PAD_BLEND_SRC_RGB:
-      gst_d3d11_compositor_pad_update_blend_function (pad, &pad->desc.SrcBlend,
-          (GstD3D11CompositorBlend) g_value_get_enum (value));
-      break;
-    case PROP_PAD_BLEND_SRC_ALPHA:
-    {
-      GstD3D11CompositorBlend blend =
-          (GstD3D11CompositorBlend) g_value_get_enum (value);
-      if (blend == GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR ||
-          blend == GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR ||
-          blend == GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR ||
-          blend == GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR) {
-        g_warning ("%d is not allowed for %s", blend, pspec->name);
-      } else {
-        gst_d3d11_compositor_pad_update_blend_function (pad,
-            &pad->desc.SrcBlendAlpha, blend);
+    case PROP_PAD_OPERATOR:{
+      GstD3D11CompositorOperator op =
+          (GstD3D11CompositorOperator) g_value_get_enum (value);
+      if (op != pad->op) {
+        pad->op = op;
+        pad->desc = blend_templ[op];
+        pad->blend_desc_updated = TRUE;
       }
       break;
     }
-    case PROP_PAD_BLEND_DEST_RGB:
-      gst_d3d11_compositor_pad_update_blend_function (pad, &pad->desc.DestBlend,
-          (GstD3D11CompositorBlend) g_value_get_enum (value));
-      break;
-    case PROP_PAD_BLEND_DEST_ALPHA:
-    {
-      GstD3D11CompositorBlend blend =
-          (GstD3D11CompositorBlend) g_value_get_enum (value);
-      if (blend == GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR ||
-          blend == GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR ||
-          blend == GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR ||
-          blend == GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR) {
-        g_warning ("%d is not allowed for %s", blend, pspec->name);
-      } else {
-        gst_d3d11_compositor_pad_update_blend_function (pad,
-            &pad->desc.DestBlendAlpha, blend);
+    case PROP_PAD_SIZING_POLICY:{
+      GstD3D11CompositorSizingPolicy policy =
+          (GstD3D11CompositorSizingPolicy) g_value_get_enum (value);
+      if (pad->sizing_policy != policy) {
+        pad->sizing_policy = policy;
+        pad->position_updated = TRUE;
       }
       break;
     }
-    case PROP_PAD_BLEND_FACTOR_RED:
-      pad->blend_factor[0] = g_value_get_float (value);
-      break;
-    case PROP_PAD_BLEND_FACTOR_GREEN:
-      pad->blend_factor[1] = g_value_get_float (value);
-      break;
-    case PROP_PAD_BLEND_FACTOR_BLUE:
-      pad->blend_factor[2] = g_value_get_float (value);
-      break;
-    case PROP_PAD_BLEND_FACTOR_ALPHA:
-      pad->blend_factor[3] = g_value_get_float (value);
-      break;
-    case PROP_PAD_SIZING_POLICY:
-      pad->sizing_policy =
-          (GstD3D11CompositorSizingPolicy) g_value_get_enum (value);
-      pad->position_updated = TRUE;
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -838,42 +516,8 @@ gst_d3d11_compositor_pad_get_property (GObject * object, guint prop_id,
     case PROP_PAD_ALPHA:
       g_value_set_double (value, pad->alpha);
       break;
-    case PROP_PAD_BLEND_OP_RGB:
-      g_value_set_enum (value,
-          gst_d3d11_compositor_blend_operation_from_native (pad->desc.BlendOp));
-      break;
-    case PROP_PAD_BLEND_OP_ALPHA:
-      g_value_set_enum (value,
-          gst_d3d11_compositor_blend_operation_from_native (pad->
-              desc.BlendOpAlpha));
-      break;
-    case PROP_PAD_BLEND_SRC_RGB:
-      g_value_set_enum (value,
-          gst_d3d11_compositor_blend_from_native (pad->desc.SrcBlend));
-      break;
-    case PROP_PAD_BLEND_SRC_ALPHA:
-      g_value_set_enum (value,
-          gst_d3d11_compositor_blend_from_native (pad->desc.SrcBlendAlpha));
-      break;
-    case PROP_PAD_BLEND_DEST_RGB:
-      g_value_set_enum (value,
-          gst_d3d11_compositor_blend_from_native (pad->desc.DestBlend));
-      break;
-    case PROP_PAD_BLEND_DEST_ALPHA:
-      g_value_set_enum (value,
-          gst_d3d11_compositor_blend_from_native (pad->desc.DestBlendAlpha));
-      break;
-    case PROP_PAD_BLEND_FACTOR_RED:
-      g_value_set_float (value, pad->blend_factor[0]);
-      break;
-    case PROP_PAD_BLEND_FACTOR_GREEN:
-      g_value_set_float (value, pad->blend_factor[1]);
-      break;
-    case PROP_PAD_BLEND_FACTOR_BLUE:
-      g_value_set_float (value, pad->blend_factor[2]);
-      break;
-    case PROP_PAD_BLEND_FACTOR_ALPHA:
-      g_value_set_float (value, pad->blend_factor[3]);
+    case PROP_PAD_OPERATOR:
+      g_value_set_enum (value, pad->op);
       break;
     case PROP_PAD_SIZING_POLICY:
       g_value_set_enum (value, pad->sizing_policy);
@@ -885,200 +529,6 @@ gst_d3d11_compositor_pad_get_property (GObject * object, guint prop_id,
 }
 
 static void
-gst_d3d11_compositor_pad_init_blend_options (GstD3D11CompositorPad * pad)
-{
-  guint i;
-
-  pad->desc.BlendEnable = TRUE;
-  pad->desc.SrcBlend =
-      gst_d3d11_compositor_blend_to_native (DEFAULT_PAD_BLEND_SRC_RGB);
-  pad->desc.DestBlend =
-      gst_d3d11_compositor_blend_to_native (DEFAULT_PAD_BLEND_DEST_RGB);
-  pad->desc.BlendOp =
-      gst_d3d11_compositor_blend_operation_to_native (DEFAULT_PAD_BLEND_OP_RGB);
-  pad->desc.SrcBlendAlpha =
-      gst_d3d11_compositor_blend_to_native (DEFAULT_PAD_BLEND_SRC_ALPHA);
-  pad->desc.DestBlendAlpha =
-      gst_d3d11_compositor_blend_to_native (DEFAULT_PAD_BLEND_DEST_ALPHA);
-  pad->desc.BlendOpAlpha =
-      gst_d3d11_compositor_blend_operation_to_native
-      (DEFAULT_PAD_BLEND_OP_ALPHA);
-  pad->desc.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
-
-  for (i = 0; i < G_N_ELEMENTS (pad->blend_factor); i++)
-    pad->blend_factor[i] = 1.0f;
-}
-
-static gboolean
-gst_d3d11_compositor_configure_fallback_pool (GstD3D11Compositor * self,
-    GstVideoInfo * info, gint bind_flags, GstBufferPool ** pool)
-{
-  GstD3D11AllocationParams *d3d11_params;
-  GstBufferPool *new_pool;
-  GstCaps *caps;
-
-  if (*pool) {
-    gst_buffer_pool_set_active (*pool, FALSE);
-    gst_clear_object (pool);
-  }
-
-  caps = gst_video_info_to_caps (info);
-  if (!caps) {
-    GST_ERROR_OBJECT (self, "Couldn't create caps from info");
-    return FALSE;
-  }
-
-  d3d11_params = gst_d3d11_allocation_params_new (self->device,
-      info, (GstD3D11AllocationFlags) 0, bind_flags);
-
-  new_pool = gst_d3d11_buffer_pool_new_with_options (self->device,
-      caps, d3d11_params, 0, 0);
-  gst_caps_unref (caps);
-  gst_d3d11_allocation_params_free (d3d11_params);
-
-  if (!new_pool) {
-    GST_ERROR_OBJECT (self, "Failed to configure fallback pool");
-    return FALSE;
-  }
-
-  gst_buffer_pool_set_active (new_pool, TRUE);
-  *pool = new_pool;
-
-  return TRUE;
-}
-
-static gboolean
-gst_d3d11_compsitor_prepare_fallback_buffer (GstD3D11Compositor * self,
-    GstVideoInfo * info, gboolean is_input, GstBufferPool ** pool,
-    GstBuffer ** fallback_buffer)
-{
-  GstBuffer *new_buf = NULL;
-  gint bind_flags = D3D11_BIND_SHADER_RESOURCE;
-  guint i;
-
-  gst_clear_buffer (fallback_buffer);
-
-  if (!is_input)
-    bind_flags = D3D11_BIND_RENDER_TARGET;
-
-  if (*pool == NULL &&
-      !gst_d3d11_compositor_configure_fallback_pool (self, info,
-          bind_flags, pool)) {
-    GST_ERROR_OBJECT (self, "Couldn't configure fallback buffer pool");
-    return FALSE;
-  }
-
-  if (gst_buffer_pool_acquire_buffer (*pool, &new_buf, NULL)
-      != GST_FLOW_OK) {
-    GST_ERROR_OBJECT (self, "Couldn't get fallback buffer from pool");
-    return FALSE;
-  }
-
-  for (i = 0; i < gst_buffer_n_memory (new_buf); i++) {
-    GstD3D11Memory *new_mem =
-        (GstD3D11Memory *) gst_buffer_peek_memory (new_buf, i);
-
-    if (is_input && !gst_d3d11_memory_get_shader_resource_view_size (new_mem)) {
-      GST_ERROR_OBJECT (self, "Couldn't prepare shader resource view");
-      gst_buffer_unref (new_buf);
-      return FALSE;
-    } else if (!is_input &&
-        !gst_d3d11_memory_get_render_target_view_size (new_mem)) {
-      GST_ERROR_OBJECT (self, "Couldn't prepare render target view");
-      gst_buffer_unref (new_buf);
-      return FALSE;
-    }
-  }
-
-  *fallback_buffer = new_buf;
-
-  return TRUE;
-}
-
-static gboolean
-gst_d3d11_compositor_copy_buffer (GstD3D11Compositor * self,
-    GstVideoInfo * info, GstBuffer * src_buf, GstBuffer * dest_buf,
-    gboolean do_device_copy)
-{
-  guint i;
-
-  if (do_device_copy) {
-    return gst_d3d11_buffer_copy_into (dest_buf, src_buf, info);
-  } else {
-    GstVideoFrame src_frame, dest_frame;
-
-    if (!gst_video_frame_map (&src_frame, info, src_buf,
-            (GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) {
-      GST_ERROR_OBJECT (self, "Couldn't map input buffer");
-      return FALSE;
-    }
-
-    if (!gst_video_frame_map (&dest_frame, info, dest_buf,
-            (GstMapFlags) (GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) {
-      GST_ERROR_OBJECT (self, "Couldn't fallback buffer");
-      gst_video_frame_unmap (&src_frame);
-      return FALSE;
-    }
-
-    for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (&src_frame); i++) {
-      if (!gst_video_frame_copy_plane (&dest_frame, &src_frame, i)) {
-        GST_ERROR_OBJECT (self, "Couldn't copy %dth plane", i);
-
-        gst_video_frame_unmap (&dest_frame);
-        gst_video_frame_unmap (&src_frame);
-
-        return FALSE;
-      }
-    }
-
-    gst_video_frame_unmap (&dest_frame);
-    gst_video_frame_unmap (&src_frame);
-  }
-
-  return TRUE;
-}
-
-static gboolean
-gst_d3d11_compositor_check_d3d11_memory (GstD3D11Compositor * self,
-    GstBuffer * buffer, gboolean is_input, gboolean * view_available)
-{
-  guint i;
-  gboolean ret = TRUE;
-
-  *view_available = TRUE;
-
-  for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
-    GstMemory *mem = gst_buffer_peek_memory (buffer, i);
-    GstD3D11Memory *dmem;
-
-    if (!gst_is_d3d11_memory (mem)) {
-      ret = FALSE;
-      goto done;
-    }
-
-    dmem = (GstD3D11Memory *) mem;
-    if (dmem->device != self->device) {
-      ret = FALSE;
-      goto done;
-    }
-
-    if (is_input) {
-      if (!gst_d3d11_memory_get_shader_resource_view_size (dmem))
-        *view_available = FALSE;
-    } else {
-      if (!gst_d3d11_memory_get_render_target_view_size (dmem))
-        *view_available = FALSE;
-    }
-  }
-
-done:
-  if (!ret)
-    *view_available = FALSE;
-
-  return ret;
-}
-
-static void
 gst_d3d11_compositor_pad_get_output_size (GstD3D11CompositorPad * comp_pad,
     gint out_par_n, gint out_par_d, gint * width, gint * height,
     gint * x_offset, gint * y_offset)
@@ -1134,8 +584,7 @@ gst_d3d11_compositor_pad_get_output_size (GstD3D11CompositorPad * comp_pad,
         pad_width = gst_util_uint64_scale_int (pad_height, dar_n, dar_d);
       }
       break;
-    case GST_D3D11_COMPOSITOR_SIZING_POLICY_KEEP_ASPECT_RATIO:
-    {
+    case GST_D3D11_COMPOSITOR_SIZING_POLICY_KEEP_ASPECT_RATIO:{
       gint from_dar_n, from_dar_d, to_dar_n, to_dar_d, num, den;
 
       /* Calculate DAR again with actual video size */
@@ -1234,28 +683,141 @@ gst_d3d11_compositor_pad_check_frame_obscured (GstVideoAggregatorPad * pad,
   GstVideoRectangle frame_rect;
   gint x_offset, y_offset;
 
-  /* There's three types of width/height here:
-   * 1. GST_VIDEO_FRAME_WIDTH/HEIGHT:
-   *     The frame width/height (same as pad->info.height/width;
-   *     see gst_video_frame_map())
-   * 2. cpad->width/height:
-   *     The optional pad property for scaling the frame (if zero, the video is
-   *     left unscaled)
-   */
+  /* There's three types of width/height here:
+   * 1. GST_VIDEO_FRAME_WIDTH/HEIGHT:
+   *     The frame width/height (same as pad->info.height/width;
+   *     see gst_video_frame_map())
+   * 2. cpad->width/height:
+   *     The optional pad property for scaling the frame (if zero, the video is
+   *     left unscaled)
+   */
+
+  gst_d3d11_compositor_pad_get_output_size (cpad, GST_VIDEO_INFO_PAR_N (info),
+      GST_VIDEO_INFO_PAR_D (info), &width, &height, &x_offset, &y_offset);
+
+  frame_rect = clamp_rectangle (cpad->xpos + x_offset, cpad->ypos + y_offset,
+      width, height, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info));
+
+  if (frame_rect.w == 0 || frame_rect.h == 0) {
+    GST_DEBUG_OBJECT (pad, "Resulting frame is zero-width or zero-height "
+        "(w: %i, h: %i), skipping", frame_rect.w, frame_rect.h);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+static gboolean
+gst_d3d11_compositor_pad_ensure_fallback_buffer (GstD3D11Compositor * self,
+    GstD3D11CompositorPad * pad, GstVideoInfo * info)
+{
+  GstD3D11AllocationParams *d3d11_params;
+  GstBufferPool *pool;
+  GstCaps *caps;
+  GstFlowReturn flow_ret;
+
+  if (pad->fallback_buf)
+    return TRUE;
+
+  caps = gst_video_info_to_caps (info);
+  if (!caps) {
+    GST_ERROR_OBJECT (pad, "Failed to create caps");
+    return FALSE;
+  }
+
+  d3d11_params = gst_d3d11_allocation_params_new (self->device,
+      info, (GstD3D11AllocationFlags) 0, D3D11_BIND_SHADER_RESOURCE);
+
+  pool = gst_d3d11_buffer_pool_new_with_options (self->device,
+      caps, d3d11_params, 0, 0);
+  gst_caps_unref (caps);
+  gst_d3d11_allocation_params_free (d3d11_params);
+
+  if (!pool) {
+    GST_ERROR_OBJECT (self, "Failed to create pool");
+    return FALSE;
+  }
+
+  if (!gst_buffer_pool_set_active (pool, TRUE)) {
+    GST_ERROR_OBJECT (self, "Failed to set active");
+    gst_object_unref (pool);
+    return FALSE;
+  }
+
+  flow_ret = gst_buffer_pool_acquire_buffer (pool, &pad->fallback_buf, nullptr);
+  if (flow_ret != GST_FLOW_OK) {
+    GST_ERROR_OBJECT (pad, "Failed to acquire buffer");
+    gst_object_unref (pool);
+    return FALSE;
+  }
+
+  gst_buffer_pool_set_active (pool, FALSE);
+  gst_object_unref (pool);
+
+  return TRUE;
+}
+
+static GstBuffer *
+gst_d3d11_compositor_upload_buffer (GstD3D11Compositor * self,
+    GstD3D11CompositorPad * pad, GstBuffer * buffer,
+    ID3D11VideoProcessorInputView ** piv)
+{
+  GstVideoAggregatorPad *vagg_pad = GST_VIDEO_AGGREGATOR_PAD_CAST (pad);
+  GstVideoInfo *info;
+  GstD3D11Device *device = self->device;
+  guint n_memory = gst_buffer_n_memory (buffer);
+
+  *piv = nullptr;
+
+  for (guint i = 0; i < n_memory; i++) {
+    GstMemory *mem = gst_buffer_peek_memory (buffer, i);
+    GstD3D11Memory *dmem;
+    D3D11_TEXTURE2D_DESC desc;
+    gboolean srv_available = FALSE;
+
+    if (!gst_is_d3d11_memory (mem))
+      goto do_copy;
+
+    dmem = GST_D3D11_MEMORY_CAST (mem);
+    if (dmem->device != device)
+      goto do_copy;
+
+    gst_d3d11_memory_get_texture_desc (dmem, &desc);
+
+    if ((desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) ==
+        D3D11_BIND_SHADER_RESOURCE) {
+      srv_available = TRUE;
+    }
 
-  gst_d3d11_compositor_pad_get_output_size (cpad, GST_VIDEO_INFO_PAR_N (info),
-      GST_VIDEO_INFO_PAR_D (info), &width, &height, &x_offset, &y_offset);
+    if (pad->processor && pad->alpha == 1.0 && n_memory == 1
+        && desc.Usage == D3D11_USAGE_DEFAULT && !srv_available &&
+        gst_d3d11_video_processor_check_bind_flags_for_input_view
+        (desc.BindFlags)) {
+      *piv = gst_d3d11_video_processor_get_input_view (pad->processor, dmem);
+      if (*piv)
+        return buffer;
+    }
 
-  frame_rect = clamp_rectangle (cpad->xpos + x_offset, cpad->ypos + y_offset,
-      width, height, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info));
+    if (desc.ArraySize != 1 || desc.Usage != D3D11_USAGE_DEFAULT ||
+        !srv_available) {
+      goto do_copy;
+    }
+  }
 
-  if (frame_rect.w == 0 || frame_rect.h == 0) {
-    GST_DEBUG_OBJECT (pad, "Resulting frame is zero-width or zero-height "
-        "(w: %i, h: %i), skipping", frame_rect.w, frame_rect.h);
-    return TRUE;
+  return buffer;
+
+do_copy:
+  info = &vagg_pad->info;
+
+  if (!gst_d3d11_compositor_pad_ensure_fallback_buffer (self, pad, info))
+    return nullptr;
+
+  if (!gst_d3d11_buffer_copy_into (pad->fallback_buf, buffer, info)) {
+    GST_ERROR_OBJECT (pad, "Failed to copy into fallback buffer");
+    return nullptr;
   }
 
-  return FALSE;
+  return pad->fallback_buf;
 }
 
 static gboolean
@@ -1265,37 +827,18 @@ gst_d3d11_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
 {
   GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (vagg);
   GstD3D11CompositorPad *cpad = GST_D3D11_COMPOSITOR_PAD (pad);
-  GstBuffer *target_buf = buffer;
-  gboolean do_device_copy = FALSE;
+  GstBuffer *upload_buf;
 
   /* Skip this frame */
   if (gst_d3d11_compositor_pad_check_frame_obscured (pad, vagg))
     return TRUE;
 
-  /* Use fallback buffer when input buffer is:
-   * - non-d3d11 memory
-   * - or, from different d3d11 device
-   * - or not bound to shader resource
-   */
-  if (!gst_d3d11_compositor_check_d3d11_memory (self,
-          buffer, TRUE, &do_device_copy) || !do_device_copy) {
-    if (!gst_d3d11_compsitor_prepare_fallback_buffer (self, &pad->info, TRUE,
-            &cpad->fallback_pool, &cpad->fallback_buf)) {
-      GST_ERROR_OBJECT (self, "Couldn't prepare fallback buffer");
-      return FALSE;
-    }
-
-    if (!gst_d3d11_compositor_copy_buffer (self, &pad->info, buffer,
-            cpad->fallback_buf, do_device_copy)) {
-      GST_ERROR_OBJECT (self, "Couldn't copy input buffer to fallback buffer");
-      gst_clear_buffer (&cpad->fallback_buf);
-      return FALSE;
-    }
-
-    target_buf = cpad->fallback_buf;
-  }
+  upload_buf = gst_d3d11_compositor_upload_buffer (self,
+      cpad, buffer, &cpad->piv);
+  if (!upload_buf)
+    return FALSE;
 
-  if (!gst_video_frame_map (prepared_frame, &pad->info, target_buf,
+  if (!gst_video_frame_map (prepared_frame, &pad->info, upload_buf,
           (GstMapFlags) (GST_MAP_READ | GST_MAP_D3D11))) {
     GST_WARNING_OBJECT (pad, "Couldn't map input buffer");
     return FALSE;
@@ -1304,18 +847,6 @@ gst_d3d11_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
   return TRUE;
 }
 
-static void
-gst_d3d11_compositor_pad_clean_frame (GstVideoAggregatorPad * pad,
-    GstVideoAggregator * vagg, GstVideoFrame * prepared_frame)
-{
-  GstD3D11CompositorPad *cpad = GST_D3D11_COMPOSITOR_PAD (pad);
-
-  GST_VIDEO_AGGREGATOR_PAD_CLASS (parent_pad_class)->clean_frame (pad,
-      vagg, prepared_frame);
-
-  gst_clear_buffer (&cpad->fallback_buf);
-}
-
 static gboolean
 gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad,
     GstVideoAggregator * vagg)
@@ -1326,41 +857,120 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad,
   GstVideoInfo *info = &vagg->info;
   GstVideoRectangle frame_rect;
   gboolean is_first = FALSE;
+  gboolean output_has_alpha_comp = FALSE;
   gint x_offset, y_offset;
 #ifndef GST_DISABLE_GST_DEBUG
   guint zorder = 0;
 #endif
+  static const D3D11_RENDER_TARGET_BLEND_DESC blend_over_no_alpha = {
+    TRUE,
+    D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_OP_ADD,
+    D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_OP_ADD,
+    D3D11_COLOR_WRITE_ENABLE_ALL,
+  };
+
+  if (GST_VIDEO_INFO_HAS_ALPHA (info) ||
+      GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_BGRx ||
+      GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_RGBx) {
+    output_has_alpha_comp = TRUE;
+  }
 
-  if (!cpad->convert || self->reconfigured) {
-    gst_clear_object (&cpad->convert);
+  if (!cpad->convert) {
+    GstD3D11Format in_format, out_format;
 
-    cpad->convert =
-        gst_d3d11_converter_new (self->device, &pad->info, &vagg->info);
+    cpad->convert = gst_d3d11_converter_new (self->device, &pad->info, info);
     if (!cpad->convert) {
       GST_ERROR_OBJECT (pad, "Couldn't create converter");
       return FALSE;
     }
 
-    g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr);
+    if (output_has_alpha_comp)
+      g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr);
 
     is_first = TRUE;
-  } else if (cpad->alpha_updated) {
-    g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr);
+
+    cpad->src_rect.left = 0;
+    cpad->src_rect.top = 0;
+    cpad->src_rect.right = pad->info.width;
+    cpad->src_rect.bottom = pad->info.height;
+
+    /* Will use videoprocessor when input has no alpha channel and
+     * alpha == 1.0, mainly for decoder output texture which could not be
+     * bound to shader resource */
+    if (GST_VIDEO_INFO_IS_YUV (&pad->info) &&
+        !GST_VIDEO_INFO_HAS_ALPHA (&pad->info) &&
+        gst_d3d11_device_get_format (self->device,
+            GST_VIDEO_INFO_FORMAT (&pad->info), &in_format) &&
+        in_format.dxgi_format != DXGI_FORMAT_UNKNOWN &&
+        gst_d3d11_device_get_format (self->device,
+            GST_VIDEO_INFO_FORMAT (info), &out_format) &&
+        out_format.dxgi_format != DXGI_FORMAT_UNKNOWN) {
+      const GstDxgiColorSpace *in_space;
+      const GstDxgiColorSpace *out_space;
+
+      in_space = gst_d3d11_video_info_to_dxgi_color_space (&pad->info);
+      out_space = gst_d3d11_video_info_to_dxgi_color_space (info);
+
+      if (in_space && out_space) {
+        GstD3D11VideoProcessor *processor =
+            gst_d3d11_video_processor_new (self->device,
+            pad->info.width, pad->info.height, info->width,
+            info->height);
+
+        if (processor) {
+          if (gst_d3d11_video_processor_check_format_conversion (processor,
+                  in_format.dxgi_format,
+                  (DXGI_COLOR_SPACE_TYPE) in_space->dxgi_color_space_type,
+                  in_format.dxgi_format,
+                  (DXGI_COLOR_SPACE_TYPE) out_space->dxgi_color_space_type) &&
+              gst_d3d11_video_processor_set_input_dxgi_color_space (processor,
+                  (DXGI_COLOR_SPACE_TYPE) in_space->dxgi_color_space_type) &&
+              gst_d3d11_video_processor_set_output_dxgi_color_space (processor,
+                  (DXGI_COLOR_SPACE_TYPE) out_space->dxgi_color_space_type)) {
+            cpad->processor = processor;
+            GST_DEBUG_OBJECT (pad, "Video processor is available");
+          } else {
+            gst_d3d11_video_processor_free (processor);
+          }
+        }
+      }
+    }
+  }
+
+  if (cpad->alpha_updated) {
+    if (output_has_alpha_comp) {
+      g_object_set (cpad->convert, "alpha", cpad->alpha, nullptr);
+    } else {
+      gfloat blend_factor = cpad->alpha;
+
+      g_object_set (cpad->convert,
+          "blend-factor-red", blend_factor,
+          "blend-factor-green", blend_factor,
+          "blend-factor-blue", blend_factor,
+          "blend-factor-alpha", blend_factor, nullptr);
+    }
+
     cpad->alpha_updated = FALSE;
   }
 
   if (!cpad->blend || cpad->blend_desc_updated) {
     HRESULT hr;
     D3D11_BLEND_DESC desc = { 0, };
-    ID3D11BlendState *blend = NULL;
+    ID3D11BlendState *blend = nullptr;
     ID3D11Device *device_handle =
         gst_d3d11_device_get_device_handle (self->device);
+    gfloat blend_factor = 1.0f;
 
     GST_D3D11_CLEAR_COM (cpad->blend);
 
     desc.AlphaToCoverageEnable = FALSE;
     desc.IndependentBlendEnable = FALSE;
     desc.RenderTarget[0] = cpad->desc;
+    if (!output_has_alpha_comp &&
+        cpad->op == GST_D3D11_COMPOSITOR_OPERATOR_OVER) {
+      desc.RenderTarget[0] = blend_over_no_alpha;
+      blend_factor = cpad->alpha;
+    }
 
     hr = device_handle->CreateBlendState (&desc, &blend);
     if (!gst_d3d11_result (hr, self->device)) {
@@ -1371,11 +981,12 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad,
 
     cpad->blend = blend;
     g_object_set (cpad->convert, "blend-state", blend,
-        "blend-factor-red", cpad->blend_factor[0],
-        "blend-factor-green", cpad->blend_factor[1],
-        "blend-factor-blue", cpad->blend_factor[2],
-        "blend-factor-alpha", cpad->blend_factor[3],
-        "blend-sample-mask", 0xffffffff, nullptr);
+        "blend-factor-red", blend_factor,
+        "blend-factor-green", blend_factor,
+        "blend-factor-blue", blend_factor,
+        "blend-factor-alpha", blend_factor, nullptr);
+
+    cpad->blend_desc_updated = FALSE;
   }
 
   if (!is_first && !cpad->position_updated)
@@ -1388,7 +999,7 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad,
       width, height, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info));
 
 #ifndef GST_DISABLE_GST_DEBUG
-  g_object_get (pad, "zorder", &zorder, NULL);
+  g_object_get (pad, "zorder", &zorder, nullptr);
 
   GST_LOG_OBJECT (pad, "Update position, pad-xpos %d, pad-ypos %d, "
       "pad-zorder %d, pad-width %d, pad-height %d, in-resolution %dx%d, "
@@ -1401,6 +1012,12 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad,
 
   cpad->position_updated = FALSE;
 
+  /* rectangle stored for video processor */
+  cpad->dest_rect.left = frame_rect.x;
+  cpad->dest_rect.top = frame_rect.y;
+  cpad->dest_rect.right = frame_rect.x + frame_rect.w;
+  cpad->dest_rect.bottom = frame_rect.y + frame_rect.h;
+
   g_object_set (cpad->convert, "dest-x", frame_rect.x,
       "dest-y", frame_rect.y, "dest-width", frame_rect.w,
       "dest-height", frame_rect.h, nullptr);
@@ -1408,9 +1025,23 @@ gst_d3d11_compositor_pad_setup_converter (GstVideoAggregatorPad * pad,
   return TRUE;
 }
 
-static GstStaticCaps pad_template_caps =
-GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
-    (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, "{ RGBA, BGRA }"));
+static GstStaticCaps sink_pad_template_caps =
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
+    (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_SINK_FORMATS) "; "
+    GST_VIDEO_CAPS_MAKE (GST_D3D11_SINK_FORMATS));
+
+/* formats we can output without conversion.
+ * Excludes 10/12 bits planar YUV (needs bitshift) and
+ * AYUV/AYUV64 (d3d11 runtime does not understand the ayuv order) */
+#define COMPOSITOR_SRC_FORMATS \
+    "{ RGBA64_LE, RGB10A2_LE, BGRA, RGBA, BGRx, RGBx, VUYA, NV12, NV21, " \
+    "P010_10LE, P012_LE, P016_LE, I420, YV12, Y42B, Y444, Y444_16LE, " \
+    "GRAY8, GRAY16_LE }"
+
+static GstStaticCaps src_pad_template_caps =
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
+    (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, COMPOSITOR_SRC_FORMATS) "; "
+    GST_VIDEO_CAPS_MAKE (COMPOSITOR_SRC_FORMATS));
 
 enum
 {
@@ -1437,19 +1068,21 @@ static void gst_d3d11_compositor_release_pad (GstElement * element,
 static void gst_d3d11_compositor_set_context (GstElement * element,
     GstContext * context);
 
-static gboolean gst_d3d11_compositor_start (GstAggregator * aggregator);
-static gboolean gst_d3d11_compositor_stop (GstAggregator * aggregator);
-static gboolean gst_d3d11_compositor_sink_query (GstAggregator * aggregator,
+static gboolean gst_d3d11_compositor_start (GstAggregator * agg);
+static gboolean gst_d3d11_compositor_stop (GstAggregator * agg);
+static gboolean gst_d3d11_compositor_sink_query (GstAggregator * agg,
     GstAggregatorPad * pad, GstQuery * query);
-static gboolean gst_d3d11_compositor_src_query (GstAggregator * aggregator,
+static gboolean gst_d3d11_compositor_src_query (GstAggregator * agg,
     GstQuery * query);
-static GstCaps *gst_d3d11_compositor_fixate_src_caps (GstAggregator *
-    aggregator, GstCaps * caps);
-static gboolean gst_d3d11_compositor_propose_allocation (GstAggregator *
-    aggregator, GstAggregatorPad * pad, GstQuery * decide_query,
+static GstCaps *gst_d3d11_compositor_fixate_src_caps (GstAggregator * agg,
+    GstCaps * caps);
+static gboolean gst_d3d11_compositor_negotiated_src_caps (GstAggregator * agg,
+    GstCaps * caps);
+static gboolean
+gst_d3d11_compositor_propose_allocation (GstAggregator * agg,
+    GstAggregatorPad * pad, GstQuery * decide_query, GstQuery * query);
+static gboolean gst_d3d11_compositor_decide_allocation (GstAggregator * agg,
     GstQuery * query);
-static gboolean gst_d3d11_compositor_decide_allocation (GstAggregator *
-    aggregator, GstQuery * query);
 static GstFlowReturn
 gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg,
     GstBuffer * outbuf);
@@ -1466,24 +1099,24 @@ G_DEFINE_TYPE_WITH_CODE (GstD3D11Compositor, gst_d3d11_compositor,
 static void
 gst_d3d11_compositor_class_init (GstD3D11CompositorClass * klass)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstAggregatorClass *aggregator_class = GST_AGGREGATOR_CLASS (klass);
+  GstAggregatorClass *agg_class = GST_AGGREGATOR_CLASS (klass);
   GstVideoAggregatorClass *vagg_class = GST_VIDEO_AGGREGATOR_CLASS (klass);
   GstCaps *caps;
 
-  gobject_class->dispose = gst_d3d11_compositor_dispose;
-  gobject_class->set_property = gst_d3d11_compositor_set_property;
-  gobject_class->get_property = gst_d3d11_compositor_get_property;
+  object_class->dispose = gst_d3d11_compositor_dispose;
+  object_class->set_property = gst_d3d11_compositor_set_property;
+  object_class->get_property = gst_d3d11_compositor_get_property;
 
-  g_object_class_install_property (gobject_class, PROP_ADAPTER,
+  g_object_class_install_property (object_class, PROP_ADAPTER,
       g_param_spec_int ("adapter", "Adapter",
           "Adapter index for creating device (-1 for default)",
           -1, G_MAXINT32, DEFAULT_ADAPTER,
           (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY |
               G_PARAM_STATIC_STRINGS)));
 
-  g_object_class_install_property (gobject_class, PROP_BACKGROUND,
+  g_object_class_install_property (object_class, PROP_BACKGROUND,
       g_param_spec_enum ("background", "Background", "Background type",
           GST_TYPE_D3D11_COMPOSITOR_BACKGROUND,
           DEFAULT_BACKGROUND,
@@ -1496,17 +1129,17 @@ gst_d3d11_compositor_class_init (GstD3D11CompositorClass * klass)
   element_class->set_context =
       GST_DEBUG_FUNCPTR (gst_d3d11_compositor_set_context);
 
-  aggregator_class->start = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_start);
-  aggregator_class->stop = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_stop);
-  aggregator_class->sink_query =
-      GST_DEBUG_FUNCPTR (gst_d3d11_compositor_sink_query);
-  aggregator_class->src_query =
-      GST_DEBUG_FUNCPTR (gst_d3d11_compositor_src_query);
-  aggregator_class->fixate_src_caps =
+  agg_class->start = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_start);
+  agg_class->stop = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_stop);
+  agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_sink_query);
+  agg_class->src_query = GST_DEBUG_FUNCPTR (gst_d3d11_compositor_src_query);
+  agg_class->fixate_src_caps =
       GST_DEBUG_FUNCPTR (gst_d3d11_compositor_fixate_src_caps);
-  aggregator_class->propose_allocation =
+  agg_class->negotiated_src_caps =
+      GST_DEBUG_FUNCPTR (gst_d3d11_compositor_negotiated_src_caps);
+  agg_class->propose_allocation =
       GST_DEBUG_FUNCPTR (gst_d3d11_compositor_propose_allocation);
-  aggregator_class->decide_allocation =
+  agg_class->decide_allocation =
       GST_DEBUG_FUNCPTR (gst_d3d11_compositor_decide_allocation);
 
   vagg_class->aggregate_frames =
@@ -1514,24 +1147,29 @@ gst_d3d11_compositor_class_init (GstD3D11CompositorClass * klass)
   vagg_class->create_output_buffer =
       GST_DEBUG_FUNCPTR (gst_d3d11_compositor_create_output_buffer);
 
-  caps = gst_d3d11_get_updated_template_caps (&pad_template_caps);
+  caps = gst_d3d11_get_updated_template_caps (&sink_pad_template_caps);
   gst_element_class_add_pad_template (element_class,
       gst_pad_template_new_with_gtype ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST,
           caps, GST_TYPE_D3D11_COMPOSITOR_PAD));
+  gst_caps_unref (caps);
 
+  caps = gst_d3d11_get_updated_template_caps (&src_pad_template_caps);
   gst_element_class_add_pad_template (element_class,
       gst_pad_template_new_with_gtype ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
           caps, GST_TYPE_AGGREGATOR_PAD));
   gst_caps_unref (caps);
 
   gst_element_class_set_static_metadata (element_class, "Direct3D11 Compositor",
-      "Filter/Editor/Video/Compositor",
-      "A Direct3D11 compositor", "Seungha Yang <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
@@ -1548,7 +1186,6 @@ gst_d3d11_compositor_dispose (GObject * object)
 
   gst_clear_object (&self->device);
   gst_clear_buffer (&self->fallback_buf);
-  gst_clear_object (&self->fallback_pool);
   g_clear_pointer (&self->checker_background, gst_d3d11_compositor_quad_free);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -1598,7 +1235,7 @@ gst_d3d11_compositor_child_proxy_get_child_by_index (GstChildProxy * proxy,
     guint index)
 {
   GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (proxy);
-  GObject *obj = NULL;
+  GObject *obj = nullptr;
 
   GST_OBJECT_LOCK (self);
   obj = (GObject *) g_list_nth_data (GST_ELEMENT_CAST (self)->sinkpads, index);
@@ -1643,8 +1280,10 @@ gst_d3d11_compositor_request_new_pad (GstElement * element,
   pad = GST_ELEMENT_CLASS (parent_class)->request_new_pad (element,
       templ, name, caps);
 
-  if (pad == NULL)
-    goto could_not_create;
+  if (!pad) {
+    GST_DEBUG_OBJECT (element, "could not create/add pad");
+    return nullptr;
+  }
 
   gst_child_proxy_child_added (GST_CHILD_PROXY (element), G_OBJECT (pad),
       GST_OBJECT_NAME (pad));
@@ -1652,12 +1291,6 @@ gst_d3d11_compositor_request_new_pad (GstElement * element,
   GST_DEBUG_OBJECT (element, "Created new pad %s:%s", GST_DEBUG_PAD_NAME (pad));
 
   return pad;
-
-could_not_create:
-  {
-    GST_DEBUG_OBJECT (element, "could not create/add pad");
-    return NULL;
-  }
 }
 
 static gboolean
@@ -1665,11 +1298,8 @@ gst_d3d11_compositor_pad_clear_resource (GstD3D11Compositor * self,
     GstD3D11CompositorPad * cpad, gpointer user_data)
 {
   gst_clear_buffer (&cpad->fallback_buf);
-  if (cpad->fallback_pool) {
-    gst_buffer_pool_set_active (cpad->fallback_pool, FALSE);
-    gst_clear_object (&cpad->fallback_pool);
-  }
   gst_clear_object (&cpad->convert);
+  g_clear_pointer (&cpad->processor, gst_d3d11_video_processor_free);
   GST_D3D11_CLEAR_COM (cpad->blend);
 
   return TRUE;
@@ -1686,7 +1316,7 @@ gst_d3d11_compositor_release_pad (GstElement * element, GstPad * pad)
   gst_child_proxy_child_removed (GST_CHILD_PROXY (self), G_OBJECT (pad),
       GST_OBJECT_NAME (pad));
 
-  gst_d3d11_compositor_pad_clear_resource (self, cpad, NULL);
+  gst_d3d11_compositor_pad_clear_resource (self, cpad, nullptr);
 
   GST_ELEMENT_CLASS (parent_class)->release_pad (element, pad);
 }
@@ -1702,9 +1332,9 @@ gst_d3d11_compositor_set_context (GstElement * element, GstContext * context)
 }
 
 static gboolean
-gst_d3d11_compositor_start (GstAggregator * aggregator)
+gst_d3d11_compositor_start (GstAggregator * agg)
 {
-  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator);
+  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg);
 
   if (!gst_d3d11_ensure_element_data (GST_ELEMENT_CAST (self),
           self->adapter, &self->device)) {
@@ -1712,18 +1342,18 @@ gst_d3d11_compositor_start (GstAggregator * aggregator)
     return FALSE;
   }
 
-  return GST_AGGREGATOR_CLASS (parent_class)->start (aggregator);
+  return GST_AGGREGATOR_CLASS (parent_class)->start (agg);
 }
 
 static gboolean
-gst_d3d11_compositor_stop (GstAggregator * aggregator)
+gst_d3d11_compositor_stop (GstAggregator * agg)
 {
-  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator);
+  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg);
 
   g_clear_pointer (&self->checker_background, gst_d3d11_compositor_quad_free);
   gst_clear_object (&self->device);
 
-  return GST_AGGREGATOR_CLASS (parent_class)->stop (aggregator);
+  return GST_AGGREGATOR_CLASS (parent_class)->stop (agg);
 }
 
 static GstCaps *
@@ -1737,7 +1367,7 @@ gst_d3d11_compositor_sink_getcaps (GstPad * pad, GstCaps * filter)
   template_caps = gst_pad_get_pad_template_caps (pad);
 
   sinkcaps = gst_pad_get_current_caps (pad);
-  if (sinkcaps == NULL) {
+  if (sinkcaps == nullptr) {
     sinkcaps = gst_caps_ref (template_caps);
   } else {
     sinkcaps = gst_caps_merge (sinkcaps, gst_caps_ref (template_caps));
@@ -1780,23 +1410,19 @@ gst_d3d11_compositor_sink_acceptcaps (GstPad * pad, GstCaps * caps)
 }
 
 static gboolean
-gst_d3d11_compositor_sink_query (GstAggregator * aggregator,
+gst_d3d11_compositor_sink_query (GstAggregator * agg,
     GstAggregatorPad * pad, GstQuery * query)
 {
-  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator);
+  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg);
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_CONTEXT:
-    {
-      gboolean ret;
-      ret = gst_d3d11_handle_context_query (GST_ELEMENT (aggregator), query,
-          self->device);
-      if (ret)
+      if (gst_d3d11_handle_context_query (GST_ELEMENT (agg), query,
+              self->device)) {
         return TRUE;
+      }
       break;
-    }
-    case GST_QUERY_CAPS:
-    {
+    case GST_QUERY_CAPS:{
       GstCaps *filter, *caps;
 
       gst_query_parse_caps (query, &filter);
@@ -1805,8 +1431,7 @@ gst_d3d11_compositor_sink_query (GstAggregator * aggregator,
       gst_caps_unref (caps);
       return TRUE;
     }
-    case GST_QUERY_ACCEPT_CAPS:
-    {
+    case GST_QUERY_ACCEPT_CAPS:{
       GstCaps *caps;
       gboolean ret;
 
@@ -1819,43 +1444,38 @@ gst_d3d11_compositor_sink_query (GstAggregator * aggregator,
       break;
   }
 
-  return GST_AGGREGATOR_CLASS (parent_class)->sink_query (aggregator,
-      pad, query);
+  return GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, pad, query);
 }
 
 static gboolean
-gst_d3d11_compositor_src_query (GstAggregator * aggregator, GstQuery * query)
+gst_d3d11_compositor_src_query (GstAggregator * agg, GstQuery * query)
 {
-  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator);
+  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg);
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_CONTEXT:
-    {
-      gboolean ret;
-      ret = gst_d3d11_handle_context_query (GST_ELEMENT (aggregator), query,
-          self->device);
-      if (ret)
+      if (gst_d3d11_handle_context_query (GST_ELEMENT (agg), query,
+              self->device)) {
         return TRUE;
+      }
       break;
-    }
     default:
       break;
   }
 
-  return GST_AGGREGATOR_CLASS (parent_class)->src_query (aggregator, query);
+  return GST_AGGREGATOR_CLASS (parent_class)->src_query (agg, query);
 }
 
 static GstCaps *
-gst_d3d11_compositor_fixate_src_caps (GstAggregator * aggregator,
-    GstCaps * caps)
+gst_d3d11_compositor_fixate_src_caps (GstAggregator * agg, GstCaps * caps)
 {
-  GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (aggregator);
+  GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg);
   GList *l;
   gint best_width = -1, best_height = -1;
   gint best_fps_n = -1, best_fps_d = -1;
   gint par_n, par_d;
   gdouble best_fps = 0.;
-  GstCaps *ret = NULL;
+  GstCaps *ret = nullptr;
   GstStructure *s;
 
   ret = gst_caps_make_writable (caps);
@@ -1924,45 +1544,302 @@ gst_d3d11_compositor_fixate_src_caps (GstAggregator * aggregator,
       best_fps_d);
   ret = gst_caps_fixate (ret);
 
-  GST_LOG_OBJECT (aggregator, "Fixated caps %" GST_PTR_FORMAT, ret);
+  GST_LOG_OBJECT (agg, "Fixated caps %" GST_PTR_FORMAT, ret);
 
   return ret;
 }
 
+static void
+convert_info_gray_to_yuv (const GstVideoInfo * gray, GstVideoInfo * yuv)
+{
+  GstVideoInfo tmp;
+
+  if (GST_VIDEO_INFO_IS_YUV (gray)) {
+    *yuv = *gray;
+    return;
+  }
+
+  if (gray->finfo->depth[0] == 8) {
+    gst_video_info_set_format (&tmp,
+        GST_VIDEO_FORMAT_Y444, gray->width, gray->height);
+  } else {
+    gst_video_info_set_format (&tmp,
+        GST_VIDEO_FORMAT_Y444_16LE, gray->width, gray->height);
+  }
+
+  tmp.colorimetry.range = gray->colorimetry.range;
+  if (tmp.colorimetry.range == GST_VIDEO_COLOR_RANGE_UNKNOWN)
+    tmp.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
+
+  tmp.colorimetry.primaries = gray->colorimetry.primaries;
+  if (tmp.colorimetry.primaries == GST_VIDEO_COLOR_PRIMARIES_UNKNOWN)
+    tmp.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
+
+  tmp.colorimetry.transfer = gray->colorimetry.transfer;
+  if (tmp.colorimetry.transfer == GST_VIDEO_TRANSFER_UNKNOWN)
+    tmp.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
+
+  tmp.colorimetry.matrix = gray->colorimetry.matrix;
+  if (tmp.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN)
+    tmp.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
+
+  *yuv = tmp;
+}
+
+static void
+gst_d3d11_compositor_calculate_background_color (GstD3D11Compositor * self,
+    const GstVideoInfo * info)
+{
+  GstD3D11ColorMatrix clear_color_matrix;
+  gdouble rgb[3];
+  gdouble converted[3];
+  GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
+
+  if (GST_VIDEO_INFO_IS_RGB (info)) {
+    GstVideoInfo rgb_info = *info;
+    rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
+
+    gst_d3d11_color_range_adjust_matrix_unorm (&rgb_info, info,
+        &clear_color_matrix);
+  } else {
+    GstVideoInfo rgb_info;
+    GstVideoInfo yuv_info;
+
+    gst_video_info_set_format (&rgb_info, GST_VIDEO_FORMAT_RGBA64_LE,
+        info->width, info->height);
+    convert_info_gray_to_yuv (info, &yuv_info);
+
+    if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN ||
+        yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) {
+      GST_WARNING_OBJECT (self, "Invalid matrix is detected");
+      yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
+    }
+
+    gst_d3d11_rgb_to_yuv_matrix_unorm (&rgb_info,
+        &yuv_info, &clear_color_matrix);
+  }
+
+  /* Calculate black and white color values */
+  for (guint i = 0; i < 2; i++) {
+    GstD3D11CompositorClearColor *clear_color = &self->clear_color[i];
+    rgb[0] = rgb[1] = rgb[2] = (gdouble) i;
+
+    for (guint j = 0; j < 3; j++) {
+      converted[j] = 0;
+      for (guint k = 0; k < 3; k++) {
+        converted[j] += clear_color_matrix.matrix[j][k] * rgb[k];
+      }
+      converted[j] += clear_color_matrix.offset[j];
+      converted[j] = CLAMP (converted[j],
+          clear_color_matrix.min[j], clear_color_matrix.max[j]);
+    }
+
+    GST_DEBUG_OBJECT (self, "Calculated background color RGB: %f, %f, %f",
+        converted[0], converted[1], converted[2]);
+
+    if (GST_VIDEO_INFO_IS_RGB (info) || GST_VIDEO_INFO_IS_GRAY (info)) {
+      for (guint j = 0; j < 3; j++)
+        clear_color->color[0][j] = converted[j];
+      clear_color->color[0][3] = 1.0;
+    } else {
+      switch (format) {
+        case GST_VIDEO_FORMAT_VUYA:
+          clear_color->color[0][0] = converted[2];
+          clear_color->color[0][1] = converted[1];
+          clear_color->color[0][2] = converted[0];
+          clear_color->color[0][3] = 1.0;
+          break;
+        case GST_VIDEO_FORMAT_NV12:
+        case GST_VIDEO_FORMAT_NV21:
+        case GST_VIDEO_FORMAT_P010_10LE:
+        case GST_VIDEO_FORMAT_P012_LE:
+        case GST_VIDEO_FORMAT_P016_LE:
+          clear_color->color[0][0] = converted[0];
+          clear_color->color[0][1] = 0;
+          clear_color->color[0][2] = 0;
+          clear_color->color[0][3] = 1.0;
+          if (format == GST_VIDEO_FORMAT_NV21) {
+            clear_color->color[1][0] = converted[2];
+            clear_color->color[1][1] = converted[1];
+          } else {
+            clear_color->color[1][0] = converted[1];
+            clear_color->color[1][1] = converted[2];
+          }
+          clear_color->color[1][2] = 0;
+          clear_color->color[1][3] = 1.0;
+          break;
+        case GST_VIDEO_FORMAT_I420:
+        case GST_VIDEO_FORMAT_YV12:
+        case GST_VIDEO_FORMAT_I420_10LE:
+        case GST_VIDEO_FORMAT_I420_12LE:
+        case GST_VIDEO_FORMAT_Y42B:
+        case GST_VIDEO_FORMAT_I422_10LE:
+        case GST_VIDEO_FORMAT_I422_12LE:
+        case GST_VIDEO_FORMAT_Y444:
+        case GST_VIDEO_FORMAT_Y444_10LE:
+        case GST_VIDEO_FORMAT_Y444_12LE:
+        case GST_VIDEO_FORMAT_Y444_16LE:
+          clear_color->color[0][0] = converted[0];
+          clear_color->color[0][1] = 0;
+          clear_color->color[0][2] = 0;
+          clear_color->color[0][3] = 1.0;
+          if (format == GST_VIDEO_FORMAT_YV12) {
+            clear_color->color[1][0] = converted[2];
+            clear_color->color[2][0] = converted[1];
+          } else {
+            clear_color->color[1][0] = converted[1];
+            clear_color->color[2][0] = converted[2];
+          }
+          clear_color->color[1][1] = 0;
+          clear_color->color[1][2] = 0;
+          clear_color->color[1][3] = 1.0;
+          clear_color->color[2][1] = 0;
+          clear_color->color[2][2] = 0;
+          clear_color->color[2][3] = 1.0;
+          break;
+        default:
+          g_assert_not_reached ();
+          break;
+      }
+    }
+  }
+}
+
+static gboolean
+gst_d3d11_compositor_negotiated_src_caps (GstAggregator * agg, GstCaps * caps)
+{
+  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg);
+  GstCapsFeatures *features;
+  GstVideoInfo info;
+
+  if (!gst_video_info_from_caps (&info, caps)) {
+    GST_ERROR_OBJECT (self, "Failed to convert caps to info");
+    return FALSE;
+  }
+
+  features = gst_caps_get_features (caps, 0);
+  if (features
+      && gst_caps_features_contains (features,
+          GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
+    GST_DEBUG_OBJECT (self, "Negotiated with D3D11 memory caps");
+    self->downstream_supports_d3d11 = TRUE;
+  } else {
+    GST_DEBUG_OBJECT (self, "Negotiated with system memory caps");
+    self->downstream_supports_d3d11 = FALSE;
+  }
+
+  gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self),
+      (GstElementForeachPadFunc) gst_d3d11_compositor_pad_clear_resource,
+      nullptr);
+
+  gst_clear_buffer (&self->fallback_buf);
+  g_clear_pointer (&self->checker_background, gst_d3d11_compositor_quad_free);
+
+  gst_d3d11_compositor_calculate_background_color (self, &info);
+
+  if (!self->downstream_supports_d3d11) {
+    GstD3D11AllocationParams *d3d11_params;
+    GstBufferPool *pool;
+    GstFlowReturn flow_ret;
+
+    d3d11_params = gst_d3d11_allocation_params_new (self->device,
+        &info, (GstD3D11AllocationFlags) 0,
+        D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
+
+    pool = gst_d3d11_buffer_pool_new_with_options (self->device,
+        caps, d3d11_params, 0, 0);
+    gst_d3d11_allocation_params_free (d3d11_params);
+
+    if (!pool) {
+      GST_ERROR_OBJECT (self, "Failed to create pool");
+      return FALSE;
+    }
+
+    if (!gst_buffer_pool_set_active (pool, TRUE)) {
+      GST_ERROR_OBJECT (self, "Failed to set active");
+      gst_object_unref (pool);
+      return FALSE;
+    }
+
+    flow_ret = gst_buffer_pool_acquire_buffer (pool, &self->fallback_buf,
+        nullptr);
+    if (flow_ret != GST_FLOW_OK) {
+      GST_ERROR_OBJECT (self, "Failed to acquire buffer");
+      gst_object_unref (pool);
+      return FALSE;
+    }
+
+    gst_buffer_pool_set_active (pool, FALSE);
+    gst_object_unref (pool);
+  }
+
+  return GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps);
+}
+
 static gboolean
-gst_d3d11_compositor_propose_allocation (GstAggregator * aggregator,
+gst_d3d11_compositor_propose_allocation (GstAggregator * agg,
     GstAggregatorPad * pad, GstQuery * decide_query, GstQuery * query)
 {
-  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator);
+  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg);
   GstVideoInfo info;
   GstBufferPool *pool;
   GstCaps *caps;
   guint size;
 
-  gst_query_parse_allocation (query, &caps, NULL);
+  gst_query_parse_allocation (query, &caps, nullptr);
 
-  if (caps == NULL)
+  if (caps == nullptr)
     return FALSE;
 
   if (!gst_video_info_from_caps (&info, caps))
     return FALSE;
 
   if (gst_query_get_n_allocation_pools (query) == 0) {
-    GstD3D11AllocationParams *d3d11_params;
+    GstCapsFeatures *features;
     GstStructure *config;
-
-    d3d11_params = gst_d3d11_allocation_params_new (self->device, &info,
-        (GstD3D11AllocationFlags) 0, D3D11_BIND_SHADER_RESOURCE);
-
-    pool = gst_d3d11_buffer_pool_new_with_options (self->device,
-        caps, d3d11_params, 0, 0);
-    gst_d3d11_allocation_params_free (d3d11_params);
+    gboolean is_d3d11 = FALSE;
+
+    features = gst_caps_get_features (caps, 0);
+    if (features
+        && gst_caps_features_contains (features,
+            GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
+      GST_DEBUG_OBJECT (pad, "upstream support d3d11 memory");
+      pool = gst_d3d11_buffer_pool_new (self->device);
+      is_d3d11 = TRUE;
+    } else {
+      pool = gst_d3d11_staging_buffer_pool_new (self->device);
+    }
 
     if (!pool) {
       GST_ERROR_OBJECT (self, "Failed to create buffer pool");
       return FALSE;
     }
 
+    config = gst_buffer_pool_get_config (pool);
+    gst_buffer_pool_config_add_option (config,
+        GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+    size = GST_VIDEO_INFO_SIZE (&info);
+    if (is_d3d11) {
+      GstD3D11AllocationParams *d3d11_params;
+
+      d3d11_params =
+          gst_d3d11_allocation_params_new (self->device,
+          &info, (GstD3D11AllocationFlags) 0, D3D11_BIND_SHADER_RESOURCE);
+
+      gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
+      gst_d3d11_allocation_params_free (d3d11_params);
+    }
+
+    gst_buffer_pool_config_set_params (config, caps, (guint) size, 0, 0);
+
+    if (!gst_buffer_pool_set_config (pool, config)) {
+      GST_ERROR_OBJECT (pool, "Couldn't set config");
+      gst_object_unref (pool);
+
+      return FALSE;
+    }
+
     /* d3d11 buffer pool will update buffer size based on allocated texture,
      * get size from config again */
     config = gst_buffer_pool_get_config (pool);
@@ -1974,71 +1851,99 @@ gst_d3d11_compositor_propose_allocation (GstAggregator * aggregator,
     gst_object_unref (pool);
   }
 
-  gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
+  gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, nullptr);
 
   return TRUE;
 }
 
 static gboolean
-gst_d3d11_compositor_decide_allocation (GstAggregator * aggregator,
-    GstQuery * query)
+gst_d3d11_compositor_decide_allocation (GstAggregator * agg, GstQuery * query)
 {
-  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (aggregator);
+  GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (agg);
   GstCaps *caps;
-  GstBufferPool *pool = NULL;
+  GstBufferPool *pool = nullptr;
   guint n, size, min, max;
   GstVideoInfo info;
   GstStructure *config;
-  GstD3D11AllocationParams *d3d11_params;
+  gboolean use_d3d11_pool;
+  gboolean has_videometa;
 
-  gst_query_parse_allocation (query, &caps, NULL);
+  gst_query_parse_allocation (query, &caps, nullptr);
 
   if (!caps) {
     GST_DEBUG_OBJECT (self, "No output caps");
     return FALSE;
   }
 
-  gst_video_info_from_caps (&info, caps);
+  if (!gst_video_info_from_caps (&info, caps)) {
+    GST_ERROR_OBJECT (self, "Invalid caps");
+    return FALSE;
+  }
+
+  has_videometa = gst_query_find_allocation_meta (query,
+      GST_VIDEO_META_API_TYPE, nullptr);
+  use_d3d11_pool = self->downstream_supports_d3d11;
+
   n = gst_query_get_n_allocation_pools (query);
   if (n > 0)
     gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
 
   /* create our own pool */
   if (pool) {
-    if (!GST_IS_D3D11_BUFFER_POOL (pool)) {
-      gst_clear_object (&pool);
-    } else {
-      GstD3D11BufferPool *dpool = GST_D3D11_BUFFER_POOL (pool);
-      if (dpool->device != self->device)
+    if (use_d3d11_pool) {
+      if (!GST_IS_D3D11_BUFFER_POOL (pool)) {
+        GST_DEBUG_OBJECT (self,
+            "Downstream pool is not d3d11, will create new one");
         gst_clear_object (&pool);
+      } else {
+        GstD3D11BufferPool *dpool = GST_D3D11_BUFFER_POOL (pool);
+        if (dpool->device != self->device) {
+          GST_DEBUG_OBJECT (self, "Different device, will create new one");
+          gst_clear_object (&pool);
+        }
+      }
+    } else if (has_videometa) {
+      /* We will use d3d11 staging buffer pool */
+      gst_clear_object (&pool);
     }
   }
 
+  size = (guint) info.size;
+
   if (!pool) {
-    pool = gst_d3d11_buffer_pool_new (self->device);
+    if (use_d3d11_pool)
+      pool = gst_d3d11_buffer_pool_new (self->device);
+    else if (has_videometa)
+      pool = gst_d3d11_staging_buffer_pool_new (self->device);
+    else
+      pool = gst_video_buffer_pool_new ();
 
-    min = max = 0;
-    size = (guint) info.size;
+    min = 0;
+    max = 0;
   }
 
   config = gst_buffer_pool_get_config (pool);
   gst_buffer_pool_config_set_params (config, caps, size, min, max);
   gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
 
-  d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
-  if (!d3d11_params) {
-    d3d11_params = gst_d3d11_allocation_params_new (self->device,
-        &info, (GstD3D11AllocationFlags) 0, D3D11_BIND_RENDER_TARGET);
-  } else {
-    guint i;
+  if (use_d3d11_pool) {
+    GstD3D11AllocationParams *d3d11_params;
+
+    d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
+    if (!d3d11_params) {
+      d3d11_params = gst_d3d11_allocation_params_new (self->device,
+          &info, (GstD3D11AllocationFlags) 0, D3D11_BIND_RENDER_TARGET);
+    } else {
+      guint i;
 
-    for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) {
-      d3d11_params->desc[i].BindFlags |= D3D11_BIND_RENDER_TARGET;
+      for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) {
+        d3d11_params->desc[i].BindFlags |= D3D11_BIND_RENDER_TARGET;
+      }
     }
-  }
 
-  gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
-  gst_d3d11_allocation_params_free (d3d11_params);
+    gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
+    gst_d3d11_allocation_params_free (d3d11_params);
+  }
 
   gst_buffer_pool_set_config (pool, config);
 
@@ -2054,8 +1959,6 @@ gst_d3d11_compositor_decide_allocation (GstAggregator * aggregator,
     gst_query_add_allocation_pool (query, pool, size, min, max);
   gst_object_unref (pool);
 
-  self->reconfigured = TRUE;
-
   return TRUE;
 }
 
@@ -2092,13 +1995,22 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self,
   ComPtr < ID3D11VertexShader > vs;
   ComPtr < ID3D11InputLayout > layout;
   HRESULT hr;
+  const gchar *ps_src;
 
   device_handle = gst_d3d11_device_get_device_handle (self->device);
   context_handle = gst_d3d11_device_get_device_context_handle (self->device);
 
-  if (!gst_d3d11_create_pixel_shader (self->device, checker_ps_src, &ps)) {
+  if (GST_VIDEO_INFO_IS_RGB (info)) {
+    ps_src = checker_ps_src_rgb;
+  } else if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_VUYA) {
+    ps_src = checker_ps_src_vuya;
+  } else {
+    ps_src = checker_ps_src_luma;
+  }
+
+  if (!gst_d3d11_create_pixel_shader (self->device, ps_src, &ps)) {
     GST_ERROR_OBJECT (self, "Couldn't setup pixel shader");
-    return NULL;
+    return nullptr;
   }
 
   memset (&input_desc, 0, sizeof (D3D11_INPUT_ELEMENT_DESC));
@@ -2113,7 +2025,7 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self,
   if (!gst_d3d11_create_vertex_shader (self->device, checker_vs_src,
           &input_desc, 1, &vs, &layout)) {
     GST_ERROR_OBJECT (self, "Couldn't setup vertex shader");
-    return NULL;
+    return nullptr;
   }
 
   memset (&buffer_desc, 0, sizeof (D3D11_BUFFER_DESC));
@@ -2122,11 +2034,11 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self,
   buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
   buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
 
-  hr = device_handle->CreateBuffer (&buffer_desc, NULL, &vertex_buffer);
+  hr = device_handle->CreateBuffer (&buffer_desc, nullptr, &vertex_buffer);
   if (!gst_d3d11_result (hr, self->device)) {
     GST_ERROR_OBJECT (self,
         "Couldn't create vertex buffer, hr: 0x%x", (guint) hr);
-    return NULL;
+    return nullptr;
   }
 
   hr = context_handle->Map (vertex_buffer.Get (),
@@ -2134,12 +2046,11 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self,
 
   if (!gst_d3d11_result (hr, self->device)) {
     GST_ERROR_OBJECT (self, "Couldn't map vertex buffer, hr: 0x%x", (guint) hr);
-    return NULL;
+    return nullptr;
   }
 
   vertex_data = (VertexData *) map.pData;
   /* bottom left */
-  /* bottom left */
   vertex_data[0].position.x = -1.0f;
   vertex_data[0].position.y = -1.0f;
   vertex_data[0].position.z = 0.0f;
@@ -2174,11 +2085,11 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self,
   buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
   buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
 
-  hr = device_handle->CreateBuffer (&buffer_desc, NULL, &index_buffer);
+  hr = device_handle->CreateBuffer (&buffer_desc, nullptr, &index_buffer);
   if (!gst_d3d11_result (hr, self->device)) {
     GST_ERROR_OBJECT (self,
         "Couldn't create index buffer, hr: 0x%x", (guint) hr);
-    return NULL;
+    return nullptr;
   }
 
   hr = context_handle->Map (index_buffer.Get (),
@@ -2186,7 +2097,7 @@ gst_d3d11_compositor_create_checker_quad (GstD3D11Compositor * self,
 
   if (!gst_d3d11_result (hr, self->device)) {
     GST_ERROR_OBJECT (self, "Couldn't map index buffer, hr: 0x%x", (guint) hr);
-    return NULL;
+    return nullptr;
   }
 
   indices = (WORD *) map.pData;
@@ -2271,32 +2182,40 @@ gst_d3d11_compositor_draw_background_checker (GstD3D11Compositor * self,
 /* Must be called with d3d11 device lock */
 static gboolean
 gst_d3d11_compositor_draw_background (GstD3D11Compositor * self,
-    ID3D11RenderTargetView * rtv)
+    ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES], guint num_rtv)
 {
   ID3D11DeviceContext *context =
       gst_d3d11_device_get_device_context_handle (self->device);
-  FLOAT rgba[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+  GstD3D11CompositorClearColor *color = &self->clear_color[0];
+
+  if (self->background == GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER) {
+    if (!gst_d3d11_compositor_draw_background_checker (self, rtv[0]))
+      return FALSE;
+
+    /* clear U and V components if needed */
+    for (guint i = 1; i < num_rtv; i++)
+      context->ClearRenderTargetView (rtv[i], color->color[i]);
+
+    return TRUE;
+  }
 
   switch (self->background) {
-    case GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER:
-      return gst_d3d11_compositor_draw_background_checker (self, rtv);
     case GST_D3D11_COMPOSITOR_BACKGROUND_BLACK:
-      /* {0, 0, 0, 1} */
+      color = &self->clear_color[0];
       break;
     case GST_D3D11_COMPOSITOR_BACKGROUND_WHITE:
-      rgba[0] = 1.0f;
-      rgba[1] = 1.0f;
-      rgba[2] = 1.0f;
+      color = &self->clear_color[1];
       break;
     case GST_D3D11_COMPOSITOR_BACKGROUND_TRANSPARENT:
-      rgba[3] = 0.0f;
+      color = &self->clear_color[2];
       break;
     default:
       g_assert_not_reached ();
       return FALSE;
   }
 
-  context->ClearRenderTargetView (rtv, rgba);
+  for (guint i = 0; i < num_rtv; i++)
+    context->ClearRenderTargetView (rtv[i], color->color[i]);
 
   return TRUE;
 }
@@ -2308,79 +2227,42 @@ gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg,
   GstD3D11Compositor *self = GST_D3D11_COMPOSITOR (vagg);
   GList *iter;
   GstBuffer *target_buf = outbuf;
-  gboolean need_copy = FALSE;
-  gboolean do_device_copy = FALSE;
   GstFlowReturn ret = GST_FLOW_OK;
-  ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES] = { NULL, };
-  guint i, j;
-  gint view_idx;
-
-  /* Use fallback buffer when output buffer is:
-   * - non-d3d11 memory
-   * - or, from different d3d11 device
-   * - or not bound to render target
-   */
-  if (!gst_d3d11_compositor_check_d3d11_memory (self,
-          outbuf, FALSE, &do_device_copy) || !do_device_copy) {
-    if (!gst_d3d11_compsitor_prepare_fallback_buffer (self, &vagg->info, FALSE,
-            &self->fallback_pool, &self->fallback_buf)) {
-      GST_ERROR_OBJECT (self, "Couldn't prepare fallback buffer");
-      return GST_FLOW_ERROR;
-    }
-
-    GST_TRACE_OBJECT (self, "Will draw on fallback texture");
+  ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES] = { nullptr, };
+  GstVideoFrame target_frame;
+  guint num_rtv = GST_VIDEO_INFO_N_PLANES (&vagg->info);
+  ID3D11VideoProcessorOutputView *pov = nullptr;
 
-    need_copy = TRUE;
+  if (!self->downstream_supports_d3d11)
     target_buf = self->fallback_buf;
-  }
-
-  view_idx = 0;
-  for (i = 0; i < gst_buffer_n_memory (target_buf); i++) {
-    GstMemory *mem = gst_buffer_peek_memory (target_buf, i);
-    GstD3D11Memory *dmem;
-    guint rtv_size;
-
-    if (!gst_is_d3d11_memory (mem)) {
-      GST_ERROR_OBJECT (self, "Invalid output memory");
-      return GST_FLOW_ERROR;
-    }
-
-    dmem = (GstD3D11Memory *) mem;
-    rtv_size = gst_d3d11_memory_get_render_target_view_size (dmem);
-    if (!rtv_size) {
-      GST_ERROR_OBJECT (self, "Render target view is unavailable");
-      return GST_FLOW_ERROR;
-    }
-
-    for (j = 0; j < rtv_size; j++) {
-      g_assert (view_idx < GST_VIDEO_MAX_PLANES);
 
-      rtv[view_idx] = gst_d3d11_memory_get_render_target_view (dmem, j);
-      view_idx++;
-    }
+  if (!gst_video_frame_map (&target_frame, &vagg->info, target_buf,
+          (GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) {
+    GST_ERROR_OBJECT (self, "Failed to map render target frame");
+    return GST_FLOW_ERROR;
+  }
 
-    /* Mark need-download for fallback buffer use case */
-    GST_MINI_OBJECT_FLAG_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
+  if (!gst_d3d11_buffer_get_render_target_view (target_buf, rtv)) {
+    GST_ERROR_OBJECT (self, "RTV is unavailable");
+    gst_video_frame_unmap (&target_frame);
+    return GST_FLOW_ERROR;
   }
 
   gst_d3d11_device_lock (self->device);
-  /* XXX: the number of render target view must be one here, since we support
-   * only RGBA or BGRA */
-  if (!gst_d3d11_compositor_draw_background (self, rtv[0])) {
+  if (!gst_d3d11_compositor_draw_background (self, rtv, num_rtv)) {
     GST_ERROR_OBJECT (self, "Couldn't draw background");
     gst_d3d11_device_unlock (self->device);
-    ret = GST_FLOW_ERROR;
-    goto done;
+    gst_video_frame_unmap (&target_frame);
+    return GST_FLOW_ERROR;
   }
 
   GST_OBJECT_LOCK (self);
-
   for (iter = GST_ELEMENT (vagg)->sinkpads; iter; iter = g_list_next (iter)) {
     GstVideoAggregatorPad *pad = GST_VIDEO_AGGREGATOR_PAD (iter->data);
     GstD3D11CompositorPad *cpad = GST_D3D11_COMPOSITOR_PAD (pad);
     GstVideoFrame *prepared_frame =
         gst_video_aggregator_pad_get_prepared_frame (pad);
-    ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES] = { NULL, };
+    ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES] = { nullptr, };
     GstBuffer *buffer;
 
     if (!prepared_frame)
@@ -2393,45 +2275,58 @@ gst_d3d11_compositor_aggregate_frames (GstVideoAggregator * vagg,
     }
 
     buffer = prepared_frame->buffer;
+    if (cpad->piv) {
+      if (!pov) {
+        GstD3D11Memory *dmem =
+            (GstD3D11Memory *) gst_buffer_peek_memory (target_buf, 0);
+        pov = gst_d3d11_video_processor_get_output_view (cpad->processor, dmem);
+      }
 
-    view_idx = 0;
-    for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
-      GstD3D11Memory *dmem =
-          (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
-      guint srv_size = gst_d3d11_memory_get_shader_resource_view_size (dmem);
+      if (!pov) {
+        GST_ERROR_OBJECT (self, "POV is unavailable");
+        ret = GST_FLOW_ERROR;
+        break;
+      }
 
-      for (j = 0; j < srv_size; j++) {
-        g_assert (view_idx < GST_VIDEO_MAX_PLANES);
+      if (!gst_d3d11_video_processor_render_unlocked (cpad->processor,
+              &cpad->src_rect, cpad->piv, &cpad->dest_rect, pov)) {
+        GST_ERROR_OBJECT (self, "Failed to convert using processor");
+        ret = GST_FLOW_ERROR;
+        break;
+      }
 
-        srv[view_idx] = gst_d3d11_memory_get_shader_resource_view (dmem, j);
-        view_idx++;
+      GST_TRACE_OBJECT (pad, "Blended using processor");
+    } else {
+      if (!gst_d3d11_buffer_get_shader_resource_view (buffer, srv)) {
+        GST_ERROR_OBJECT (pad, "SRV is unavailable");
+        ret = GST_FLOW_ERROR;
+        break;
       }
-    }
 
-    if (!gst_d3d11_converter_convert_unlocked (cpad->convert, srv, rtv)) {
-      GST_ERROR_OBJECT (self, "Couldn't convert frame");
-      ret = GST_FLOW_ERROR;
-      break;
+      if (!gst_d3d11_converter_convert_unlocked (cpad->convert, srv, rtv)) {
+        GST_ERROR_OBJECT (self, "Couldn't convert frame");
+        ret = GST_FLOW_ERROR;
+        break;
+      }
+
+      GST_TRACE_OBJECT (pad, "Blended using converter");
     }
   }
-
-  self->reconfigured = FALSE;
   GST_OBJECT_UNLOCK (self);
   gst_d3d11_device_unlock (self->device);
+  gst_video_frame_unmap (&target_frame);
 
   if (ret != GST_FLOW_OK)
-    goto done;
+    return ret;
 
-  if (need_copy && !gst_d3d11_compositor_copy_buffer (self, &vagg->info,
-          target_buf, outbuf, do_device_copy)) {
-    GST_ERROR_OBJECT (self, "Couldn't copy input buffer to fallback buffer");
-    ret = GST_FLOW_ERROR;
+  if (!self->downstream_supports_d3d11) {
+    if (!gst_d3d11_buffer_copy_into (outbuf, self->fallback_buf, &vagg->info)) {
+      GST_ERROR_OBJECT (self, "Couldn't copy input buffer to fallback buffer");
+      return GST_FLOW_ERROR;
+    }
   }
 
-done:
-  gst_clear_buffer (&self->fallback_buf);
-
-  return ret;
+  return GST_FLOW_OK;
 }
 
 typedef struct
@@ -2462,13 +2357,8 @@ gst_d3d11_compositor_check_device_update (GstElement * agg,
   }
 
   mem = gst_buffer_peek_memory (buf, 0);
-  /* FIXME: we should be able to accept non-d3d11 memory later once
-   * we remove intermediate elements (d3d11upload and d3d11colorconvert)
-   */
-  if (!gst_is_d3d11_memory (mem)) {
-    GST_ELEMENT_ERROR (agg, CORE, FAILED, (NULL), ("Invalid memory"));
-    return FALSE;
-  }
+  if (!gst_is_d3d11_memory (mem))
+    return TRUE;
 
   dmem = GST_D3D11_MEMORY_CAST (mem);
 
@@ -2483,7 +2373,7 @@ gst_d3d11_compositor_check_device_update (GstElement * agg,
   } else {
     guint adapter = 0;
 
-    g_object_get (dmem->device, "adapter", &adapter, NULL);
+    g_object_get (dmem->device, "adapter", &adapter, nullptr);
     /* The same GPU as what user wanted, update */
     if (adapter == (guint) self->adapter)
       update_device = TRUE;
@@ -2508,25 +2398,25 @@ gst_d3d11_compositor_create_output_buffer (GstVideoAggregator * vagg,
 
   /* Check whether there is at least one sinkpad which holds d3d11 buffer
    * with compatible device, and if not, update our device */
-  data.other_device = NULL;
+  data.other_device = nullptr;
   data.have_same_device = FALSE;
 
   gst_element_foreach_sink_pad (GST_ELEMENT_CAST (vagg),
       (GstElementForeachPadFunc) gst_d3d11_compositor_check_device_update,
       &data);
 
-  if (data.have_same_device || !data.other_device)
-    goto done;
+  if (data.have_same_device || !data.other_device) {
+    return
+        GST_VIDEO_AGGREGATOR_CLASS (parent_class)->create_output_buffer (vagg,
+        outbuffer);
+  }
 
   /* Clear all device dependent resources */
   gst_element_foreach_sink_pad (GST_ELEMENT_CAST (vagg),
-      (GstElementForeachPadFunc) gst_d3d11_compositor_pad_clear_resource, NULL);
+      (GstElementForeachPadFunc) gst_d3d11_compositor_pad_clear_resource,
+      nullptr);
 
   gst_clear_buffer (&self->fallback_buf);
-  if (self->fallback_pool) {
-    gst_buffer_pool_set_active (self->fallback_pool, FALSE);
-    gst_clear_object (&self->fallback_pool);
-  }
   g_clear_pointer (&self->checker_background, gst_d3d11_compositor_quad_free);
 
   GST_INFO_OBJECT (self, "Updating device %" GST_PTR_FORMAT " -> %"
@@ -2540,8 +2430,4 @@ gst_d3d11_compositor_create_output_buffer (GstVideoAggregator * vagg,
   gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (vagg));
 
   return GST_AGGREGATOR_FLOW_NEED_DATA;
-
-done:
-  return GST_VIDEO_AGGREGATOR_CLASS (parent_class)->create_output_buffer (vagg,
-      outbuffer);
 }
index 78a79ab..ed084a0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * GStreamer
- * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
+ * Copyright (C) 2022 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
@@ -18,8 +18,7 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef __GST_D3D11_COMPOSITOR_H__
-#define __GST_D3D11_COMPOSITOR_H__
+#pragma once
 
 #include <gst/gst.h>
 #include <gst/video/video.h>
@@ -36,58 +35,5 @@ G_DECLARE_FINAL_TYPE (GstD3D11CompositorPad, gst_d3d11_compositor_pad,
 G_DECLARE_FINAL_TYPE (GstD3D11Compositor, gst_d3d11_compositor,
     GST, D3D11_COMPOSITOR, GstVideoAggregator)
 
-typedef enum
-{
-  GST_D3D11_COMPOSITOR_BLEND_OP_ADD,
-  GST_D3D11_COMPOSITOR_BLEND_OP_SUBTRACT,
-  GST_D3D11_COMPOSITOR_BLEND_OP_REV_SUBTRACT,
-  GST_D3D11_COMPOSITOR_BLEND_OP_MIN,
-  GST_D3D11_COMPOSITOR_BLEND_OP_MAX
-} GstD3D11CompositorBlendOperation;
-
-#define GST_TYPE_D3D11_COMPOSITOR_BLEND_OPERATION (gst_d3d11_compositor_blend_operation_get_type())
-GType gst_d3d11_compositor_blend_operation_get_type (void);
-
-typedef enum
-{
-  GST_D3D11_COMPOSITOR_BLEND_ZERO,
-  GST_D3D11_COMPOSITOR_BLEND_ONE,
-  GST_D3D11_COMPOSITOR_BLEND_SRC_COLOR,
-  GST_D3D11_COMPOSITOR_BLEND_INV_SRC_COLOR,
-  GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA,
-  GST_D3D11_COMPOSITOR_BLEND_INV_SRC_ALPHA,
-  GST_D3D11_COMPOSITOR_BLEND_DEST_ALPHA,
-  GST_D3D11_COMPOSITOR_BLEND_INV_DEST_ALPHA,
-  GST_D3D11_COMPOSITOR_BLEND_DEST_COLOR,
-  GST_D3D11_COMPOSITOR_BLEND_INV_DEST_COLOR,
-  GST_D3D11_COMPOSITOR_BLEND_SRC_ALPHA_SAT,
-  GST_D3D11_COMPOSITOR_BLEND_BLEND_FACTOR,
-  GST_D3D11_COMPOSITOR_BLEND_INV_BLEND_FACTOR,
-} GstD3D11CompositorBlend;
-
-#define GST_TYPE_D3D11_COMPOSITOR_BLEND (gst_d3d11_compositor_blend_get_type())
-GType gst_d3d11_compositor_blend_get_type (void);
-
-typedef enum
-{
-  GST_D3D11_COMPOSITOR_BACKGROUND_CHECKER,
-  GST_D3D11_COMPOSITOR_BACKGROUND_BLACK,
-  GST_D3D11_COMPOSITOR_BACKGROUND_WHITE,
-  GST_D3D11_COMPOSITOR_BACKGROUND_TRANSPARENT,
-} GstD3D11CompositorBackground;
-
-#define GST_TYPE_D3D11_COMPOSITOR_BACKGROUND (gst_d3d11_compositor_background_get_type())
-GType gst_d3d11_compositor_background_get_type (void);
-
-typedef enum
-{
-  GST_D3D11_COMPOSITOR_SIZING_POLICY_NONE,
-  GST_D3D11_COMPOSITOR_SIZING_POLICY_KEEP_ASPECT_RATIO,
-} GstD3D11CompositorSizingPolicy;
-
-#define GST_TYPE_D3D11_COMPOSITOR_SIZING_POLICY (gst_d3d11_compositor_sizing_policy_get_type())
-GType gst_d3d11_compositor_sizing_policy_get_type (void);
-
 G_END_DECLS
 
-#endif /* __GST_D3D11_COMPOSITOR_H__ */
diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.cpp
deleted file mode 100644 (file)
index 1e60797..0000000
+++ /dev/null
@@ -1,1011 +0,0 @@
-/*
- * 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;
-}
diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.h b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositorbin.h
deleted file mode 100644 (file)
index bf58670..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * GStreamer
- * 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.
- */
-
-#ifndef __GST_D3D11_COMPOSITOR_BIN_H__
-#define __GST_D3D11_COMPOSITOR_BIN_H__
-
-#include <gst/gst.h>
-#include <gst/video/video.h>
-#include <gst/video/gstvideoaggregator.h>
-#include <gst/d3d11/gstd3d11.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_D3D11_COMPOSITOR_BIN_PAD (gst_d3d11_compositor_bin_pad_get_type())
-#define GST_D3D11_COMPOSITOR_BIN_PAD(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD, GstD3D11CompositorBinPad))
-#define GST_D3D11_COMPOSITOR_BIN_PAD_CLASS(klass) \
-    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD, GstD3D11CompositorBinPadClass))
-#define GST_IS_D3D11_COMPOSITOR_BIN_PAD(obj) \
-    (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD))
-#define GST_IS_D3D11_COMPOSITOR_BIN_PAD_CLASS(klass) \
-    (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD))
-#define GST_D3D11_COMPOSITOR_BIN_PAD_GET_CLASS(obj) \
-    (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_D3D11_COMPOSITOR_BIN_PAD,GstD3D11CompositorBinPadClass))
-
-typedef struct _GstD3D11CompositorBinPad GstD3D11CompositorBinPad;
-typedef struct _GstD3D11CompositorBinPadClass GstD3D11CompositorBinPadClass;
-
-struct _GstD3D11CompositorBinPadClass
-{
-  GstGhostPadClass parent_class;
-
-  void (*set_target) (GstD3D11CompositorBinPad * pad, GstPad * target);
-};
-
-GType gst_d3d11_compositor_bin_pad_get_type (void);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstD3D11CompositorBinPad, gst_object_unref)
-
-#define GST_TYPE_D3D11_COMPOSITOR_BIN_INPUT (gst_d3d11_compositor_bin_input_get_type())
-G_DECLARE_FINAL_TYPE (GstD3D11CompositorBinInput, gst_d3d11_compositor_bin_input,
-    GST, D3D11_COMPOSITOR_BIN_INPUT, GstD3D11CompositorBinPad);
-
-#define GST_TYPE_D3D11_COMPOSITOR_BIN (gst_d3d11_compositor_bin_get_type())
-G_DECLARE_FINAL_TYPE (GstD3D11CompositorBin, gst_d3d11_compositor_bin,
-    GST, D3D11_COMPOSITOR_BIN, GstBin)
-
-G_END_DECLS
-
-#endif /* __GST_D3D11_COMPOSITOR_BIN_H__ */
index e9a8262..39b1977 100644 (file)
@@ -2,7 +2,6 @@ d3d11_sources = [
   'gstd3d11av1dec.cpp',
   'gstd3d11basefilter.cpp',
   'gstd3d11compositor.cpp',
-  'gstd3d11compositorbin.cpp',
   'gstd3d11convert.cpp',
   'gstd3d11converter.cpp',
   'gstd3d11decoder.cpp',
index 6a19f12..279ee28 100644 (file)
@@ -68,7 +68,6 @@
 #include "gstd3d11convert.h"
 #include "gstd3d11shader.h"
 #include "gstd3d11compositor.h"
-#include "gstd3d11compositorbin.h"
 #include "gstd3d11h264dec.h"
 #include "gstd3d11h265dec.h"
 #include "gstd3d11vp9dec.h"
@@ -91,7 +90,6 @@ GST_DEBUG_CATEGORY (gst_d3d11_device_debug);
 GST_DEBUG_CATEGORY (gst_d3d11_overlay_compositor_debug);
 GST_DEBUG_CATEGORY (gst_d3d11_window_debug);
 GST_DEBUG_CATEGORY (gst_d3d11_video_processor_debug);
-GST_DEBUG_CATEGORY (gst_d3d11_compositor_debug);
 GST_DEBUG_CATEGORY (gst_d3d11_decoder_debug);
 GST_DEBUG_CATEGORY (gst_d3d11_h264_dec_debug);
 GST_DEBUG_CATEGORY (gst_d3d11_h265_dec_debug);
@@ -126,8 +124,6 @@ plugin_init (GstPlugin * plugin)
       "d3d11window", 0, "d3d11window");
   GST_DEBUG_CATEGORY_INIT (gst_d3d11_video_processor_debug,
       "d3d11videoprocessor", 0, "d3d11videoprocessor");
-  GST_DEBUG_CATEGORY_INIT (gst_d3d11_compositor_debug,
-      "d3d11compositor", 0, "d3d11compositor element");
 
   if (!gst_d3d11_shader_init ()) {
     GST_WARNING ("Cannot initialize d3d11 shader");
@@ -223,9 +219,7 @@ plugin_init (GstPlugin * plugin)
       "d3d11videosink", video_sink_rank, GST_TYPE_D3D11_VIDEO_SINK);
 
   gst_element_register (plugin,
-      "d3d11compositorelement", GST_RANK_NONE, GST_TYPE_D3D11_COMPOSITOR);
-  gst_element_register (plugin,
-      "d3d11compositor", GST_RANK_SECONDARY, GST_TYPE_D3D11_COMPOSITOR_BIN);
+      "d3d11compositor", GST_RANK_SECONDARY, GST_TYPE_D3D11_COMPOSITOR);
   gst_element_register (plugin,
       "d3d11testsrc", GST_RANK_NONE, GST_TYPE_D3D11_TEST_SRC);