d3d11colorconverter: Add support for RGB to YUV conversion

... and remove code for RGBx since it's not supported format
by our d3d11 implementation for now.
This commit is contained in:
Seungha Yang 2020-01-08 23:09:51 +09:00
parent da50cc4d92
commit a122f305f9

View file

@ -33,6 +33,8 @@
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_colorconverter_debug); GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_colorconverter_debug);
#define GST_CAT_DEFAULT gst_d3d11_colorconverter_debug #define GST_CAT_DEFAULT gst_d3d11_colorconverter_debug
#define CONVERTER_MAX_QUADS 2
/* *INDENT-OFF* */ /* *INDENT-OFF* */
typedef struct typedef struct
{ {
@ -89,17 +91,11 @@ static const PixelShaderTemplate templ_REORDER =
static const PixelShaderTemplate templ_YUV_to_RGB = static const PixelShaderTemplate templ_YUV_to_RGB =
{ COLOR_TRANSFORM_COEFF, HLSL_FUNC_YUV_TO_RGB }; { COLOR_TRANSFORM_COEFF, HLSL_FUNC_YUV_TO_RGB };
#if 0
static const PixelShaderTemplate templ_RGB_to_YUV = static const PixelShaderTemplate templ_RGB_to_YUV =
{ COLOR_TRANSFORM_COEFF, HLSL_FUNC_RGB_TO_YUV }; { COLOR_TRANSFORM_COEFF, HLSL_FUNC_RGB_TO_YUV };
#endif
static const gchar templ_REORDER_BODY[] = static const gchar templ_REORDER_BODY[] =
" float4 sample;\n" " output.Plane_0 = shaderTexture[0].Sample(samplerState, input.Texture);\n";
" sample = shaderTexture[0].Sample(samplerState, input.Texture);\n"
/* alpha channel */
" %s\n"
" return sample;\n";
static const gchar templ_VUYA_to_RGB_BODY[] = static const gchar templ_VUYA_to_RGB_BODY[] =
" float4 sample, rgba;\n" " float4 sample, rgba;\n"
@ -109,37 +105,24 @@ static const gchar templ_VUYA_to_RGB_BODY[] =
" sample.a = shaderTexture[0].Sample(samplerState, input.Texture).a;\n" " sample.a = shaderTexture[0].Sample(samplerState, input.Texture).a;\n"
" rgba.rgb = yuv_to_rgb (sample.xyz);\n" " rgba.rgb = yuv_to_rgb (sample.xyz);\n"
" rgba.a = sample.a;\n" " rgba.a = sample.a;\n"
" return rgba;\n"; " output.Plane_0 = rgba;\n";
#if 0
static const gchar templ_RGB_to_VUYA_BODY[] = static const gchar templ_RGB_to_VUYA_BODY[] =
" float4 sample, vuya;\n" " float4 sample, vuya;\n"
" sample = shaderTexture[0].Sample(samplerState, input.Texture);\n" " sample = shaderTexture[0].Sample(samplerState, input.Texture);\n"
" vuya.zyx = rgb_to_yuv (sample.rgb);\n" " vuya.zyx = rgb_to_yuv (sample.rgb);\n"
" vuya.a = %s;\n" " vuya.a = sample.a;\n"
" return vuya;\n"; " output.Plane_0 = vuya;\n";
#endif
/* YUV to RGB conversion */ /* YUV to RGB conversion */
static const gchar templ_PLANAR_YUV_to_RGB_BODY[] = static const gchar templ_PLANAR_YUV_to_RGB_BODY[] =
" float4 sample, rgba;\n"
" sample.x = shaderTexture[0].Sample(samplerState, input.Texture).x;\n"
" sample.y = shaderTexture[1].Sample(samplerState, input.Texture).x;\n"
" sample.z = shaderTexture[2].Sample(samplerState, input.Texture).x;\n"
" rgba.rgb = yuv_to_rgb (sample.xyz);\n"
" rgba.a = 1.0;\n"
" return rgba;\n";
static const gchar templ_PLANAR_YUV_HIGH_to_RGB_BODY[] =
" float4 sample, rgba;\n" " float4 sample, rgba;\n"
" sample.x = shaderTexture[0].Sample(samplerState, input.Texture).x * %d;\n" " sample.x = shaderTexture[0].Sample(samplerState, input.Texture).x * %d;\n"
" sample.y = shaderTexture[1].Sample(samplerState, input.Texture).x * %d;\n" " sample.y = shaderTexture[1].Sample(samplerState, input.Texture).x * %d;\n"
" sample.z = shaderTexture[2].Sample(samplerState, input.Texture).x * %d;\n" " sample.z = shaderTexture[2].Sample(samplerState, input.Texture).x * %d;\n"
" rgba.rgb = yuv_to_rgb (sample.xyz);\n" " rgba.rgb = yuv_to_rgb (sample.xyz);\n"
" rgba.a = 1.0;\n" " rgba.a = 1.0;\n"
" return rgba;\n"; " output.Plane_0 = rgba;\n";
/* FIXME: add RGB to planar */
static const gchar templ_SEMI_PLANAR_to_RGB_BODY[] = static const gchar templ_SEMI_PLANAR_to_RGB_BODY[] =
" float4 sample, rgba;\n" " float4 sample, rgba;\n"
@ -147,9 +130,35 @@ static const gchar templ_SEMI_PLANAR_to_RGB_BODY[] =
" sample.yz = shaderTexture[1].Sample(samplerState, input.Texture).xy;\n" " sample.yz = shaderTexture[1].Sample(samplerState, input.Texture).xy;\n"
" rgba.rgb = yuv_to_rgb (sample.xyz);\n" " rgba.rgb = yuv_to_rgb (sample.xyz);\n"
" rgba.a = 1.0;\n" " rgba.a = 1.0;\n"
" return rgba;\n"; " output.Plane_0 = rgba;\n";
/* FIXME: add RGB to semi-planar */ /* RGB to YUV conversion */
static const gchar templ_RGB_to_LUMA_BODY[] =
" float4 sample, rgba;\n"
" rgba.rgb = shaderTexture[0].Sample(samplerState, input.Texture).rgb;\n"
" sample.xyz = rgb_to_yuv (rgba.rgb);\n"
" sample.y = 0.0;\n"
" sample.z = 0.0;\n"
" sample.a = 0.0;\n"
" sample.x = sample.x / %d;\n"
" output.Plane_0 = sample;\n";
static const gchar templ_RGB_to_SEMI_PLANAR_CHROMA_BODY[] =
" float4 sample, rgba;\n"
" rgba.rgb = shaderTexture[0].Sample(samplerState, input.Texture).rgb;\n"
" sample.xyz = rgb_to_yuv (rgba.rgb);\n"
" sample.x = sample.y;\n"
" sample.y = sample.z;\n"
" sample.z = 0.0;\n"
" sample.a = 0.0;\n"
" output.Plane_0 = sample;\n";
static const gchar templ_RGB_to_PLANAR_CHROMA_BODY[] =
" float4 sample, rgba;\n"
" rgba.rgb = shaderTexture[0].Sample(samplerState, input.Texture).rgb;\n"
" sample.xyz = rgb_to_yuv (rgba.rgb);\n"
" output.Plane_0 = float4(sample.y / %d, 0.0, 0.0, 0.0);\n"
" output.Plane_1 = float4(sample.z / %d, 0.0, 0.0, 0.0);\n";
static const gchar templ_pixel_shader[] = static const gchar templ_pixel_shader[] =
/* constant buffer */ /* constant buffer */
@ -163,11 +172,19 @@ static const gchar templ_pixel_shader[] =
" float3 Texture: TEXCOORD0;\n" " float3 Texture: TEXCOORD0;\n"
"};\n" "};\n"
"\n" "\n"
"struct PS_OUTPUT\n"
"{\n"
" float4 Plane_0: SV_TARGET0;\n"
" float4 Plane_1: SV_TARGET1;\n"
"};\n"
"\n"
/* rgb <-> yuv function */ /* rgb <-> yuv function */
"%s\n" "%s\n"
"float4 main(PS_INPUT input): SV_TARGET\n" "PS_OUTPUT main(PS_INPUT input)\n"
"{\n" "{\n"
" PS_OUTPUT output;\n"
"%s" "%s"
" return output;\n"
"}\n"; "}\n";
static const gchar templ_vertex_shader[] = static const gchar templ_vertex_shader[] =
@ -193,7 +210,7 @@ static const gchar templ_vertex_shader[] =
typedef struct typedef struct
{ {
const PixelShaderTemplate *templ; const PixelShaderTemplate *templ;
gchar *ps_body; gchar *ps_body[CONVERTER_MAX_QUADS];
PixelShaderColorTransform transform; PixelShaderColorTransform transform;
} ConvertInfo; } ConvertInfo;
@ -209,9 +226,9 @@ struct _GstD3D11ColorConverter
guint num_input_view; guint num_input_view;
guint num_output_view; guint num_output_view;
GstD3D11Quad *quad; GstD3D11Quad *quad[CONVERTER_MAX_QUADS];
D3D11_VIEWPORT viewport; D3D11_VIEWPORT viewport[GST_VIDEO_MAX_PLANES];
ConvertInfo convert_info; ConvertInfo convert_info;
}; };
@ -453,19 +470,9 @@ setup_convert_info_rgb_to_rgb (GstD3D11ColorConverter * self,
const GstVideoInfo * in_info, const GstVideoInfo * out_info) const GstVideoInfo * in_info, const GstVideoInfo * out_info)
{ {
ConvertInfo *convert_info = &self->convert_info; ConvertInfo *convert_info = &self->convert_info;
GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (in_info);
#define IS_RGBX_FORMAT(f) \
((f) == GST_VIDEO_FORMAT_RGBx || \
(f) == GST_VIDEO_FORMAT_xRGB || \
(f) == GST_VIDEO_FORMAT_BGRx || \
(f) == GST_VIDEO_FORMAT_xBGR)
convert_info->templ = &templ_REORDER; convert_info->templ = &templ_REORDER;
convert_info->ps_body = g_strdup_printf (templ_REORDER_BODY, convert_info->ps_body[0] = g_strdup_printf (templ_REORDER_BODY);
IS_RGBX_FORMAT (in_format) ? "sample.a = 1.0f;" : "");
#undef IS_RGBX_FORMAT
return TRUE; return TRUE;
} }
@ -480,18 +487,19 @@ setup_convert_info_yuv_to_rgb (GstD3D11ColorConverter * self,
switch (GST_VIDEO_INFO_FORMAT (in_info)) { switch (GST_VIDEO_INFO_FORMAT (in_info)) {
case GST_VIDEO_FORMAT_VUYA: case GST_VIDEO_FORMAT_VUYA:
info->ps_body = g_strdup_printf (templ_VUYA_to_RGB_BODY); info->ps_body[0] = g_strdup_printf (templ_VUYA_to_RGB_BODY);
break; break;
case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_I420:
info->ps_body = g_strdup_printf (templ_PLANAR_YUV_to_RGB_BODY); info->ps_body[0] =
g_strdup_printf (templ_PLANAR_YUV_to_RGB_BODY, 1, 1, 1);
break; break;
case GST_VIDEO_FORMAT_I420_10LE: case GST_VIDEO_FORMAT_I420_10LE:
info->ps_body = info->ps_body[0] =
g_strdup_printf (templ_PLANAR_YUV_HIGH_to_RGB_BODY, 64, 64, 64); g_strdup_printf (templ_PLANAR_YUV_to_RGB_BODY, 64, 64, 64);
break; break;
case GST_VIDEO_FORMAT_NV12: case GST_VIDEO_FORMAT_NV12:
case GST_VIDEO_FORMAT_P010_10LE: case GST_VIDEO_FORMAT_P010_10LE:
info->ps_body = g_strdup_printf (templ_SEMI_PLANAR_to_RGB_BODY); info->ps_body[0] = g_strdup_printf (templ_SEMI_PLANAR_to_RGB_BODY);
break; break;
default: default:
GST_FIXME_OBJECT (self, GST_FIXME_OBJECT (self,
@ -507,8 +515,37 @@ static gboolean
setup_convert_info_rgb_to_yuv (GstD3D11ColorConverter * self, setup_convert_info_rgb_to_yuv (GstD3D11ColorConverter * self,
const GstVideoInfo * in_info, const GstVideoInfo * out_info) const GstVideoInfo * in_info, const GstVideoInfo * out_info)
{ {
GST_FIXME ("Implement RGB to YUV format conversion"); ConvertInfo *info = &self->convert_info;
return FALSE;
info->templ = &templ_RGB_to_YUV;
switch (GST_VIDEO_INFO_FORMAT (out_info)) {
case GST_VIDEO_FORMAT_VUYA:
info->ps_body[0] = g_strdup_printf (templ_RGB_to_VUYA_BODY);
break;
case GST_VIDEO_FORMAT_NV12:
case GST_VIDEO_FORMAT_P010_10LE:
info->ps_body[0] = g_strdup_printf (templ_RGB_to_LUMA_BODY, 1);
info->ps_body[1] = g_strdup_printf (templ_RGB_to_SEMI_PLANAR_CHROMA_BODY);
break;
case GST_VIDEO_FORMAT_I420:
info->ps_body[0] = g_strdup_printf (templ_RGB_to_LUMA_BODY, 1);
info->ps_body[1] =
g_strdup_printf (templ_RGB_to_PLANAR_CHROMA_BODY, 1, 1);
break;
case GST_VIDEO_FORMAT_I420_10LE:
info->ps_body[0] = g_strdup_printf (templ_RGB_to_LUMA_BODY, 64);
info->ps_body[1] =
g_strdup_printf (templ_RGB_to_PLANAR_CHROMA_BODY, 64, 64);
break;
default:
GST_FIXME_OBJECT (self,
"Unhandled output format %s",
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info)));
return FALSE;
}
return TRUE;
} }
static gboolean static gboolean
@ -519,19 +556,10 @@ setup_convert_info_yuv_to_yuv (GstD3D11ColorConverter * self,
return FALSE; return FALSE;
} }
typedef struct static gboolean
gst_d3d11_color_convert_setup_shader (GstD3D11ColorConverter * self,
GstD3D11Device * device, GstVideoInfo * in_info, GstVideoInfo * out_info)
{ {
GstD3D11ColorConverter *self;
GstVideoInfo *in_info;
GstVideoInfo *out_info;
gboolean ret;
} SetupShaderData;
static void
gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
SetupShaderData * data)
{
GstD3D11ColorConverter *self = data->self;
HRESULT hr; HRESULT hr;
D3D11_SAMPLER_DESC sampler_desc = { 0, }; D3D11_SAMPLER_DESC sampler_desc = { 0, };
D3D11_INPUT_ELEMENT_DESC input_desc[2] = { 0, }; D3D11_INPUT_ELEMENT_DESC input_desc[2] = { 0, };
@ -541,9 +569,8 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
WORD *indices; WORD *indices;
ID3D11Device *device_handle; ID3D11Device *device_handle;
ID3D11DeviceContext *context_handle; ID3D11DeviceContext *context_handle;
gchar *shader_code = NULL;
ConvertInfo *convert_info = &self->convert_info; ConvertInfo *convert_info = &self->convert_info;
ID3D11PixelShader *ps = NULL; ID3D11PixelShader *ps[CONVERTER_MAX_QUADS] = { NULL, NULL };
ID3D11VertexShader *vs = NULL; ID3D11VertexShader *vs = NULL;
ID3D11InputLayout *layout = NULL; ID3D11InputLayout *layout = NULL;
ID3D11SamplerState *sampler = NULL; ID3D11SamplerState *sampler = NULL;
@ -551,8 +578,8 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
ID3D11Buffer *vertex_buffer = NULL; ID3D11Buffer *vertex_buffer = NULL;
ID3D11Buffer *index_buffer = NULL; ID3D11Buffer *index_buffer = NULL;
const guint index_count = 2 * 3; const guint index_count = 2 * 3;
gboolean ret = TRUE;
data->ret = TRUE; gint i;
device_handle = gst_d3d11_device_get_device_handle (device); device_handle = gst_d3d11_device_get_device_handle (device);
context_handle = gst_d3d11_device_get_device_context_handle (device); context_handle = gst_d3d11_device_get_device_context_handle (device);
@ -569,28 +596,29 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
hr = ID3D11Device_CreateSamplerState (device_handle, &sampler_desc, &sampler); hr = ID3D11Device_CreateSamplerState (device_handle, &sampler_desc, &sampler);
if (!gst_d3d11_result (hr, device)) { if (!gst_d3d11_result (hr, device)) {
GST_ERROR ("Couldn't create sampler state, hr: 0x%x", (guint) hr); GST_ERROR ("Couldn't create sampler state, hr: 0x%x", (guint) hr);
data->ret = FALSE; ret = FALSE;
goto clear; goto clear;
} }
shader_code = g_strdup_printf (templ_pixel_shader, for (i = 0; i < CONVERTER_MAX_QUADS; i++) {
convert_info->templ->constant_buffer ? gchar *shader_code = NULL;
convert_info->templ->constant_buffer : "",
convert_info->templ->func ? convert_info->templ->func : "",
convert_info->ps_body);
GST_LOG ("Create Pixel Shader \n%s", shader_code); if (convert_info->ps_body[i]) {
shader_code = g_strdup_printf (templ_pixel_shader,
convert_info->templ->constant_buffer ?
convert_info->templ->constant_buffer : "",
convert_info->templ->func ? convert_info->templ->func : "",
convert_info->ps_body[i]);
if (!gst_d3d11_create_pixel_shader (device, shader_code, &ps)) { ret = gst_d3d11_create_pixel_shader (device, shader_code, &ps[i]);
GST_ERROR ("Couldn't create pixel shader"); g_free (shader_code);
if (!ret) {
g_free (shader_code); GST_ERROR ("Couldn't create pixel shader");
data->ret = FALSE; goto clear;
goto clear; }
}
} }
g_free (shader_code);
if (convert_info->templ->constant_buffer) { if (convert_info->templ->constant_buffer) {
D3D11_BUFFER_DESC const_buffer_desc = { 0, }; D3D11_BUFFER_DESC const_buffer_desc = { 0, };
@ -606,7 +634,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
if (!gst_d3d11_result (hr, device)) { if (!gst_d3d11_result (hr, device)) {
GST_ERROR ("Couldn't create constant buffer, hr: 0x%x", (guint) hr); GST_ERROR ("Couldn't create constant buffer, hr: 0x%x", (guint) hr);
data->ret = FALSE; ret = FALSE;
goto clear; goto clear;
} }
@ -616,8 +644,8 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
if (!gst_d3d11_result (hr, device)) { if (!gst_d3d11_result (hr, device)) {
GST_ERROR ("Couldn't map constant buffer, hr: 0x%x", (guint) hr); GST_ERROR ("Couldn't map constant buffer, hr: 0x%x", (guint) hr);
data->ret = FALSE;
gst_d3d11_device_unlock (device); gst_d3d11_device_unlock (device);
ret = FALSE;
goto clear; goto clear;
} }
@ -648,7 +676,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
if (!gst_d3d11_create_vertex_shader (device, templ_vertex_shader, if (!gst_d3d11_create_vertex_shader (device, templ_vertex_shader,
input_desc, G_N_ELEMENTS (input_desc), &vs, &layout)) { input_desc, G_N_ELEMENTS (input_desc), &vs, &layout)) {
GST_ERROR ("Couldn't vertex pixel shader"); GST_ERROR ("Couldn't vertex pixel shader");
data->ret = FALSE; ret = FALSE;
goto clear; goto clear;
} }
@ -663,7 +691,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
if (!gst_d3d11_result (hr, device)) { if (!gst_d3d11_result (hr, device)) {
GST_ERROR ("Couldn't create vertex buffer, hr: 0x%x", (guint) hr); GST_ERROR ("Couldn't create vertex buffer, hr: 0x%x", (guint) hr);
data->ret = FALSE; ret = FALSE;
goto clear; goto clear;
} }
@ -677,7 +705,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
if (!gst_d3d11_result (hr, device)) { if (!gst_d3d11_result (hr, device)) {
GST_ERROR ("Couldn't create index buffer, hr: 0x%x", (guint) hr); GST_ERROR ("Couldn't create index buffer, hr: 0x%x", (guint) hr);
data->ret = FALSE; ret = FALSE;
goto clear; goto clear;
} }
@ -687,8 +715,8 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
if (!gst_d3d11_result (hr, device)) { if (!gst_d3d11_result (hr, device)) {
GST_ERROR ("Couldn't map vertex buffer, hr: 0x%x", (guint) hr); GST_ERROR ("Couldn't map vertex buffer, hr: 0x%x", (guint) hr);
data->ret = FALSE;
gst_d3d11_device_unlock (device); gst_d3d11_device_unlock (device);
ret = FALSE;
goto clear; goto clear;
} }
@ -702,7 +730,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
ID3D11DeviceContext_Unmap (context_handle, ID3D11DeviceContext_Unmap (context_handle,
(ID3D11Resource *) vertex_buffer, 0); (ID3D11Resource *) vertex_buffer, 0);
gst_d3d11_device_unlock (device); gst_d3d11_device_unlock (device);
data->ret = FALSE; ret = FALSE;
goto clear; goto clear;
} }
@ -751,16 +779,24 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device,
(ID3D11Resource *) index_buffer, 0); (ID3D11Resource *) index_buffer, 0);
gst_d3d11_device_unlock (device); gst_d3d11_device_unlock (device);
self->quad = gst_d3d11_quad_new (device, self->quad[0] = gst_d3d11_quad_new (device,
ps, vs, layout, sampler, NULL, NULL, const_buffer, vertex_buffer, ps[0], vs, layout, sampler, NULL, NULL, const_buffer, vertex_buffer,
sizeof (VertexData), index_buffer, DXGI_FORMAT_R16_UINT, index_count); sizeof (VertexData), index_buffer, DXGI_FORMAT_R16_UINT, index_count);
self->num_input_view = GST_VIDEO_INFO_N_PLANES (data->in_info); if (ps[1]) {
self->num_output_view = GST_VIDEO_INFO_N_PLANES (data->out_info); self->quad[1] = gst_d3d11_quad_new (device,
ps[1], vs, layout, sampler, NULL, NULL, const_buffer, vertex_buffer,
sizeof (VertexData), index_buffer, DXGI_FORMAT_R16_UINT, index_count);
}
self->num_input_view = GST_VIDEO_INFO_N_PLANES (in_info);
self->num_output_view = GST_VIDEO_INFO_N_PLANES (out_info);
clear: clear:
if (ps) for (i = 0; i < CONVERTER_MAX_QUADS; i++) {
ID3D11PixelShader_Release (ps); if (ps[i])
ID3D11PixelShader_Release (ps[i]);
}
if (vs) if (vs)
ID3D11VertexShader_Release (vs); ID3D11VertexShader_Release (vs);
if (layout) if (layout)
@ -774,20 +810,21 @@ clear:
if (index_buffer) if (index_buffer)
ID3D11Buffer_Release (index_buffer); ID3D11Buffer_Release (index_buffer);
return; return ret;
} }
GstD3D11ColorConverter * GstD3D11ColorConverter *
gst_d3d11_color_converter_new (GstD3D11Device * device, gst_d3d11_color_converter_new (GstD3D11Device * device,
GstVideoInfo * in_info, GstVideoInfo * out_info) GstVideoInfo * in_info, GstVideoInfo * out_info)
{ {
SetupShaderData data;
const GstVideoInfo *unknown_info; const GstVideoInfo *unknown_info;
const GstD3D11Format *in_d3d11_format; const GstD3D11Format *in_d3d11_format;
const GstD3D11Format *out_d3d11_format; const GstD3D11Format *out_d3d11_format;
gboolean is_supported = FALSE; gboolean is_supported = FALSE;
MatrixData matrix; MatrixData matrix;
GstD3D11ColorConverter *converter = NULL; GstD3D11ColorConverter *converter = NULL;
gboolean ret;
gint i;
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
g_return_val_if_fail (in_info != NULL, NULL); g_return_val_if_fail (in_info != NULL, NULL);
@ -853,22 +890,25 @@ gst_d3d11_color_converter_new (GstD3D11Device * device,
transform->trans_matrix[11] = 0; transform->trans_matrix[11] = 0;
} }
converter->viewport.TopLeftX = 0; for (i = 0; i < GST_VIDEO_INFO_N_PLANES (out_info); i++) {
converter->viewport.TopLeftY = 0; converter->viewport[i].TopLeftX = 0;
converter->viewport.Width = GST_VIDEO_INFO_WIDTH (out_info); converter->viewport[i].TopLeftY = 0;
converter->viewport.Height = GST_VIDEO_INFO_HEIGHT (out_info); converter->viewport[i].Width = GST_VIDEO_INFO_COMP_WIDTH (out_info, i);
converter->viewport.MinDepth = 0.0f; converter->viewport[i].Height = GST_VIDEO_INFO_COMP_HEIGHT (out_info, i);
converter->viewport.MaxDepth = 1.0f; converter->viewport[i].MinDepth = 0.0f;
converter->viewport[i].MaxDepth = 1.0f;
}
data.self = converter; ret = gst_d3d11_color_convert_setup_shader (converter,
data.in_info = in_info; device, in_info, out_info);
data.out_info = out_info;
gst_d3d11_color_convert_setup_shader (device, &data);
if (!data.ret || !converter->quad) { if (!ret) {
GST_ERROR ("Couldn't setup shader"); GST_ERROR ("Couldn't setup shader");
gst_d3d11_color_converter_free (converter); gst_d3d11_color_converter_free (converter);
converter = NULL; converter = NULL;
} else {
converter->in_info = *in_info;
converter->out_info = *out_info;
} }
return converter; return converter;
@ -893,13 +933,18 @@ conversion_not_supported:
void void
gst_d3d11_color_converter_free (GstD3D11ColorConverter * converter) gst_d3d11_color_converter_free (GstD3D11ColorConverter * converter)
{ {
gint i;
g_return_if_fail (converter != NULL); g_return_if_fail (converter != NULL);
if (converter->quad) for (i = 0; i < CONVERTER_MAX_QUADS; i++) {
gst_d3d11_quad_free (converter->quad); if (converter->quad[i])
gst_d3d11_quad_free (converter->quad[i]);
g_free (converter->convert_info.ps_body[i]);
}
gst_clear_object (&converter->device); gst_clear_object (&converter->device);
g_free (converter->convert_info.ps_body);
g_free (converter); g_free (converter);
} }
@ -926,12 +971,29 @@ gst_d3d11_color_converter_convert_unlocked (GstD3D11ColorConverter * converter,
ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES], ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES],
ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES]) ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES])
{ {
gboolean ret;
g_return_val_if_fail (converter != NULL, FALSE); g_return_val_if_fail (converter != NULL, FALSE);
g_return_val_if_fail (srv != NULL, FALSE); g_return_val_if_fail (srv != NULL, FALSE);
g_return_val_if_fail (rtv != NULL, FALSE); g_return_val_if_fail (rtv != NULL, FALSE);
return gst_d3d11_draw_quad_unlocked (converter->quad, &converter->viewport, 1, ret = gst_d3d11_draw_quad_unlocked (converter->quad[0], converter->viewport,
srv, converter->num_input_view, rtv, converter->num_output_view, NULL); 1, srv, converter->num_input_view, rtv, 1, NULL);
if (!ret)
return FALSE;
if (converter->quad[1]) {
ret = gst_d3d11_draw_quad_unlocked (converter->quad[1],
&converter->viewport[1], converter->num_output_view - 1,
srv, converter->num_input_view, &rtv[1], converter->num_output_view - 1,
NULL);
if (!ret)
return FALSE;
}
return TRUE;
} }
gboolean gboolean
@ -941,10 +1003,32 @@ gst_d3d11_color_converter_update_rect (GstD3D11ColorConverter * converter,
g_return_val_if_fail (converter != NULL, FALSE); g_return_val_if_fail (converter != NULL, FALSE);
g_return_val_if_fail (rect != NULL, FALSE); g_return_val_if_fail (rect != NULL, FALSE);
converter->viewport.TopLeftX = rect->left; converter->viewport[0].TopLeftX = rect->left;
converter->viewport.TopLeftY = rect->top; converter->viewport[0].TopLeftY = rect->top;
converter->viewport.Width = rect->right - rect->left; converter->viewport[0].Width = rect->right - rect->left;
converter->viewport.Height = rect->bottom - rect->top; converter->viewport[0].Height = rect->bottom - rect->top;
switch (GST_VIDEO_INFO_FORMAT (&converter->out_info)) {
case GST_VIDEO_FORMAT_NV12:
case GST_VIDEO_FORMAT_P010_10LE:
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_I420_10LE:{
gint i;
converter->viewport[1].TopLeftX = converter->viewport[0].TopLeftX / 2;
converter->viewport[1].TopLeftY = converter->viewport[0].TopLeftY / 2;
converter->viewport[1].Width = converter->viewport[0].Width / 2;
converter->viewport[1].Height = converter->viewport[0].Height / 2;
for (i = 2; i < GST_VIDEO_INFO_N_PLANES (&converter->out_info); i++)
converter->viewport[i] = converter->viewport[1];
break;
}
default:
if (converter->num_output_view > 1)
g_assert_not_reached ();
break;
}
return TRUE; return TRUE;
} }