From 6335c5d00581fdb5fd83c9e57029a4cd72895a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Hu=20=28=E8=83=A1=E9=AA=9E=29?= Date: Mon, 19 Aug 2024 13:50:48 +0800 Subject: [PATCH] meta: add aggregation function for allocation meta api params since tee do allocation query for each downstream element, and get allocation query params from them. this function will aggregate all params, and propose it for upstream element of tee Part-of: --- .../gst-libs/gst/video/gstvideometa.c | 65 +++++++++++++++++++ subprojects/gstreamer/gst/gstmeta.c | 59 +++++++++++++++++ subprojects/gstreamer/gst/gstmeta.h | 28 ++++++++ .../gstreamer/plugins/elements/gsttee.c | 13 +++- 4 files changed, 164 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.c b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.c index f191820818..794d920aaa 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.c @@ -124,6 +124,68 @@ gst_video_meta_transform (GstBuffer * dest, GstMeta * meta, return TRUE; } +static gboolean +gst_video_meta_api_params_aggregator (GstStructure ** aggregated_params, + const GstStructure * params0, const GstStructure * params1) +{ + GstVideoAlignment align0; + GstVideoAlignment align1; + GstVideoAlignment aggregated_align; + + gst_video_alignment_reset (&align0); + gst_video_alignment_reset (&align1); + gst_video_alignment_reset (&aggregated_align); + + if (params0 && (!gst_structure_has_name (params0, "video-meta") || + !gst_buffer_pool_config_get_video_alignment (params0, &align0))) { + GST_WARNING ("Invalid params"); + params0 = NULL; + } + + if (params1 && (!gst_structure_has_name (params1, "video-meta") || + !gst_buffer_pool_config_get_video_alignment (params1, &align1))) { + GST_WARNING ("Invalid params"); + params1 = NULL; + } + + if (!params0 && !params1) { + *aggregated_params = NULL; + return TRUE; + } + + if (params0 && !params1) { + *aggregated_params = gst_structure_copy (params0); + return TRUE; + } + + if (!params0 && params1) { + *aggregated_params = gst_structure_copy (params1); + return TRUE; + } + + aggregated_align.padding_top = MAX (align0.padding_top, align1.padding_top); + + aggregated_align.padding_bottom = + MAX (align0.padding_bottom, align1.padding_bottom); + + aggregated_align.padding_left = + MAX (align0.padding_left, align1.padding_left); + + aggregated_align.padding_right = + MAX (align0.padding_right, align1.padding_right); + + for (int n = 0; n < GST_VIDEO_MAX_PLANES; ++n) + aggregated_align.stride_align[n] = + align0.stride_align[n] | align1.stride_align[n]; + + *aggregated_params = gst_structure_new_empty ("video-meta"); + + gst_buffer_pool_config_set_video_alignment (*aggregated_params, + &aggregated_align); + + return TRUE; +} + GType gst_video_meta_api_get_type (void) { @@ -136,6 +198,9 @@ gst_video_meta_api_get_type (void) if (g_once_init_enter (&type)) { GType _type = gst_meta_api_type_register ("GstVideoMetaAPI", tags); + + gst_meta_api_type_set_params_aggregator (_type, + gst_video_meta_api_params_aggregator); g_once_init_leave (&type, _type); } return type; diff --git a/subprojects/gstreamer/gst/gstmeta.c b/subprojects/gstreamer/gst/gstmeta.c index 96b273e5d5..1e961e6410 100644 --- a/subprojects/gstreamer/gst/gstmeta.c +++ b/subprojects/gstreamer/gst/gstmeta.c @@ -58,6 +58,7 @@ GQuark _gst_meta_transform_copy; GQuark _gst_meta_tag_memory; GQuark _gst_meta_tag_memory_reference; static GQuark _gst_meta_tags_quark; +static GQuark _gst_allocation_meta_params_aggregator_quark; typedef struct { @@ -85,6 +86,8 @@ _priv_gst_meta_initialize (void) _gst_meta_tag_memory_reference = g_quark_from_static_string ("memory-reference"); _gst_meta_tags_quark = g_quark_from_static_string ("tags"); + _gst_allocation_meta_params_aggregator_quark = + g_quark_from_static_string ("GstAllocationMetaParamsAggregator"); } static gboolean @@ -409,6 +412,62 @@ gst_meta_api_type_get_tags (GType api) return (const gchar * const *) tags; } +/** + * gst_meta_api_type_aggregate_params: + * @api: the GType of the API for which the parameters are being aggregated. + * @aggregated_params: This structure will be updated with the + * combined parameters from both @params0 and @params1. + * @params0: a #GstStructure containing the new parameters to be aggregated. + * @params1: a #GstStructure containing the new parameters to be aggregated. + * + * When a element like `tee` decides the allocation, each downstream element may + * fill different parameters and pass them to gst_query_add_allocation_meta(). + * In order to keep these parameters, a merge operation is needed. This + * aggregate function can combine the parameters from @params0 and @param1, and + * write the result back into @aggregated_params. + * + * Returns: %TRUE if the parameters were successfully aggregated, %FALSE otherwise. + * + * Since: 1.26 + */ +gboolean +gst_meta_api_type_aggregate_params (GType api, + GstStructure ** aggregated_params, const GstStructure * params0, + const GstStructure * params1) +{ + g_return_val_if_fail (api != 0, FALSE); + g_return_val_if_fail (aggregated_params != NULL, FALSE); + + GstAllocationMetaParamsAggregator aggregator_func = + g_type_get_qdata (api, _gst_allocation_meta_params_aggregator_quark); + + if (!aggregator_func) + return FALSE; + + return aggregator_func (aggregated_params, params0, params1); +} + +/** + * gst_meta_api_type_set_params_aggregator: + * @api: the #GType of the API for which the aggregator function is being set. + * @aggregator: the aggregator function to be associated with the given API + * type. + * + * This function sets the aggregator function for a specific API type. + * + * Since: 1.26 + */ +void +gst_meta_api_type_set_params_aggregator (GType api, + GstAllocationMetaParamsAggregator aggregator) +{ + g_return_if_fail (api != 0); + g_return_if_fail (aggregator != NULL); + + g_type_set_qdata (api, _gst_allocation_meta_params_aggregator_quark, + (GstAllocationMetaParamsAggregator) aggregator); +} + static const GstMetaInfo * gst_meta_register_internal (GType api, const gchar * impl, gsize size, GstMetaInitFunction init_func, GstMetaFreeFunction free_func, diff --git a/subprojects/gstreamer/gst/gstmeta.h b/subprojects/gstreamer/gst/gstmeta.h index 214847146c..ddeb0988ab 100644 --- a/subprojects/gstreamer/gst/gstmeta.h +++ b/subprojects/gstreamer/gst/gstmeta.h @@ -292,6 +292,24 @@ typedef GstMeta *(*GstMetaDeserializeFunction) (const GstMetaInfo *info, */ typedef void (*GstMetaClearFunction) (GstBuffer *buffer, GstMeta *meta); +/** + * GstAllocationMetaParamsAggregator: + * @aggregated_params: This structure will be updated with the + * combined parameters from both @params0 and @params1. + * @params0: a #GstStructure containing the new parameters to be aggregated. + * @params1: a #GstStructure containing the new parameters to be aggregated. + * + * The aggregator function will combine the parameters from @params0 and @param1 + * and write the result back into @aggregated_params. + * + * Returns: %TRUE if the parameters were successfully aggregated, %FALSE otherwise. + * + * Since: 1.26 + */ +typedef gboolean (*GstAllocationMetaParamsAggregator) (GstStructure ** aggregated_params, + const GstStructure * params0, + const GstStructure * params1); + /** * GstMetaInfo.serialize_func: * @@ -359,6 +377,16 @@ GType gst_meta_api_type_register (const gchar *api, GST_API gboolean gst_meta_api_type_has_tag (GType api, GQuark tag); +GST_API +gboolean gst_meta_api_type_aggregate_params (GType api, + GstStructure ** aggregated_params, + const GstStructure * params0, + const GstStructure * params1); + +GST_API +void gst_meta_api_type_set_params_aggregator (GType api, + GstAllocationMetaParamsAggregator aggregator); + GST_API const GstMetaInfo * gst_meta_register (GType api, const gchar *impl, gsize size, diff --git a/subprojects/gstreamer/plugins/elements/gsttee.c b/subprojects/gstreamer/plugins/elements/gsttee.c index dd90c38671..27a4b76fec 100644 --- a/subprojects/gstreamer/plugins/elements/gsttee.c +++ b/subprojects/gstreamer/plugins/elements/gsttee.c @@ -685,6 +685,7 @@ gst_tee_query_allocation (const GValue * item, GValue * ret, gpointer user_data) /* Afterward, aggregate the common params */ if (gst_query_find_allocation_meta (ctx->query, api, &ctx_index)) { const GstStructure *ctx_param; + GstStructure *aggregated_params = NULL; gst_query_parse_nth_allocation_meta (ctx->query, ctx_index, &ctx_param); @@ -692,7 +693,17 @@ gst_tee_query_allocation (const GValue * item, GValue * ret, gpointer user_data) if (ctx_param == NULL && param == NULL) continue; - GST_DEBUG_OBJECT (ctx->tee, "Dropping allocation meta %s", + /* Aggregate the two params, if successful, add it to the query. + * and then, we always Drop the old params from the query. */ + if (gst_meta_api_type_aggregate_params (api, &aggregated_params, + ctx_param, param)) { + gst_query_add_allocation_meta (ctx->query, api, aggregated_params); + + if (aggregated_params) + gst_structure_free (aggregated_params); + } + + GST_DEBUG_OBJECT (ctx->tee, "Dropping old allocation meta %s", g_type_name (api)); gst_query_remove_nth_allocation_meta (ctx->query, ctx_index); }