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;
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");
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);
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);
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)
{
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);
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");
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));
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)
}
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
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;
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 =
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) {
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];
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];
/* 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;
}
}
- 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),
* (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);
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);
* 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;
+ }
+ }
}
}
}
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");
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) {
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;
}
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;
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);
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;
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);
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);
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 =
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);
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) {
}
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)
{
}
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))
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,
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;
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)) {
}
}
- 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;
}