diff --git a/gst/Makefile.am b/gst/Makefile.am index 059f7cb64a..6337565942 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -73,6 +73,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \ gstatomicqueue.c \ gstmessage.c \ gstmeta.c \ + gstmemory.c \ gstminiobject.c \ gstpad.c \ gstpadtemplate.c \ @@ -168,6 +169,7 @@ gst_headers = \ gstmacros.h \ gstmessage.h \ gstmeta.h \ + gstmemory.h \ gstminiobject.h \ gstpad.h \ gstpadtemplate.h \ diff --git a/gst/gst.h b/gst/gst.h index 9870f554fa..954fd6c885 100644 --- a/gst/gst.h +++ b/gst/gst.h @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include diff --git a/gst/gstmemory.c b/gst/gstmemory.c new file mode 100644 index 0000000000..10b6d75950 --- /dev/null +++ b/gst/gstmemory.c @@ -0,0 +1,249 @@ +/* GStreamer + * Copyright (C) 2011 Wim Taymans + * + * gstmemory.c: memory block handling + * + * 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 "config.h" + +#include "gst_private.h" + +#include "gstmemory.h" + +struct _GstMemoryImpl +{ + GQuark name; + + GstMemoryInfo info; +}; + +typedef struct +{ + GstMemory mem; + + guint8 *data; + GFreeFunc free_func; + gsize maxsize; + gsize offset; + gsize size; +} GstMemoryDefault; + +static const GstMemoryImpl *_default_memory_impl; + +static gsize +_default_get_sizes (GstMemory * mem, gsize * maxsize) +{ + GstMemoryDefault *def = (GstMemoryDefault *) mem; + + if (maxsize) + *maxsize = def->maxsize; + + return def->size; +} + +static void +_default_set_size (GstMemory * mem, gsize size) +{ + GstMemoryDefault *def = (GstMemoryDefault *) mem; + + g_return_if_fail (def->size + def->offset > def->maxsize); + + def->size = size; +} + +static gpointer +_default_map (GstMemory * mem, gsize * size, gsize * maxsize, GstMapFlags flags) +{ + GstMemoryDefault *def = (GstMemoryDefault *) mem; + + if (size) + *size = def->size; + if (maxsize) + *maxsize = def->maxsize; + + return def->data + def->offset; +} + +static gboolean +_default_unmap (GstMemory * mem, gpointer data, gsize size) +{ + GstMemoryDefault *def = (GstMemoryDefault *) mem; + + def->size = size; + + return TRUE; +} + +static void +_default_free (GstMemory * mem) +{ + GstMemoryDefault *def = (GstMemoryDefault *) mem; + + if (def->free_func) + def->free_func (def->data); +} + +static GstMemory * +_default_copy (GstMemory * mem) +{ + GstMemoryDefault *def = (GstMemoryDefault *) mem; + GstMemoryDefault *copy; + + copy = g_slice_new (GstMemoryDefault); + copy->mem.impl = _default_memory_impl; + copy->data = g_memdup (def->data, def->maxsize); + copy->free_func = g_free; + copy->maxsize = def->maxsize; + copy->offset = def->offset; + copy->size = def->size; + + return (GstMemory *) copy; +} + +const GstMemoryImpl * +gst_memory_register (const gchar * name, const GstMemoryInfo * info) +{ + GstMemoryImpl *impl; + + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (info != NULL, NULL); + + impl = g_slice_new (GstMemoryImpl); + impl->name = g_quark_from_string (name); + impl->info = *info; + + GST_DEBUG ("register \"%s\" of size %" G_GSIZE_FORMAT, name); + +#if 0 + g_static_rw_lock_writer_lock (&lock); + g_hash_table_insert (memoryimpl, (gpointer) name, (gpointer) impl); + g_static_rw_lock_writer_unlock (&lock); +#endif + + return impl; +} + +void +_gst_memory_init (void) +{ + static const GstMemoryInfo info = { + _default_get_sizes, + _default_set_size, + _default_map, + _default_unmap, + _default_free, + _default_copy + }; + _default_memory_impl = gst_memory_register ("GstMemoryDefault", &info); +} + +GstMemory * +gst_memory_ref (GstMemory * mem) +{ + g_return_val_if_fail (mem != NULL, NULL); + + g_atomic_int_inc (&mem->refcount); + + return mem; +} + +void +gst_memory_unref (GstMemory * mem) +{ + g_return_if_fail (mem != NULL); + + if (g_atomic_int_dec_and_test (&mem->refcount)) + mem->impl->info.free (mem); +} + +gsize +gst_memory_get_sizes (GstMemory * mem, gsize * maxsize) +{ + g_return_val_if_fail (mem != NULL, 0); + + return mem->impl->info.get_sizes (mem, maxsize); +} + +void +gst_memory_set_size (GstMemory * mem, gsize size) +{ + g_return_if_fail (mem != NULL); + + mem->impl->info.set_size (mem, size); +} + +gpointer +gst_memory_map (GstMemory * mem, gsize * size, gsize * maxsize, + GstMapFlags flags) +{ + g_return_val_if_fail (mem != NULL, NULL); + + return mem->impl->info.map (mem, size, maxsize, flags); +} + +gboolean +gst_memory_unmap (GstMemory * mem, gpointer data, gsize size) +{ + g_return_val_if_fail (mem != NULL, FALSE); + + return mem->impl->info.unmap (mem, data, size); +} + +GstMemory * +gst_memory_copy (GstMemory * mem) +{ + g_return_val_if_fail (mem != NULL, NULL); + + return mem->impl->info.copy (mem); +} + +GstMemory * +gst_memory_new_wrapped (gpointer data, GFreeFunc free_func, + gsize maxsize, gsize offset, gsize size) +{ + GstMemoryDefault *mem; + + mem = g_slice_new (GstMemoryDefault); + mem->mem.impl = _default_memory_impl; + mem->data = data; + mem->free_func = free_func; + mem->maxsize = maxsize; + mem->offset = offset; + mem->size = size; + + return (GstMemory *) mem; +} + +GstMemory * +gst_memory_new_alloc (gsize maxsize, gsize align) +{ + GstMemory *mem; + gpointer data; + gsize offset; + + data = g_try_malloc (maxsize + align); + if (data == NULL) + return NULL; + + if ((offset = ((guintptr) data & align))) + offset = align - offset; + + mem = gst_memory_new_wrapped (data, g_free, maxsize + align, offset, maxsize); + + return mem; +} diff --git a/gst/gstmemory.h b/gst/gstmemory.h index 97ee524f79..ecd54edfe6 100644 --- a/gst/gstmemory.h +++ b/gst/gstmemory.h @@ -23,10 +23,13 @@ #ifndef __GST_MEMORY_H__ #define __GST_MEMORY_H__ +#include + G_BEGIN_DECLS typedef struct _GstMemory GstMemory; typedef struct _GstMemoryInfo GstMemoryInfo; +typedef struct _GstMemoryImpl GstMemoryImpl; /** * GstMemory: @@ -36,11 +39,16 @@ typedef struct _GstMemoryInfo GstMemoryInfo; * as the first member of their structure. */ struct _GstMemory { - const GstMemoryInfo *info; + const GstMemoryImpl *impl; gint refcount; }; +typedef enum { + GST_MAP_READ, + GST_MAP_WRITE, +} GstMapFlags; + /** * GST_MEMORY_TRACE_NAME: * @@ -51,10 +59,11 @@ struct _GstMemory { typedef gsize (*GstMemoryGetSizesFunction) (GstMemory *mem, gsize *maxsize); typedef void (*GstMemorySetSizeFunction) (GstMemory *mem, gsize size); -typedef gpointer (*GstMemoryMapFunction) (GstMemory *mem, gsize offset, gsize *size, +typedef gpointer (*GstMemoryMapFunction) (GstMemory *mem, gsize *size, gsize *maxsize, GstMapFlags flags); typedef gboolean (*GstMemoryUnmapFunction) (GstMemory *mem, gpointer data, gsize size); +typedef void (*GstMemoryFreeFunction) (GstMemory *mem); typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem); /** @@ -66,13 +75,11 @@ typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem); * structure. */ struct _GstMemoryInfo { - GQuark impl; - gsize size; - GstMemoryGetSizesFunction get_sizes; GstMemorySetSizeFunction set_size; GstMemoryMapFunction map; GstMemoryUnmapFunction unmap; + GstMemoryFreeFunction free; GstMemoryCopyFunction copy; }; @@ -96,12 +103,9 @@ GstMemory * gst_memory_new_wrapped (gpointer data, GFreeFunc free_func, GstMemory * gst_memory_new_alloc (gsize maxsize, gsize align); +const GstMemoryImpl * gst_memory_register (const gchar *impl, const GstMemoryInfo *info); + #if 0 -const GstMemoryInfo * gst_memory_register (const gchar *impl, gsize size, - GstMemoryGetSizesFunction get_sizes, - GstMemorySetSizeFunction set_size, - GstMemoryMapFunction map, - GstMemoryUnmapFunction unmap); const GstMemoryInfo * gst_memory_get_info (const gchar * impl); #endif