+2007-04-26 Tim-Philipp Müller <tim at centricular dot net>
+
+ * docs/gst/gstreamer-sections.txt:
+ * gst/gstbuffer.c: (gst_buffer_try_new_and_alloc):
+ * gst/gstbuffer.h:
+ * tests/check/gst/gstbuffer.c: (GST_START_TEST),
+ (gst_buffer_suite):
+ API: add gst_buffer_try_new_and_alloc() plus unit test (#431940).
+
2007-04-26 Stefan Kost <ensonic@users.sf.net>
* gst/gstregistrybinary.c: (gst_registry_binary_write_cache),
gst_buffer_new
gst_buffer_new_and_alloc
+gst_buffer_try_new_and_alloc
gst_buffer_ref
gst_buffer_unref
* @size: the size of the new buffer's data.
*
* Creates a newly allocated buffer with data of the given size.
- * The buffer memory is not cleared.
+ * The buffer memory is not cleared. If the requested amount of
+ * memory can't be allocated, the program will abort. Use
+ * gst_buffer_try_new_and_alloc() if you want to handle this case
+ * gracefully or have gotten the size to allocate from an untrusted
+ * source such as a media stream.
+ *
*
* Note that when @size == 0, the buffer data pointer will be NULL.
*
return newbuf;
}
+/**
+ * gst_buffer_try_new_and_alloc:
+ * @size: the size of the new buffer's data.
+ *
+ * Tries to create a newly allocated buffer with data of the given size. If
+ * the requested amount of memory can't be allocated, NULL will be returned.
+ * The buffer memory is not cleared.
+ *
+ * Note that when @size == 0, the buffer data pointer will be NULL.
+ *
+ * MT safe.
+ *
+ * Returns: a new #GstBuffer, or NULL if the memory couldn't be allocated.
+ *
+ * Since: 0.10.13
+ */
+GstBuffer *
+gst_buffer_try_new_and_alloc (guint size)
+{
+ GstBuffer *newbuf;
+ guint8 *malloc_data;
+
+ malloc_data = g_try_malloc (size);
+
+ if (G_UNLIKELY (malloc_data == NULL && size != 0)) {
+ GST_CAT_WARNING (GST_CAT_BUFFER, "failed to allocate %d bytes", size);
+ return NULL;
+ }
+
+ /* FIXME: there's no g_type_try_create_instance() in GObject yet, so this
+ * will still abort if a new GstBuffer structure can't be allocated */
+ newbuf = gst_buffer_new ();
+
+ GST_BUFFER_MALLOCDATA (newbuf) = malloc_data;
+ GST_BUFFER_DATA (newbuf) = malloc_data;
+ GST_BUFFER_SIZE (newbuf) = size;
+
+ GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size);
+
+ return newbuf;
+}
+
/**
* gst_buffer_get_caps:
* @buffer: a #GstBuffer.
GstMiniObjectClass mini_object_class;
};
+GType gst_buffer_get_type (void);
+
/* allocation */
-GType gst_buffer_get_type (void);
-GstBuffer* gst_buffer_new (void);
-GstBuffer* gst_buffer_new_and_alloc (guint size);
+GstBuffer * gst_buffer_new (void);
+GstBuffer * gst_buffer_new_and_alloc (guint size);
+GstBuffer * gst_buffer_try_new_and_alloc (guint size);
/**
* gst_buffer_set_data:
* Boston, MA 02111-1307, USA.
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_VALGRIND
+# include <valgrind/valgrind.h>
+#else
+# define RUNNING_ON_VALGRIND FALSE
+#endif
+
#include <gst/check/gstcheck.h>
GST_START_TEST (test_caps)
GST_END_TEST;
-Suite *
+GST_START_TEST (test_try_new_and_alloc)
+{
+ GstBuffer *buf;
+
+ /* special case: alloc of 0 bytes results in new buffer with NULL data */
+ buf = gst_buffer_try_new_and_alloc (0);
+ fail_unless (buf != NULL);
+ fail_unless (GST_IS_BUFFER (buf));
+ fail_unless (GST_BUFFER_SIZE (buf) == 0);
+ fail_unless (GST_BUFFER_DATA (buf) == NULL);
+ fail_unless (GST_BUFFER_MALLOCDATA (buf) == NULL);
+ gst_buffer_unref (buf);
+
+ /* normal alloc should still work */
+ buf = gst_buffer_try_new_and_alloc (640 * 480 * 4);
+ fail_unless (buf != NULL);
+ fail_unless (GST_IS_BUFFER (buf));
+ fail_unless (GST_BUFFER_SIZE (buf) == (640 * 480 * 4));
+ fail_unless (GST_BUFFER_DATA (buf) != NULL);
+ fail_unless (GST_BUFFER_MALLOCDATA (buf) != NULL);
+ GST_BUFFER_DATA (buf)[640 * 479 * 4 + 479] = 0xff;
+ gst_buffer_unref (buf);
+
+ /* now this better fail (don't run in valgrind, it will abort
+ * or warn when passing silly arguments to malloc) */
+ if (!RUNNING_ON_VALGRIND) {
+ buf = gst_buffer_try_new_and_alloc ((guint) - 1);
+ fail_unless (buf == NULL);
+ }
+}
+
+GST_END_TEST;
+
+static Suite *
gst_buffer_suite (void)
{
Suite *s = suite_create ("GstBuffer");
tcase_add_test (tc_chain, test_span);
tcase_add_test (tc_chain, test_metadata_writable);
tcase_add_test (tc_chain, test_copy);
+ tcase_add_test (tc_chain, test_try_new_and_alloc);
return s;
}