summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2012-03-02 17:32:28 +0100
committerWim Taymans <wim.taymans@collabora.co.uk>2012-03-02 17:32:28 +0100
commit7eae198be21ebd57aa99f3aa1fb4dd6f005746ab (patch)
tree0320decb73c5357a6c6371c2aa9f51ac0486f8ce /libs
parent0d9f22d21299a5c744d8e205bac8f45c9d8e48f9 (diff)
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.
Diffstat (limited to 'libs')
-rw-r--r--libs/gst/base/gstbasetransform.c97
-rw-r--r--libs/gst/base/gstbasetransform.h25
2 files changed, 112 insertions, 10 deletions
diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c
index 0d18549ae..d0d02592d 100644
--- a/libs/gst/base/gstbasetransform.c
+++ b/libs/gst/base/gstbasetransform.c
@@ -802,22 +802,41 @@ gst_base_transform_default_decide_allocation (GstBaseTransform * trans,
GstQuery * query)
{
guint i, n_metas;
+ GstBaseTransformClass *klass;
+
+ klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
n_metas = gst_query_get_n_allocation_metas (query);
for (i = 0; i < n_metas; i++) {
GType api;
+ gboolean remove;
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)) {
- 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);
i--;
n_metas--;
}
}
-
return TRUE;
}
@@ -1306,7 +1325,18 @@ gst_base_transform_default_propose_allocation (GstBaseTransform * trans,
GST_DEBUG_OBJECT (trans, "doing passthrough query");
ret = gst_pad_peer_query (trans->srcpad, query);
} 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;
}
@@ -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, &copy_data);
+ }
+ return TRUE;
+}
+
static gboolean
default_copy_metadata (GstBaseTransform * trans,
GstBuffer * inbuf, GstBuffer * outbuf)
{
GstBaseTransformPrivate *priv = trans->priv;
+ CopyMetaData data;
/* now copy the metadata */
GST_DEBUG_OBJECT (trans, "copying metadata");
@@ -1540,6 +1621,12 @@ default_copy_metadata (GstBaseTransform * trans,
if (!priv->gap_aware)
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;
/* ERRORS */
diff --git a/libs/gst/base/gstbasetransform.h b/libs/gst/base/gstbasetransform.h
index 9a664addd..2251d11cd 100644
--- a/libs/gst/base/gstbasetransform.h
+++ b/libs/gst/base/gstbasetransform.h
@@ -141,16 +141,22 @@ struct _GstBaseTransform {
* @decide_allocation: Setup the allocation parameters for allocating output
* buffers. The passed in query contains the result of the
* downstream allocation query. This function is only called
- * when not operating in passthrough mode. the default
- * implementation will remove metadata that depends on the
- * memory.
+ * when not operating in passthrough mode. The default
+ * implementation will remove all memory dependent metadata.
+ * 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.
* This function must be implemented if the element reads or
* writes the buffer content. The query that was passed to
* the decide_allocation is passed in this method (or NULL
* when the element is in passthrough mode). The default
* 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
* with the given caps, calculate the size in bytes of a buffer
* 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.
* The default implementation will copy the flags, timestamps and
* 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
* This method is called right before the base class will
* start processing. Dynamic properties or other delayed
@@ -221,6 +231,8 @@ struct _GstBaseTransformClass {
/* decide allocation query for output buffers */
gboolean (*decide_allocation) (GstBaseTransform *trans, GstQuery *query);
+ gboolean (*filter_meta) (GstBaseTransform *trans, GstQuery *query, GType api);
+
/* propose allocation query parameters for input buffers */
gboolean (*propose_allocation) (GstBaseTransform *trans, GstQuery *decide_query,
GstQuery *query);
@@ -245,8 +257,11 @@ struct _GstBaseTransformClass {
GstFlowReturn (*prepare_output_buffer) (GstBaseTransform * trans,
GstBuffer *input, GstBuffer **outbuf);
- gboolean (*copy_metadata) (GstBaseTransform * trans, GstBuffer *input,
+ /* metadata */
+ gboolean (*copy_metadata) (GstBaseTransform *trans, GstBuffer *input,
GstBuffer *outbuf);
+ gboolean (*transform_meta) (GstBaseTransform *trans, GstBuffer *outbuf,
+ GstMeta *meta, GstBuffer *inbuf);
void (*before_transform) (GstBaseTransform *trans, GstBuffer *buffer);