From 968de7b725a568a9a4c2843b2a362c83cbeffa56 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 5 Jul 2012 18:07:52 +0200 Subject: [PATCH] memory: add more examples Add an example of a custom allocator with a custom API. --- tests/examples/memory/Makefile.am | 2 +- tests/examples/memory/memory_test.c | 26 ++++++ tests/examples/memory/my-memory.h | 2 + tests/examples/memory/my-vidmem.c | 167 ++++++++++++++++++++++++++++++++++++ tests/examples/memory/my-vidmem.h | 31 +++++++ 5 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 tests/examples/memory/my-vidmem.c create mode 100644 tests/examples/memory/my-vidmem.h diff --git a/tests/examples/memory/Makefile.am b/tests/examples/memory/Makefile.am index 5611d3e..b0399c0 100644 --- a/tests/examples/memory/Makefile.am +++ b/tests/examples/memory/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = memory_test -memory_test_SOURCES = memory_test.c my-memory.c my-memory.h +memory_test_SOURCES = memory_test.c my-memory.c my-memory.h my-vidmem.c my-vidmem.h memory_test_LDADD = $(GST_OBJ_LIBS) memory_test_CFLAGS = $(GST_OBJ_CFLAGS) diff --git a/tests/examples/memory/memory_test.c b/tests/examples/memory/memory_test.c index 5290344..421a0dd 100644 --- a/tests/examples/memory/memory_test.c +++ b/tests/examples/memory/memory_test.c @@ -6,6 +6,7 @@ #include #include "my-memory.h" +#include "my-vidmem.h" int main (int argc, char **argv) @@ -14,9 +15,11 @@ main (int argc, char **argv) GstMemory *mem; GstAllocationParams params; GstMapInfo info; + guint f, w, h; gst_init (&argc, &argv); + /* memory using the default API */ my_memory_init (); alloc = gst_allocator_find ("MyMemory"); @@ -28,6 +31,29 @@ main (int argc, char **argv) gst_memory_unmap (mem, &info); gst_memory_unref (mem); + gst_allocator_unref (alloc); + + /* allocator with custom alloc API */ + my_vidmem_init (); + + /* we can get the allocator but we can only make objects from it when we know + * the API */ + alloc = gst_allocator_find ("MyVidmem"); + + /* use custom api to alloc */ + mem = my_vidmem_alloc (0, 640, 480); + g_assert (my_is_vidmem (mem)); + + my_vidmem_get_format (mem, &f, &w, &h); + g_assert (f == 0); + g_assert (w == 640); + g_assert (h == 480); + + gst_memory_map (mem, &info, GST_MAP_READ); + gst_memory_unmap (mem, &info); + + gst_memory_unref (mem); + gst_allocator_unref (alloc); return 0; } diff --git a/tests/examples/memory/my-memory.h b/tests/examples/memory/my-memory.h index 84a6d8c..c814003 100644 --- a/tests/examples/memory/my-memory.h +++ b/tests/examples/memory/my-memory.h @@ -19,5 +19,7 @@ #include +/* example of an allocator that delays allocation of the memory + * until the memory is mapped */ void my_memory_init (void); diff --git a/tests/examples/memory/my-vidmem.c b/tests/examples/memory/my-vidmem.c new file mode 100644 index 0000000..b254678 --- /dev/null +++ b/tests/examples/memory/my-vidmem.c @@ -0,0 +1,167 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "my-vidmem.h" + +static GstAllocator *_my_allocator; + +typedef struct +{ + GstMemory mem; + + guint format; + guint width; + guint height; + gpointer data; + +} MyVidmem; + + +static GstMemory * +_my_alloc_alloc (GstAllocator * allocator, gsize size, + GstAllocationParams * params, gpointer user_data) +{ + g_warning ("Use my_vidmem_alloc() to allocate from this allocator"); + + return NULL; +} + +static gpointer +_my_vidmem_map (MyVidmem * mem, gsize maxsize, GstMapFlags flags) +{ + gpointer res; + + while (TRUE) { + if ((res = g_atomic_pointer_get (&mem->data)) != NULL) + break; + + res = g_malloc (maxsize); + + if (g_atomic_pointer_compare_and_exchange (&mem->data, NULL, res)) + break; + + g_free (res); + } + + GST_DEBUG ("%p: mapped %p", mem, res); + + return res; +} + +static gboolean +_my_vidmem_unmap (MyVidmem * mem) +{ + GST_DEBUG ("%p: unmapped", mem); + return TRUE; +} + +static void +_my_vidmem_free (MyVidmem * mem) +{ + g_free (mem->data); + g_slice_free (MyVidmem, mem); + GST_DEBUG ("%p: freed", mem); +} + +static MyVidmem * +_my_vidmem_share (MyVidmem * mem, gssize offset, gsize size) +{ + MyVidmem *sub; + GstMemory *parent; + + GST_DEBUG ("%p: share %" G_GSSIZE_FORMAT, G_GSIZE_FORMAT, mem, offset, size); + + /* find the real parent */ + if ((parent = mem->mem.parent) == NULL) + parent = (GstMemory *) mem; + + if (size == -1) + size = mem->mem.size - offset; + + sub = g_slice_new (MyVidmem); + /* the shared memory is always readonly */ + gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) | + GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent, + mem->mem.maxsize, mem->mem.align, mem->mem.offset + offset, size); + + /* install pointer */ + sub->data = _my_vidmem_map (mem, mem->mem.maxsize, GST_MAP_READ); + + return sub; +} + +void +my_vidmem_init (void) +{ + static const GstMemoryInfo info = { + "MyVidmem", + (GstAllocatorAllocFunction) _my_alloc_alloc, + (GstMemoryMapFunction) _my_vidmem_map, + (GstMemoryUnmapFunction) _my_vidmem_unmap, + (GstMemoryFreeFunction) _my_vidmem_free, + (GstMemoryCopyFunction) NULL, + (GstMemoryShareFunction) _my_vidmem_share, + (GstMemoryIsSpanFunction) NULL, + }; + + _my_allocator = gst_allocator_new (&info, NULL, NULL); + + gst_allocator_register ("MyVidmem", gst_allocator_ref (_my_allocator)); +} + + +GstMemory * +my_vidmem_alloc (guint format, guint width, guint height) +{ + MyVidmem *mem; + gsize maxsize; + + GST_DEBUG ("alloc frame format %u %ux%u", format, width, height); + + maxsize = (GST_ROUND_UP_4 (width) * height); + + mem = g_slice_new (MyVidmem); + + gst_memory_init (GST_MEMORY_CAST (mem), 0, _my_allocator, NULL, + maxsize, 31, 0, maxsize); + + mem->format = format; + mem->width = width; + mem->height = height; + mem->data = NULL; + + return (GstMemory *) mem; +} + +gboolean +my_is_vidmem (GstMemory * mem) +{ + return mem->allocator == _my_allocator; +} + +void +my_vidmem_get_format (GstMemory * mem, guint * format, guint * width, + guint * height) +{ + MyVidmem *vmem = (MyVidmem *) mem; + + *format = vmem->format; + *width = vmem->width; + *height = vmem->height; +} diff --git a/tests/examples/memory/my-vidmem.h b/tests/examples/memory/my-vidmem.h new file mode 100644 index 0000000..337ebbb --- /dev/null +++ b/tests/examples/memory/my-vidmem.h @@ -0,0 +1,31 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +/* example of an allocator that needs a custom alloc function */ +void my_vidmem_init (void); + +GstMemory * my_vidmem_alloc (guint format, guint width, guint height); + +gboolean my_is_vidmem (GstMemory *mem); + +void my_vidmem_get_format (GstMemory *mem, guint *format, + guint *width, guint *height); + -- 2.7.4