From 5965b6ef8538ea766c7306abfdbde0dd26dbe451 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sun, 29 Mar 2020 23:31:13 +0900 Subject: [PATCH] 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: --- sys/d3d11/gstd3d11decoder.c | 151 ++++++++++++++++++++++++++++++++++++ sys/d3d11/gstd3d11decoder.h | 14 ++++ sys/d3d11/gstd3d11h264dec.c | 119 ++-------------------------- sys/d3d11/gstd3d11h265dec.c | 119 ++-------------------------- sys/d3d11/gstd3d11vp9dec.c | 123 ++--------------------------- 5 files changed, 183 insertions(+), 343 deletions(-) diff --git a/sys/d3d11/gstd3d11decoder.c b/sys/d3d11/gstd3d11decoder.c index 2328a5542e..5bb21a0e2a 100644 --- a/sys/d3d11/gstd3d11decoder.c +++ b/sys/d3d11/gstd3d11decoder.c @@ -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[] = { diff --git a/sys/d3d11/gstd3d11decoder.h b/sys/d3d11/gstd3d11decoder.h index e43f49adbc..32f8026e17 100644 --- a/sys/d3d11/gstd3d11decoder.h +++ b/sys/d3d11/gstd3d11decoder.h @@ -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); diff --git a/sys/d3d11/gstd3d11h264dec.c b/sys/d3d11/gstd3d11h264dec.c index 31444e6b71..4d97969109 100644 --- a/sys/d3d11/gstd3d11h264dec.c +++ b/sys/d3d11/gstd3d11h264dec.c @@ -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); diff --git a/sys/d3d11/gstd3d11h265dec.c b/sys/d3d11/gstd3d11h265dec.c index a8517a67f1..6556d4b945 100644 --- a/sys/d3d11/gstd3d11h265dec.c +++ b/sys/d3d11/gstd3d11h265dec.c @@ -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); diff --git a/sys/d3d11/gstd3d11vp9dec.c b/sys/d3d11/gstd3d11vp9dec.c index 67c471ebe6..d5f49a26c2 100644 --- a/sys/d3d11/gstd3d11vp9dec.c +++ b/sys/d3d11/gstd3d11vp9dec.c @@ -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);