d3d11videosink: Use single GstD3D11Converter object
authorSeungha Yang <seungha@centricular.com>
Fri, 1 Jul 2022 14:49:49 +0000 (23:49 +0900)
committerSeungha Yang <seungha@centricular.com>
Fri, 1 Jul 2022 20:40:47 +0000 (05:40 +0900)
GstD3D11Converter supports videoprocessor and texture upload.

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

subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp

index 2fe593d..49a144e 100644 (file)
@@ -125,10 +125,6 @@ struct _GstD3D11VideoSink
   GstVideoRectangle render_rect;
   gboolean pending_render_rect;
 
-  GstBufferPool *fallback_pool;
-  gboolean have_video_processor;
-  gboolean processor_in_use;
-
   /* For drawing on user texture */
   gboolean drawing;
   GstBuffer *current_buffer;
@@ -596,10 +592,8 @@ gst_d3d11_video_sink_update_window (GstD3D11VideoSink * self, GstCaps * caps)
     GST_OBJECT_UNLOCK (self);
   }
 
-  self->have_video_processor = FALSE;
   if (!gst_d3d11_window_prepare (self->window, GST_VIDEO_SINK_WIDTH (self),
-          GST_VIDEO_SINK_HEIGHT (self), caps, &self->have_video_processor,
-          &error)) {
+          GST_VIDEO_SINK_HEIGHT (self), caps, &error)) {
     GstMessage *error_msg;
 
     GST_ERROR_OBJECT (self, "cannot create swapchain");
@@ -611,44 +605,6 @@ gst_d3d11_video_sink_update_window (GstD3D11VideoSink * self, GstCaps * caps)
     return FALSE;
   }
 
-  if (self->fallback_pool) {
-    gst_buffer_pool_set_active (self->fallback_pool, FALSE);
-    gst_clear_object (&self->fallback_pool);
-  }
-
-  {
-    GstD3D11AllocationParams *d3d11_params;
-    gint bind_flags = D3D11_BIND_SHADER_RESOURCE;
-
-    if (self->have_video_processor) {
-      /* To create video processor input view, one of following bind flags
-       * is required
-       * NOTE: Any texture arrays which were created with D3D11_BIND_DECODER flag
-       * cannot be used for shader input.
-       *
-       * D3D11_BIND_DECODER
-       * D3D11_BIND_VIDEO_ENCODER
-       * D3D11_BIND_RENDER_TARGET
-       * D3D11_BIND_UNORDERED_ACCESS_VIEW
-       */
-      bind_flags |= D3D11_BIND_RENDER_TARGET;
-    }
-
-    d3d11_params = gst_d3d11_allocation_params_new (self->device,
-        &self->info, GST_D3D11_ALLOCATION_FLAG_DEFAULT, bind_flags, 0);
-
-    self->fallback_pool = gst_d3d11_buffer_pool_new_with_options (self->device,
-        caps, d3d11_params, 2, 0);
-    gst_d3d11_allocation_params_free (d3d11_params);
-  }
-
-  if (!self->fallback_pool) {
-    GST_ERROR_OBJECT (self, "Failed to configure fallback pool");
-    return FALSE;
-  }
-
-  self->processor_in_use = FALSE;
-
   if (self->title) {
     gst_d3d11_window_set_title (self->window, self->title);
     g_clear_pointer (&self->title, g_free);
@@ -838,12 +794,6 @@ gst_d3d11_video_sink_stop (GstBaseSink * sink)
 
   GST_DEBUG_OBJECT (self, "Stop");
 
-  if (self->fallback_pool) {
-    gst_buffer_pool_set_active (self->fallback_pool, FALSE);
-    gst_object_unref (self->fallback_pool);
-    self->fallback_pool = NULL;
-  }
-
   if (self->window)
     gst_d3d11_window_unprepare (self->window);
 
@@ -1050,108 +1000,6 @@ gst_d3d11_video_sink_event (GstBaseSink * sink, GstEvent * event)
   return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
 }
 
-static gboolean
-gst_d3d11_video_sink_upload_frame (GstD3D11VideoSink * self, GstBuffer * inbuf,
-    GstBuffer * outbuf)
-{
-  GstVideoFrame in_frame, out_frame;
-  gboolean ret;
-
-  GST_LOG_OBJECT (self, "Copy to fallback buffer");
-
-  if (!gst_video_frame_map (&in_frame, &self->info, inbuf,
-          (GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)))
-    goto invalid_buffer;
-
-  if (!gst_video_frame_map (&out_frame, &self->info, outbuf,
-          (GstMapFlags) (GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) {
-    gst_video_frame_unmap (&in_frame);
-    goto invalid_buffer;
-  }
-
-  ret = gst_video_frame_copy (&out_frame, &in_frame);
-
-  gst_video_frame_unmap (&in_frame);
-  gst_video_frame_unmap (&out_frame);
-
-  return ret;
-
-  /* ERRORS */
-invalid_buffer:
-  {
-    GST_ELEMENT_WARNING (self, CORE, NOT_IMPLEMENTED, (NULL),
-        ("invalid video buffer received"));
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_d3d11_video_sink_copy_d3d11_to_d3d11 (GstD3D11VideoSink * self,
-    GstBuffer * inbuf, GstBuffer * outbuf)
-{
-  GST_LOG_OBJECT (self, "Copy to fallback buffer using device memory copy");
-
-  return gst_d3d11_buffer_copy_into (outbuf, inbuf, &self->info);
-}
-
-static gboolean
-gst_d3d11_video_sink_get_fallback_buffer (GstD3D11VideoSink * self,
-    GstBuffer * inbuf, GstBuffer ** fallback_buf, gboolean device_copy)
-{
-  GstBuffer *outbuf = NULL;
-  ID3D11ShaderResourceView *view[GST_VIDEO_MAX_PLANES];
-  GstVideoOverlayCompositionMeta *compo_meta;
-  GstVideoCropMeta *crop_meta;
-
-  if (!self->fallback_pool ||
-      !gst_buffer_pool_set_active (self->fallback_pool, TRUE) ||
-      gst_buffer_pool_acquire_buffer (self->fallback_pool, &outbuf,
-          NULL) != GST_FLOW_OK) {
-    GST_ERROR_OBJECT (self, "fallback pool is unavailable");
-    return FALSE;
-  }
-
-  /* Ensure SRV */
-  if (!gst_d3d11_buffer_get_shader_resource_view (outbuf, view)) {
-    GST_ERROR_OBJECT (self, "fallback SRV is unavailable");
-    goto error;
-  }
-
-  if (device_copy) {
-    if (!gst_d3d11_video_sink_copy_d3d11_to_d3d11 (self, inbuf, outbuf)) {
-      GST_ERROR_OBJECT (self, "cannot copy frame");
-      goto error;
-    }
-  } else if (!gst_d3d11_video_sink_upload_frame (self, inbuf, outbuf)) {
-    GST_ERROR_OBJECT (self, "cannot upload frame");
-    goto error;
-  }
-
-  /* Copy overlaycomposition meta if any */
-  compo_meta = gst_buffer_get_video_overlay_composition_meta (inbuf);
-  if (compo_meta)
-    gst_buffer_add_video_overlay_composition_meta (outbuf, compo_meta->overlay);
-
-  /* And copy crop meta as well */
-  crop_meta = gst_buffer_get_video_crop_meta (inbuf);
-  if (crop_meta) {
-    GstVideoCropMeta *new_crop_meta = gst_buffer_add_video_crop_meta (outbuf);
-
-    new_crop_meta->x = crop_meta->x;
-    new_crop_meta->y = crop_meta->y;
-    new_crop_meta->width = crop_meta->width;
-    new_crop_meta->height = crop_meta->height;
-  }
-
-  *fallback_buf = outbuf;
-
-  return TRUE;
-
-error:
-  gst_buffer_unref (outbuf);
-  return FALSE;
-}
-
 static void
 gst_d3d11_video_sink_check_device_update (GstD3D11VideoSink * self,
     GstBuffer * buf)
@@ -1199,10 +1047,6 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
 {
   GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
   GstFlowReturn ret = GST_FLOW_OK;
-  GstBuffer *fallback_buf = NULL;
-  ID3D11Device *device_handle =
-      gst_d3d11_device_get_device_handle (self->device);
-  ID3D11ShaderResourceView *view[GST_VIDEO_MAX_PLANES];
 
   gst_d3d11_video_sink_check_device_update (self, buf);
 
@@ -1221,54 +1065,11 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
       return GST_FLOW_NOT_NEGOTIATED;
   }
 
-  if (!gst_d3d11_buffer_can_access_device (buf, device_handle)) {
-    GST_LOG_OBJECT (self, "Need fallback buffer");
-
-    if (!gst_d3d11_video_sink_get_fallback_buffer (self, buf, &fallback_buf,
-            FALSE)) {
-      return GST_FLOW_ERROR;
-    }
-  } else {
-    gboolean direct_rendering = FALSE;
-
-    /* Check if we can use video processor for conversion */
-    if (gst_buffer_n_memory (buf) == 1 && self->have_video_processor) {
-      GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buf, 0);
-      D3D11_TEXTURE2D_DESC desc;
-
-      gst_d3d11_memory_get_texture_desc (mem, &desc);
-      if ((desc.BindFlags & D3D11_BIND_DECODER) == D3D11_BIND_DECODER) {
-        GST_TRACE_OBJECT (self,
-            "Got VideoProcessor compatible texture, do direct rendering");
-        direct_rendering = TRUE;
-        self->processor_in_use = TRUE;
-      } else if (self->processor_in_use &&
-          (desc.BindFlags & D3D11_BIND_RENDER_TARGET) ==
-          D3D11_BIND_RENDER_TARGET) {
-        direct_rendering = TRUE;
-      }
-    }
-
-    /* Or, SRV should be available */
-    if (!direct_rendering) {
-      if (gst_d3d11_buffer_get_shader_resource_view (buf, view)) {
-        GST_TRACE_OBJECT (self, "SRV is available, do direct rendering");
-        direct_rendering = TRUE;
-      }
-    }
-
-    if (!direct_rendering &&
-        !gst_d3d11_video_sink_get_fallback_buffer (self, buf, &fallback_buf,
-            TRUE)) {
-      return GST_FLOW_ERROR;
-    }
-  }
-
   gst_d3d11_window_show (self->window);
 
   if (self->draw_on_shared_texture) {
     g_rec_mutex_lock (&self->draw_lock);
-    self->current_buffer = fallback_buf ? fallback_buf : buf;
+    self->current_buffer = buf;
     self->drawing = TRUE;
 
     GST_LOG_OBJECT (self, "Begin drawing");
@@ -1279,15 +1080,12 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
 
     GST_LOG_OBJECT (self, "End drawing");
     self->drawing = FALSE;
-    self->current_buffer = NULL;
+    self->current_buffer = nullptr;
     g_rec_mutex_unlock (&self->draw_lock);
   } else {
-    ret = gst_d3d11_window_render (self->window,
-        fallback_buf ? fallback_buf : buf);
+    ret = gst_d3d11_window_render (self->window, buf);
   }
 
-  gst_clear_buffer (&fallback_buf);
-
   if (ret == GST_D3D11_WINDOW_FLOW_CLOSED) {
     GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
         ("Output window was closed"), (NULL));
index 2d0121e..dc97281 100644 (file)
@@ -103,13 +103,11 @@ static void gst_d3d11_window_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static void gst_d3d11_window_dispose (GObject * object);
 static GstFlowReturn gst_d3d111_window_present (GstD3D11Window * self,
-    GstBuffer * buffer, ID3D11VideoProcessorOutputView * pov,
-    ID3D11RenderTargetView * rtv);
+    GstBuffer * buffer, GstBuffer * render_target);
 static void gst_d3d11_window_on_resize_default (GstD3D11Window * window,
     guint width, guint height);
 static gboolean gst_d3d11_window_prepare_default (GstD3D11Window * window,
-    guint display_width, guint display_height, GstCaps * caps,
-    gboolean * video_processor_available, GError ** error);
+    guint display_width, guint display_height, GstCaps * caps, GError ** error);
 
 static void
 gst_d3d11_window_class_init (GstD3D11WindowClass * klass)
@@ -252,131 +250,115 @@ gst_d3d11_window_get_property (GObject * object, guint prop_id,
 }
 
 static void
-gst_d3d11_window_release_resources (GstD3D11Device * device,
-    GstD3D11Window * window)
-{
-  GST_D3D11_CLEAR_COM (window->rtv);
-  GST_D3D11_CLEAR_COM (window->pov);
-  GST_D3D11_CLEAR_COM (window->swap_chain);
-}
-
-static void
 gst_d3d11_window_dispose (GObject * object)
 {
   GstD3D11Window *self = GST_D3D11_WINDOW (object);
 
-  if (self->device)
-    gst_d3d11_window_release_resources (self->device, self);
+  gst_clear_buffer (&self->backbuffer);
+  GST_D3D11_CLEAR_COM (self->swap_chain);
 
-  g_clear_pointer (&self->processor, gst_d3d11_video_processor_free);
   gst_clear_object (&self->compositor);
   gst_clear_object (&self->converter);
 
   gst_clear_buffer (&self->cached_buffer);
   gst_clear_object (&self->device);
+  gst_clear_object (&self->allocator);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
-gst_d3d11_window_on_resize_default (GstD3D11Window * window, guint width,
+gst_d3d11_window_on_resize_default (GstD3D11Window * self, guint width,
     guint height)
 {
+  GstD3D11Device *device = self->device;
   HRESULT hr;
-  ID3D11Device *device_handle;
   D3D11_TEXTURE2D_DESC desc;
   DXGI_SWAP_CHAIN_DESC swap_desc;
-  ID3D11Texture2D *backbuffer = NULL;
+  ComPtr < ID3D11Texture2D > backbuffer;
   GstVideoRectangle src_rect, dst_rect, rst_rect;
   IDXGISwapChain *swap_chain;
+  GstMemory *mem;
+  GstD3D11Memory *dmem;
+  ID3D11RenderTargetView *rtv;
 
-  gst_d3d11_device_lock (window->device);
-  if (!window->swap_chain)
-    goto done;
-
-  device_handle = gst_d3d11_device_get_device_handle (window->device);
-  swap_chain = window->swap_chain;
+  gst_d3d11_device_lock (device);
 
-  GST_D3D11_CLEAR_COM (window->rtv);
-  GST_D3D11_CLEAR_COM (window->pov);
+  gst_clear_buffer (&self->backbuffer);
+  if (!self->swap_chain)
+    goto done;
 
+  swap_chain = self->swap_chain;
   swap_chain->GetDesc (&swap_desc);
-  hr = swap_chain->ResizeBuffers (0, width, height, window->dxgi_format,
+  hr = swap_chain->ResizeBuffers (0, width, height, self->dxgi_format,
       swap_desc.Flags);
-  if (!gst_d3d11_result (hr, window->device)) {
-    GST_ERROR_OBJECT (window, "Couldn't resize buffers, hr: 0x%x", (guint) hr);
+  if (!gst_d3d11_result (hr, device)) {
+    GST_ERROR_OBJECT (self, "Couldn't resize buffers, hr: 0x%x", (guint) hr);
     goto done;
   }
 
   hr = swap_chain->GetBuffer (0, IID_PPV_ARGS (&backbuffer));
-  if (!gst_d3d11_result (hr, window->device)) {
-    GST_ERROR_OBJECT (window,
+  if (!gst_d3d11_result (hr, device)) {
+    GST_ERROR_OBJECT (self,
         "Cannot get backbuffer from swapchain, hr: 0x%x", (guint) hr);
     goto done;
   }
 
-  backbuffer->GetDesc (&desc);
-  window->surface_width = desc.Width;
-  window->surface_height = desc.Height;
+  mem = gst_d3d11_allocator_alloc_wrapped_native_size (self->allocator,
+      self->device, backbuffer.Get (), nullptr, nullptr);
+  if (!mem) {
+    GST_ERROR_OBJECT (self, "Couldn't allocate wrapped memory");
+    goto done;
+  }
 
-  {
-    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) {
-      src_rect.x = 0;
-      src_rect.y = 0;
-      src_rect.w = GST_VIDEO_INFO_WIDTH (&window->render_info);
-      src_rect.h = GST_VIDEO_INFO_HEIGHT (&window->render_info);
-
-      gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE);
-    } else {
-      rst_rect = dst_rect;
-    }
+  dmem = GST_D3D11_MEMORY_CAST (mem);
+  rtv = gst_d3d11_memory_get_render_target_view (dmem, 0);
+  if (!rtv) {
+    GST_ERROR_OBJECT (self, "RTV is unavailable");
+    gst_memory_unref (mem);
+    goto done;
   }
 
-  window->render_rect.left = rst_rect.x;
-  window->render_rect.top = rst_rect.y;
-  window->render_rect.right = rst_rect.x + rst_rect.w;
-  window->render_rect.bottom = rst_rect.y + rst_rect.h;
+  self->backbuffer = gst_buffer_new ();
+  gst_buffer_append_memory (self->backbuffer, mem);
 
-  GST_LOG_OBJECT (window,
-      "New client area %dx%d, render rect x: %d, y: %d, %dx%d",
-      desc.Width, desc.Height, rst_rect.x, rst_rect.y, rst_rect.w, rst_rect.h);
+  backbuffer->GetDesc (&desc);
+  self->surface_width = desc.Width;
+  self->surface_height = desc.Height;
 
-  hr = device_handle->CreateRenderTargetView (backbuffer, NULL, &window->rtv);
-  if (!gst_d3d11_result (hr, window->device)) {
-    GST_ERROR_OBJECT (window, "Cannot create render target view, hr: 0x%x",
-        (guint) hr);
+  dst_rect.x = 0;
+  dst_rect.y = 0;
+  dst_rect.w = self->surface_width;
+  dst_rect.h = self->surface_height;
 
-    goto done;
-  }
+  if (self->force_aspect_ratio) {
+    src_rect.x = 0;
+    src_rect.y = 0;
+    src_rect.w = GST_VIDEO_INFO_WIDTH (&self->render_info);
+    src_rect.h = GST_VIDEO_INFO_HEIGHT (&self->render_info);
 
-  if (window->processor) {
-    D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC pov_desc;
+    gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE);
+  } else {
+    rst_rect = dst_rect;
+  }
 
-    pov_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
-    pov_desc.Texture2D.MipSlice = 0;
+  self->render_rect.left = rst_rect.x;
+  self->render_rect.top = rst_rect.y;
+  self->render_rect.right = rst_rect.x + rst_rect.w;
+  self->render_rect.bottom = rst_rect.y + rst_rect.h;
 
-    if (!gst_d3d11_video_processor_create_output_view (window->processor,
-            &pov_desc, backbuffer, &window->pov))
-      goto done;
-  }
+  GST_LOG_OBJECT (self,
+      "New client area %dx%d, render rect x: %d, y: %d, %dx%d",
+      desc.Width, desc.Height, rst_rect.x, rst_rect.y, rst_rect.w, rst_rect.h);
 
-  window->first_present = TRUE;
+  self->first_present = TRUE;
 
   /* redraw the last scene if cached buffer exits */
-  if (window->cached_buffer) {
-    gst_d3d111_window_present (window, window->cached_buffer,
-        window->pov, window->rtv);
-  }
+  if (self->cached_buffer)
+    gst_d3d111_window_present (self, self->cached_buffer, self->backbuffer);
 
 done:
-  GST_D3D11_CLEAR_COM (backbuffer);
-
-  gst_d3d11_device_unlock (window->device);
+  gst_d3d11_device_unlock (device);
 }
 
 void
@@ -413,8 +395,7 @@ typedef struct
 
 gboolean
 gst_d3d11_window_prepare (GstD3D11Window * window, guint display_width,
-    guint display_height, GstCaps * caps, gboolean * video_processor_available,
-    GError ** error)
+    guint display_height, GstCaps * caps, GError ** error)
 {
   GstD3D11WindowClass *klass;
 
@@ -426,19 +407,17 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint display_width,
   GST_DEBUG_OBJECT (window, "Prepare window, display resolution %dx%d, caps %"
       GST_PTR_FORMAT, display_width, display_height, caps);
 
-  return klass->prepare (window, display_width, display_height, caps,
-      video_processor_available, error);
+  return klass->prepare (window, display_width, display_height, caps, error);
 }
 
 static gboolean
 gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
-    guint display_height, GstCaps * caps, gboolean * video_processor_available,
-    GError ** error)
+    guint display_height, GstCaps * caps, GError ** error)
 {
+  GstD3D11Device *device = window->device;
   GstD3D11WindowClass *klass;
   guint swapchain_flags = 0;
   ID3D11Device *device_handle;
-  guint i;
   guint num_supported_format = 0;
   HRESULT hr;
   UINT display_flags =
@@ -452,28 +431,41 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
   const GstD3D11WindowDisplayFormat *chosen_format = NULL;
   GstDxgiColorSpace swapchain_colorspace;
   gboolean found_swapchain_colorspace = FALSE;
-  gboolean have_hdr10 = FALSE;
+  gboolean hdr10_aware = FALSE;
+  gboolean have_hdr10_meta = FALSE;
   DXGI_COLOR_SPACE_TYPE native_colorspace_type =
       DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
-  DXGI_HDR_METADATA_HDR10 hdr10_metadata = { 0, };
-  GstDxgiColorSpace in_dxgi_colorspace;
-  GstD3D11ConverterMethod method = GST_D3D11_CONVERTER_METHOD_SHADER;
+  ComPtr < IDXGIFactory5 > factory5;
+  IDXGIFactory1 *factory_handle;
+  BOOL allow_tearing = FALSE;
+  GstVideoMasteringDisplayInfo mdcv;
+  GstVideoContentLightLevel cll;
+  ComPtr < IDXGISwapChain3 > swapchain3;
+  GstStructure *s;
+  const gchar *cll_str = nullptr;
+  const gchar *mdcv_str = nullptr;
+
+  if (!window->allocator) {
+    window->allocator =
+        (GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
+    if (!window->allocator) {
+      GST_ERROR_OBJECT (window, "Allocator is unavailable");
+      return FALSE;
+    }
+  }
 
   /* Step 1: Clear old resources and objects */
   gst_clear_buffer (&window->cached_buffer);
-  g_clear_pointer (&window->processor, gst_d3d11_video_processor_free);
   gst_clear_object (&window->compositor);
   gst_clear_object (&window->converter);
 
-  window->processor_in_use = FALSE;
-
   /* Step 2: Decide display color format
    * If upstream format is 10bits, try DXGI_FORMAT_R10G10B10A2_UNORM first
    * Otherwise, use DXGI_FORMAT_B8G8R8A8_UNORM or DXGI_FORMAT_B8G8R8A8_UNORM
    */
   gst_video_info_from_caps (&window->info, caps);
-  device_handle = gst_d3d11_device_get_device_handle (window->device);
-  for (i = 0; i < G_N_ELEMENTS (formats); i++) {
+  device_handle = gst_d3d11_device_get_device_handle (device);
+  for (guint i = 0; i < G_N_ELEMENTS (formats); i++) {
     hr = device_handle->CheckFormatSupport (formats[i].dxgi_format,
         &supported_flags);
     if (SUCCEEDED (hr) && (supported_flags & display_flags) == display_flags) {
@@ -492,7 +484,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
     return FALSE;
   }
 
-  for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (&window->info); i++) {
+  for (guint i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (&window->info); i++) {
     if (GST_VIDEO_INFO_COMP_DEPTH (&window->info, i) > 8) {
       if (formats[2].supported) {
         chosen_format = &formats[2];
@@ -503,7 +495,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
 
   if (!chosen_format) {
     /* prefer native format over conversion */
-    for (i = 0; i < 2; i++) {
+    for (guint i = 0; i < 2; i++) {
       if (formats[i].supported &&
           formats[i].gst_format == GST_VIDEO_INFO_FORMAT (&window->info)) {
         chosen_format = &formats[i];
@@ -513,7 +505,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
 
     /* choose any color space then */
     if (!chosen_format) {
-      for (i = 0; i < G_N_ELEMENTS (formats); i++) {
+      for (guint i = 0; i < G_N_ELEMENTS (formats); i++) {
         if (formats[i].supported) {
           chosen_format = &formats[i];
           break;
@@ -522,7 +514,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
     }
   }
 
-  g_assert (chosen_format != NULL);
+  g_assert (chosen_format != nullptr);
 
   GST_DEBUG_OBJECT (window, "chosen render format %s (DXGI_FORMAT %d)",
       gst_video_format_to_string (chosen_format->gst_format),
@@ -532,28 +524,17 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
    * (or reuse old swapchain if the format is not changed) */
   window->allow_tearing = FALSE;
 
-  {
-    ComPtr < IDXGIFactory5 > factory5;
-    IDXGIFactory1 *factory_handle;
-    BOOL allow_tearing = FALSE;
-
-    factory_handle = gst_d3d11_device_get_dxgi_factory_handle (window->device);
-    hr = factory_handle->QueryInterface (IID_PPV_ARGS (&factory5));
-    if (SUCCEEDED (hr)) {
-      hr = factory5->CheckFeatureSupport (DXGI_FEATURE_PRESENT_ALLOW_TEARING,
-          (void *) &allow_tearing, sizeof (allow_tearing));
-    }
-
-    if (SUCCEEDED (hr) && allow_tearing)
-      window->allow_tearing = allow_tearing;
+  factory_handle = gst_d3d11_device_get_dxgi_factory_handle (device);
+  hr = factory_handle->QueryInterface (IID_PPV_ARGS (&factory5));
+  if (SUCCEEDED (hr)) {
+    hr = factory5->CheckFeatureSupport (DXGI_FEATURE_PRESENT_ALLOW_TEARING,
+        (void *) &allow_tearing, sizeof (allow_tearing));
   }
 
-  if (window->allow_tearing) {
-    GST_DEBUG_OBJECT (window, "device supports tearing");
-    swapchain_flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
-  }
+  if (SUCCEEDED (hr) && allow_tearing)
+    window->allow_tearing = allow_tearing;
 
-  gst_d3d11_device_lock (window->device);
+  gst_d3d11_device_lock (device);
   window->dxgi_format = chosen_format->dxgi_format;
 
   klass = GST_D3D11_WINDOW_GET_CLASS (window);
@@ -580,35 +561,6 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
 
   window->prev_input_rect = window->input_rect;
 
-  /* Step 4: Decide render color space and set it on converter/processor */
-  {
-    GstVideoMasteringDisplayInfo minfo;
-    GstVideoContentLightLevel cll;
-
-    if (gst_video_mastering_display_info_from_caps (&minfo, caps) &&
-        gst_video_content_light_level_from_caps (&cll, caps)) {
-      ComPtr < IDXGISwapChain4 > swapchain4;
-      HRESULT hr;
-
-      hr = window->swap_chain->QueryInterface (IID_PPV_ARGS (&swapchain4));
-      if (gst_d3d11_result (hr, window->device)) {
-        GST_DEBUG_OBJECT (window, "Have HDR metadata, set to DXGI swapchain");
-
-        gst_d3d11_hdr_meta_data_to_dxgi (&minfo, &cll, &hdr10_metadata);
-
-        hr = swapchain4->SetHDRMetaData (DXGI_HDR_METADATA_TYPE_HDR10,
-            sizeof (DXGI_HDR_METADATA_HDR10), &hdr10_metadata);
-        if (!gst_d3d11_result (hr, window->device)) {
-          GST_WARNING_OBJECT (window, "Couldn't set HDR metadata, hr 0x%x",
-              (guint) hr);
-        } else {
-          have_hdr10 = TRUE;
-        }
-      }
-    }
-  }
-
-  /* Step 5: Choose display color space */
   gst_video_info_set_format (&window->render_info,
       chosen_format->gst_format, display_width, display_height);
 
@@ -621,36 +573,63 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
    * target display color space type */
   window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
 
-  {
-    ComPtr < IDXGISwapChain3 > swapchain3;
-    HRESULT hr;
-
-    hr = window->swap_chain->QueryInterface (IID_PPV_ARGS (&swapchain3));
-
-    if (gst_d3d11_result (hr, window->device)) {
-      found_swapchain_colorspace =
-          gst_d3d11_find_swap_chain_color_space (&window->render_info,
-          swapchain3.Get (), &swapchain_colorspace);
-      if (found_swapchain_colorspace) {
-        native_colorspace_type =
-            (DXGI_COLOR_SPACE_TYPE) swapchain_colorspace.dxgi_color_space_type;
-        hr = swapchain3->SetColorSpace1 (native_colorspace_type);
-        if (!gst_d3d11_result (hr, window->device)) {
-          GST_WARNING_OBJECT (window, "Failed to set colorspace %d, hr: 0x%x",
-              native_colorspace_type, (guint) hr);
-          found_swapchain_colorspace = FALSE;
-          native_colorspace_type = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
-        } else {
-          GST_DEBUG_OBJECT (window,
-              "Set colorspace %d", native_colorspace_type);
-
-          /* update with selected display color space */
-          window->render_info.colorimetry.primaries =
-              swapchain_colorspace.primaries;
-          window->render_info.colorimetry.transfer =
-              swapchain_colorspace.transfer;
-          window->render_info.colorimetry.range = swapchain_colorspace.range;
-          window->render_info.colorimetry.matrix = swapchain_colorspace.matrix;
+  s = gst_caps_get_structure (caps, 0);
+  mdcv_str = gst_structure_get_string (s, "mastering-display-info");
+  cll_str = gst_structure_get_string (s, "content-light-level");
+  if (mdcv_str && cll_str &&
+      gst_video_mastering_display_info_from_string (&mdcv, mdcv_str) &&
+      gst_video_content_light_level_from_string (&cll, cll_str)) {
+    have_hdr10_meta = TRUE;
+  }
+
+  hr = window->swap_chain->QueryInterface (IID_PPV_ARGS (&swapchain3));
+  if (gst_d3d11_result (hr, device)) {
+    found_swapchain_colorspace =
+        gst_d3d11_find_swap_chain_color_space (&window->render_info,
+        swapchain3.Get (), &swapchain_colorspace);
+    if (found_swapchain_colorspace) {
+      native_colorspace_type =
+          (DXGI_COLOR_SPACE_TYPE) swapchain_colorspace.dxgi_color_space_type;
+      hr = swapchain3->SetColorSpace1 (native_colorspace_type);
+      if (!gst_d3d11_result (hr, window->device)) {
+        GST_WARNING_OBJECT (window, "Failed to set colorspace %d, hr: 0x%x",
+            native_colorspace_type, (guint) hr);
+        found_swapchain_colorspace = FALSE;
+        native_colorspace_type = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
+      } else {
+        ComPtr < IDXGISwapChain4 > swapchain4;
+
+        GST_DEBUG_OBJECT (window, "Set colorspace %d", native_colorspace_type);
+
+        /* update with selected display color space */
+        window->render_info.colorimetry.primaries =
+            swapchain_colorspace.primaries;
+        window->render_info.colorimetry.transfer =
+            swapchain_colorspace.transfer;
+        window->render_info.colorimetry.range = swapchain_colorspace.range;
+        window->render_info.colorimetry.matrix = swapchain_colorspace.matrix;
+
+        /* DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 = 12, undefined in old
+         * mingw header */
+        if (native_colorspace_type == 12 && have_hdr10_meta) {
+          hr = swapchain3.As (&swapchain4);
+          if (gst_d3d11_result (hr, device)) {
+            DXGI_HDR_METADATA_HDR10 hdr10_metadata = { 0, };
+
+            GST_DEBUG_OBJECT (window,
+                "Have HDR metadata, set to DXGI swapchain");
+
+            gst_d3d11_hdr_meta_data_to_dxgi (&mdcv, &cll, &hdr10_metadata);
+
+            hr = swapchain4->SetHDRMetaData (DXGI_HDR_METADATA_TYPE_HDR10,
+                sizeof (DXGI_HDR_METADATA_HDR10), &hdr10_metadata);
+            if (!gst_d3d11_result (hr, device)) {
+              GST_WARNING_OBJECT (window,
+                  "Couldn't set HDR metadata, hr 0x%x", (guint) hr);
+            } else {
+              hdr10_aware = TRUE;
+            }
+          }
         }
       }
     }
@@ -664,66 +643,10 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
     window->render_info.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
     window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
     window->render_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
-  } else if (gst_d3d11_video_info_to_dxgi_color_space (&window->info,
-          &in_dxgi_colorspace)) {
-    GstD3D11Format in_format;
-    gboolean hardware = FALSE;
-    GstD3D11VideoProcessor *processor = NULL;
-    DXGI_FORMAT in_dxgi_format;
-
-    gst_d3d11_device_get_format (window->device,
-        GST_VIDEO_INFO_FORMAT (&window->info), &in_format);
-    in_dxgi_format = in_format.dxgi_format;
-
-    if (in_format.dxgi_format != DXGI_FORMAT_UNKNOWN) {
-      g_object_get (window->device, "hardware", &hardware, NULL);
-    }
-
-    if (hardware) {
-      processor =
-          gst_d3d11_video_processor_new (window->device,
-          GST_VIDEO_INFO_WIDTH (&window->info),
-          GST_VIDEO_INFO_HEIGHT (&window->info), display_width, display_height);
-    }
-
-    if (processor) {
-      DXGI_FORMAT out_dxgi_format = chosen_format->dxgi_format;
-      DXGI_COLOR_SPACE_TYPE in_dxgi_color_space =
-          (DXGI_COLOR_SPACE_TYPE) in_dxgi_colorspace.dxgi_color_space_type;
-      DXGI_COLOR_SPACE_TYPE out_dxgi_color_space = native_colorspace_type;
-
-      if (!gst_d3d11_video_processor_check_format_conversion (processor,
-              in_dxgi_format, in_dxgi_color_space, out_dxgi_format,
-              out_dxgi_color_space)) {
-        GST_DEBUG_OBJECT (window, "Conversion is not supported by device");
-        gst_d3d11_video_processor_free (processor);
-        processor = NULL;
-      } else {
-        GST_DEBUG_OBJECT (window, "video processor supports conversion");
-        gst_d3d11_video_processor_set_input_dxgi_color_space (processor,
-            in_dxgi_color_space);
-        gst_d3d11_video_processor_set_output_dxgi_color_space (processor,
-            out_dxgi_color_space);
-
-        if (have_hdr10) {
-          GST_DEBUG_OBJECT (window, "Set HDR metadata on video processor");
-          gst_d3d11_video_processor_set_input_hdr10_metadata (processor,
-              &hdr10_metadata);
-          gst_d3d11_video_processor_set_output_hdr10_metadata (processor,
-              &hdr10_metadata);
-        }
-      }
-
-      window->processor = processor;
-    }
   }
 
-  *video_processor_available = !!window->processor;
-
-  /* configure shader even if video processor is available for fallback */
-  window->converter =
-      gst_d3d11_converter_new (window->device, &window->info,
-      &window->render_info, &method);
+  window->converter = gst_d3d11_converter_new (device,
+      &window->info, &window->render_info, nullptr);
 
   if (!window->converter) {
     GST_ERROR_OBJECT (window, "Cannot create converter");
@@ -732,6 +655,15 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
     goto error;
   }
 
+  if (have_hdr10_meta) {
+    g_object_set (window->converter, "src-mastering-display-info", mdcv_str,
+        "src-content-light-level", cll_str, nullptr);
+    if (hdr10_aware) {
+      g_object_set (window->converter, "dest-mastering-display-info", mdcv_str,
+          "dest-content-light-level", cll_str, nullptr);
+    }
+  }
+
   window->compositor =
       gst_d3d11_overlay_compositor_new (window->device, &window->render_info);
   if (!window->compositor) {
@@ -799,198 +731,95 @@ gst_d3d11_window_set_title (GstD3D11Window * window, const gchar * title)
     klass->set_title (window, title);
 }
 
-static gboolean
-gst_d3d11_window_buffer_ensure_processor_input (GstD3D11Window * self,
-    GstBuffer * buffer, ID3D11VideoProcessorInputView ** in_view)
-{
-  GstD3D11Memory *mem;
-  ID3D11VideoProcessorInputView *piv;
-
-  if (!self->processor)
-    return FALSE;
-
-  if (gst_buffer_n_memory (buffer) != 1)
-    return FALSE;
-
-  mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
-  piv = gst_d3d11_video_processor_get_input_view (self->processor, mem);
-  if (!piv) {
-    GST_LOG_OBJECT (self, "Failed to get processor input view");
-    return FALSE;
-  }
-
-  *in_view = piv;
-
-  return TRUE;
-}
-
-static gboolean
-gst_d3d11_window_do_processor (GstD3D11Window * self,
-    ID3D11VideoProcessorInputView * piv, ID3D11VideoProcessorOutputView * pov,
-    RECT * input_rect)
-{
-  gboolean ret;
-
-  ret = gst_d3d11_video_processor_render_unlocked (self->processor,
-      input_rect, piv, &self->render_rect, pov);
-  if (!ret) {
-    GST_ERROR_OBJECT (self, "Couldn't render to backbuffer using processor");
-  } else {
-    GST_TRACE_OBJECT (self, "Rendered using processor");
-    self->processor_in_use = TRUE;
-  }
-
-  return ret;
-}
-
-static gboolean
-gst_d3d11_window_do_convert (GstD3D11Window * self,
-    ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES],
-    ID3D11RenderTargetView * rtv, RECT * input_rect)
-{
-  RECT *prev = &self->prev_input_rect;
-
-  if (input_rect->left != prev->left || input_rect->top != prev->top ||
-      input_rect->right != prev->right || input_rect->bottom != prev->bottom) {
-    g_object_set (self->converter, "src-x", (gint) input_rect->left,
-        "src-y", (gint) input_rect->top,
-        "src-width", (gint) (input_rect->right - input_rect->left),
-        "src-height", (gint) (input_rect->bottom - input_rect->top), nullptr);
-
-    *prev = *input_rect;
-  }
-
-  if (!gst_d3d11_converter_convert_unlocked (self->converter, srv, &rtv)) {
-    GST_ERROR_OBJECT (self, "Couldn't render to backbuffer using converter");
-    return FALSE;
-  } else {
-    GST_TRACE_OBJECT (self, "Rendered using converter");
-  }
-
-  return TRUE;
-}
-
 static GstFlowReturn
 gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer,
-    ID3D11VideoProcessorOutputView * pov, ID3D11RenderTargetView * rtv)
+    GstBuffer * backbuffer)
 {
   GstD3D11WindowClass *klass = GST_D3D11_WINDOW_GET_CLASS (self);
   GstFlowReturn ret = GST_FLOW_OK;
   guint present_flags = 0;
+  GstVideoCropMeta *crop_meta;
+  RECT input_rect = self->input_rect;
+  RECT *prev_rect = &self->prev_input_rect;
+  ID3D11RenderTargetView *rtv;
+  GstMemory *mem;
+  GstD3D11Memory *dmem;
 
   if (!buffer)
     return GST_FLOW_OK;
 
-  {
-    GstMapInfo infos[GST_VIDEO_MAX_PLANES];
-    ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES];
-    ID3D11VideoProcessorInputView *piv = NULL;
-    ID3D11Device *device_handle =
-        gst_d3d11_device_get_device_handle (self->device);
-    gboolean can_convert = FALSE;
-    gboolean can_process = FALSE;
-    gboolean convert_ret = FALSE;
-    RECT input_rect = self->input_rect;
-    GstVideoCropMeta *crop_meta;
-
-    /* Map memory in any case so that we can upload pending stage texture */
-    if (!gst_d3d11_buffer_map (buffer, device_handle, infos, GST_MAP_READ)) {
-      GST_ERROR_OBJECT (self, "Couldn't map buffer");
-      return GST_FLOW_ERROR;
-    }
-
-    can_convert = gst_d3d11_buffer_get_shader_resource_view (buffer, srv);
-    if (pov) {
-      can_process = gst_d3d11_window_buffer_ensure_processor_input (self,
-          buffer, &piv);
-    }
-
-    if (!can_convert && !can_process) {
-      GST_ERROR_OBJECT (self, "Input texture cannot be used for converter");
-      return GST_FLOW_ERROR;
-    }
+  if (!backbuffer) {
+    GST_ERROR_OBJECT (self, "Empty render target");
+    return GST_FLOW_ERROR;
+  }
 
-    crop_meta = gst_buffer_get_video_crop_meta (buffer);
-    /* Do minimal validate */
-    if (crop_meta) {
-      ID3D11Texture2D *texture = (ID3D11Texture2D *) infos[0].data;
-      D3D11_TEXTURE2D_DESC desc = { 0, };
+  mem = gst_buffer_peek_memory (backbuffer, 0);
+  if (!gst_is_d3d11_memory (mem)) {
+    GST_ERROR_OBJECT (self, "Invalid back buffer");
+    return GST_FLOW_ERROR;
+  }
 
-      texture->GetDesc (&desc);
+  dmem = GST_D3D11_MEMORY_CAST (mem);
+  rtv = gst_d3d11_memory_get_render_target_view (dmem, 0);
+  if (!rtv) {
+    GST_ERROR_OBJECT (self, "RTV is unavailable");
+    return GST_FLOW_ERROR;
+  }
 
-      if (desc.Width < crop_meta->x + crop_meta->width ||
-          desc.Height < crop_meta->y + crop_meta->height) {
-        GST_WARNING_OBJECT (self, "Invalid crop meta, ignore");
+  crop_meta = gst_buffer_get_video_crop_meta (buffer);
+  if (crop_meta) {
+    input_rect.left = crop_meta->x;
+    input_rect.right = crop_meta->x + crop_meta->width;
+    input_rect.top = crop_meta->y;
+    input_rect.bottom = crop_meta->y + crop_meta->height;
+  }
 
-        crop_meta = nullptr;
-      }
-    }
+  if (input_rect.left != prev_rect->left || input_rect.top != prev_rect->top ||
+      input_rect.right != prev_rect->right ||
+      input_rect.bottom != prev_rect->bottom) {
+    g_object_set (self->converter, "src-x", (gint) input_rect.left,
+        "src-y", (gint) input_rect.top,
+        "src-width", (gint) (input_rect.right - input_rect.left),
+        "src-height", (gint) (input_rect.bottom - input_rect.top), nullptr);
 
-    if (crop_meta) {
-      input_rect.left = crop_meta->x;
-      input_rect.right = crop_meta->x + crop_meta->width;
-      input_rect.top = crop_meta->y;
-      input_rect.bottom = crop_meta->y + crop_meta->height;
-    }
+    self->prev_input_rect = input_rect;
+  }
 
-    if (self->first_present) {
-      D3D11_VIEWPORT viewport;
-
-      viewport.TopLeftX = self->render_rect.left;
-      viewport.TopLeftY = self->render_rect.top;
-      viewport.Width = self->render_rect.right - self->render_rect.left;
-      viewport.Height = self->render_rect.bottom - self->render_rect.top;
-      viewport.MinDepth = 0.0f;
-      viewport.MaxDepth = 1.0f;
-
-      g_object_set (self->converter, "dest-x", (gint) self->render_rect.left,
-          "dest-y", (gint) self->render_rect.top,
-          "dest-width",
-          (gint) (self->render_rect.right - self->render_rect.left),
-          "dest-height",
-          (gint) (self->render_rect.bottom - self->render_rect.top), nullptr);
-      gst_d3d11_overlay_compositor_update_viewport (self->compositor,
-          &viewport);
-    }
+  if (self->first_present) {
+    D3D11_VIEWPORT viewport;
 
-    /* Converter preference order
-     * 1) If this texture can be converted via processor, and we used processor
-     *    previously, use processor
-     * 2) If SRV is available, use converter
-     * 3) otherwise, use processor
-     */
-    if (can_process && self->processor_in_use) {
-      convert_ret = gst_d3d11_window_do_processor (self, piv, pov, &input_rect);
-    } else if (can_convert) {
-      convert_ret = gst_d3d11_window_do_convert (self, srv, rtv, &input_rect);
-    } else if (can_process) {
-      convert_ret = gst_d3d11_window_do_processor (self, piv, pov, &input_rect);
-    } else {
-      g_assert_not_reached ();
-      ret = GST_FLOW_ERROR;
-      goto unmap_and_out;
-    }
+    viewport.TopLeftX = self->render_rect.left;
+    viewport.TopLeftY = self->render_rect.top;
+    viewport.Width = self->render_rect.right - self->render_rect.left;
+    viewport.Height = self->render_rect.bottom - self->render_rect.top;
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 1.0f;
 
-    if (!convert_ret) {
-      ret = GST_FLOW_ERROR;
-      goto unmap_and_out;
-    }
+    g_object_set (self->converter, "dest-x", (gint) self->render_rect.left,
+        "dest-y", (gint) self->render_rect.top,
+        "dest-width",
+        (gint) (self->render_rect.right - self->render_rect.left),
+        "dest-height",
+        (gint) (self->render_rect.bottom - self->render_rect.top), nullptr);
+    gst_d3d11_overlay_compositor_update_viewport (self->compositor, &viewport);
+  }
 
-    gst_d3d11_overlay_compositor_upload (self->compositor, buffer);
-    gst_d3d11_overlay_compositor_draw_unlocked (self->compositor, &rtv);
+  if (!gst_d3d11_converter_convert_buffer_unlocked (self->converter,
+          buffer, backbuffer)) {
+    GST_ERROR_OBJECT (self, "Couldn't render buffer");
+    return GST_FLOW_ERROR;
+  }
 
-    if (self->allow_tearing && self->fullscreen) {
-      present_flags |= DXGI_PRESENT_ALLOW_TEARING;
-    }
+  gst_d3d11_overlay_compositor_upload (self->compositor, buffer);
+  gst_d3d11_overlay_compositor_draw_unlocked (self->compositor, &rtv);
 
-    if (klass->present)
-      ret = klass->present (self, present_flags);
+  if (self->allow_tearing && self->fullscreen)
+    present_flags |= DXGI_PRESENT_ALLOW_TEARING;
 
-    self->first_present = FALSE;
+  if (klass->present)
+    ret = klass->present (self, present_flags);
 
-  unmap_and_out:
-    gst_d3d11_buffer_unmap (buffer, infos);
-  }
+  self->first_present = FALSE;
 
   return ret;
 }
@@ -998,26 +827,16 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer,
 GstFlowReturn
 gst_d3d11_window_render (GstD3D11Window * window, GstBuffer * buffer)
 {
-  GstMemory *mem;
   GstFlowReturn ret;
 
   g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), GST_FLOW_ERROR);
 
-  if (buffer) {
-    mem = gst_buffer_peek_memory (buffer, 0);
-    if (!gst_is_d3d11_memory (mem)) {
-      GST_ERROR_OBJECT (window, "Invalid buffer");
-
-      return GST_FLOW_ERROR;
-    }
-  }
-
   gst_d3d11_device_lock (window->device);
   if (buffer)
     gst_buffer_replace (&window->cached_buffer, buffer);
 
   ret = gst_d3d111_window_present (window, window->cached_buffer,
-      window->pov, window->rtv);
+      window->backbuffer);
   gst_d3d11_device_unlock (window->device);
 
   return ret;
@@ -1029,11 +848,8 @@ gst_d3d11_window_render_on_shared_handle (GstD3D11Window * window,
     guint64 acquire_key, guint64 release_key)
 {
   GstD3D11WindowClass *klass;
-  GstMemory *mem;
   GstFlowReturn ret = GST_FLOW_OK;
-  GstD3D11WindowSharedHandleData data = { NULL, };
-  ID3D11VideoProcessorOutputView *pov = NULL;
-  ID3D11RenderTargetView *rtv = NULL;
+  GstD3D11WindowSharedHandleData data = { nullptr, };
 
   g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), GST_FLOW_ERROR);
 
@@ -1042,13 +858,6 @@ gst_d3d11_window_render_on_shared_handle (GstD3D11Window * window,
   g_assert (klass->open_shared_handle != NULL);
   g_assert (klass->release_shared_handle != NULL);
 
-  mem = gst_buffer_peek_memory (buffer, 0);
-  if (!gst_is_d3d11_memory (mem)) {
-    GST_ERROR_OBJECT (window, "Invalid buffer");
-
-    return GST_FLOW_ERROR;
-  }
-
   data.shared_handle = shared_handle;
   data.texture_misc_flags = texture_misc_flags;
   data.acquire_key = acquire_key;
@@ -1061,15 +870,7 @@ gst_d3d11_window_render_on_shared_handle (GstD3D11Window * window,
     return GST_FLOW_OK;
   }
 
-  if (data.fallback_rtv) {
-    rtv = data.fallback_rtv;
-    pov = data.fallback_pov;
-  } else {
-    rtv = data.rtv;
-    pov = data.pov;
-  }
-
-  ret = gst_d3d111_window_present (window, buffer, pov, rtv);
+  ret = gst_d3d111_window_present (window, buffer, data.render_target);
 
   klass->release_shared_handle (window, &data);
   gst_d3d11_device_unlock (window->device);
index 585157f..1324e00 100644 (file)
@@ -69,13 +69,8 @@ typedef struct
   guint64 acquire_key;
   guint64 release_key;
 
-  ID3D11Texture2D *texture;
+  GstBuffer *render_target;
   IDXGIKeyedMutex *keyed_mutex;
-  ID3D11VideoProcessorOutputView *pov;
-  ID3D11RenderTargetView *rtv;
-
-  ID3D11VideoProcessorOutputView *fallback_pov;
-  ID3D11RenderTargetView *fallback_rtv;
 } GstD3D11WindowSharedHandleData;
 
 struct _GstD3D11Window
@@ -85,6 +80,7 @@ struct _GstD3D11Window
   /*< protected >*/
   gboolean initialized;
   GstD3D11Device *device;
+  GstD3D11Allocator *allocator;
   guintptr external_handle;
 
   /* properties */
@@ -97,12 +93,9 @@ struct _GstD3D11Window
 
   GstVideoInfo info;
   GstVideoInfo render_info;
-  GstD3D11VideoProcessor *processor;
   GstD3D11Converter *converter;
   GstD3D11OverlayCompositor *compositor;
 
-  gboolean processor_in_use;
-
   /* calculated rect with aspect ratio and window area */
   RECT render_rect;
 
@@ -117,8 +110,7 @@ struct _GstD3D11Window
   guint surface_height;
 
   IDXGISwapChain *swap_chain;
-  ID3D11RenderTargetView *rtv;
-  ID3D11VideoProcessorOutputView *pov;
+  GstBuffer *backbuffer;
   DXGI_FORMAT dxgi_format;
 
   GstBuffer *cached_buffer;
@@ -158,7 +150,6 @@ struct _GstD3D11WindowClass
                                            guint display_width,
                                            guint display_height,
                                            GstCaps * caps,
-                                           gboolean * video_processor_available,
                                            GError ** error);
 
   void          (*unprepare)              (GstD3D11Window * window);
@@ -190,7 +181,6 @@ gboolean      gst_d3d11_window_prepare              (GstD3D11Window * window,
                                                      guint display_width,
                                                      guint display_height,
                                                      GstCaps * caps,
-                                                     gboolean * video_processor_available,
                                                      GError ** error);
 
 GstFlowReturn gst_d3d11_window_render               (GstD3D11Window * window,
index 4d04ed4..65498bb 100644 (file)
@@ -49,9 +49,7 @@ G_DEFINE_TYPE (GstD3D11WindowDummy, gst_d3d11_window_dummy,
 static void gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
     guint width, guint height);
 static gboolean gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
-    guint display_width, guint display_height, GstCaps * caps,
-    gboolean * video_processor_available, GError ** error);
-static void gst_d3d11_window_dummy_unprepare (GstD3D11Window * window);
+    guint display_width, guint display_height, GstCaps * caps, GError ** error);
 static gboolean
 gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
     GstD3D11WindowSharedHandleData * data);
@@ -67,8 +65,6 @@ gst_d3d11_window_dummy_class_init (GstD3D11WindowDummyClass * klass)
   window_class->on_resize =
       GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_on_resize);
   window_class->prepare = GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_prepare);
-  window_class->unprepare =
-      GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_unprepare);
   window_class->open_shared_handle =
       GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_open_shared_handle);
   window_class->release_shared_handle =
@@ -82,13 +78,19 @@ gst_d3d11_window_dummy_init (GstD3D11WindowDummy * self)
 
 static gboolean
 gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
-    guint display_width, guint display_height, GstCaps * caps,
-    gboolean * video_processor_available, GError ** error)
+    guint display_width, guint display_height, GstCaps * caps, GError ** error)
 {
-  GstDxgiColorSpace in_space;
   GstD3D11ConverterMethod method = GST_D3D11_CONVERTER_METHOD_SHADER;
 
-  g_clear_pointer (&window->processor, gst_d3d11_video_processor_free);
+  if (!window->allocator) {
+    window->allocator =
+        (GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
+    if (!window->allocator) {
+      GST_ERROR_OBJECT (window, "Allocator is unavailable");
+      return FALSE;
+    }
+  }
+
   gst_clear_object (&window->compositor);
   gst_clear_object (&window->converter);
 
@@ -116,63 +118,7 @@ gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
   window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
 
   gst_d3d11_device_lock (window->device);
-
-  if (gst_d3d11_video_info_to_dxgi_color_space (&window->info, &in_space)) {
-    GstD3D11Format in_format;
-    gboolean hardware = FALSE;
-    GstD3D11VideoProcessor *processor = NULL;
-    guint i;
-    DXGI_FORMAT formats_to_check[] = {
-      DXGI_FORMAT_R8G8B8A8_UNORM,
-      DXGI_FORMAT_B8G8R8A8_UNORM,
-      DXGI_FORMAT_R10G10B10A2_UNORM
-    };
-    DXGI_FORMAT in_dxgi_format;
-
-    gst_d3d11_device_get_format (window->device,
-        GST_VIDEO_INFO_FORMAT (&window->info), &in_format);
-    in_dxgi_format = in_format.dxgi_format;
-
-    if (in_format.dxgi_format != DXGI_FORMAT_UNKNOWN) {
-      g_object_get (window->device, "hardware", &hardware, NULL);
-    }
-
-    if (hardware) {
-      processor =
-          gst_d3d11_video_processor_new (window->device,
-          GST_VIDEO_INFO_WIDTH (&window->info),
-          GST_VIDEO_INFO_HEIGHT (&window->info), display_width, display_height);
-    }
-
-    /* Check if video processor can support all possible output dxgi formats */
-    for (i = 0; i < G_N_ELEMENTS (formats_to_check) && processor; i++) {
-      DXGI_FORMAT out_dxgi_format = formats_to_check[i];
-      DXGI_COLOR_SPACE_TYPE in_dxgi_color_space =
-          (DXGI_COLOR_SPACE_TYPE) in_space.dxgi_color_space_type;
-
-      if (!gst_d3d11_video_processor_check_format_conversion (processor,
-              in_dxgi_format, in_dxgi_color_space, out_dxgi_format,
-              DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709)) {
-        GST_DEBUG_OBJECT (window, "Conversion is not supported by device");
-        g_clear_pointer (&processor, gst_d3d11_video_processor_free);
-        break;
-      }
-    }
-
-    if (processor) {
-      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_RGB_FULL_G22_NONE_P709);
-    }
-
-    window->processor = processor;
-  }
-
-  *video_processor_available = !!window->processor;
-
-  window->converter =
-      gst_d3d11_converter_new (window->device, &window->info,
+  window->converter = gst_d3d11_converter_new (window->device, &window->info,
       &window->render_info, &method);
 
   if (!window->converter) {
@@ -202,22 +148,6 @@ error:
 }
 
 static void
-gst_d3d11_window_dummy_clear_resources (GstD3D11WindowDummy * self)
-{
-  GST_D3D11_CLEAR_COM (self->fallback_pov);
-  GST_D3D11_CLEAR_COM (self->fallback_rtv);
-  GST_D3D11_CLEAR_COM (self->fallback_texture);
-}
-
-static void
-gst_d3d11_window_dummy_unprepare (GstD3D11Window * window)
-{
-  GstD3D11WindowDummy *self = GST_D3D11_WINDOW_DUMMY (window);
-
-  gst_d3d11_window_dummy_clear_resources (self);
-}
-
-static void
 gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
     guint width, guint height)
 {
@@ -248,107 +178,25 @@ gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
 }
 
 static gboolean
-gst_d3d11_window_dummy_setup_fallback_texture (GstD3D11Window * window,
-    D3D11_TEXTURE2D_DESC * shared_desc)
-{
-  GstD3D11WindowDummy *self = GST_D3D11_WINDOW_DUMMY (window);
-  D3D11_TEXTURE2D_DESC desc = { 0, };
-  D3D11_RENDER_TARGET_VIEW_DESC rtv_desc;
-  ID3D11Device *device_handle =
-      gst_d3d11_device_get_device_handle (window->device);
-  gboolean need_new_texture = FALSE;
-  HRESULT hr;
-
-  if (!self->fallback_texture) {
-    GST_DEBUG_OBJECT (self,
-        "We have no configured fallback texture, create new one");
-    need_new_texture = TRUE;
-  } else {
-    self->fallback_texture->GetDesc (&desc);
-    if (shared_desc->Format != desc.Format) {
-      GST_DEBUG_OBJECT (self, "Texture formats are different, create new one");
-      need_new_texture = TRUE;
-    } else if (shared_desc->Width > desc.Width ||
-        shared_desc->Height > desc.Height) {
-      GST_DEBUG_OBJECT (self, "Needs larger size of fallback texture");
-      need_new_texture = TRUE;
-    }
-  }
-
-  if (!need_new_texture)
-    return TRUE;
-
-  gst_d3d11_window_dummy_clear_resources (self);
-
-  desc.Width = shared_desc->Width;
-  desc.Height = shared_desc->Height;
-  desc.MipLevels = 1;
-  desc.ArraySize = 1;
-  desc.Format = shared_desc->Format;
-  desc.SampleDesc.Count = 1;
-  desc.SampleDesc.Quality = 0;
-  desc.Usage = D3D11_USAGE_DEFAULT;
-  desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
-
-  hr = device_handle->CreateTexture2D (&desc, NULL, &self->fallback_texture);
-  if (!gst_d3d11_result (hr, window->device)) {
-    GST_ERROR_OBJECT (self, "Couldn't create fallback texture");
-    return FALSE;
-  }
-
-  rtv_desc.Format = DXGI_FORMAT_UNKNOWN;
-  rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-  rtv_desc.Texture2D.MipSlice = 0;
-
-  hr = device_handle->CreateRenderTargetView (self->fallback_texture, &rtv_desc,
-      &self->fallback_rtv);
-  if (!gst_d3d11_result (hr, window->device)) {
-    GST_ERROR_OBJECT (self,
-        "Couldn't get render target view from fallback texture");
-    gst_d3d11_window_dummy_clear_resources (self);
-    return FALSE;
-  }
-
-  if (window->processor) {
-    D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC pov_desc;
-
-    pov_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
-    pov_desc.Texture2D.MipSlice = 0;
-
-    if (!gst_d3d11_video_processor_create_output_view (window->processor,
-            &pov_desc, self->fallback_texture, &self->fallback_pov)) {
-      GST_ERROR_OBJECT (window,
-          "ID3D11VideoProcessorOutputView is unavailable");
-      gst_d3d11_window_dummy_clear_resources (self);
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
-
-/* *INDENT-OFF* */
-static gboolean
 gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
     GstD3D11WindowSharedHandleData * data)
 {
-  GstD3D11WindowDummy *self = GST_D3D11_WINDOW_DUMMY (window);
   GstD3D11Device *device = window->device;
   ID3D11Device *device_handle;
   HRESULT hr;
-  ID3D11Texture2D *texture = NULL;
-  IDXGIKeyedMutex *keyed_mutex = NULL;
-  ID3D11VideoProcessorOutputView *pov = NULL;
-  ID3D11RenderTargetView *rtv = NULL;
+  ComPtr < ID3D11Texture2D > texture;
+  ComPtr < IDXGIKeyedMutex > keyed_mutex;
+  ID3D11RenderTargetView *rtv;
+  GstMemory *mem;
+  GstD3D11Memory *dmem;
   D3D11_TEXTURE2D_DESC desc;
   gboolean use_keyed_mutex = FALSE;
-  gboolean need_fallback_texture = FALSE;
 
   device_handle = gst_d3d11_device_get_device_handle (device);
 
   if ((data->texture_misc_flags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE) ==
       D3D11_RESOURCE_MISC_SHARED_NTHANDLE) {
-    ComPtr<ID3D11Device1> device1_handle;
+    ComPtr < ID3D11Device1 > device1_handle;
 
     hr = device_handle->QueryInterface (IID_PPV_ARGS (&device1_handle));
     if (!gst_d3d11_result (hr, device))
@@ -370,82 +218,47 @@ gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
 
   if (use_keyed_mutex) {
     hr = texture->QueryInterface (IID_PPV_ARGS (&keyed_mutex));
-    if (!gst_d3d11_result (hr, device))
-      goto out;
+    if (!gst_d3d11_result (hr, device)) {
+      GST_ERROR_OBJECT (window, "Keyed mutex is unavailable");
+      return FALSE;
+    }
   }
 
-  if (window->processor) {
-    if (use_keyed_mutex) {
-      D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC pov_desc;
-
-      pov_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
-      pov_desc.Texture2D.MipSlice = 0;
-
-      if (!gst_d3d11_video_processor_create_output_view (window->processor,
-          &pov_desc, texture, &pov)) {
-        GST_WARNING_OBJECT (window,
-            "ID3D11VideoProcessorOutputView is unavailable");
-      }
-    } else {
-      /* HACK: If external texture was created without keyed mutext
-       * and we need to used videoprocessor to convert decoder output texture
-       * to external texture, converted texture by videoprocessor seems to be broken
-       * Probably that's because of missing flush/sync API around videoprocessor.
-       * (e.g., ID3D11VideoContext and ID3D11VideoProcessor have no
-       * flushing api such as ID3D11DeviceContext::Flush).
-       * To workaround the case, we need to use fallback texture and copy back
-       * to external texture
-       */
-
-      need_fallback_texture = TRUE;
-
-      GST_TRACE_OBJECT (window,
-          "We are using video processor but keyed mutex is unavailable");
-      if (!gst_d3d11_window_dummy_setup_fallback_texture (window, &desc)) {
-        goto out;
-      }
-    }
+  mem = gst_d3d11_allocator_alloc_wrapped_native_size (window->allocator,
+      device, texture.Get (), nullptr, nullptr);
+  if (!mem) {
+    GST_ERROR_OBJECT (window, "Couldn't allocate memory");
+    return FALSE;
   }
 
-  hr = device_handle->CreateRenderTargetView ((ID3D11Resource *) texture,
-      NULL, &rtv);
-  if (!gst_d3d11_result (hr, device))
-    goto out;
+  dmem = GST_D3D11_MEMORY_CAST (mem);
+  rtv = gst_d3d11_memory_get_render_target_view (dmem, 0);
+  if (!rtv) {
+    GST_ERROR_OBJECT (window, "Render target view is unavailable");
+    gst_memory_unref (mem);
+    return FALSE;
+  }
 
   if (keyed_mutex) {
-    hr = keyed_mutex->AcquireSync(data->acquire_key, INFINITE);
-    if (!gst_d3d11_result (hr, device))
-      goto out;
+    hr = keyed_mutex->AcquireSync (data->acquire_key, INFINITE);
+    if (!gst_d3d11_result (hr, device)) {
+      GST_ERROR_OBJECT (window, "Couldn't acquire sync");
+      gst_memory_unref (mem);
+      return FALSE;
+    }
   }
 
   /* Everything is prepared now */
   gst_d3d11_window_dummy_on_resize (window, desc.Width, desc.Height);
 
   /* Move owned resources */
-  data->texture = texture;
-  data->keyed_mutex = keyed_mutex;
-  data->pov = pov;
-  data->rtv = rtv;
-
-  if (need_fallback_texture) {
-    data->fallback_pov = self->fallback_pov;
-    data->fallback_rtv = self->fallback_rtv;
-  } else {
-    data->fallback_pov = nullptr;
-    data->fallback_rtv = nullptr;
-  }
+  data->render_target = gst_buffer_new ();
+  gst_buffer_append_memory (data->render_target, mem);
+  if (keyed_mutex)
+    data->keyed_mutex = keyed_mutex.Detach ();
 
   return TRUE;
-
-out:
-  GST_D3D11_CLEAR_COM (texture);
-  GST_D3D11_CLEAR_COM (keyed_mutex);
-  GST_D3D11_CLEAR_COM (pov);
-  GST_D3D11_CLEAR_COM (rtv);
-
-  return FALSE;
 }
-/* *INDENT-ON* */
 
 static gboolean
 gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
@@ -460,7 +273,7 @@ gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
     hr = data->keyed_mutex->ReleaseSync (data->release_key);
     gst_d3d11_result (hr, device);
 
-    data->keyed_mutex->Release ();
+    GST_D3D11_CLEAR_COM (data->keyed_mutex);
   } else {
     /* *INDENT-OFF* */
     ComPtr<ID3D11Query> query;
@@ -482,30 +295,11 @@ gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
       return FALSE;
     }
 
-    /* Copy from fallback texture to user's texture */
-    if (data->fallback_rtv) {
-      D3D11_BOX src_box;
-      D3D11_TEXTURE2D_DESC desc;
-      ID3D11DeviceContext *context_handle =
-          gst_d3d11_device_get_device_context_handle (device);
-
-      data->texture->GetDesc (&desc);
-
-      src_box.left = 0;
-      src_box.top = 0;
-      src_box.front = 0;
-      src_box.back = 1;
-      src_box.right = desc.Width;
-      src_box.bottom = desc.Height;
-
-      context_handle->CopySubresourceRegion (data->texture, 0, 0, 0, 0,
-          self->fallback_texture, 0, &src_box);
-    }
     context_handle->End (query.Get ());
 
     /* Wait until all issued GPU commands are finished */
     do {
-      context_handle->GetData (query.Get (), &sync_done, sizeof (BOOL), 0);
+      hr = context_handle->GetData (query.Get (), &sync_done, sizeof (BOOL), 0);
     } while (!sync_done && (hr == S_OK || hr == S_FALSE));
 
     if (!gst_d3d11_result (hr, device)) {
@@ -514,9 +308,7 @@ gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
     }
   }
 
-  GST_D3D11_CLEAR_COM (data->rtv);
-  GST_D3D11_CLEAR_COM (data->pov);
-  GST_D3D11_CLEAR_COM (data->texture);
+  gst_clear_buffer (&data->render_target);
 
   return TRUE;
 }