mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 15:38:53 +00:00
basetransform: refine metadata filter and transform
Add a vmethod to filter metadata that should be passed upstream. By default, don't pass anything. Add a vmethod to transform metadata from the input buffer to the output buffer. By default, nothing is transformed or copied.
This commit is contained in:
parent
0d9f22d212
commit
7eae198be2
2 changed files with 112 additions and 10 deletions
|
@ -802,22 +802,41 @@ gst_base_transform_default_decide_allocation (GstBaseTransform * trans,
|
||||||
GstQuery * query)
|
GstQuery * query)
|
||||||
{
|
{
|
||||||
guint i, n_metas;
|
guint i, n_metas;
|
||||||
|
GstBaseTransformClass *klass;
|
||||||
|
|
||||||
|
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
n_metas = gst_query_get_n_allocation_metas (query);
|
n_metas = gst_query_get_n_allocation_metas (query);
|
||||||
for (i = 0; i < n_metas; i++) {
|
for (i = 0; i < n_metas; i++) {
|
||||||
GType api;
|
GType api;
|
||||||
|
gboolean remove;
|
||||||
|
|
||||||
api = gst_query_parse_nth_allocation_meta (query, i);
|
api = gst_query_parse_nth_allocation_meta (query, i);
|
||||||
/* remove all memory dependent metadata because we are going to have to
|
|
||||||
* allocate different memory for input and output. */
|
/* by default we remove all metadata, subclasses should implement a
|
||||||
|
* filter_meta function */
|
||||||
if (gst_meta_api_type_has_tag (api, GST_META_TAG_MEMORY)) {
|
if (gst_meta_api_type_has_tag (api, GST_META_TAG_MEMORY)) {
|
||||||
GST_LOG_OBJECT (trans, "removing memory metadata %s", g_type_name (api));
|
/* remove all memory dependent metadata because we are going to have to
|
||||||
|
* allocate different memory for input and output. */
|
||||||
|
GST_LOG_OBJECT (trans, "removing memory specific metadata %s",
|
||||||
|
g_type_name (api));
|
||||||
|
remove = TRUE;
|
||||||
|
} else if (G_LIKELY (klass->filter_meta)) {
|
||||||
|
/* remove if the subclass said so */
|
||||||
|
remove = !klass->filter_meta (trans, query, api);
|
||||||
|
GST_LOG_OBJECT (trans, "filter_meta for api %s returned: %s",
|
||||||
|
g_type_name (api), (remove ? "remove" : "keep"));
|
||||||
|
} else {
|
||||||
|
GST_LOG_OBJECT (trans, "removing metadata %s", g_type_name (api));
|
||||||
|
remove = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remove) {
|
||||||
gst_query_remove_nth_allocation_meta (query, i);
|
gst_query_remove_nth_allocation_meta (query, i);
|
||||||
i--;
|
i--;
|
||||||
n_metas--;
|
n_metas--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1306,7 +1325,18 @@ gst_base_transform_default_propose_allocation (GstBaseTransform * trans,
|
||||||
GST_DEBUG_OBJECT (trans, "doing passthrough query");
|
GST_DEBUG_OBJECT (trans, "doing passthrough query");
|
||||||
ret = gst_pad_peer_query (trans->srcpad, query);
|
ret = gst_pad_peer_query (trans->srcpad, query);
|
||||||
} else {
|
} else {
|
||||||
ret = FALSE;
|
guint i, n_metas;
|
||||||
|
/* non-passthrough, copy all metadata, decide_query does not contain the
|
||||||
|
* metadata anymore that depends on the buffer memory */
|
||||||
|
n_metas = gst_query_get_n_allocation_metas (decide_query);
|
||||||
|
for (i = 0; i < n_metas; i++) {
|
||||||
|
GType api;
|
||||||
|
|
||||||
|
api = gst_query_parse_nth_allocation_meta (decide_query, i);
|
||||||
|
GST_DEBUG_OBJECT (trans, "proposing metadata %s", g_type_name (api));
|
||||||
|
gst_query_add_allocation_meta (query, api);
|
||||||
|
}
|
||||||
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1518,11 +1548,62 @@ unknown_size:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GstBaseTransform *trans;
|
||||||
|
GstBuffer *outbuf;
|
||||||
|
} CopyMetaData;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
|
||||||
|
{
|
||||||
|
CopyMetaData *data = user_data;
|
||||||
|
GstBaseTransform *trans = data->trans;
|
||||||
|
GstBaseTransformClass *klass;
|
||||||
|
const GstMetaInfo *info = (*meta)->info;
|
||||||
|
GstBuffer *outbuf = data->outbuf;
|
||||||
|
gboolean do_copy;
|
||||||
|
|
||||||
|
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
|
if (GST_META_FLAG_IS_SET (*meta, GST_META_FLAG_POOLED)) {
|
||||||
|
/* never call the transform_meta with pool private metadata */
|
||||||
|
GST_DEBUG_OBJECT (trans, "not copying pooled metadata %s",
|
||||||
|
g_type_name (info->api));
|
||||||
|
do_copy = FALSE;
|
||||||
|
} else if (gst_meta_api_type_has_tag (info->api, GST_META_TAG_MEMORY)) {
|
||||||
|
/* never call the transform_meta with memory specific metadata */
|
||||||
|
GST_DEBUG_OBJECT (trans, "not copying memory specific metadata %s",
|
||||||
|
g_type_name (info->api));
|
||||||
|
do_copy = FALSE;
|
||||||
|
} else if (klass->transform_meta) {
|
||||||
|
do_copy = klass->transform_meta (trans, outbuf, *meta, inbuf);
|
||||||
|
GST_DEBUG_OBJECT (trans, "transformed metadata %s: copy: %d",
|
||||||
|
g_type_name (info->api), do_copy);
|
||||||
|
} else {
|
||||||
|
do_copy = FALSE;
|
||||||
|
GST_DEBUG_OBJECT (trans, "not copying metadata %s",
|
||||||
|
g_type_name (info->api));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we only copy metadata when the subclass implemented a transform_meta
|
||||||
|
* function and when it returns TRUE */
|
||||||
|
if (do_copy) {
|
||||||
|
GstMetaTransformCopy copy_data = { FALSE, 0, -1 };
|
||||||
|
GST_DEBUG_OBJECT (trans, "copy metadata %s", g_type_name (info->api));
|
||||||
|
/* simply copy then */
|
||||||
|
info->transform_func (outbuf, *meta, inbuf,
|
||||||
|
_gst_meta_transform_copy, ©_data);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
default_copy_metadata (GstBaseTransform * trans,
|
default_copy_metadata (GstBaseTransform * trans,
|
||||||
GstBuffer * inbuf, GstBuffer * outbuf)
|
GstBuffer * inbuf, GstBuffer * outbuf)
|
||||||
{
|
{
|
||||||
GstBaseTransformPrivate *priv = trans->priv;
|
GstBaseTransformPrivate *priv = trans->priv;
|
||||||
|
CopyMetaData data;
|
||||||
|
|
||||||
/* now copy the metadata */
|
/* now copy the metadata */
|
||||||
GST_DEBUG_OBJECT (trans, "copying metadata");
|
GST_DEBUG_OBJECT (trans, "copying metadata");
|
||||||
|
@ -1540,6 +1621,12 @@ default_copy_metadata (GstBaseTransform * trans,
|
||||||
if (!priv->gap_aware)
|
if (!priv->gap_aware)
|
||||||
GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_GAP);
|
GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_GAP);
|
||||||
|
|
||||||
|
|
||||||
|
data.trans = trans;
|
||||||
|
data.outbuf = outbuf;
|
||||||
|
|
||||||
|
gst_buffer_foreach_meta (inbuf, foreach_metadata, &data);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
|
|
@ -141,16 +141,22 @@ struct _GstBaseTransform {
|
||||||
* @decide_allocation: Setup the allocation parameters for allocating output
|
* @decide_allocation: Setup the allocation parameters for allocating output
|
||||||
* buffers. The passed in query contains the result of the
|
* buffers. The passed in query contains the result of the
|
||||||
* downstream allocation query. This function is only called
|
* downstream allocation query. This function is only called
|
||||||
* when not operating in passthrough mode. the default
|
* when not operating in passthrough mode. The default
|
||||||
* implementation will remove metadata that depends on the
|
* implementation will remove all memory dependent metadata.
|
||||||
* memory.
|
* If there is ia @filter_meta method implementation, it will
|
||||||
|
* be called for all metadata API in the downstream query,
|
||||||
|
* otherwise the metadata API is removed.
|
||||||
|
* @filter_meta: Return TRUE if the metadata API should be proposed in the
|
||||||
|
* upstream allocation query. The default implementation is NULL
|
||||||
|
* and will cause all metadata to be removed.
|
||||||
* @propose_allocation: Propose buffer allocation parameters for upstream elements.
|
* @propose_allocation: Propose buffer allocation parameters for upstream elements.
|
||||||
* This function must be implemented if the element reads or
|
* This function must be implemented if the element reads or
|
||||||
* writes the buffer content. The query that was passed to
|
* writes the buffer content. The query that was passed to
|
||||||
* the decide_allocation is passed in this method (or NULL
|
* the decide_allocation is passed in this method (or NULL
|
||||||
* when the element is in passthrough mode). The default
|
* when the element is in passthrough mode). The default
|
||||||
* implementation will pass the query downstream when in
|
* implementation will pass the query downstream when in
|
||||||
* passthrough mode.
|
* passthrough mode and will copy all the filtered metadata
|
||||||
|
* API in non-passthrough mode.
|
||||||
* @transform_size: Optional. Given the size of a buffer in the given direction
|
* @transform_size: Optional. Given the size of a buffer in the given direction
|
||||||
* with the given caps, calculate the size in bytes of a buffer
|
* with the given caps, calculate the size in bytes of a buffer
|
||||||
* on the other pad with the given other caps.
|
* on the other pad with the given other caps.
|
||||||
|
@ -183,6 +189,10 @@ struct _GstBaseTransform {
|
||||||
* Copy the metadata from the input buffer to the output buffer.
|
* Copy the metadata from the input buffer to the output buffer.
|
||||||
* The default implementation will copy the flags, timestamps and
|
* The default implementation will copy the flags, timestamps and
|
||||||
* offsets of the buffer.
|
* offsets of the buffer.
|
||||||
|
* @transform_meta: Optional. Transform the metadata on the input buffer to the
|
||||||
|
* output buffer. By default this method is NULL and no
|
||||||
|
* metadata is copied. subclasses can implement this method and
|
||||||
|
* return TRUE if the metadata is to be copied.
|
||||||
* @before_transform: Optional. Since 0.10.22
|
* @before_transform: Optional. Since 0.10.22
|
||||||
* This method is called right before the base class will
|
* This method is called right before the base class will
|
||||||
* start processing. Dynamic properties or other delayed
|
* start processing. Dynamic properties or other delayed
|
||||||
|
@ -221,6 +231,8 @@ struct _GstBaseTransformClass {
|
||||||
|
|
||||||
/* decide allocation query for output buffers */
|
/* decide allocation query for output buffers */
|
||||||
gboolean (*decide_allocation) (GstBaseTransform *trans, GstQuery *query);
|
gboolean (*decide_allocation) (GstBaseTransform *trans, GstQuery *query);
|
||||||
|
gboolean (*filter_meta) (GstBaseTransform *trans, GstQuery *query, GType api);
|
||||||
|
|
||||||
/* propose allocation query parameters for input buffers */
|
/* propose allocation query parameters for input buffers */
|
||||||
gboolean (*propose_allocation) (GstBaseTransform *trans, GstQuery *decide_query,
|
gboolean (*propose_allocation) (GstBaseTransform *trans, GstQuery *decide_query,
|
||||||
GstQuery *query);
|
GstQuery *query);
|
||||||
|
@ -245,8 +257,11 @@ struct _GstBaseTransformClass {
|
||||||
GstFlowReturn (*prepare_output_buffer) (GstBaseTransform * trans,
|
GstFlowReturn (*prepare_output_buffer) (GstBaseTransform * trans,
|
||||||
GstBuffer *input, GstBuffer **outbuf);
|
GstBuffer *input, GstBuffer **outbuf);
|
||||||
|
|
||||||
gboolean (*copy_metadata) (GstBaseTransform * trans, GstBuffer *input,
|
/* metadata */
|
||||||
|
gboolean (*copy_metadata) (GstBaseTransform *trans, GstBuffer *input,
|
||||||
GstBuffer *outbuf);
|
GstBuffer *outbuf);
|
||||||
|
gboolean (*transform_meta) (GstBaseTransform *trans, GstBuffer *outbuf,
|
||||||
|
GstMeta *meta, GstBuffer *inbuf);
|
||||||
|
|
||||||
void (*before_transform) (GstBaseTransform *trans, GstBuffer *buffer);
|
void (*before_transform) (GstBaseTransform *trans, GstBuffer *buffer);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue