if (G_UNLIKELY (result != GST_FLOW_OK))
goto alloc_failed;
+ /* lock all metadata and mark as pooled, we want this to remain on
+ * the buffer and we want to remove any other metadata that gets added
+ * later */
gst_buffer_foreach_meta (*buffer, mark_meta_pooled, pool);
+ /* tag memory, this is how we expect the buffer when it is
+ * released again */
+ GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_TAG_MEMORY);
GST_LOG_OBJECT (pool, "allocated buffer %d/%d, %p", cur_buffers,
max_buffers, buffer);
static void
default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer)
{
- GST_BUFFER_FLAGS (buffer) = 0;
+ GST_BUFFER_FLAGS (buffer) &= GST_BUFFER_FLAG_TAG_MEMORY;
GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
static void
default_release_buffer (GstBufferPool * pool, GstBuffer * buffer)
{
- /* keep it around in our queue */
- GST_LOG_OBJECT (pool, "released buffer %p", buffer);
- gst_atomic_queue_push (pool->priv->queue, buffer);
- gst_poll_write_control (pool->priv->poll);
+ GST_LOG_OBJECT (pool, "released buffer %p %d", buffer,
+ GST_MINI_OBJECT_FLAGS (buffer));
+
+ if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY)) {
+ /* keep it around in our queue */
+ gst_atomic_queue_push (pool->priv->queue, buffer);
+ gst_poll_write_control (pool->priv->poll);
+ } else {
+ do_free_buffer (pool, buffer);
+ }
}
/**
* 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 #GST_META_FLAG_LOCKED and will
- * not be removed from the buffer in @reset_buffer.
+ * not be removed from the buffer in @reset_buffer. Memory will be marked
+ * with GST_BUFFER_FLAG_TAG_MEMORY.
* @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 (even
- * the metadata with #GST_META_FLAG_LOCKED).
+ * the metadata with #GST_META_FLAG_LOCKED). If the
+ * #GST_BUFFER_FLAG_TAG_MEMORY was removed, this function can also try to
+ * restore the memory and set the #GST_BUFFER_FLAG_TAG_MEMORY again.
* @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.
+ * blocking acquire_buffer calls when the #GST_BUFFER_FLAG_TAG_MEMORY
+ * is set on the buffer. If #GST_BUFFER_FLAG_TAG_MEMORY is not set, the
+ * buffer will be freed with @free_buffer.
* @free_buffer: free a buffer. The default implementation unrefs the buffer.
*
* The GstBufferPool class.
GST_END_TEST;
+GST_START_TEST (test_buffer_modify_discard)
+{
+
+ GstBufferPool *pool = create_pool (10, 0, 0);
+ GstBuffer *buf = NULL, *prev;
+ GstMemory *mem;
+
+ gst_buffer_pool_set_active (pool, TRUE);
+ gst_buffer_pool_acquire_buffer (pool, &buf, NULL);
+ prev = buf;
+ /* remove all memory, pool should not reuse this buffer */
+ gst_buffer_remove_all_memory (buf);
+ gst_buffer_unref (buf);
+
+ gst_buffer_pool_acquire_buffer (pool, &buf, NULL);
+ fail_if (buf == prev, "got a reused buffer instead of new one");
+ prev = buf;
+ /* do resize, pool should not reuse this buffer */
+ gst_buffer_resize (buf, 5, 2);
+ gst_buffer_unref (buf);
+
+ gst_buffer_pool_acquire_buffer (pool, &buf, NULL);
+ fail_if (buf == prev, "got a reused buffer instead of new one");
+ prev = buf;
+ /* keep ref to memory, not exclusive so pool should reuse this buffer */
+ mem = gst_buffer_get_memory (buf, 0);
+ gst_buffer_unref (buf);
+ gst_memory_unref (mem);
+
+ gst_buffer_pool_acquire_buffer (pool, &buf, NULL);
+ fail_unless (buf == prev, "got a fresh buffer instead of previous");
+ mem = gst_buffer_get_memory (buf, 0);
+
+ gst_buffer_unref (buf);
+
+ gst_buffer_pool_set_active (pool, FALSE);
+ gst_object_unref (pool);
+}
+
+GST_END_TEST;
static Suite *
gst_buffer_pool_suite (void)
tcase_add_test (tc_chain, test_buffer_out_of_order_reuse);
tcase_add_test (tc_chain, test_pool_config_buffer_size);
tcase_add_test (tc_chain, test_inactive_pool_returns_flushing);
+ tcase_add_test (tc_chain, test_buffer_modify_discard);
return s;
}