1e5ca6d325f1fc83497d9c2ae00218fd5e418769
[platform/upstream/gstreamer.git] / tests / examples / memory / my-memory.c
1 /* GStreamer
2  * Copyright (C) 2012 Wim Taymans <wim.taymans@gmail.be>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "my-memory.h"
21
22 typedef struct
23 {
24   GstMemory mem;
25
26   gpointer data;
27
28 } MyMemory;
29
30
31 static GstMemory *
32 _my_alloc (GstAllocator * allocator, gsize size,
33     GstAllocationParams * params, gpointer user_data)
34 {
35   MyMemory *mem;
36   gsize maxsize = size + params->prefix + params->padding;
37
38   GST_DEBUG ("alloc from allocator %p", allocator);
39
40   mem = g_slice_new (MyMemory);
41
42   gst_memory_init (GST_MEMORY_CAST (mem), params->flags, allocator, NULL,
43       maxsize, params->align, params->prefix, size);
44
45   mem->data = NULL;
46
47   return (GstMemory *) mem;
48 }
49
50 static void
51 _my_free (GstAllocator * allocator, GstMemory * mem)
52 {
53   MyMemory *mmem = (MyMemory *) mem;
54
55   g_free (mmem->data);
56   g_slice_free (MyMemory, mmem);
57   GST_DEBUG ("%p: freed", mmem);
58 }
59
60 static gpointer
61 _my_mem_map (MyMemory * mem, gsize maxsize, GstMapFlags flags)
62 {
63   gpointer res;
64
65   while (TRUE) {
66     if ((res = g_atomic_pointer_get (&mem->data)) != NULL)
67       break;
68
69     res = g_malloc (maxsize);
70
71     if (g_atomic_pointer_compare_and_exchange (&mem->data, NULL, res))
72       break;
73
74     g_free (res);
75   }
76
77   GST_DEBUG ("%p: mapped %p", mem, res);
78
79   return res;
80 }
81
82 static gboolean
83 _my_mem_unmap (MyMemory * mem)
84 {
85   GST_DEBUG ("%p: unmapped", mem);
86   return TRUE;
87 }
88
89 static MyMemory *
90 _my_mem_share (MyMemory * mem, gssize offset, gsize size)
91 {
92   MyMemory *sub;
93   GstMemory *parent;
94
95   GST_DEBUG ("%p: share %" G_GSSIZE_FORMAT " %" G_GSIZE_FORMAT, mem, offset,
96       size);
97
98   /* find the real parent */
99   if ((parent = mem->mem.parent) == NULL)
100     parent = (GstMemory *) mem;
101
102   if (size == -1)
103     size = mem->mem.size - offset;
104
105   sub = g_slice_new (MyMemory);
106   /* the shared memory is always readonly */
107   gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) |
108       GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent,
109       mem->mem.maxsize, mem->mem.align, mem->mem.offset + offset, size);
110
111   /* install pointer */
112   sub->data = _my_mem_map (mem, mem->mem.maxsize, GST_MAP_READ);
113
114   return sub;
115 }
116
117 typedef struct
118 {
119   GstAllocator parent;
120 } MyMemoryAllocator;
121
122 typedef struct
123 {
124   GstAllocatorClass parent_class;
125 } MyMemoryAllocatorClass;
126
127 GType my_memory_allocator_get_type (void);
128 G_DEFINE_TYPE (MyMemoryAllocator, my_memory_allocator, GST_TYPE_ALLOCATOR);
129
130 static void
131 my_memory_allocator_class_init (MyMemoryAllocatorClass * klass)
132 {
133   GstAllocatorClass *allocator_class;
134
135   allocator_class = (GstAllocatorClass *) klass;
136
137   allocator_class->alloc = _my_alloc;
138   allocator_class->free = _my_free;
139 }
140
141 static void
142 my_memory_allocator_init (MyMemoryAllocator * allocator)
143 {
144   GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
145
146   alloc->mem_type = "MyMemory";
147   alloc->mem_map = (GstMemoryMapFunction) _my_mem_map;
148   alloc->mem_unmap = (GstMemoryUnmapFunction) _my_mem_unmap;
149   alloc->mem_share = (GstMemoryShareFunction) _my_mem_share;
150 }
151
152 void
153 my_memory_init (void)
154 {
155   GstAllocator *allocator;
156
157   allocator = g_object_new (my_memory_allocator_get_type (), NULL);
158
159   gst_allocator_register ("MyMemory", allocator);
160 }