d3d11converter: Port to converter helper

... add support YUY2 and Y410 output

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5691>
This commit is contained in:
Seungha Yang 2023-11-18 20:45:57 +09:00
parent c57fe82a93
commit 2afa0fe7d0

View file

@ -33,6 +33,7 @@
#include "gstd3d11compile.h" #include "gstd3d11compile.h"
#include "gstd3d11bufferpool.h" #include "gstd3d11bufferpool.h"
#include "gstd3d11converter-builder.h" #include "gstd3d11converter-builder.h"
#include "gstd3d11converter-helper.h"
#include <wrl.h> #include <wrl.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
@ -272,11 +273,14 @@ struct _GstD3D11ConverterPrivate
g_free (in_cll_str); g_free (in_cll_str);
g_free (out_cll_str); g_free (out_cll_str);
if (unpack_convert) if (preproc)
gst_video_converter_free (unpack_convert); gst_d3d11_converter_helper_free (preproc);
if (postproc)
gst_d3d11_converter_helper_free (postproc);
gst_clear_buffer (&postproc_buf);
gst_clear_buffer (&piv_inbuf); gst_clear_buffer (&piv_inbuf);
gst_clear_buffer (&fallback_inbuf);
} }
GstVideoInfo in_info; GstVideoInfo in_info;
@ -326,7 +330,15 @@ struct _GstD3D11ConverterPrivate
FLOAT clear_color[4][4]; FLOAT clear_color[4][4];
GstD3D11ColorMatrix clear_color_matrix; GstD3D11ColorMatrix clear_color_matrix;
GstVideoConverter *unpack_convert = nullptr; GstVideoInfo preproc_info;
gboolean need_preproc = FALSE;
GstVideoInfo postproc_info;
gboolean need_postproc = FALSE;
GstD3D11ConverterHelper *preproc = nullptr;
GstD3D11ConverterHelper *postproc = nullptr;
GstBuffer *postproc_buf = nullptr;
/* video processor */ /* video processor */
D3D11_VIDEO_COLOR background_color; D3D11_VIDEO_COLOR background_color;
@ -360,10 +372,6 @@ struct _GstD3D11ConverterPrivate
gchar *in_cll_str = nullptr; gchar *in_cll_str = nullptr;
gchar *out_cll_str = nullptr; gchar *out_cll_str = nullptr;
/* Fallback buffer and info, for shader */
GstVideoInfo fallback_info;
GstBuffer *fallback_inbuf = nullptr;
/* Fallback buffer used for processor */ /* Fallback buffer used for processor */
GstVideoInfo piv_info; GstVideoInfo piv_info;
GstBuffer *piv_inbuf = nullptr; GstBuffer *piv_inbuf = nullptr;
@ -1244,7 +1252,7 @@ gst_d3d11_converter_update_dest_rect (GstD3D11Converter * self)
gst_d3d11_converter_update_clear_background (self); gst_d3d11_converter_update_clear_background (self);
switch (GST_VIDEO_INFO_FORMAT (&priv->out_info)) { switch (GST_VIDEO_INFO_FORMAT (&priv->postproc_info)) {
case GST_VIDEO_FORMAT_NV12: case GST_VIDEO_FORMAT_NV12:
case GST_VIDEO_FORMAT_NV21: case GST_VIDEO_FORMAT_NV21:
case GST_VIDEO_FORMAT_P010_10LE: case GST_VIDEO_FORMAT_P010_10LE:
@ -1259,7 +1267,7 @@ gst_d3d11_converter_update_dest_rect (GstD3D11Converter * self)
priv->viewport[1].Width = priv->viewport[0].Width / 2; priv->viewport[1].Width = priv->viewport[0].Width / 2;
priv->viewport[1].Height = priv->viewport[0].Height / 2; priv->viewport[1].Height = priv->viewport[0].Height / 2;
for (guint i = 2; i < GST_VIDEO_INFO_N_PLANES (&priv->out_info); i++) for (guint i = 2; i < GST_VIDEO_INFO_N_PLANES (&priv->postproc_info); i++)
priv->viewport[i] = priv->viewport[1]; priv->viewport[i] = priv->viewport[1];
break; break;
@ -1271,7 +1279,7 @@ gst_d3d11_converter_update_dest_rect (GstD3D11Converter * self)
priv->viewport[1].Width = priv->viewport[0].Width / 2; priv->viewport[1].Width = priv->viewport[0].Width / 2;
priv->viewport[1].Height = priv->viewport[0].Height; priv->viewport[1].Height = priv->viewport[0].Height;
for (guint i = 2; i < GST_VIDEO_INFO_N_PLANES (&priv->out_info); i++) for (guint i = 2; i < GST_VIDEO_INFO_N_PLANES (&priv->postproc_info); i++)
priv->viewport[i] = priv->viewport[1]; priv->viewport[i] = priv->viewport[1];
break; break;
case GST_VIDEO_FORMAT_Y444: case GST_VIDEO_FORMAT_Y444:
@ -1287,7 +1295,7 @@ gst_d3d11_converter_update_dest_rect (GstD3D11Converter * self)
case GST_VIDEO_FORMAT_GBRA: case GST_VIDEO_FORMAT_GBRA:
case GST_VIDEO_FORMAT_GBRA_10LE: case GST_VIDEO_FORMAT_GBRA_10LE:
case GST_VIDEO_FORMAT_GBRA_12LE: case GST_VIDEO_FORMAT_GBRA_12LE:
for (guint i = 1; i < GST_VIDEO_INFO_N_PLANES (&priv->out_info); i++) for (guint i = 1; i < GST_VIDEO_INFO_N_PLANES (&priv->postproc_info); i++)
priv->viewport[i] = priv->viewport[0]; priv->viewport[i] = priv->viewport[0];
break; break;
default: default:
@ -1591,7 +1599,7 @@ gst_d3d11_converter_calculate_border_color (GstD3D11Converter * self)
{ {
GstD3D11ConverterPrivate *priv = self->priv; GstD3D11ConverterPrivate *priv = self->priv;
GstD3D11ColorMatrix *m = &priv->clear_color_matrix; GstD3D11ColorMatrix *m = &priv->clear_color_matrix;
const GstVideoInfo *out_info = &priv->out_info; const GstVideoInfo *out_info = &priv->postproc_info;
gdouble a; gdouble a;
gdouble rgb[3]; gdouble rgb[3];
gdouble converted[3]; gdouble converted[3];
@ -2010,9 +2018,10 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
self->device = (GstD3D11Device *) gst_object_ref (device); self->device = (GstD3D11Device *) gst_object_ref (device);
priv->const_data.alpha = 1.0; priv->const_data.alpha = 1.0;
priv->in_info = *in_info; priv->in_info = *in_info;
priv->fallback_info = *in_info; priv->preproc_info = *in_info;
priv->piv_info = *in_info; priv->piv_info = *in_info;
priv->out_info = *out_info; priv->out_info = *out_info;
priv->postproc_info = *out_info;
priv->in_d3d11_format = in_d3d11_format; priv->in_d3d11_format = in_d3d11_format;
priv->out_d3d11_format = out_d3d11_format; priv->out_d3d11_format = out_d3d11_format;
@ -2027,18 +2036,58 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
priv->blend_sample_mask = 0xffffffff; priv->blend_sample_mask = 0xffffffff;
priv->border_color = 0xffff000000000000; priv->border_color = 0xffff000000000000;
if (GST_VIDEO_INFO_IS_RGB (out_info)) { /* Preprocess packed and subsampled texture */
GstVideoInfo rgb_info = *out_info; if (GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_FORMAT_YUY2) {
GstVideoInfo tmp_info;
gst_video_info_set_interlaced_format (&tmp_info, GST_VIDEO_FORMAT_VUYA,
GST_VIDEO_INFO_INTERLACE_MODE (in_info),
GST_VIDEO_INFO_WIDTH (in_info), GST_VIDEO_INFO_HEIGHT (in_info));
tmp_info.chroma_site = in_info->chroma_site;
tmp_info.colorimetry = in_info->colorimetry;
tmp_info.fps_n = in_info->fps_n;
tmp_info.fps_d = in_info->fps_d;
tmp_info.par_n = in_info->par_n;
tmp_info.par_d = in_info->par_d;
priv->preproc_info = tmp_info;
priv->need_preproc = TRUE;
}
if (GST_VIDEO_INFO_FORMAT (out_info) == GST_VIDEO_FORMAT_YUY2 ||
GST_VIDEO_INFO_FORMAT (out_info) == GST_VIDEO_FORMAT_Y410) {
GstVideoInfo tmp_info;
GstVideoFormat postproc_format = GST_VIDEO_FORMAT_VUYA;
if (GST_VIDEO_INFO_FORMAT (out_info) == GST_VIDEO_FORMAT_Y410)
postproc_format = GST_VIDEO_FORMAT_AYUV64;
gst_video_info_set_interlaced_format (&tmp_info, postproc_format,
GST_VIDEO_INFO_INTERLACE_MODE (out_info),
GST_VIDEO_INFO_WIDTH (out_info), GST_VIDEO_INFO_HEIGHT (out_info));
tmp_info.chroma_site = out_info->chroma_site;
tmp_info.colorimetry = out_info->colorimetry;
tmp_info.fps_n = out_info->fps_n;
tmp_info.fps_d = out_info->fps_d;
tmp_info.par_n = out_info->par_n;
tmp_info.par_d = out_info->par_d;
priv->postproc_info = tmp_info;
priv->need_postproc = TRUE;
}
if (GST_VIDEO_INFO_IS_RGB (&priv->postproc_info)) {
GstVideoInfo rgb_info = priv->postproc_info;
rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
gst_d3d11_color_range_adjust_matrix_unorm (&rgb_info, out_info, gst_d3d11_color_range_adjust_matrix_unorm (&rgb_info, &priv->postproc_info,
&priv->clear_color_matrix); &priv->clear_color_matrix);
} else { } else {
GstVideoInfo rgb_info; GstVideoInfo rgb_info;
GstVideoInfo yuv_info; GstVideoInfo yuv_info;
gst_video_info_set_format (&rgb_info, GST_VIDEO_FORMAT_RGBA64_LE, gst_video_info_set_format (&rgb_info, GST_VIDEO_FORMAT_RGBA64_LE,
out_info->width, out_info->height); priv->postproc_info.width, priv->postproc_info.height);
convert_info_gray_to_yuv (out_info, &yuv_info); convert_info_gray_to_yuv (&priv->postproc_info, &yuv_info);
if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN ||
yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) {
@ -2093,52 +2142,27 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
priv->convert_type = CONVERT_TYPE::PRIMARY; priv->convert_type = CONVERT_TYPE::PRIMARY;
} }
/* XXX: hard to make sampling of packed 4:2:2 format, use software
* converter to convert YUV2 to Y42B */
if (GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_FORMAT_YUY2) {
GstVideoInfo tmp_info;
gst_video_info_set_interlaced_format (&tmp_info, GST_VIDEO_FORMAT_Y42B,
GST_VIDEO_INFO_INTERLACE_MODE (in_info),
GST_VIDEO_INFO_WIDTH (in_info), GST_VIDEO_INFO_HEIGHT (in_info));
tmp_info.chroma_site = in_info->chroma_site;
tmp_info.colorimetry = in_info->colorimetry;
tmp_info.fps_n = in_info->fps_n;
tmp_info.fps_d = in_info->fps_d;
tmp_info.par_n = in_info->par_n;
tmp_info.par_d = in_info->par_d;
priv->unpack_convert =
gst_video_converter_new (in_info, &tmp_info, nullptr);
if (!priv->unpack_convert) {
GST_ERROR_OBJECT (self, "Couldn't create unpack convert");
goto out;
}
priv->fallback_info = tmp_info;
in_info = &priv->fallback_info;
}
if ((priv->convert_type == CONVERT_TYPE::GAMMA || if ((priv->convert_type == CONVERT_TYPE::GAMMA ||
priv->convert_type == CONVERT_TYPE::PRIMARY)) { priv->convert_type == CONVERT_TYPE::PRIMARY)) {
if (!gst_d3d11_converter_setup_lut (self, in_info, out_info)) if (!gst_d3d11_converter_setup_lut (self, &priv->preproc_info,
&priv->postproc_info))
goto out; goto out;
} }
if (GST_VIDEO_INFO_IS_RGB (in_info)) { if (GST_VIDEO_INFO_IS_RGB (&priv->preproc_info)) {
matrix_in_info = *in_info; matrix_in_info = priv->preproc_info;
} else { } else {
convert_info_gray_to_yuv (in_info, &matrix_in_info); convert_info_gray_to_yuv (&priv->preproc_info, &matrix_in_info);
if (matrix_in_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || if (matrix_in_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN ||
matrix_in_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { matrix_in_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) {
matrix_in_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; matrix_in_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
} }
} }
if (GST_VIDEO_INFO_IS_RGB (out_info)) { if (GST_VIDEO_INFO_IS_RGB (&priv->postproc_info)) {
matrix_out_info = *out_info; matrix_out_info = priv->postproc_info;
} else { } else {
convert_info_gray_to_yuv (out_info, &matrix_out_info); convert_info_gray_to_yuv (&priv->postproc_info, &matrix_out_info);
if (matrix_out_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || if (matrix_out_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN ||
matrix_out_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { matrix_out_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) {
matrix_out_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; matrix_out_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
@ -2150,11 +2174,20 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
goto out; goto out;
} }
if (!gst_d3d11_color_convert_setup_shader (self, in_info, out_info, if (!gst_d3d11_color_convert_setup_shader (self, &priv->preproc_info,
sampler_filter)) { &priv->postproc_info, sampler_filter)) {
goto out; goto out;
} }
priv->preproc = gst_d3d11_converter_helper_new (self->device,
GST_VIDEO_INFO_FORMAT (in_info),
GST_VIDEO_INFO_FORMAT (&priv->preproc_info), in_info->width,
in_info->height);
priv->postproc = gst_d3d11_converter_helper_new (self->device,
GST_VIDEO_INFO_FORMAT (&priv->postproc_info),
GST_VIDEO_INFO_FORMAT (out_info), out_info->width, out_info->height);
priv->supported_backend |= GST_D3D11_CONVERTER_BACKEND_SHADER; priv->supported_backend |= GST_D3D11_CONVERTER_BACKEND_SHADER;
out: out:
@ -2337,125 +2370,6 @@ gst_d3d11_converter_is_d3d11_buffer (GstD3D11Converter * self,
return TRUE; return TRUE;
} }
static gboolean
gst_d3d11_converter_create_fallback_buffer (GstD3D11Converter * self)
{
GstD3D11ConverterPrivate *priv = self->priv;
GstD3D11AllocationParams *params;
GstBufferPool *pool;
GstCaps *caps;
guint bind_flags = D3D11_BIND_SHADER_RESOURCE;
GstStructure *config;
gst_clear_buffer (&priv->fallback_inbuf);
params = gst_d3d11_allocation_params_new (self->device, &priv->fallback_info,
GST_D3D11_ALLOCATION_FLAG_DEFAULT, bind_flags, 0);
caps = gst_video_info_to_caps (&priv->fallback_info);
pool = gst_d3d11_buffer_pool_new (self->device);
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, caps, priv->fallback_info.size,
0, 0);
gst_buffer_pool_config_set_d3d11_allocation_params (config, params);
gst_caps_unref (caps);
gst_d3d11_allocation_params_free (params);
if (!gst_buffer_pool_set_config (pool, config)) {
GST_ERROR_OBJECT (self, "Failed to set pool config");
gst_object_unref (pool);
return FALSE;
}
if (!gst_buffer_pool_set_active (pool, TRUE)) {
GST_ERROR_OBJECT (self, "Failed to set active");
gst_object_unref (pool);
return FALSE;
}
gst_buffer_pool_acquire_buffer (pool, &priv->fallback_inbuf, nullptr);
gst_buffer_pool_set_active (pool, FALSE);
gst_object_unref (pool);
if (!priv->fallback_inbuf) {
GST_ERROR_OBJECT (self, "Failed to create fallback buffer");
return FALSE;
}
return TRUE;
}
static gboolean
gst_d3d11_converter_upload_for_shader (GstD3D11Converter * self,
GstBuffer * in_buf)
{
GstD3D11ConverterPrivate *priv = self->priv;
GstVideoFrame frame, fallback_frame;
GstVideoInfo *fallback_info = &priv->fallback_info;
gboolean ret = TRUE;
if (!gst_video_frame_map (&frame, &priv->in_info, in_buf, GST_MAP_READ)) {
GST_ERROR_OBJECT (self, "Failed to map input buffer");
return FALSE;
}
/* Probably cropped buffer */
if (fallback_info->width != GST_VIDEO_FRAME_WIDTH (&frame) ||
fallback_info->height != GST_VIDEO_FRAME_HEIGHT (&frame)) {
gst_clear_buffer (&priv->fallback_inbuf);
if (GST_VIDEO_INFO_FORMAT (&priv->in_info) == GST_VIDEO_FORMAT_YUY2 &&
priv->unpack_convert) {
gst_video_info_set_interlaced_format (fallback_info,
GST_VIDEO_FORMAT_Y42B, GST_VIDEO_INFO_INTERLACE_MODE (&frame.info),
GST_VIDEO_INFO_WIDTH (&frame.info),
GST_VIDEO_INFO_HEIGHT (&frame.info));
fallback_info->chroma_site = frame.info.chroma_site;
fallback_info->colorimetry = frame.info.colorimetry;
fallback_info->fps_n = frame.info.fps_n;
fallback_info->fps_d = frame.info.fps_d;
fallback_info->par_n = frame.info.par_n;
fallback_info->par_d = frame.info.par_d;
if (priv->unpack_convert)
gst_video_converter_free (priv->unpack_convert);
priv->unpack_convert =
gst_video_converter_new (&frame.info, fallback_info, nullptr);
g_assert (priv->unpack_convert);
} else {
*fallback_info = frame.info;
}
}
if (!priv->fallback_inbuf &&
!gst_d3d11_converter_create_fallback_buffer (self)) {
goto error;
}
if (!gst_video_frame_map (&fallback_frame,
&priv->fallback_info, priv->fallback_inbuf, GST_MAP_WRITE)) {
GST_ERROR_OBJECT (self, "Couldn't map fallback buffer");
goto error;
}
if (priv->unpack_convert) {
gst_video_converter_frame (priv->unpack_convert, &frame, &fallback_frame);
} else {
ret = gst_video_frame_copy (&fallback_frame, &frame);
}
gst_video_frame_unmap (&fallback_frame);
gst_video_frame_unmap (&frame);
return ret;
error:
gst_video_frame_unmap (&frame);
return FALSE;
}
static gboolean static gboolean
gst_d3d11_converter_map_buffer (GstD3D11Converter * self, GstBuffer * buffer, gst_d3d11_converter_map_buffer (GstD3D11Converter * self, GstBuffer * buffer,
GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags) GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags)
@ -2552,83 +2466,6 @@ gst_d3d11_converter_get_rtv (GstD3D11Converter * self, GstBuffer * buffer,
return num_views; return num_views;
} }
static gboolean
gst_d3d11_converter_ensure_fallback_inbuf (GstD3D11Converter * self,
GstBuffer * in_buf, GstMapInfo in_info[GST_VIDEO_MAX_PLANES])
{
GstD3D11ConverterPrivate *priv = self->priv;
D3D11_TEXTURE2D_DESC desc[GST_VIDEO_MAX_PLANES];
gboolean same_size = TRUE;
ID3D11DeviceContext *context;
for (guint i = 0; i < gst_buffer_n_memory (in_buf); i++) {
GstD3D11Memory *in_mem =
(GstD3D11Memory *) gst_buffer_peek_memory (in_buf, i);
gst_d3d11_memory_get_texture_desc (in_mem, &desc[i]);
if (same_size && priv->fallback_inbuf) {
D3D11_TEXTURE2D_DESC prev_desc;
GstD3D11Memory *prev_mem =
(GstD3D11Memory *) gst_buffer_peek_memory (priv->fallback_inbuf, i);
gst_d3d11_memory_get_texture_desc (prev_mem, &prev_desc);
if (prev_desc.Width != desc[i].Width ||
prev_desc.Height != desc[i].Height) {
same_size = FALSE;
}
}
}
priv->fallback_info.width = desc[0].Width;
priv->fallback_info.height = desc[0].Height;
if (priv->fallback_inbuf && !same_size) {
GST_DEBUG_OBJECT (self,
"Size of new buffer is different from previous fallback");
gst_clear_buffer (&priv->fallback_inbuf);
}
if (!priv->fallback_inbuf &&
!gst_d3d11_converter_create_fallback_buffer (self)) {
return FALSE;
}
context = gst_d3d11_device_get_device_context_handle (self->device);
for (guint i = 0; i < gst_buffer_n_memory (in_buf); i++) {
GstMemory *mem = gst_buffer_peek_memory (priv->fallback_inbuf, i);
GstD3D11Memory *dmem = GST_D3D11_MEMORY_CAST (mem);
GstMapInfo info;
ID3D11Resource *src_tex = (ID3D11Resource *) in_info[i].data;
guint src_subresource = GPOINTER_TO_UINT (in_info[i].user_data[0]);
ID3D11Resource *fallback_tex;
D3D11_TEXTURE2D_DESC fallback_desc;
D3D11_BOX src_box = { 0, };
if (!gst_memory_map (mem, &info, (GstMapFlags)
(GST_MAP_WRITE | GST_MAP_D3D11))) {
GST_ERROR_OBJECT (self, "Couldn't map fallback memory");
}
fallback_tex = (ID3D11Resource *) info.data;
gst_d3d11_memory_get_texture_desc (dmem, &fallback_desc);
src_box.left = 0;
src_box.top = 0;
src_box.front = 0;
src_box.back = 1;
src_box.right = MIN (fallback_desc.Width, desc[i].Width);
src_box.bottom = MIN (fallback_desc.Height, desc[i].Height);
context->CopySubresourceRegion (fallback_tex, 0, 0, 0, 0,
src_tex, src_subresource, &src_box);
gst_memory_unmap (mem, &info);
}
return TRUE;
}
static void static void
gst_d3d11_converter_fill_hdr10_meta (const GstVideoMasteringDisplayInfo * mdcv, gst_d3d11_converter_fill_hdr10_meta (const GstVideoMasteringDisplayInfo * mdcv,
const GstVideoContentLightLevel * cll, DXGI_HDR_METADATA_HDR10 * meta) const GstVideoContentLightLevel * cll, DXGI_HDR_METADATA_HDR10 * meta)
@ -2749,25 +2586,25 @@ gst_d3d11_converter_piv_available (GstD3D11Converter * self, GstBuffer * in_buf)
return gst_d3d11_converter_check_bind_flags_for_piv (desc.BindFlags); return gst_d3d11_converter_check_bind_flags_for_piv (desc.BindFlags);
} }
static gboolean static GstBuffer *
gst_d3d11_converter_create_piv_buffer (GstD3D11Converter * self) gst_d3d11_converter_create_buffer (GstD3D11Converter * self,
const GstVideoInfo * info, guint bind_flags)
{ {
GstD3D11ConverterPrivate *priv = self->priv; GstD3D11ConverterPrivate *priv = self->priv;
GstD3D11AllocationParams *params; GstD3D11AllocationParams *params;
GstBufferPool *pool; GstBufferPool *pool;
GstCaps *caps; GstCaps *caps;
GstStructure *config; GstStructure *config;
GstBuffer *buf = nullptr;
gst_clear_buffer (&priv->piv_inbuf); params = gst_d3d11_allocation_params_new (self->device, info,
GST_D3D11_ALLOCATION_FLAG_DEFAULT, bind_flags, 0);
params = gst_d3d11_allocation_params_new (self->device, &priv->piv_info,
GST_D3D11_ALLOCATION_FLAG_DEFAULT, 0, 0);
caps = gst_video_info_to_caps (&priv->piv_info); caps = gst_video_info_to_caps (&priv->piv_info);
pool = gst_d3d11_buffer_pool_new (self->device); pool = gst_d3d11_buffer_pool_new (self->device);
config = gst_buffer_pool_get_config (pool); config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, caps, priv->piv_info.size, 0, 0); gst_buffer_pool_config_set_params (config, caps, info->size, 0, 0);
gst_buffer_pool_config_set_d3d11_allocation_params (config, params); gst_buffer_pool_config_set_d3d11_allocation_params (config, params);
gst_caps_unref (caps); gst_caps_unref (caps);
gst_d3d11_allocation_params_free (params); gst_d3d11_allocation_params_free (params);
@ -2775,25 +2612,20 @@ gst_d3d11_converter_create_piv_buffer (GstD3D11Converter * self)
if (!gst_buffer_pool_set_config (pool, config)) { if (!gst_buffer_pool_set_config (pool, config)) {
GST_ERROR_OBJECT (self, "Failed to set pool config"); GST_ERROR_OBJECT (self, "Failed to set pool config");
gst_object_unref (pool); gst_object_unref (pool);
return FALSE; return nullptr;
} }
if (!gst_buffer_pool_set_active (pool, TRUE)) { if (!gst_buffer_pool_set_active (pool, TRUE)) {
GST_ERROR_OBJECT (self, "Failed to set active"); GST_ERROR_OBJECT (self, "Failed to set active");
gst_object_unref (pool); gst_object_unref (pool);
return FALSE; return nullptr;
} }
gst_buffer_pool_acquire_buffer (pool, &priv->piv_inbuf, nullptr); gst_buffer_pool_acquire_buffer (pool, &buf, nullptr);
gst_buffer_pool_set_active (pool, FALSE); gst_buffer_pool_set_active (pool, FALSE);
gst_object_unref (pool); gst_object_unref (pool);
if (!priv->piv_inbuf) { return buf;
GST_ERROR_OBJECT (self, "Failed to create PIV buffer");
return FALSE;
}
return TRUE;
} }
static gboolean static gboolean
@ -2818,9 +2650,11 @@ gst_d3d11_converter_upload_for_processor (GstD3D11Converter * self,
*piv_info = frame.info; *piv_info = frame.info;
} }
if (!priv->piv_inbuf && !gst_d3d11_converter_create_piv_buffer (self)) { if (!priv->piv_inbuf)
priv->piv_inbuf = gst_d3d11_converter_create_buffer (self, piv_info, 0);
if (!priv->piv_inbuf)
goto error; goto error;
}
if (!gst_video_frame_map (&fallback_frame, if (!gst_video_frame_map (&fallback_frame,
&priv->piv_info, priv->piv_inbuf, GST_MAP_WRITE)) { &priv->piv_info, priv->piv_inbuf, GST_MAP_WRITE)) {
@ -2949,6 +2783,32 @@ out:
return ret; return ret;
} }
static gboolean
gst_d3d11_converter_ensure_postproc_buf (GstD3D11Converter * self,
const D3D11_TEXTURE2D_DESC * desc)
{
GstD3D11ConverterPrivate *priv = self->priv;
if (desc->Width != (UINT) priv->postproc_info.width ||
desc->Height != (UINT) priv->postproc_info.height) {
gst_video_info_set_format (&priv->postproc_info,
GST_VIDEO_INFO_FORMAT (&priv->postproc_info),
desc->Width, desc->Height);
gst_clear_buffer (&priv->postproc_buf);
}
if (!priv->postproc_buf) {
priv->postproc_buf = gst_d3d11_converter_create_buffer (self,
&priv->postproc_info,
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
if (!priv->postproc_buf)
return FALSE;
}
return TRUE;
}
static gboolean static gboolean
gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self, gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
GstBuffer * in_buf, GstBuffer * out_buf) GstBuffer * in_buf, GstBuffer * out_buf)
@ -2965,6 +2825,8 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
gboolean ret = FALSE; gboolean ret = FALSE;
gboolean in_d3d11; gboolean in_d3d11;
gboolean multisampled = FALSE; gboolean multisampled = FALSE;
gboolean rtv_bound = TRUE;
GstBuffer *shader_output = out_buf;
std::lock_guard < std::mutex > lk (priv->prop_lock); std::lock_guard < std::mutex > lk (priv->prop_lock);
@ -2985,10 +2847,8 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
return FALSE; return FALSE;
} }
if ((desc.BindFlags & D3D11_BIND_RENDER_TARGET) == 0) { if ((desc.BindFlags & D3D11_BIND_RENDER_TARGET) == 0)
GST_ERROR_OBJECT (self, "Output is not bound to render target"); rtv_bound = FALSE;
return FALSE;
}
if (desc.SampleDesc.Count > 1) if (desc.SampleDesc.Count > 1)
multisampled = TRUE; multisampled = TRUE;
@ -3011,7 +2871,8 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
} }
in_d3d11 = gst_d3d11_converter_is_d3d11_buffer (self, in_buf); in_d3d11 = gst_d3d11_converter_is_d3d11_buffer (self, in_buf);
if (!multisampled && gst_d3d11_converter_processor_available (self)) { if (!multisampled && rtv_bound &&
gst_d3d11_converter_processor_available (self)) {
gboolean use_processor = FALSE; gboolean use_processor = FALSE;
gboolean piv_available = FALSE; gboolean piv_available = FALSE;
@ -3031,8 +2892,8 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
} else if (piv_available) { } else if (piv_available) {
in_dmem = (GstD3D11Memory *) gst_buffer_peek_memory (in_buf, 0); in_dmem = (GstD3D11Memory *) gst_buffer_peek_memory (in_buf, 0);
if (GST_VIDEO_INFO_FORMAT (&priv->in_info) == GST_VIDEO_FORMAT_YUY2) { if (priv->need_preproc || priv->need_postproc) {
/* Always use processor for packed YUV */ /* Prefer processor for packed YUV */
use_processor = TRUE; use_processor = TRUE;
} else if (!gst_d3d11_memory_get_shader_resource_view_size (in_dmem)) { } else if (!gst_d3d11_memory_get_shader_resource_view_size (in_dmem)) {
/* SRV is unavailable, use processor */ /* SRV is unavailable, use processor */
@ -3062,17 +2923,24 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
if ((priv->supported_backend & GST_D3D11_CONVERTER_BACKEND_SHADER) == 0) { if ((priv->supported_backend & GST_D3D11_CONVERTER_BACKEND_SHADER) == 0) {
GST_ERROR_OBJECT (self, "Conversion is not supported"); GST_ERROR_OBJECT (self, "Conversion is not supported");
goto out; return FALSE;
} }
if (!in_d3d11 || in_buf = gst_d3d11_converter_helper_preproc (priv->preproc, in_buf);
GST_VIDEO_INFO_FORMAT (&priv->in_info) == GST_VIDEO_FORMAT_YUY2) { if (!in_buf) {
if (!gst_d3d11_converter_upload_for_shader (self, in_buf)) { GST_ERROR_OBJECT (self, "Preprocess failed");
GST_ERROR_OBJECT (self, "Couldn't copy into fallback buffer"); return FALSE;
}
if (!rtv_bound || priv->need_postproc) {
if (!gst_d3d11_converter_ensure_postproc_buf (self, &desc)) {
GST_ERROR_OBJECT (self, "Postproc buffer failed");
return FALSE; return FALSE;
} }
in_buf = priv->fallback_inbuf; gst_d3d11_converter_helper_update_size (priv->postproc,
desc.Width, desc.Height);
shader_output = priv->postproc_buf;
} }
if (!gst_d3d11_converter_map_buffer (self, in_buf, in_info, if (!gst_d3d11_converter_map_buffer (self, in_buf, in_info,
@ -3081,14 +2949,14 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
return FALSE; return FALSE;
} }
if (!gst_d3d11_converter_map_buffer (self, out_buf, out_info, if (!gst_d3d11_converter_map_buffer (self, shader_output, out_info,
(GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) { (GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) {
GST_ERROR_OBJECT (self, "Couldn't map output buffer"); GST_ERROR_OBJECT (self, "Couldn't map output buffer");
gst_d3d11_converter_unmap_buffer (self, in_buf, in_info); gst_d3d11_converter_unmap_buffer (self, in_buf, in_info);
return FALSE; return FALSE;
} }
num_rtv = gst_d3d11_converter_get_rtv (self, out_buf, rtv); num_rtv = gst_d3d11_converter_get_rtv (self, shader_output, rtv);
if (!num_rtv) { if (!num_rtv) {
GST_ERROR_OBJECT (self, "RTV is unavailable"); GST_ERROR_OBJECT (self, "RTV is unavailable");
goto out; goto out;
@ -3096,30 +2964,8 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
num_srv = gst_d3d11_converter_get_srv (self, in_buf, srv); num_srv = gst_d3d11_converter_get_srv (self, in_buf, srv);
if (!num_srv) { if (!num_srv) {
if (in_buf == priv->fallback_inbuf) { GST_ERROR_OBJECT (self, "SRV is unavailable");
GST_ERROR_OBJECT (self, "Unable to get SRV from fallback buffer"); goto out;
goto out;
} else if (!gst_d3d11_converter_ensure_fallback_inbuf (self,
in_buf, in_info)) {
GST_ERROR_OBJECT (self, "Couldn't copy into fallback texture");
goto out;
}
gst_d3d11_converter_unmap_buffer (self, in_buf, in_info);
in_buf = priv->fallback_inbuf;
if (!gst_d3d11_converter_map_buffer (self,
in_buf, in_info, (GstMapFlags) (GST_MAP_READ | GST_MAP_D3D11))) {
GST_ERROR_OBJECT (self, "Couldn't map fallback buffer");
in_buf = nullptr;
goto out;
}
num_srv = gst_d3d11_converter_get_srv (self, in_buf, srv);
if (!num_srv) {
GST_ERROR_OBJECT (self, "Couldn't get SRV from fallback input");
goto out;
}
} }
GST_TRACE_OBJECT (self, "Converting using shader"); GST_TRACE_OBJECT (self, "Converting using shader");
@ -3127,9 +2973,13 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
ret = gst_d3d11_converter_convert_internal (self, srv, rtv, multisampled); ret = gst_d3d11_converter_convert_internal (self, srv, rtv, multisampled);
out: out:
if (in_buf) gst_d3d11_converter_unmap_buffer (self, in_buf, in_info);
gst_d3d11_converter_unmap_buffer (self, in_buf, in_info); gst_d3d11_converter_unmap_buffer (self, shader_output, out_info);
gst_d3d11_converter_unmap_buffer (self, out_buf, out_info);
if (ret) {
ret = gst_d3d11_converter_helper_postproc (priv->postproc, shader_output,
out_buf);
}
return ret; return ret;
} }