From 5eeec16502ec47cd12496914368ca4d1868e77c8 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 1 Jul 2022 23:49:49 +0900 Subject: [PATCH] d3d11videosink: Use single GstD3D11Converter object GstD3D11Converter supports videoprocessor and texture upload. Part-of: --- .../sys/d3d11/gstd3d11videosink.cpp | 210 +----- .../sys/d3d11/gstd3d11window.cpp | 701 +++++++----------- .../sys/d3d11/gstd3d11window.h | 16 +- .../sys/d3d11/gstd3d11window_dummy.cpp | 304 ++------ 4 files changed, 306 insertions(+), 925 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp index 2fe593d60b..49a144ed66 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp @@ -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)); diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp index 2d0121e946..dc97281798 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp @@ -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) @@ -251,132 +249,116 @@ 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) + gst_d3d11_device_lock (device); + + gst_clear_buffer (&self->backbuffer); + if (!self->swap_chain) goto done; - device_handle = gst_d3d11_device_get_device_handle (window->device); - swap_chain = window->swap_chain; - - GST_D3D11_CLEAR_COM (window->rtv); - GST_D3D11_CLEAR_COM (window->pov); - + 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; - - { - 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; - } - } - - 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; - - 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); - - 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); - + 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; } - 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, backbuffer, &window->pov)) - goto done; + 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->first_present = TRUE; + self->backbuffer = gst_buffer_new (); + gst_buffer_append_memory (self->backbuffer, mem); + + backbuffer->GetDesc (&desc); + self->surface_width = desc.Width; + self->surface_height = desc.Height; + + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.w = self->surface_width; + dst_rect.h = self->surface_height; + + 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); + + gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE); + } else { + rst_rect = dst_rect; + } + + 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; + + 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); + + 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; + 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)); + 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; - 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); + 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; + /* 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,225 +731,112 @@ 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; - } - - 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, }; - - texture->GetDesc (&desc); - - 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 = 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; - } - - 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); - } - - /* 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; - } - - if (!convert_ret) { - ret = GST_FLOW_ERROR; - goto unmap_and_out; - } - - gst_d3d11_overlay_compositor_upload (self->compositor, buffer); - gst_d3d11_overlay_compositor_draw_unlocked (self->compositor, &rtv); - - if (self->allow_tearing && self->fullscreen) { - present_flags |= DXGI_PRESENT_ALLOW_TEARING; - } - - if (klass->present) - ret = klass->present (self, present_flags); - - self->first_present = FALSE; - - unmap_and_out: - gst_d3d11_buffer_unmap (buffer, infos); + if (!backbuffer) { + GST_ERROR_OBJECT (self, "Empty render target"); + return GST_FLOW_ERROR; } + mem = gst_buffer_peek_memory (backbuffer, 0); + if (!gst_is_d3d11_memory (mem)) { + GST_ERROR_OBJECT (self, "Invalid back buffer"); + return GST_FLOW_ERROR; + } + + 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; + } + + 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; + } + + 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); + + 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 (!gst_d3d11_converter_convert_buffer_unlocked (self->converter, + buffer, backbuffer)) { + GST_ERROR_OBJECT (self, "Couldn't render buffer"); + return GST_FLOW_ERROR; + } + + gst_d3d11_overlay_compositor_upload (self->compositor, buffer); + gst_d3d11_overlay_compositor_draw_unlocked (self->compositor, &rtv); + + if (self->allow_tearing && self->fullscreen) + present_flags |= DXGI_PRESENT_ALLOW_TEARING; + + if (klass->present) + ret = klass->present (self, present_flags); + + self->first_present = FALSE; + return ret; } 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); diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h index 585157f032..1324e00d73 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h @@ -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, diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp index 4d04ed4511..65498bbfae 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp @@ -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) { @@ -201,22 +147,6 @@ error: return FALSE; } -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) @@ -247,108 +177,26 @@ gst_d3d11_window_dummy_on_resize (GstD3D11Window * window, window->first_present = TRUE; } -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 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 (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; - } + if (!gst_d3d11_result (hr, device)) { + GST_ERROR_OBJECT (window, "Keyed mutex is unavailable"); + return FALSE; } } - hr = device_handle->CreateRenderTargetView ((ID3D11Resource *) texture, - NULL, &rtv); - if (!gst_d3d11_result (hr, device)) - 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; + } + + 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 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; }