diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 019810f427..b9783c57b5 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -1625,6 +1625,8 @@ gst_buffer_remove_meta (GstBuffer * buffer, GstMeta * meta) g_return_val_if_fail (buffer != NULL, FALSE); g_return_val_if_fail (meta != NULL, FALSE); g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE); + g_return_val_if_fail (!GST_META_FLAG_IS_SET (meta, GST_META_FLAG_LOCKED), + FALSE); /* find the metadata and delete */ prev = GST_BUFFER_META (buffer); @@ -1724,6 +1726,7 @@ gst_buffer_foreach_meta (GstBuffer * buffer, GstBufferForeachMetaFunc func, g_type_name (info->type)); g_return_if_fail (gst_buffer_is_writable (buffer)); + g_return_if_fail (!GST_META_FLAG_IS_SET (m, GST_META_FLAG_LOCKED)); /* remove from list */ if (GST_BUFFER_META (buffer) == walk) diff --git a/gst/gstbufferpool.c b/gst/gstbufferpool.c index 7020345a29..f32aa89d61 100644 --- a/gst/gstbufferpool.c +++ b/gst/gstbufferpool.c @@ -243,6 +243,7 @@ mark_meta_pooled (GstBuffer * buffer, GstMeta ** meta, gpointer user_data) GST_DEBUG_OBJECT (pool, "marking meta %p as POOLED in buffer %p", *meta, buffer); GST_META_FLAG_SET (*meta, GST_META_FLAG_POOLED); + GST_META_FLAG_SET (*meta, GST_META_FLAG_LOCKED); return TRUE; } @@ -988,8 +989,10 @@ dec_outstanding (GstBufferPool * pool) static gboolean remove_meta_unpooled (GstBuffer * buffer, GstMeta ** meta, gpointer user_data) { - if (!GST_META_FLAG_IS_SET (*meta, GST_META_FLAG_POOLED)) + if (!GST_META_FLAG_IS_SET (*meta, GST_META_FLAG_POOLED)) { + GST_META_FLAG_UNSET (*meta, GST_META_FLAG_LOCKED); *meta = NULL; + } return TRUE; } diff --git a/gst/gstbufferpool.h b/gst/gstbufferpool.h index aad3b2202a..c798223e55 100644 --- a/gst/gstbufferpool.h +++ b/gst/gstbufferpool.h @@ -129,11 +129,12 @@ struct _GstBufferPool { * @alloc_buffer: allocate a buffer. the default implementation allocates * buffers from the configured memory allocator and with the configured * parameters. All metadata that is present on the allocated buffer will - * be marked as #GST_META_FLAG_POOLED and will not be removed from the - * buffer in @reset_buffer. + * be marked as #GST_META_FLAG_POOLED and #GST_META_FLAG_LOCKED and will + * not be removed from the buffer in @reset_buffer. * @reset_buffer: reset the buffer to its state when it was freshly allocated. * The default implementation will clear the flags, timestamps and - * will remove the metadata without the #GST_META_FLAG_POOLED flag. + * will remove the metadata without the #GST_META_FLAG_POOLED flag (even + * the metadata with #GST_META_FLAG_LOCKED). * @release_buffer: release a buffer back in the pool. The default * implementation will put the buffer back in the queue and notify any * blocking acquire_buffer calls. diff --git a/gst/gstmeta.h b/gst/gstmeta.h index bd7b2e2ceb..e6d4f0061b 100644 --- a/gst/gstmeta.h +++ b/gst/gstmeta.h @@ -34,8 +34,8 @@ typedef struct _GstMetaInfo GstMetaInfo; * GstMetaFlags: * @GST_META_FLAG_NONE: no flags * @GST_META_FLAG_READONLY: metadata should not be modified - * @GST_META_FLAG_POOLED: metadata is managed by a bufferpool and should not - * be removed + * @GST_META_FLAG_POOLED: metadata is managed by a bufferpool + * @GST_META_FLAG_LOCKED: metadata should not be removed * @GST_META_FLAG_LAST: additional flags can be added starting from this flag. * * Extra metadata flags. @@ -44,6 +44,7 @@ typedef enum { GST_META_FLAG_NONE = 0, GST_META_FLAG_READONLY = (1 << 0), GST_META_FLAG_POOLED = (1 << 1), + GST_META_FLAG_LOCKED = (1 << 2), GST_META_FLAG_LAST = (1 << 16) } GstMetaFlags; diff --git a/tests/check/gst/gstmeta.c b/tests/check/gst/gstmeta.c index 2840196cc4..73b5d56c52 100644 --- a/tests/check/gst/gstmeta.c +++ b/tests/check/gst/gstmeta.c @@ -210,6 +210,40 @@ GST_START_TEST (test_meta_test) GST_END_TEST; +static gboolean +foreach_meta (GstBuffer * buffer, GstMeta ** meta, gpointer user_data) +{ + /* try to remove */ + *meta = NULL; + return TRUE; +} + +GST_START_TEST (test_meta_locked) +{ + GstBuffer *buffer; + GstMetaTest *meta; + + buffer = gst_buffer_new_and_alloc (4); + fail_if (buffer == NULL); + + /* add some metadata */ + meta = GST_META_TEST_ADD (buffer); + fail_if (meta == NULL); + GST_META_FLAG_SET (meta, GST_META_FLAG_LOCKED); + + ASSERT_CRITICAL (gst_buffer_remove_meta (buffer, (GstMeta *) meta)); + ASSERT_CRITICAL (gst_buffer_foreach_meta (buffer, foreach_meta, NULL)); + + GST_META_FLAG_UNSET (meta, GST_META_FLAG_LOCKED); + + gst_buffer_remove_meta (buffer, (GstMeta *) meta); + + /* clean up */ + gst_buffer_unref (buffer); +} + +GST_END_TEST; + static Suite * gst_buffermeta_suite (void) { @@ -218,6 +252,7 @@ gst_buffermeta_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_meta_test); + tcase_add_test (tc_chain, test_meta_locked); return s; }