d3d11videosink: Add color conversion support
authorSeungha Yang <seungha.yang@navercorp.com>
Tue, 3 Dec 2019 13:54:26 +0000 (22:54 +0900)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 5 Dec 2019 02:29:18 +0000 (02:29 +0000)
Draw to back buffer texture directly. It would reduce the number of
copy at least once when color conversion is required.

sys/d3d11/gstd3d11colorconverter.c
sys/d3d11/gstd3d11colorconverter.h
sys/d3d11/gstd3d11videosink.c
sys/d3d11/gstd3d11videosink.h
sys/d3d11/gstd3d11window.c
sys/d3d11/gstd3d11window.h

index f05bfb0..d0a2934 100644 (file)
@@ -943,3 +943,17 @@ gst_d3d11_color_converter_convert (GstD3D11ColorConverter * converter,
 
   return data.ret;
 }
+
+gboolean
+gst_d3d11_color_converter_update_rect (GstD3D11ColorConverter * converter,
+    RECT * rect)
+{
+  g_return_val_if_fail (converter != NULL, FALSE);
+
+  converter->viewport.TopLeftX = rect->left;
+  converter->viewport.TopLeftY = rect->top;
+  converter->viewport.Width = rect->right - rect->left;
+  converter->viewport.Height = rect->bottom - rect->top;
+
+  return TRUE;
+}
index 760d6cf..ad9fde9 100644 (file)
@@ -38,6 +38,9 @@ gboolean                 gst_d3d11_color_converter_convert (GstD3D11ColorConvert
                                                             ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES],
                                                             ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES]);
 
+gboolean                 gst_d3d11_color_converter_update_rect (GstD3D11ColorConverter * converter,
+                                                                RECT *rect);
+
 G_END_DECLS
 
 #endif /* __GST_D3D11_COLOR_CONVERTER_H__ */
index 35e96b6..cb1f7fc 100644 (file)
@@ -26,6 +26,7 @@
 #include "gstd3d11utils.h"
 #include "gstd3d11device.h"
 #include "gstd3d11bufferpool.h"
+#include "gstd3d11format.h"
 
 enum
 {
@@ -39,13 +40,11 @@ enum
 #define DEFAULT_FORCE_ASPECT_RATIO        TRUE
 #define DEFAULT_ENABLE_NAVIGATION_EVENTS  TRUE
 
-#define CAPS_FORMAT "{ BGRA, RGBA, RGB10A2_LE }"
-
 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
-        (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, CAPS_FORMAT)
+        (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_FORMATS)
     ));
 
 GST_DEBUG_CATEGORY (d3d11_video_sink_debug);
@@ -221,10 +220,9 @@ gst_d3d11_video_sink_get_caps (GstBaseSink * sink, GstCaps * filter)
   GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
   GstCaps *caps = NULL;
 
-  if (self->device)
+  if (self->device && !self->can_convert)
     caps = gst_d3d11_device_get_supported_caps (self->device,
-        D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DISPLAY |
-        D3D11_FORMAT_SUPPORT_RENDER_TARGET);
+        D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DISPLAY);
 
   if (!caps)
     caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
@@ -243,36 +241,20 @@ static gboolean
 gst_d3d11_video_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
 {
   GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
-  GstCaps *sink_caps = NULL;
   gint video_width, video_height;
   gint video_par_n, video_par_d;        /* video's PAR */
   gint display_par_n = 1, display_par_d = 1;    /* display's PAR */
   guint num, den;
   GError *error = NULL;
-  const GstD3D11Format *d3d11_format = NULL;
   GstStructure *config;
+  GstD3D11AllocationParams *d3d11_params;
+  gint i;
 
   GST_DEBUG_OBJECT (self, "set caps %" GST_PTR_FORMAT, caps);
 
-  sink_caps = gst_d3d11_device_get_supported_caps (self->device,
-      D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DISPLAY |
-      D3D11_FORMAT_SUPPORT_RENDER_TARGET);
-
-  GST_DEBUG_OBJECT (self, "supported caps %" GST_PTR_FORMAT, sink_caps);
-
-  if (!gst_caps_can_intersect (sink_caps, caps))
-    goto incompatible_caps;
-
-  gst_clear_caps (&sink_caps);
-
   if (!gst_video_info_from_caps (&self->info, caps))
     goto invalid_format;
 
-  d3d11_format =
-      gst_d3d11_format_from_gst (GST_VIDEO_INFO_FORMAT (&self->info));
-  if (!d3d11_format || d3d11_format->dxgi_format == DXGI_FORMAT_UNKNOWN)
-    goto invalid_format;
-
   video_width = GST_VIDEO_INFO_WIDTH (&self->info);
   video_height = GST_VIDEO_INFO_HEIGHT (&self->info);
   video_par_n = GST_VIDEO_INFO_PAR_N (&self->info);
@@ -326,8 +308,6 @@ gst_d3d11_video_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
   if (GST_VIDEO_SINK_WIDTH (self) <= 0 || GST_VIDEO_SINK_HEIGHT (self) <= 0)
     goto no_display_size;
 
-  self->dxgi_format = d3d11_format->dxgi_format;
-
   if (!self->window_id)
     gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (self));
 
@@ -359,7 +339,7 @@ gst_d3d11_video_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
 
   if (!gst_d3d11_window_prepare (self->window, GST_VIDEO_SINK_WIDTH (self),
           GST_VIDEO_SINK_HEIGHT (self), video_par_n, video_par_d,
-          self->dxgi_format, caps, &error)) {
+          caps, &error)) {
     GstMessage *error_msg;
 
     GST_ERROR_OBJECT (self, "cannot create swapchain");
@@ -380,17 +360,26 @@ gst_d3d11_video_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
   config = gst_buffer_pool_get_config (self->fallback_pool);
   gst_buffer_pool_config_set_params (config,
       caps, GST_VIDEO_INFO_SIZE (&self->info), 0, 2);
+
+  d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
+  if (!d3d11_params) {
+    d3d11_params = gst_d3d11_allocation_params_new (&self->info,
+        GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT, D3D11_USAGE_DEFAULT,
+        D3D11_BIND_SHADER_RESOURCE);
+  } else {
+    /* Set bind flag */
+    for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->info); i++) {
+      d3d11_params->desc[i].BindFlags |= 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_set_config (self->fallback_pool, config);
 
   return TRUE;
 
   /* ERRORS */
-incompatible_caps:
-  {
-    GST_ERROR_OBJECT (sink, "caps incompatible");
-    gst_clear_caps (&sink_caps);
-    return FALSE;
-  }
 invalid_format:
   {
     GST_DEBUG_OBJECT (sink,
@@ -447,6 +436,7 @@ static gboolean
 gst_d3d11_video_sink_start (GstBaseSink * sink)
 {
   GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
+  gboolean is_hardware = TRUE;
 
   GST_DEBUG_OBJECT (self, "Start");
 
@@ -462,6 +452,15 @@ gst_d3d11_video_sink_start (GstBaseSink * sink)
     return FALSE;
   }
 
+  g_object_get (self->device, "hardware", &is_hardware, NULL);
+
+  if (!is_hardware) {
+    GST_WARNING_OBJECT (self, "D3D11 device is running on software emulation");
+    self->can_convert = FALSE;
+  } else {
+    self->can_convert = TRUE;
+  }
+
   g_object_set (self->window,
       "enable-navigation-events", self->enable_navigation_events, NULL);
 
@@ -520,6 +519,9 @@ gst_d3d11_video_sink_propose_allocation (GstBaseSink * sink, GstQuery * query)
   size = info.size;
 
   if (need_pool) {
+    GstD3D11AllocationParams *d3d11_params;
+    gint i;
+
     GST_DEBUG_OBJECT (self, "create new pool");
 
     pool = gst_d3d11_buffer_pool_new (self->device);
@@ -527,6 +529,21 @@ gst_d3d11_video_sink_propose_allocation (GstBaseSink * sink, GstQuery * query)
     gst_buffer_pool_config_set_params (config, caps, size, 2,
         DXGI_MAX_SWAP_CHAIN_BUFFERS);
 
+    d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
+    if (!d3d11_params) {
+      d3d11_params = gst_d3d11_allocation_params_new (&info,
+          GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT, D3D11_USAGE_DEFAULT,
+          D3D11_BIND_SHADER_RESOURCE);
+    } else {
+      /* Set bind flag */
+      for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) {
+        d3d11_params->desc[i].BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+      }
+    }
+
+    gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
+    gst_d3d11_allocation_params_free (d3d11_params);
+
     if (!gst_buffer_pool_set_config (pool, config)) {
       g_object_unref (pool);
       goto config_failed;
@@ -612,19 +629,34 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
   GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
   GstMapInfo map;
   GstFlowReturn ret;
-  GstMemory *mem;
   GstVideoRectangle rect = { 0, };
   GstVideoCropMeta *crop;
   GstBuffer *render_buf;
   gboolean need_unref = FALSE;
+  gint i;
+
+  render_buf = buf;
+
+  for (i = 0; i < gst_buffer_n_memory (buf); i++) {
+    GstMemory *mem;
+    GstD3D11Memory *dmem;
 
-  if (gst_buffer_n_memory (buf) == 1 && (mem = gst_buffer_peek_memory (buf, 0))
-      && gst_memory_is_type (mem, GST_D3D11_MEMORY_NAME)) {
-    GstD3D11Memory *dmem = (GstD3D11Memory *) mem;
+    mem = gst_buffer_peek_memory (buf, i);
+    if (!gst_is_d3d11_memory (mem)) {
+      render_buf = NULL;
+      break;
+    }
 
-    /* If this buffer has been allocated using our buffer management we simply
-       put the ximage which is in the PRIVATE pointer */
-    GST_TRACE_OBJECT (self, "buffer %p from our pool, writing directly", buf);
+    dmem = (GstD3D11Memory *) mem;
+    if (dmem->device != self->device) {
+      render_buf = NULL;
+      break;
+    }
+
+    if (!gst_d3d11_memory_ensure_shader_resource_view (mem)) {
+      render_buf = NULL;
+      break;
+    }
 
     if (dmem->desc.Usage == D3D11_USAGE_DEFAULT) {
       if (!gst_memory_map (mem, &map, (GST_MAP_READ | GST_MAP_D3D11))) {
@@ -634,9 +666,9 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
 
       gst_memory_unmap (mem, &map);
     }
+  }
 
-    render_buf = buf;
-  } else {
+  if (!render_buf) {
     GstVideoFrame frame, fallback_frame;
 
     if (!self->fallback_pool ||
index 5e6ac7c..768bdf0 100644 (file)
@@ -50,7 +50,6 @@ struct _GstD3D11VideoSink
   gint video_height;
 
   GstVideoInfo info;
-  DXGI_FORMAT dxgi_format;
 
   guintptr window_id;
 
@@ -64,6 +63,7 @@ struct _GstD3D11VideoSink
   gboolean pending_render_rect;
 
   GstBufferPool *fallback_pool;
+  gboolean can_convert;
 };
 
 struct _GstD3D11VideoSinkClass
index 316d591..bd68617 100644 (file)
@@ -27,6 +27,7 @@
 #include "gstd3d11window.h"
 #include "gstd3d11device.h"
 #include "gstd3d11memory.h"
+#include "gstd3d11utils.h"
 
 #include <windows.h>
 
@@ -258,6 +259,11 @@ gst_d3d11_window_dispose (GObject * object)
         (GstD3D11DeviceThreadFunc) gst_d3d11_window_release_resources, self);
   }
 
+  if (self->converter) {
+    gst_d3d11_color_converter_free (self->converter);
+    self->converter = NULL;
+  }
+
   gst_clear_buffer (&self->cached_buffer);
   gst_clear_object (&self->device);
 
@@ -521,52 +527,75 @@ gst_d3d11_window_on_resize (GstD3D11Device * device, GstD3D11Window * window)
     window->rtv = NULL;
   }
 
-  /* NOTE: there can be various way to resize texture, but
-   * we just copy incoming texture toward resized swap chain buffer in order to
-   * avoid shader coding.
-   * To keep aspect ratio, required vertical or horizontal padding area
-   * will be calculated in here.
-   */
   width = window->width;
   height = window->height;
 
   if (width != window->surface_width || height != window->surface_height) {
     GstVideoRectangle src_rect, dst_rect;
-    gdouble src_ratio, dst_ratio;
-    gdouble aspect_ratio =
-        (gdouble) window->aspect_ratio_n / (gdouble) window->aspect_ratio_d;
-
-    src_ratio = (gdouble) width / height;
-    dst_ratio =
-        (gdouble) window->surface_width / window->surface_height / aspect_ratio;
 
     src_rect.x = 0;
     src_rect.y = 0;
-    src_rect.w = width;
-    src_rect.h = height;
+    src_rect.w = width * window->aspect_ratio_n;
+    src_rect.h = height * window->aspect_ratio_d;
 
     dst_rect.x = 0;
     dst_rect.y = 0;
+    dst_rect.w = window->surface_width;
+    dst_rect.h = window->surface_height;
 
-    if (window->force_aspect_ratio) {
-      if (src_ratio > dst_ratio) {
-        /* padding top and bottom */
-        dst_rect.w = width;
-        dst_rect.h = width / dst_ratio;
+    if (window->converter) {
+      if (window->force_aspect_ratio) {
+        src_rect.w = width * window->aspect_ratio_n;
+        src_rect.h = height * window->aspect_ratio_d;
+
+        gst_video_sink_center_rect (src_rect, dst_rect, &window->render_rect,
+            TRUE);
       } else {
-        /* padding left and right */
-        dst_rect.w = height * dst_ratio;
-        dst_rect.h = height;
+        window->render_rect = dst_rect;
       }
+
+      width = window->surface_width;
+      height = window->surface_height;
     } else {
-      dst_rect.w = width;
-      dst_rect.h = height;
-    }
+      /* NOTE: there can be various way to resize texture, but
+       * we just copy incoming texture toward resized swap chain buffer in order to
+       * avoid shader coding.
+       * To keep aspect ratio, required vertical or horizontal padding area
+       * will be calculated in here.
+       */
+      gdouble src_ratio, dst_ratio;
+      gdouble aspect_ratio =
+          (gdouble) window->aspect_ratio_n / (gdouble) window->aspect_ratio_d;
+
+      src_ratio = (gdouble) width / height;
+      dst_ratio =
+          (gdouble) window->surface_width / window->surface_height /
+          aspect_ratio;
+
+      src_rect.w = width;
+      src_rect.h = height;
+
+      if (window->force_aspect_ratio) {
+        if (src_ratio > dst_ratio) {
+          /* padding top and bottom */
+          dst_rect.w = width;
+          dst_rect.h = width / dst_ratio;
+        } else {
+          /* padding left and right */
+          dst_rect.w = height * dst_ratio;
+          dst_rect.h = height;
+        }
+      } else {
+        dst_rect.w = width;
+        dst_rect.h = height;
+      }
 
-    gst_video_sink_center_rect (src_rect, dst_rect, &window->render_rect, TRUE);
+      gst_video_sink_center_rect (src_rect, dst_rect, &window->render_rect,
+          TRUE);
 
-    width = dst_rect.w;
-    height = dst_rect.h;
+      width = dst_rect.w;
+      height = dst_rect.h;
+    }
   }
 
   hr = IDXGISwapChain_ResizeBuffers (window->swap_chain,
@@ -824,21 +853,63 @@ mastering_display_gst_to_dxgi (GstVideoMasteringDisplayInfo * m,
 
 gboolean
 gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height,
-    guint aspect_ratio_n, guint aspect_ratio_d, DXGI_FORMAT format,
-    GstCaps * caps, GError ** error)
+    guint aspect_ratio_n, guint aspect_ratio_d, GstCaps * caps, GError ** error)
 {
   DXGI_SWAP_CHAIN_DESC desc = { 0, };
   gboolean have_cll = FALSE;
   gboolean have_mastering = FALSE;
   gboolean hdr_api_available = FALSE;
   GstD3D11ThreadFuncData data;
+  GstCaps *render_caps;
 
   g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), FALSE);
   g_return_val_if_fail (aspect_ratio_n > 0, FALSE);
   g_return_val_if_fail (aspect_ratio_d > 0, FALSE);
 
-  GST_DEBUG_OBJECT (window, "Prepare window with %dx%d format %d",
-      width, height, format);
+  GST_DEBUG_OBJECT (window, "Prepare window with %dx%d caps %" GST_PTR_FORMAT,
+      width, height, caps);
+
+  render_caps = gst_d3d11_device_get_supported_caps (window->device,
+      D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DISPLAY);
+
+  GST_DEBUG_OBJECT (window, "rendering caps %" GST_PTR_FORMAT, render_caps);
+  render_caps = gst_d3d11_caps_fixate_format (caps, render_caps);
+
+  if (!render_caps || gst_caps_is_empty (render_caps)) {
+    GST_ERROR_OBJECT (window, "Couldn't define render caps");
+    gst_clear_caps (&render_caps);
+    return FALSE;
+  }
+
+  render_caps = gst_caps_fixate (render_caps);
+  gst_video_info_from_caps (&window->render_info, render_caps);
+  gst_clear_caps (&render_caps);
+
+  window->render_format =
+      gst_d3d11_format_from_gst (GST_VIDEO_INFO_FORMAT (&window->render_info));
+  if (!window->render_format ||
+      window->render_format->dxgi_format == DXGI_FORMAT_UNKNOWN) {
+    GST_ERROR_OBJECT (window, "Unknown dxgi render format");
+    return FALSE;
+  }
+
+  gst_video_info_from_caps (&window->info, caps);
+
+  if (window->converter)
+    gst_d3d11_color_converter_free (window->converter);
+  window->converter = NULL;
+
+  if (GST_VIDEO_INFO_FORMAT (&window->info) !=
+      GST_VIDEO_INFO_FORMAT (&window->render_info)) {
+    window->converter =
+        gst_d3d11_color_converter_new (window->device, &window->info,
+        &window->render_info);
+
+    if (!window->converter) {
+      GST_ERROR_OBJECT (window, "Cannot create converter");
+      return FALSE;
+    }
+  }
 
   data.self = window;
   data.error = error;
@@ -861,7 +932,6 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height,
     window->thread = NULL;
   }
 
-  gst_video_info_from_caps (&window->info, caps);
   if (!gst_video_content_light_level_from_caps (&window->content_light_level,
           caps)) {
     gst_video_content_light_level_init (&window->content_light_level);
@@ -897,7 +967,7 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height,
   /* don't care refresh rate */
   desc.BufferDesc.RefreshRate.Numerator = 0;
   desc.BufferDesc.RefreshRate.Denominator = 1;
-  desc.BufferDesc.Format = format;
+  desc.BufferDesc.Format = window->render_format->dxgi_format;
   desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
   desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
   desc.SampleDesc.Count = 1;
@@ -925,7 +995,8 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height,
     return FALSE;
   }
 #ifdef HAVE_DXGI_1_5_H
-  if (hdr_api_available && format == DXGI_FORMAT_R10G10B10A2_UNORM &&
+  if (hdr_api_available &&
+      window->render_format->dxgi_format == DXGI_FORMAT_R10G10B10A2_UNORM &&
       have_cll && have_mastering) {
     UINT can_support = 0;
     HRESULT hr;
@@ -1068,24 +1139,47 @@ _present_on_device_thread (GstD3D11Device * device, FramePresentData * data)
   gst_buffer_replace (&self->cached_buffer, data->buffer);
 
   if (self->cached_buffer) {
-    GstD3D11Memory *mem =
-        (GstD3D11Memory *) gst_buffer_peek_memory (self->cached_buffer, 0);
-
-    self->rect = *data->rect;
-    src_box.left = self->rect.x;
-    src_box.right = self->rect.x + self->rect.w;
-    src_box.top = self->rect.y;
-    src_box.bottom = self->rect.y + self->rect.h;
-    src_box.front = 0;
-    src_box.back = 1;
-
-    ID3D11DeviceContext_OMSetRenderTargets (device_context,
-        1, &self->rtv, NULL);
-    ID3D11DeviceContext_ClearRenderTargetView (device_context, self->rtv,
-        black);
-    ID3D11DeviceContext_CopySubresourceRegion (device_context,
-        (ID3D11Resource *) self->backbuffer, 0, self->render_rect.x,
-        self->render_rect.y, 0, (ID3D11Resource *) mem->texture, 0, &src_box);
+    if (self->converter) {
+      ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES];
+      gint i, j, k;
+      RECT rect;
+
+      for (i = 0, j = 0; i < gst_buffer_n_memory (self->cached_buffer); i++) {
+        GstD3D11Memory *mem =
+            (GstD3D11Memory *) gst_buffer_peek_memory (self->cached_buffer, i);
+        for (k = 0; k < mem->num_shader_resource_views; k++) {
+          srv[j] = mem->shader_resource_view[k];
+          j++;
+        }
+      }
+
+      rect.left = self->render_rect.x;
+      rect.right = self->render_rect.x + self->render_rect.w;
+      rect.top = self->render_rect.y;
+      rect.bottom = self->render_rect.y + self->render_rect.h;
+
+      gst_d3d11_color_converter_update_rect (self->converter, &rect);
+      gst_d3d11_color_converter_convert (self->converter, srv, &self->rtv);
+    } else {
+      GstD3D11Memory *mem =
+          (GstD3D11Memory *) gst_buffer_peek_memory (self->cached_buffer, 0);
+
+      self->rect = *data->rect;
+      src_box.left = self->rect.x;
+      src_box.right = self->rect.x + self->rect.w;
+      src_box.top = self->rect.y;
+      src_box.bottom = self->rect.y + self->rect.h;
+      src_box.front = 0;
+      src_box.back = 1;
+
+      ID3D11DeviceContext_OMSetRenderTargets (device_context,
+          1, &self->rtv, NULL);
+      ID3D11DeviceContext_ClearRenderTargetView (device_context, self->rtv,
+          black);
+      ID3D11DeviceContext_CopySubresourceRegion (device_context,
+          (ID3D11Resource *) self->backbuffer, 0, self->render_rect.x,
+          self->render_rect.y, 0, (ID3D11Resource *) mem->texture, 0, &src_box);
+    }
   }
 
   hr = IDXGISwapChain_Present (self->swap_chain, 0, DXGI_PRESENT_DO_NOT_WAIT);
index 91229e3..dc9d0dc 100644 (file)
@@ -25,6 +25,7 @@
 #include <gst/gst.h>
 #include <gst/video/video.h>
 #include "gstd3d11_fwd.h"
+#include "gstd3d11colorconverter.h"
 
 G_BEGIN_DECLS
 
@@ -45,6 +46,10 @@ struct _GstD3D11Window
   GstObject parent;
 
   GstVideoInfo info;
+  GstVideoInfo render_info;
+  const GstD3D11Format *render_format;
+  GstD3D11ColorConverter *converter;
+
   GstVideoMasteringDisplayInfo mastering_display_info;
   GstVideoContentLightLevel content_light_level;
 
@@ -124,7 +129,6 @@ gboolean gst_d3d11_window_prepare (GstD3D11Window * window,
                                    guint height,
                                    guint aspect_ratio_n,
                                    guint aspect_ratio_d,
-                                   DXGI_FORMAT format,
                                    GstCaps * caps,
                                    GError ** error);