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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7201>
This commit is contained in:
Qian Hu (胡骞) 2024-08-19 13:50:48 +08:00 committed by GStreamer Marge Bot
parent be95be4b31
commit 6335c5d005
4 changed files with 164 additions and 1 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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,

View file

@ -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);
}