d3d11decoder: Add helper methods for negotiation and decide_allocation

The implementation for all codecs is almost the same.
No need to duplicate code.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1079>
This commit is contained in:
Seungha Yang 2020-03-29 23:31:13 +09:00 committed by GStreamer Merge Bot
parent 9524e6adec
commit 5965b6ef85
5 changed files with 183 additions and 343 deletions

View file

@ -1429,6 +1429,157 @@ do_process:
need_convert, decoder_buffer, output);
}
gboolean
gst_d3d11_decoder_negotiate (GstVideoDecoder * decoder,
GstVideoCodecState * input_state, GstVideoFormat format,
guint width, guint height, GstVideoCodecState ** output_state,
gboolean * downstream_supports_d3d11)
{
GstCaps *peer_caps;
GstVideoCodecState *state;
g_return_val_if_fail (GST_IS_VIDEO_DECODER (decoder), FALSE);
g_return_val_if_fail (input_state != NULL, FALSE);
g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
g_return_val_if_fail (width > 0, FALSE);
g_return_val_if_fail (height > 0, FALSE);
g_return_val_if_fail (output_state != NULL, FALSE);
g_return_val_if_fail (downstream_supports_d3d11 != NULL, FALSE);
state = gst_video_decoder_set_output_state (decoder,
format, width, height, input_state);
state->caps = gst_video_info_to_caps (&state->info);
if (*output_state)
gst_video_codec_state_unref (*output_state);
*output_state = state;
peer_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (decoder));
GST_DEBUG_OBJECT (decoder, "Allowed caps %" GST_PTR_FORMAT, peer_caps);
*downstream_supports_d3d11 = FALSE;
if (!peer_caps || gst_caps_is_any (peer_caps)) {
GST_DEBUG_OBJECT (decoder,
"cannot determine output format, use system memory");
} else {
GstCapsFeatures *features;
guint size = gst_caps_get_size (peer_caps);
guint i;
for (i = 0; i < size; i++) {
features = gst_caps_get_features (peer_caps, i);
if (features && gst_caps_features_contains (features,
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
GST_DEBUG_OBJECT (decoder, "found D3D11 memory feature");
gst_caps_set_features (state->caps, 0,
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, NULL));
*downstream_supports_d3d11 = TRUE;
break;
}
}
}
gst_clear_caps (&peer_caps);
return TRUE;
}
gboolean
gst_d3d11_decoder_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query, GstD3D11Device * device, GstD3D11Codec codec,
gboolean use_d3d11_pool)
{
GstCaps *outcaps;
GstBufferPool *pool = NULL;
guint n, size, min, max;
GstVideoInfo vinfo = { 0, };
GstStructure *config;
GstD3D11AllocationParams *d3d11_params;
g_return_val_if_fail (GST_IS_VIDEO_DECODER (decoder), FALSE);
g_return_val_if_fail (query != NULL, FALSE);
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE);
g_return_val_if_fail (codec > GST_D3D11_CODEC_NONE &&
codec < GST_D3D11_CODEC_LAST, FALSE);
gst_query_parse_allocation (query, &outcaps, NULL);
if (!outcaps) {
GST_DEBUG_OBJECT (decoder, "No output caps");
return FALSE;
}
gst_video_info_from_caps (&vinfo, outcaps);
n = gst_query_get_n_allocation_pools (query);
if (n > 0)
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
/* create our own pool */
if (pool && (use_d3d11_pool && !GST_D3D11_BUFFER_POOL (pool))) {
gst_object_unref (pool);
pool = NULL;
}
if (!pool) {
if (use_d3d11_pool)
pool = gst_d3d11_buffer_pool_new (device);
else
pool = gst_video_buffer_pool_new ();
min = max = 0;
size = (guint) vinfo.size;
}
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
if (use_d3d11_pool) {
GstVideoAlignment align;
gint width, height;
gst_video_alignment_reset (&align);
d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
if (!d3d11_params)
d3d11_params = gst_d3d11_allocation_params_new (device, &vinfo, 0, 0);
width = GST_VIDEO_INFO_WIDTH (&vinfo);
height = GST_VIDEO_INFO_HEIGHT (&vinfo);
/* need alignment to copy decoder output texture to downstream texture */
align.padding_right = GST_ROUND_UP_16 (width) - width;
align.padding_bottom = GST_ROUND_UP_16 (height) - height;
if (!gst_d3d11_allocation_params_alignment (d3d11_params, &align)) {
GST_ERROR_OBJECT (decoder, "Cannot set alignment");
return FALSE;
}
if (codec == GST_D3D11_CODEC_VP9) {
/* Needs render target bind flag so that it can be used for
* output of shader pipeline if internal resizing is required */
d3d11_params->desc[0].BindFlags |= D3D11_BIND_RENDER_TARGET;
}
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
gst_d3d11_allocation_params_free (d3d11_params);
}
gst_buffer_pool_set_config (pool, config);
if (use_d3d11_pool)
size = GST_D3D11_BUFFER_POOL (pool)->buffer_size;
if (n > 0)
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
else
gst_query_add_allocation_pool (query, pool, size, min, max);
gst_object_unref (pool);
return TRUE;
}
/* Keep sync with chromium and keep in sorted order.
* See supported_profile_helpers.cc in chromium */
static const guint legacy_amd_list[] = {

View file

@ -137,6 +137,20 @@ gboolean gst_d3d11_decoder_process_output (GstD3D11Decoder * decod
GstBuffer * decoder_buffer,
GstBuffer * output);
gboolean gst_d3d11_decoder_negotiate (GstVideoDecoder * decoder,
GstVideoCodecState * input_state,
GstVideoFormat format,
guint width,
guint height,
GstVideoCodecState ** output_state,
gboolean * downstream_supports_d3d11);
gboolean gst_d3d11_decoder_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query,
GstD3D11Device * device,
GstD3D11Codec codec,
gboolean use_d3d11_pool);
/* Utils for class registration */
gboolean gst_d3d11_decoder_util_is_legacy_device (GstD3D11Device * device);

View file

@ -330,46 +330,11 @@ gst_d3d11_h264_dec_negotiate (GstVideoDecoder * decoder)
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
GstH264Decoder *h264dec = GST_H264_DECODER (decoder);
GstCaps *peer_caps;
GST_DEBUG_OBJECT (self, "negotiate");
if (self->output_state)
gst_video_codec_state_unref (self->output_state);
self->output_state =
gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
self->out_format, self->width, self->height, h264dec->input_state);
self->output_state->caps = gst_video_info_to_caps (&self->output_state->info);
peer_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (self));
GST_DEBUG_OBJECT (self, "Allowed caps %" GST_PTR_FORMAT, peer_caps);
self->use_d3d11_output = FALSE;
if (!peer_caps || gst_caps_is_any (peer_caps)) {
GST_DEBUG_OBJECT (self,
"cannot determine output format, use system memory");
} else {
GstCapsFeatures *features;
guint size = gst_caps_get_size (peer_caps);
guint i;
for (i = 0; i < size; i++) {
features = gst_caps_get_features (peer_caps, i);
if (features && gst_caps_features_contains (features,
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
GST_DEBUG_OBJECT (self, "found D3D11 memory feature");
gst_caps_set_features (self->output_state->caps, 0,
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, NULL));
self->use_d3d11_output = TRUE;
break;
}
}
}
gst_clear_caps (&peer_caps);
if (!gst_d3d11_decoder_negotiate (decoder, h264dec->input_state,
self->out_format, self->width, self->height, &self->output_state,
&self->use_d3d11_output))
return FALSE;
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
@ -379,82 +344,10 @@ gst_d3d11_h264_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query)
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
GstCaps *outcaps;
GstBufferPool *pool = NULL;
guint n, size, min, max;
GstVideoInfo vinfo = { 0, };
GstStructure *config;
GstD3D11AllocationParams *d3d11_params;
GST_DEBUG_OBJECT (self, "decide allocation");
gst_query_parse_allocation (query, &outcaps, NULL);
if (!outcaps) {
GST_DEBUG_OBJECT (self, "No output caps");
if (!gst_d3d11_decoder_decide_allocation (decoder, query, self->device,
GST_D3D11_CODEC_H264, self->use_d3d11_output))
return FALSE;
}
gst_video_info_from_caps (&vinfo, outcaps);
n = gst_query_get_n_allocation_pools (query);
if (n > 0)
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
/* create our own pool */
if (pool && (self->use_d3d11_output && !GST_D3D11_BUFFER_POOL (pool))) {
gst_object_unref (pool);
pool = NULL;
}
if (!pool) {
if (self->use_d3d11_output)
pool = gst_d3d11_buffer_pool_new (self->device);
else
pool = gst_video_buffer_pool_new ();
min = max = 0;
size = (guint) vinfo.size;
}
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
if (self->use_d3d11_output) {
GstVideoAlignment align;
gint width, height;
gst_video_alignment_reset (&align);
d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
if (!d3d11_params)
d3d11_params = gst_d3d11_allocation_params_new (self->device,
&vinfo, 0, 0);
width = GST_VIDEO_INFO_WIDTH (&vinfo);
height = GST_VIDEO_INFO_HEIGHT (&vinfo);
/* need alignment to copy decoder output texture to downstream texture */
align.padding_right = GST_ROUND_UP_16 (width) - width;
align.padding_bottom = GST_ROUND_UP_16 (height) - height;
if (!gst_d3d11_allocation_params_alignment (d3d11_params, &align)) {
GST_ERROR_OBJECT (self, "Cannot set alignment");
return FALSE;
}
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
gst_d3d11_allocation_params_free (d3d11_params);
}
gst_buffer_pool_set_config (pool, config);
if (self->use_d3d11_output)
size = GST_D3D11_BUFFER_POOL (pool)->buffer_size;
if (n > 0)
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
else
gst_query_add_allocation_pool (query, pool, size, min, max);
gst_object_unref (pool);
return GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation
(decoder, query);

View file

@ -299,46 +299,11 @@ gst_d3d11_h265_dec_negotiate (GstVideoDecoder * decoder)
{
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
GstH265Decoder *h265dec = GST_H265_DECODER (decoder);
GstCaps *peer_caps;
GST_DEBUG_OBJECT (self, "negotiate");
if (self->output_state)
gst_video_codec_state_unref (self->output_state);
self->output_state =
gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
self->out_format, self->width, self->height, h265dec->input_state);
self->output_state->caps = gst_video_info_to_caps (&self->output_state->info);
peer_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (self));
GST_DEBUG_OBJECT (self, "Allowed caps %" GST_PTR_FORMAT, peer_caps);
self->use_d3d11_output = FALSE;
if (!peer_caps || gst_caps_is_any (peer_caps)) {
GST_DEBUG_OBJECT (self,
"cannot determine output format, use system memory");
} else {
GstCapsFeatures *features;
guint size = gst_caps_get_size (peer_caps);
guint i;
for (i = 0; i < size; i++) {
features = gst_caps_get_features (peer_caps, i);
if (features && gst_caps_features_contains (features,
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
GST_DEBUG_OBJECT (self, "found D3D11 memory feature");
gst_caps_set_features (self->output_state->caps, 0,
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, NULL));
self->use_d3d11_output = TRUE;
break;
}
}
}
gst_clear_caps (&peer_caps);
if (!gst_d3d11_decoder_negotiate (decoder, h265dec->input_state,
self->out_format, self->width, self->height, &self->output_state,
&self->use_d3d11_output))
return FALSE;
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
@ -348,82 +313,10 @@ gst_d3d11_h265_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query)
{
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
GstCaps *outcaps;
GstBufferPool *pool = NULL;
guint n, size, min, max;
GstVideoInfo vinfo = { 0, };
GstStructure *config;
GstD3D11AllocationParams *d3d11_params;
GST_DEBUG_OBJECT (self, "decide allocation");
gst_query_parse_allocation (query, &outcaps, NULL);
if (!outcaps) {
GST_DEBUG_OBJECT (self, "No output caps");
if (!gst_d3d11_decoder_decide_allocation (decoder, query, self->device,
GST_D3D11_CODEC_H265, self->use_d3d11_output))
return FALSE;
}
gst_video_info_from_caps (&vinfo, outcaps);
n = gst_query_get_n_allocation_pools (query);
if (n > 0)
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
/* create our own pool */
if (pool && (self->use_d3d11_output && !GST_D3D11_BUFFER_POOL (pool))) {
gst_object_unref (pool);
pool = NULL;
}
if (!pool) {
if (self->use_d3d11_output)
pool = gst_d3d11_buffer_pool_new (self->device);
else
pool = gst_video_buffer_pool_new ();
min = max = 0;
size = (guint) vinfo.size;
}
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
if (self->use_d3d11_output) {
GstVideoAlignment align;
gint width, height;
gst_video_alignment_reset (&align);
d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
if (!d3d11_params)
d3d11_params = gst_d3d11_allocation_params_new (self->device,
&vinfo, 0, 0);
width = GST_VIDEO_INFO_WIDTH (&vinfo);
height = GST_VIDEO_INFO_HEIGHT (&vinfo);
/* need alignment to copy decoder output texture to downstream texture */
align.padding_right = GST_ROUND_UP_16 (width) - width;
align.padding_bottom = GST_ROUND_UP_16 (height) - height;
if (!gst_d3d11_allocation_params_alignment (d3d11_params, &align)) {
GST_ERROR_OBJECT (self, "Cannot set alignment");
return FALSE;
}
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
gst_d3d11_allocation_params_free (d3d11_params);
}
gst_buffer_pool_set_config (pool, config);
if (self->use_d3d11_output)
size = GST_D3D11_BUFFER_POOL (pool)->buffer_size;
if (n > 0)
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
else
gst_query_add_allocation_pool (query, pool, size, min, max);
gst_object_unref (pool);
return GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation
(decoder, query);

View file

@ -298,46 +298,11 @@ gst_d3d11_vp9_dec_negotiate (GstVideoDecoder * decoder)
{
GstD3D11Vp9Dec *self = GST_D3D11_VP9_DEC (decoder);
GstVp9Decoder *vp9dec = GST_VP9_DECODER (decoder);
GstCaps *peer_caps;
GST_DEBUG_OBJECT (self, "negotiate");
if (self->output_state)
gst_video_codec_state_unref (self->output_state);
self->output_state =
gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
self->out_format, self->width, self->height, vp9dec->input_state);
self->output_state->caps = gst_video_info_to_caps (&self->output_state->info);
peer_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (self));
GST_DEBUG_OBJECT (self, "Allowed caps %" GST_PTR_FORMAT, peer_caps);
self->use_d3d11_output = FALSE;
if (!peer_caps || gst_caps_is_any (peer_caps)) {
GST_DEBUG_OBJECT (self,
"cannot determine output format, use system memory");
} else {
GstCapsFeatures *features;
guint size = gst_caps_get_size (peer_caps);
guint i;
for (i = 0; i < size; i++) {
features = gst_caps_get_features (peer_caps, i);
if (features && gst_caps_features_contains (features,
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
GST_DEBUG_OBJECT (self, "found D3D11 memory feature");
gst_caps_set_features (self->output_state->caps, 0,
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, NULL));
self->use_d3d11_output = TRUE;
break;
}
}
}
gst_clear_caps (&peer_caps);
if (!gst_d3d11_decoder_negotiate (decoder, vp9dec->input_state,
self->out_format, self->width, self->height, &self->output_state,
&self->use_d3d11_output))
return FALSE;
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
@ -347,86 +312,10 @@ gst_d3d11_vp9_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query)
{
GstD3D11Vp9Dec *self = GST_D3D11_VP9_DEC (decoder);
GstCaps *outcaps;
GstBufferPool *pool = NULL;
guint n, size, min, max;
GstVideoInfo vinfo = { 0, };
GstStructure *config;
GstD3D11AllocationParams *d3d11_params;
GST_DEBUG_OBJECT (self, "decide allocation");
gst_query_parse_allocation (query, &outcaps, NULL);
if (!outcaps) {
GST_DEBUG_OBJECT (self, "No output caps");
if (!gst_d3d11_decoder_decide_allocation (decoder, query, self->device,
GST_D3D11_CODEC_VP9, self->use_d3d11_output))
return FALSE;
}
gst_video_info_from_caps (&vinfo, outcaps);
n = gst_query_get_n_allocation_pools (query);
if (n > 0)
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
/* create our own pool */
if (pool && (self->use_d3d11_output && !GST_D3D11_BUFFER_POOL (pool))) {
gst_object_unref (pool);
pool = NULL;
}
if (!pool) {
if (self->use_d3d11_output)
pool = gst_d3d11_buffer_pool_new (self->device);
else
pool = gst_video_buffer_pool_new ();
min = max = 0;
size = (guint) vinfo.size;
}
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
if (self->use_d3d11_output) {
GstVideoAlignment align;
gint width, height;
gst_video_alignment_reset (&align);
d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
if (!d3d11_params)
d3d11_params = gst_d3d11_allocation_params_new (self->device,
&vinfo, 0, 0);
width = GST_VIDEO_INFO_WIDTH (&vinfo);
height = GST_VIDEO_INFO_HEIGHT (&vinfo);
/* need alignment to copy decoder output texture to downstream texture */
align.padding_right = GST_ROUND_UP_16 (width) - width;
align.padding_bottom = GST_ROUND_UP_16 (height) - height;
if (!gst_d3d11_allocation_params_alignment (d3d11_params, &align)) {
GST_ERROR_OBJECT (self, "Cannot set alignment");
return FALSE;
}
/* Needs render target bind flag so that it can be used for
* output of shader pipeline if internal resizing is required */
d3d11_params->desc[0].BindFlags |= D3D11_BIND_RENDER_TARGET;
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
gst_d3d11_allocation_params_free (d3d11_params);
}
gst_buffer_pool_set_config (pool, config);
if (self->use_d3d11_output)
size = GST_D3D11_BUFFER_POOL (pool)->buffer_size;
if (n > 0)
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
else
gst_query_add_allocation_pool (query, pool, size, min, max);
gst_object_unref (pool);
return GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation
(decoder, query);