mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
d3d11videosink: Avoid switching conversion tool during playback
Decoder might be able to copy decoded texture to the other buffer pool during playback depending on context. In that case, copied one has no D3D11_BIND_DECODER bind flag. If we used ID3D11VideoProcessor previously for decoder texture, and incoming texture supports ID3D11VideoProcessor as well even if it has no D3D11_BIND_DECODER flag (having D3D11_BIND_RENDER_TARGET for example), allow zero-copying instead of using our fallback texture. Frequent conversion tool change (between ID3D11VideoProcessor and generic shader) might result in inconsistent image quality. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2084>
This commit is contained in:
parent
c74b230579
commit
3a99517f7c
3 changed files with 78 additions and 25 deletions
|
@ -125,6 +125,7 @@ struct _GstD3D11VideoSink
|
||||||
GstBufferPool *fallback_pool;
|
GstBufferPool *fallback_pool;
|
||||||
gboolean can_convert;
|
gboolean can_convert;
|
||||||
gboolean have_video_processor;
|
gboolean have_video_processor;
|
||||||
|
gboolean processor_in_use;
|
||||||
|
|
||||||
/* For drawing on user texture */
|
/* For drawing on user texture */
|
||||||
GstD3D11VideoSinkCallbacks callbacks;
|
GstD3D11VideoSinkCallbacks callbacks;
|
||||||
|
@ -701,6 +702,8 @@ gst_d3d11_video_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->processor_in_use = FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
@ -1118,6 +1121,11 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
|
||||||
GST_TRACE_OBJECT (self,
|
GST_TRACE_OBJECT (self,
|
||||||
"Got VideoProcessor compatible texture, do direct rendering");
|
"Got VideoProcessor compatible texture, do direct rendering");
|
||||||
direct_rendering = TRUE;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -650,6 +650,8 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
|
||||||
g_clear_pointer (&window->converter, gst_d3d11_converter_free);
|
g_clear_pointer (&window->converter, gst_d3d11_converter_free);
|
||||||
g_clear_pointer (&window->compositor, gst_d3d11_overlay_compositor_free);
|
g_clear_pointer (&window->compositor, gst_d3d11_overlay_compositor_free);
|
||||||
|
|
||||||
|
window->processor_in_use = FALSE;
|
||||||
|
|
||||||
/* Step 2: Decide display color format
|
/* Step 2: Decide display color format
|
||||||
* If upstream format is 10bits, try DXGI_FORMAT_R10G10B10A2_UNORM first
|
* If upstream format is 10bits, try DXGI_FORMAT_R10G10B10A2_UNORM first
|
||||||
* Otherwise, use DXGI_FORMAT_B8G8R8A8_UNORM or DXGI_FORMAT_B8G8R8A8_UNORM
|
* Otherwise, use DXGI_FORMAT_B8G8R8A8_UNORM or DXGI_FORMAT_B8G8R8A8_UNORM
|
||||||
|
@ -1059,6 +1061,40 @@ gst_d3d11_window_present_d2d (GstD3D11Window * self, GstStructure * stats)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_d3d11_window_do_processor (GstD3D11Window * self,
|
||||||
|
ID3D11VideoProcessorInputView * piv, ID3D11VideoProcessorOutputView * pov)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gst_d3d11_video_processor_render_unlocked (self->processor,
|
||||||
|
&self->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)
|
||||||
|
{
|
||||||
|
if (!gst_d3d11_converter_convert_unlocked (self->converter,
|
||||||
|
srv, &rtv, NULL, NULL)) {
|
||||||
|
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
|
static GstFlowReturn
|
||||||
gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer,
|
gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer,
|
||||||
GstStructure * stats, ID3D11VideoProcessorOutputView * pov,
|
GstStructure * stats, ID3D11VideoProcessorOutputView * pov,
|
||||||
|
@ -1077,19 +1113,25 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer,
|
||||||
ID3D11VideoProcessorInputView *piv = NULL;
|
ID3D11VideoProcessorInputView *piv = NULL;
|
||||||
ID3D11Device *device_handle =
|
ID3D11Device *device_handle =
|
||||||
gst_d3d11_device_get_device_handle (self->device);
|
gst_d3d11_device_get_device_handle (self->device);
|
||||||
|
gboolean can_convert = FALSE;
|
||||||
|
gboolean can_process = FALSE;
|
||||||
|
gboolean convert_ret = FALSE;
|
||||||
|
|
||||||
/* Map memory in any case so that we can upload pending stage texture */
|
/* 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)) {
|
if (!gst_d3d11_buffer_map (buffer, device_handle, infos, GST_MAP_READ)) {
|
||||||
GST_ERROR_OBJECT (self, "Couldn't map buffer");
|
GST_ERROR_OBJECT (self, "Couldn't map buffer");
|
||||||
|
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_d3d11_buffer_get_shader_resource_view (buffer, srv)) {
|
can_convert = gst_d3d11_buffer_get_shader_resource_view (buffer, srv);
|
||||||
if (!gst_d3d11_window_buffer_ensure_processor_input (self, buffer, &piv)) {
|
if (pov) {
|
||||||
GST_ERROR_OBJECT (self, "Input texture cannot be used for converter");
|
can_process = gst_d3d11_window_buffer_ensure_processor_input (self,
|
||||||
return GST_FLOW_ERROR;
|
buffer, &piv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!can_convert && !can_process) {
|
||||||
|
GST_ERROR_OBJECT (self, "Input texture cannot be used for converter");
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->first_present) {
|
if (self->first_present) {
|
||||||
|
@ -1106,26 +1148,27 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer,
|
||||||
&viewport);
|
&viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->processor && piv && pov) {
|
/* Converter preference order
|
||||||
if (!gst_d3d11_video_processor_render_unlocked (self->processor,
|
* 1) If this texture can be converted via processor, and we used processor
|
||||||
&self->input_rect, piv, &self->render_rect, pov)) {
|
* previously, use processor
|
||||||
GST_ERROR_OBJECT (self,
|
* 2) If SRV is available, use converter
|
||||||
"Couldn't render to backbuffer using processor");
|
* 3) otherwise, use processor
|
||||||
ret = GST_FLOW_ERROR;
|
*/
|
||||||
goto unmap_and_out;
|
if (can_process && self->processor_in_use) {
|
||||||
} else {
|
convert_ret = gst_d3d11_window_do_processor (self, piv, pov);
|
||||||
GST_TRACE_OBJECT (self, "Rendered using processor");
|
} else if (can_convert) {
|
||||||
}
|
convert_ret = gst_d3d11_window_do_convert (self, srv, rtv);
|
||||||
|
} else if (can_process) {
|
||||||
|
convert_ret = gst_d3d11_window_do_processor (self, piv, pov);
|
||||||
} else {
|
} else {
|
||||||
if (!gst_d3d11_converter_convert_unlocked (self->converter,
|
g_assert_not_reached ();
|
||||||
srv, &rtv, NULL, NULL)) {
|
ret = GST_FLOW_ERROR;
|
||||||
GST_ERROR_OBJECT (self,
|
goto unmap_and_out;
|
||||||
"Couldn't render to backbuffer using converter");
|
}
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
goto unmap_and_out;
|
if (!convert_ret) {
|
||||||
} else {
|
ret = GST_FLOW_ERROR;
|
||||||
GST_TRACE_OBJECT (self, "Rendered using converter");
|
goto unmap_and_out;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_d3d11_overlay_compositor_upload (self->compositor, buffer);
|
gst_d3d11_overlay_compositor_upload (self->compositor, buffer);
|
||||||
|
|
|
@ -102,6 +102,8 @@ struct _GstD3D11Window
|
||||||
GstD3D11Converter *converter;
|
GstD3D11Converter *converter;
|
||||||
GstD3D11OverlayCompositor *compositor;
|
GstD3D11OverlayCompositor *compositor;
|
||||||
|
|
||||||
|
gboolean processor_in_use;
|
||||||
|
|
||||||
/* calculated rect with aspect ratio and window area */
|
/* calculated rect with aspect ratio and window area */
|
||||||
RECT render_rect;
|
RECT render_rect;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue