mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-30 04:00:37 +00:00
d3d11convert: Use single GstD3D11Converter object
... and don't use GstD3D11VideoProcessor. Now GstD3D11Converter will be able to convert using videoprocessor, and texture upload is also supported by GstD3D11Converter. All the noisy code can be removed therefore. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2697>
This commit is contained in:
parent
91a732fe90
commit
6a59dd95e8
1 changed files with 8 additions and 701 deletions
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
#include "gstd3d11convert.h"
|
#include "gstd3d11convert.h"
|
||||||
#include "gstd3d11converter.h"
|
#include "gstd3d11converter.h"
|
||||||
#include "gstd3d11videoprocessor.h"
|
|
||||||
#include "gstd3d11pluginutils.h"
|
#include "gstd3d11pluginutils.h"
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_d3d11_convert_debug);
|
GST_DEBUG_CATEGORY_STATIC (gst_d3d11_convert_debug);
|
||||||
|
@ -56,20 +55,7 @@ struct _GstD3D11BaseConvert
|
||||||
{
|
{
|
||||||
GstD3D11BaseFilter parent;
|
GstD3D11BaseFilter parent;
|
||||||
|
|
||||||
GstD3D11Format in_d3d11_format;
|
|
||||||
GstD3D11Format out_d3d11_format;
|
|
||||||
|
|
||||||
ID3D11Texture2D *in_texture[GST_VIDEO_MAX_PLANES];
|
|
||||||
ID3D11ShaderResourceView *shader_resource_view[GST_VIDEO_MAX_PLANES];
|
|
||||||
guint num_input_view;
|
|
||||||
|
|
||||||
ID3D11Texture2D *out_texture[GST_VIDEO_MAX_PLANES];
|
|
||||||
ID3D11RenderTargetView *render_target_view[GST_VIDEO_MAX_PLANES];
|
|
||||||
guint num_output_view;
|
|
||||||
|
|
||||||
GstD3D11Converter *converter;
|
GstD3D11Converter *converter;
|
||||||
GstD3D11VideoProcessor *processor;
|
|
||||||
gboolean processor_in_use;
|
|
||||||
gboolean same_caps;
|
gboolean same_caps;
|
||||||
gboolean downstream_supports_crop_meta;
|
gboolean downstream_supports_crop_meta;
|
||||||
|
|
||||||
|
@ -294,36 +280,12 @@ gst_d3d11_base_convert_init (GstD3D11BaseConvert * self)
|
||||||
self->add_borders = DEFAULT_ADD_BORDERS;
|
self->add_borders = DEFAULT_ADD_BORDERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_d3d11_base_convert_clear_shader_resource (GstD3D11BaseConvert * self)
|
|
||||||
{
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
GST_D3D11_CLEAR_COM (self->shader_resource_view[i]);
|
|
||||||
GST_D3D11_CLEAR_COM (self->render_target_view[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
self->num_input_view = 0;
|
|
||||||
self->num_output_view = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
GST_D3D11_CLEAR_COM (self->in_texture[i]);
|
|
||||||
GST_D3D11_CLEAR_COM (self->out_texture[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_clear_object (&self->converter);
|
|
||||||
g_clear_pointer (&self->processor, gst_d3d11_video_processor_free);
|
|
||||||
|
|
||||||
self->processor_in_use = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_d3d11_base_convert_dispose (GObject * object)
|
gst_d3d11_base_convert_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
GstD3D11BaseConvert *self = GST_D3D11_BASE_CONVERT (object);
|
GstD3D11BaseConvert *self = GST_D3D11_BASE_CONVERT (object);
|
||||||
|
|
||||||
gst_d3d11_base_convert_clear_shader_resource (self);
|
gst_clear_object (&self->converter);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
@ -1381,344 +1343,15 @@ gst_d3d11_base_convert_decide_allocation (GstBaseTransform * trans,
|
||||||
query);
|
query);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
create_shader_input_resource (GstD3D11BaseConvert * self,
|
|
||||||
GstD3D11Device * device, const GstD3D11Format * format, GstVideoInfo * info)
|
|
||||||
{
|
|
||||||
D3D11_TEXTURE2D_DESC texture_desc;
|
|
||||||
D3D11_SHADER_RESOURCE_VIEW_DESC view_desc;
|
|
||||||
HRESULT hr;
|
|
||||||
ID3D11Device *device_handle;
|
|
||||||
ID3D11Texture2D *tex[GST_VIDEO_MAX_PLANES] = { NULL, };
|
|
||||||
ID3D11ShaderResourceView *view[GST_VIDEO_MAX_PLANES] = { NULL, };
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
if (self->num_input_view)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
memset (&texture_desc, 0, sizeof (texture_desc));
|
|
||||||
memset (&view_desc, 0, sizeof (view_desc));
|
|
||||||
|
|
||||||
device_handle = gst_d3d11_device_get_device_handle (device);
|
|
||||||
|
|
||||||
texture_desc.MipLevels = 1;
|
|
||||||
texture_desc.ArraySize = 1;
|
|
||||||
texture_desc.SampleDesc.Count = 1;
|
|
||||||
texture_desc.SampleDesc.Quality = 0;
|
|
||||||
texture_desc.Usage = D3D11_USAGE_DEFAULT;
|
|
||||||
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
||||||
|
|
||||||
if (format->dxgi_format == DXGI_FORMAT_UNKNOWN) {
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
if (format->resource_format[i] == DXGI_FORMAT_UNKNOWN)
|
|
||||||
break;
|
|
||||||
|
|
||||||
texture_desc.Width = GST_VIDEO_INFO_COMP_WIDTH (info, i);
|
|
||||||
texture_desc.Height = GST_VIDEO_INFO_COMP_HEIGHT (info, i);
|
|
||||||
texture_desc.Format = format->resource_format[i];
|
|
||||||
|
|
||||||
hr = device_handle->CreateTexture2D (&texture_desc, NULL, &tex[i]);
|
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
|
||||||
GST_ERROR_OBJECT (self, "Failed to create texture (0x%x)", (guint) hr);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gboolean is_semiplanar = FALSE;
|
|
||||||
|
|
||||||
if (format->dxgi_format == DXGI_FORMAT_NV12 ||
|
|
||||||
format->dxgi_format == DXGI_FORMAT_P010 ||
|
|
||||||
format->dxgi_format == DXGI_FORMAT_P016)
|
|
||||||
is_semiplanar = TRUE;
|
|
||||||
|
|
||||||
texture_desc.Width = GST_VIDEO_INFO_WIDTH (info);
|
|
||||||
texture_desc.Height = GST_VIDEO_INFO_HEIGHT (info);
|
|
||||||
texture_desc.Format = format->dxgi_format;
|
|
||||||
|
|
||||||
/* semiplanar format resolution of should be even number */
|
|
||||||
if (is_semiplanar) {
|
|
||||||
texture_desc.Width = GST_ROUND_UP_2 (texture_desc.Width);
|
|
||||||
texture_desc.Height = GST_ROUND_UP_2 (texture_desc.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = device_handle->CreateTexture2D (&texture_desc, NULL, &tex[0]);
|
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
|
||||||
GST_ERROR_OBJECT (self, "Failed to create texture (0x%x)", (guint) hr);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_semiplanar) {
|
|
||||||
tex[0]->AddRef ();
|
|
||||||
tex[1] = tex[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
||||||
view_desc.Texture2D.MipLevels = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
if (format->resource_format[i] == DXGI_FORMAT_UNKNOWN)
|
|
||||||
break;
|
|
||||||
|
|
||||||
view_desc.Format = format->resource_format[i];
|
|
||||||
hr = device_handle->CreateShaderResourceView (tex[i], &view_desc, &view[i]);
|
|
||||||
|
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
|
||||||
GST_ERROR_OBJECT (self,
|
|
||||||
"Failed to create resource view (0x%x)", (guint) hr);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self->num_input_view = i;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self,
|
|
||||||
"%d shader resource view created", self->num_input_view);
|
|
||||||
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
self->in_texture[i] = tex[i];
|
|
||||||
self->shader_resource_view[i] = view[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
error:
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
GST_D3D11_CLEAR_COM (view[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
GST_D3D11_CLEAR_COM (tex[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 16.0 / 255.0 ~= 0.062745 */
|
|
||||||
static const float luma_black_level_limited = 0.062745f;
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
clear_rtv_color_rgb (GstD3D11BaseConvert * self,
|
|
||||||
ID3D11DeviceContext * context_handle, ID3D11RenderTargetView * rtv,
|
|
||||||
gboolean full_range)
|
|
||||||
{
|
|
||||||
const FLOAT clear_color_full[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
||||||
const FLOAT clear_color_limited[4] =
|
|
||||||
{ luma_black_level_limited, luma_black_level_limited,
|
|
||||||
luma_black_level_limited, 1.0f
|
|
||||||
};
|
|
||||||
const FLOAT *target;
|
|
||||||
|
|
||||||
if (full_range)
|
|
||||||
target = clear_color_full;
|
|
||||||
else
|
|
||||||
target = clear_color_limited;
|
|
||||||
|
|
||||||
context_handle->ClearRenderTargetView (rtv, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
clear_rtv_color_vuya (GstD3D11BaseConvert * self,
|
|
||||||
ID3D11DeviceContext * context_handle, ID3D11RenderTargetView * rtv,
|
|
||||||
gboolean full_range)
|
|
||||||
{
|
|
||||||
const FLOAT clear_color_full[4] = { 0.5f, 0.5f, 0.0f, 1.0f };
|
|
||||||
const FLOAT clear_color_limited[4] =
|
|
||||||
{ 0.5f, 0.5f, luma_black_level_limited, 1.0f };
|
|
||||||
const FLOAT *target;
|
|
||||||
|
|
||||||
if (full_range)
|
|
||||||
target = clear_color_full;
|
|
||||||
else
|
|
||||||
target = clear_color_limited;
|
|
||||||
|
|
||||||
context_handle->ClearRenderTargetView (rtv, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
clear_rtv_color_luma (GstD3D11BaseConvert * self,
|
|
||||||
ID3D11DeviceContext * context_handle, ID3D11RenderTargetView * rtv,
|
|
||||||
gboolean full_range)
|
|
||||||
{
|
|
||||||
const FLOAT clear_color_full[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
||||||
const FLOAT clear_color_limited[4] =
|
|
||||||
{ luma_black_level_limited, luma_black_level_limited,
|
|
||||||
luma_black_level_limited, 1.0f
|
|
||||||
};
|
|
||||||
const FLOAT *target;
|
|
||||||
|
|
||||||
if (full_range)
|
|
||||||
target = clear_color_full;
|
|
||||||
else
|
|
||||||
target = clear_color_limited;
|
|
||||||
|
|
||||||
context_handle->ClearRenderTargetView (rtv, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
clear_rtv_color_chroma (GstD3D11BaseConvert * self,
|
|
||||||
ID3D11DeviceContext * context_handle, ID3D11RenderTargetView * rtv)
|
|
||||||
{
|
|
||||||
const FLOAT clear_color[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
|
||||||
|
|
||||||
context_handle->ClearRenderTargetView (rtv, clear_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clear_rtv_color_all (GstD3D11BaseConvert * self, GstVideoInfo * info,
|
|
||||||
ID3D11DeviceContext * context_handle,
|
|
||||||
ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES])
|
|
||||||
{
|
|
||||||
gint i;
|
|
||||||
gboolean full_range = info->colorimetry.range == GST_VIDEO_COLOR_RANGE_0_255;
|
|
||||||
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
if (!rtv[i])
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (GST_VIDEO_INFO_IS_RGB (info)) {
|
|
||||||
clear_rtv_color_rgb (self, context_handle, rtv[i], full_range);
|
|
||||||
} else {
|
|
||||||
if (GST_VIDEO_INFO_N_PLANES (info) == 1) {
|
|
||||||
clear_rtv_color_vuya (self, context_handle, rtv[i], full_range);
|
|
||||||
} else {
|
|
||||||
if (i == 0)
|
|
||||||
clear_rtv_color_luma (self, context_handle, rtv[i], full_range);
|
|
||||||
else
|
|
||||||
clear_rtv_color_chroma (self, context_handle, rtv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
create_shader_output_resource (GstD3D11BaseConvert * self,
|
|
||||||
GstD3D11Device * device, const GstD3D11Format * format, GstVideoInfo * info)
|
|
||||||
{
|
|
||||||
D3D11_TEXTURE2D_DESC texture_desc;
|
|
||||||
D3D11_RENDER_TARGET_VIEW_DESC view_desc;
|
|
||||||
HRESULT hr;
|
|
||||||
ID3D11Device *device_handle;
|
|
||||||
ID3D11DeviceContext *context_handle;
|
|
||||||
ID3D11Texture2D *tex[GST_VIDEO_MAX_PLANES] = { NULL, };
|
|
||||||
ID3D11RenderTargetView *view[GST_VIDEO_MAX_PLANES] = { NULL, };
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
if (self->num_output_view)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
memset (&texture_desc, 0, sizeof (texture_desc));
|
|
||||||
memset (&view_desc, 0, sizeof (view_desc));
|
|
||||||
|
|
||||||
device_handle = gst_d3d11_device_get_device_handle (device);
|
|
||||||
context_handle = gst_d3d11_device_get_device_context_handle (device);
|
|
||||||
|
|
||||||
texture_desc.MipLevels = 1;
|
|
||||||
texture_desc.ArraySize = 1;
|
|
||||||
texture_desc.SampleDesc.Count = 1;
|
|
||||||
texture_desc.SampleDesc.Quality = 0;
|
|
||||||
texture_desc.Usage = D3D11_USAGE_DEFAULT;
|
|
||||||
texture_desc.BindFlags =
|
|
||||||
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
|
||||||
|
|
||||||
if (format->dxgi_format == DXGI_FORMAT_UNKNOWN) {
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
if (format->resource_format[i] == DXGI_FORMAT_UNKNOWN)
|
|
||||||
break;
|
|
||||||
|
|
||||||
texture_desc.Width = GST_VIDEO_INFO_COMP_WIDTH (info, i);
|
|
||||||
texture_desc.Height = GST_VIDEO_INFO_COMP_HEIGHT (info, i);
|
|
||||||
texture_desc.Format = format->resource_format[i];
|
|
||||||
|
|
||||||
hr = device_handle->CreateTexture2D (&texture_desc, NULL, &tex[i]);
|
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
|
||||||
GST_ERROR_OBJECT (self, "Failed to create texture (0x%x)", (guint) hr);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gboolean is_semiplanar = FALSE;
|
|
||||||
|
|
||||||
if (format->dxgi_format == DXGI_FORMAT_NV12 ||
|
|
||||||
format->dxgi_format == DXGI_FORMAT_P010 ||
|
|
||||||
format->dxgi_format == DXGI_FORMAT_P016)
|
|
||||||
is_semiplanar = TRUE;
|
|
||||||
|
|
||||||
texture_desc.Width = GST_VIDEO_INFO_WIDTH (info);
|
|
||||||
texture_desc.Height = GST_VIDEO_INFO_HEIGHT (info);
|
|
||||||
texture_desc.Format = format->dxgi_format;
|
|
||||||
|
|
||||||
/* semiplanar format resolution of should be even number */
|
|
||||||
if (is_semiplanar) {
|
|
||||||
texture_desc.Width = GST_ROUND_UP_2 (texture_desc.Width);
|
|
||||||
texture_desc.Height = GST_ROUND_UP_2 (texture_desc.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = device_handle->CreateTexture2D (&texture_desc, NULL, &tex[0]);
|
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
|
||||||
GST_ERROR_OBJECT (self, "Failed to create texture (0x%x)", (guint) hr);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_semiplanar) {
|
|
||||||
tex[0]->AddRef ();
|
|
||||||
tex[1] = tex[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
|
||||||
view_desc.Texture2D.MipSlice = 0;
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
if (format->resource_format[i] == DXGI_FORMAT_UNKNOWN)
|
|
||||||
break;
|
|
||||||
|
|
||||||
view_desc.Format = format->resource_format[i];
|
|
||||||
hr = device_handle->CreateRenderTargetView (tex[i], &view_desc, &view[i]);
|
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
|
||||||
GST_ERROR_OBJECT (self,
|
|
||||||
"Failed to create %dth render target view (0x%x)", i, (guint) hr);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_d3d11_device_lock (device);
|
|
||||||
clear_rtv_color_all (self, info, context_handle, view);
|
|
||||||
gst_d3d11_device_unlock (device);
|
|
||||||
|
|
||||||
self->num_output_view = i;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "%d render view created", self->num_output_view);
|
|
||||||
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
self->out_texture[i] = tex[i];
|
|
||||||
self->render_target_view[i] = view[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
error:
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
GST_D3D11_CLEAR_COM (view[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
|
||||||
GST_D3D11_CLEAR_COM (tex[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_d3d11_base_convert_set_info (GstD3D11BaseFilter * filter,
|
gst_d3d11_base_convert_set_info (GstD3D11BaseFilter * filter,
|
||||||
GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
|
GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
|
||||||
GstVideoInfo * out_info)
|
GstVideoInfo * out_info)
|
||||||
{
|
{
|
||||||
GstD3D11BaseConvert *self = GST_D3D11_BASE_CONVERT (filter);
|
GstD3D11BaseConvert *self = GST_D3D11_BASE_CONVERT (filter);
|
||||||
const GstVideoInfo *unknown_info;
|
|
||||||
gint from_dar_n, from_dar_d, to_dar_n, to_dar_d;
|
gint from_dar_n, from_dar_d, to_dar_n, to_dar_d;
|
||||||
gint border_offset_x = 0;
|
gint border_offset_x = 0;
|
||||||
gint border_offset_y = 0;
|
gint border_offset_y = 0;
|
||||||
GstD3D11ConverterMethod method = GST_D3D11_CONVERTER_METHOD_SHADER;
|
|
||||||
|
|
||||||
if (gst_caps_is_equal (incaps, outcaps)) {
|
if (gst_caps_is_equal (incaps, outcaps)) {
|
||||||
self->same_caps = TRUE;
|
self->same_caps = TRUE;
|
||||||
|
@ -1766,7 +1399,7 @@ gst_d3d11_base_convert_set_info (GstD3D11BaseFilter * filter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_d3d11_base_convert_clear_shader_resource (self);
|
gst_clear_object (&self->converter);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Setup convert with format %s -> %s",
|
GST_DEBUG_OBJECT (self, "Setup convert with format %s -> %s",
|
||||||
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)),
|
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)),
|
||||||
|
@ -1785,75 +1418,13 @@ gst_d3d11_base_convert_set_info (GstD3D11BaseFilter * filter,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_d3d11_device_get_format (filter->device,
|
|
||||||
GST_VIDEO_INFO_FORMAT (in_info), &self->in_d3d11_format)) {
|
|
||||||
unknown_info = in_info;
|
|
||||||
goto format_unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_d3d11_device_get_format (filter->device,
|
|
||||||
GST_VIDEO_INFO_FORMAT (out_info), &self->out_d3d11_format)) {
|
|
||||||
unknown_info = out_info;
|
|
||||||
goto format_unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->converter = gst_d3d11_converter_new (filter->device, in_info, out_info,
|
self->converter = gst_d3d11_converter_new (filter->device, in_info, out_info,
|
||||||
&method);
|
nullptr);
|
||||||
if (!self->converter) {
|
if (!self->converter) {
|
||||||
GST_ERROR_OBJECT (self, "couldn't set converter");
|
GST_ERROR_OBJECT (self, "Couldn't create converter");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If both input and output formats are native DXGI format */
|
|
||||||
if (self->in_d3d11_format.dxgi_format != DXGI_FORMAT_UNKNOWN &&
|
|
||||||
self->out_d3d11_format.dxgi_format != DXGI_FORMAT_UNKNOWN) {
|
|
||||||
gboolean hardware = FALSE;
|
|
||||||
GstD3D11VideoProcessor *processor = NULL;
|
|
||||||
|
|
||||||
gst_d3d11_device_lock (filter->device);
|
|
||||||
g_object_get (filter->device, "hardware", &hardware, NULL);
|
|
||||||
if (hardware) {
|
|
||||||
processor = gst_d3d11_video_processor_new (filter->device,
|
|
||||||
in_info->width, in_info->height, out_info->width, out_info->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (processor) {
|
|
||||||
GstDxgiColorSpace in_space, out_space;
|
|
||||||
|
|
||||||
if (gst_d3d11_video_info_to_dxgi_color_space (in_info, &in_space) &&
|
|
||||||
gst_d3d11_video_info_to_dxgi_color_space (out_info, &out_space)) {
|
|
||||||
DXGI_FORMAT in_dxgi_format = self->in_d3d11_format.dxgi_format;
|
|
||||||
DXGI_FORMAT out_dxgi_format = self->out_d3d11_format.dxgi_format;
|
|
||||||
DXGI_COLOR_SPACE_TYPE in_dxgi_color_space =
|
|
||||||
(DXGI_COLOR_SPACE_TYPE) in_space.dxgi_color_space_type;
|
|
||||||
DXGI_COLOR_SPACE_TYPE out_dxgi_color_space =
|
|
||||||
(DXGI_COLOR_SPACE_TYPE) out_space.dxgi_color_space_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 (self, "Conversion is not supported by device");
|
|
||||||
gst_d3d11_video_processor_free (processor);
|
|
||||||
processor = NULL;
|
|
||||||
} else {
|
|
||||||
GST_DEBUG_OBJECT (self, "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);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
GST_WARNING_OBJECT (self,
|
|
||||||
"Couldn't determine input and/or output dxgi colorspace");
|
|
||||||
gst_d3d11_video_processor_free (processor);
|
|
||||||
processor = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self->processor = processor;
|
|
||||||
gst_d3d11_device_unlock (filter->device);
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "from=%dx%d (par=%d/%d dar=%d/%d), size %"
|
GST_DEBUG_OBJECT (self, "from=%dx%d (par=%d/%d dar=%d/%d), size %"
|
||||||
G_GSIZE_FORMAT " -> to=%dx%d (par=%d/%d dar=%d/%d borders=%d:%d), "
|
G_GSIZE_FORMAT " -> to=%dx%d (par=%d/%d dar=%d/%d borders=%d:%d), "
|
||||||
"size %" G_GSIZE_FORMAT,
|
"size %" G_GSIZE_FORMAT,
|
||||||
|
@ -1903,117 +1474,6 @@ format_mismatch:
|
||||||
GST_ERROR_OBJECT (self, "input and output formats do not match");
|
GST_ERROR_OBJECT (self, "input and output formats do not match");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
format_unknown:
|
|
||||||
{
|
|
||||||
GST_ERROR_OBJECT (self,
|
|
||||||
"%s couldn't be converted to d3d11 format",
|
|
||||||
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (unknown_info)));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_d3d11_base_convert_prefer_video_processor (GstD3D11BaseConvert * self,
|
|
||||||
GstBuffer * inbuf, GstBuffer * outbuf)
|
|
||||||
{
|
|
||||||
GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (self);
|
|
||||||
GstMemory *mem;
|
|
||||||
GstD3D11Memory *dmem;
|
|
||||||
|
|
||||||
if (!self->processor) {
|
|
||||||
GST_TRACE_OBJECT (self, "Processor is unavailable");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gst_buffer_n_memory (inbuf) != 1 || gst_buffer_n_memory (outbuf) != 1) {
|
|
||||||
GST_TRACE_OBJECT (self, "Num memory objects is mismatched, in: %d, out: %d",
|
|
||||||
gst_buffer_n_memory (inbuf), gst_buffer_n_memory (outbuf));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
mem = gst_buffer_peek_memory (inbuf, 0);
|
|
||||||
g_assert (gst_is_d3d11_memory (mem));
|
|
||||||
|
|
||||||
dmem = (GstD3D11Memory *) mem;
|
|
||||||
if (dmem->device != filter->device) {
|
|
||||||
GST_TRACE_OBJECT (self, "Input memory belongs to different device");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we can use shader, and video processor was not used previously,
|
|
||||||
* we prefer to use shader instead of video processor
|
|
||||||
* because video processor implementation is vendor dependent
|
|
||||||
* and not flexible */
|
|
||||||
if (!self->processor_in_use &&
|
|
||||||
gst_d3d11_memory_get_shader_resource_view_size (dmem)) {
|
|
||||||
GST_TRACE_OBJECT (self, "SRV is available");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_d3d11_video_processor_get_input_view (self->processor, dmem)) {
|
|
||||||
GST_TRACE_OBJECT (self, "PIV is unavailable");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
mem = gst_buffer_peek_memory (outbuf, 0);
|
|
||||||
g_assert (gst_is_d3d11_memory (mem));
|
|
||||||
|
|
||||||
dmem = (GstD3D11Memory *) mem;
|
|
||||||
if (dmem->device != filter->device) {
|
|
||||||
GST_TRACE_OBJECT (self, "Output memory belongs to different device");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_d3d11_video_processor_get_output_view (self->processor, dmem)) {
|
|
||||||
GST_TRACE_OBJECT (self, "POV is unavailable");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_d3d11_base_convert_transform_using_processor (GstD3D11BaseConvert * self,
|
|
||||||
GstBuffer * inbuf, GstBuffer * outbuf, RECT * in_rect)
|
|
||||||
{
|
|
||||||
GstD3D11Memory *in_mem, *out_mem;
|
|
||||||
ID3D11VideoProcessorInputView *piv;
|
|
||||||
ID3D11VideoProcessorOutputView *pov;
|
|
||||||
|
|
||||||
in_mem = (GstD3D11Memory *) gst_buffer_peek_memory (inbuf, 0);
|
|
||||||
out_mem = (GstD3D11Memory *) gst_buffer_peek_memory (outbuf, 0);
|
|
||||||
|
|
||||||
piv = gst_d3d11_video_processor_get_input_view (self->processor, in_mem);
|
|
||||||
if (!piv) {
|
|
||||||
GST_ERROR_OBJECT (self, "ID3D11VideoProcessorInputView is unavailable");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pov = gst_d3d11_video_processor_get_output_view (self->processor, out_mem);
|
|
||||||
if (!pov) {
|
|
||||||
GST_ERROR_OBJECT (self, "ID3D11VideoProcessorOutputView is unavailable");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear background color with black */
|
|
||||||
if (self->borders_w || self->borders_h) {
|
|
||||||
GstD3D11BaseFilter *bfilter = GST_D3D11_BASE_FILTER_CAST (self);
|
|
||||||
ID3D11DeviceContext *context_handle =
|
|
||||||
gst_d3d11_device_get_device_context_handle (bfilter->device);
|
|
||||||
ID3D11RenderTargetView *render_view[GST_VIDEO_MAX_PLANES] = { NULL, };
|
|
||||||
|
|
||||||
if (!gst_d3d11_buffer_get_render_target_view (outbuf, render_view)) {
|
|
||||||
GST_ERROR_OBJECT (self, "ID3D11RenderTargetView is unavailable");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_d3d11_device_lock (bfilter->device);
|
|
||||||
clear_rtv_color_all (self, &bfilter->out_info, context_handle, render_view);
|
|
||||||
gst_d3d11_device_unlock (bfilter->device);
|
|
||||||
}
|
|
||||||
|
|
||||||
return gst_d3d11_video_processor_render (self->processor,
|
|
||||||
in_rect, piv, &self->out_rect, pov);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -2275,36 +1735,10 @@ static GstFlowReturn
|
||||||
gst_d3d11_base_convert_transform (GstBaseTransform * trans,
|
gst_d3d11_base_convert_transform (GstBaseTransform * trans,
|
||||||
GstBuffer * inbuf, GstBuffer * outbuf)
|
GstBuffer * inbuf, GstBuffer * outbuf)
|
||||||
{
|
{
|
||||||
GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans);
|
|
||||||
GstD3D11BaseConvert *self = GST_D3D11_BASE_CONVERT (trans);
|
GstD3D11BaseConvert *self = GST_D3D11_BASE_CONVERT (trans);
|
||||||
GstD3D11Device *device = filter->device;
|
|
||||||
ID3D11Device *device_handle;
|
|
||||||
ID3D11DeviceContext *context_handle;
|
|
||||||
ID3D11ShaderResourceView *resource_view[GST_VIDEO_MAX_PLANES] = { NULL, };
|
|
||||||
ID3D11RenderTargetView *render_view[GST_VIDEO_MAX_PLANES] = { NULL, };
|
|
||||||
ID3D11RenderTargetView **target_rtv;
|
|
||||||
guint i;
|
|
||||||
gboolean copy_input = FALSE;
|
|
||||||
gboolean copy_output = FALSE;
|
|
||||||
GstMapInfo in_map[GST_VIDEO_MAX_PLANES];
|
|
||||||
GstMapInfo out_map[GST_VIDEO_MAX_PLANES];
|
|
||||||
RECT in_rect;
|
RECT in_rect;
|
||||||
GstVideoCropMeta *crop_meta;
|
GstVideoCropMeta *crop_meta;
|
||||||
|
|
||||||
device_handle = gst_d3d11_device_get_device_handle (device);
|
|
||||||
context_handle = gst_d3d11_device_get_device_context_handle (device);
|
|
||||||
|
|
||||||
if (!gst_d3d11_buffer_map (inbuf, device_handle, in_map, GST_MAP_READ)) {
|
|
||||||
GST_ERROR_OBJECT (self, "Couldn't map input buffer");
|
|
||||||
goto invalid_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_d3d11_buffer_map (outbuf, device_handle, out_map, GST_MAP_WRITE)) {
|
|
||||||
GST_ERROR_OBJECT (self, "Couldn't map output buffer");
|
|
||||||
gst_d3d11_buffer_unmap (inbuf, in_map);
|
|
||||||
goto invalid_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
crop_meta = gst_buffer_get_video_crop_meta (inbuf);
|
crop_meta = gst_buffer_get_video_crop_meta (inbuf);
|
||||||
if (crop_meta) {
|
if (crop_meta) {
|
||||||
GST_TRACE_OBJECT (self, "Have crop rect, x:y:w:h = %d:%d:%d:%d",
|
GST_TRACE_OBJECT (self, "Have crop rect, x:y:w:h = %d:%d:%d:%d",
|
||||||
|
@ -2329,140 +1763,13 @@ gst_d3d11_base_convert_transform (GstBaseTransform * trans,
|
||||||
"src-height", (gint) in_rect.bottom - in_rect.top, nullptr);
|
"src-height", (gint) in_rect.bottom - in_rect.top, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_d3d11_base_convert_prefer_video_processor (self, inbuf, outbuf)) {
|
if (!gst_d3d11_converter_convert_buffer (self->converter, inbuf, outbuf)) {
|
||||||
gboolean ret = gst_d3d11_base_convert_transform_using_processor (self,
|
GST_ELEMENT_ERROR (self, CORE, FAILED, (nullptr),
|
||||||
inbuf, outbuf, &in_rect);
|
("Couldn't convert texture"));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
if (!ret) {
|
|
||||||
GST_ERROR_OBJECT (self, "Couldn't convert using video processor");
|
|
||||||
goto conversion_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->processor_in_use = TRUE;
|
|
||||||
|
|
||||||
GST_TRACE_OBJECT (self, "Conversion done by video processor");
|
|
||||||
|
|
||||||
gst_d3d11_buffer_unmap (inbuf, in_map);
|
|
||||||
gst_d3d11_buffer_unmap (outbuf, out_map);
|
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure shader resource views */
|
|
||||||
if (!gst_d3d11_buffer_get_shader_resource_view (inbuf, resource_view)) {
|
|
||||||
if (!create_shader_input_resource (self, device,
|
|
||||||
&self->in_d3d11_format, &filter->in_info)) {
|
|
||||||
GST_ERROR_OBJECT (self, "Failed to configure fallback input texture");
|
|
||||||
goto fallback_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_input = TRUE;
|
|
||||||
gst_d3d11_device_lock (device);
|
|
||||||
for (i = 0; i < gst_buffer_n_memory (inbuf); i++) {
|
|
||||||
GstD3D11Memory *mem =
|
|
||||||
(GstD3D11Memory *) gst_buffer_peek_memory (inbuf, i);
|
|
||||||
guint subidx;
|
|
||||||
D3D11_BOX src_box = { 0, };
|
|
||||||
D3D11_TEXTURE2D_DESC src_desc;
|
|
||||||
D3D11_TEXTURE2D_DESC dst_desc;
|
|
||||||
|
|
||||||
subidx = gst_d3d11_memory_get_subresource_index (mem);
|
|
||||||
gst_d3d11_memory_get_texture_desc (mem, &src_desc);
|
|
||||||
|
|
||||||
self->in_texture[i]->GetDesc (&dst_desc);
|
|
||||||
|
|
||||||
src_box.left = 0;
|
|
||||||
src_box.top = 0;
|
|
||||||
src_box.front = 0;
|
|
||||||
src_box.back = 1;
|
|
||||||
src_box.right = MIN (src_desc.Width, dst_desc.Width);
|
|
||||||
src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
|
|
||||||
|
|
||||||
context_handle->CopySubresourceRegion (self->in_texture[i], 0, 0, 0, 0,
|
|
||||||
(ID3D11Resource *) in_map[i].data, subidx, &src_box);
|
|
||||||
}
|
|
||||||
gst_d3d11_device_unlock (device);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure render target views */
|
|
||||||
if (!gst_d3d11_buffer_get_render_target_view (outbuf, render_view)) {
|
|
||||||
if (!create_shader_output_resource (self, device,
|
|
||||||
&self->out_d3d11_format, &filter->out_info)) {
|
|
||||||
GST_ERROR_OBJECT (self, "Failed to configure fallback output texture");
|
|
||||||
goto fallback_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_output = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we need border, clear render target view first */
|
|
||||||
if (copy_output) {
|
|
||||||
target_rtv = self->render_target_view;
|
|
||||||
} else {
|
|
||||||
target_rtv = render_view;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_d3d11_converter_convert (self->converter,
|
|
||||||
copy_input ? self->shader_resource_view : resource_view,
|
|
||||||
target_rtv)) {
|
|
||||||
goto conversion_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_output) {
|
|
||||||
gst_d3d11_device_lock (device);
|
|
||||||
for (i = 0; i < gst_buffer_n_memory (outbuf); i++) {
|
|
||||||
GstD3D11Memory *mem =
|
|
||||||
(GstD3D11Memory *) gst_buffer_peek_memory (outbuf, i);
|
|
||||||
guint subidx;
|
|
||||||
D3D11_BOX src_box = { 0, };
|
|
||||||
D3D11_TEXTURE2D_DESC src_desc;
|
|
||||||
D3D11_TEXTURE2D_DESC dst_desc;
|
|
||||||
|
|
||||||
self->out_texture[i]->GetDesc (&src_desc);
|
|
||||||
subidx = gst_d3d11_memory_get_subresource_index (mem);
|
|
||||||
gst_d3d11_memory_get_texture_desc (mem, &dst_desc);
|
|
||||||
|
|
||||||
src_box.left = 0;
|
|
||||||
src_box.top = 0;
|
|
||||||
src_box.front = 0;
|
|
||||||
src_box.back = 1;
|
|
||||||
src_box.right = MIN (src_desc.Width, dst_desc.Width);
|
|
||||||
src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
|
|
||||||
|
|
||||||
context_handle->CopySubresourceRegion ((ID3D11Resource *) out_map[i].data,
|
|
||||||
subidx, 0, 0, 0, self->out_texture[i], 0, &src_box);
|
|
||||||
}
|
|
||||||
gst_d3d11_device_unlock (device);
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_d3d11_buffer_unmap (inbuf, in_map);
|
|
||||||
gst_d3d11_buffer_unmap (outbuf, out_map);
|
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
invalid_memory:
|
|
||||||
{
|
|
||||||
GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL), ("Invalid memory"));
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
fallback_failed:
|
|
||||||
{
|
|
||||||
GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL),
|
|
||||||
("Couldn't prepare fallback memory"));
|
|
||||||
gst_d3d11_buffer_unmap (inbuf, in_map);
|
|
||||||
gst_d3d11_buffer_unmap (outbuf, out_map);
|
|
||||||
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
conversion_failed:
|
|
||||||
{
|
|
||||||
GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL),
|
|
||||||
("Couldn't convert texture"));
|
|
||||||
gst_d3d11_buffer_unmap (inbuf, in_map);
|
|
||||||
gst_d3d11_buffer_unmap (outbuf, out_map);
|
|
||||||
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue