768a6160fc9b8f112e228670904397daf857b1f0
[platform/upstream/gstreamer.git] / tests / examples / memory / my-vidmem.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-vidmem.h"
21
22 static GstAllocator *_my_allocator;
23
24 typedef struct
25 {
26   GstMemory mem;
27
28   guint format;
29   guint width;
30   guint height;
31   gpointer data;
32
33 } MyVidmem;
34
35
36 static GstMemory *
37 _my_alloc_alloc (GstAllocator * allocator, gsize size,
38     GstAllocationParams * params, gpointer user_data)
39 {
40   g_warning ("Use my_vidmem_alloc() to allocate from this allocator");
41
42   return NULL;
43 }
44
45 static gpointer
46 _my_vidmem_map (MyVidmem * mem, gsize maxsize, GstMapFlags flags)
47 {
48   gpointer res;
49
50   while (TRUE) {
51     if ((res = g_atomic_pointer_get (&mem->data)) != NULL)
52       break;
53
54     res = g_malloc (maxsize);
55
56     if (g_atomic_pointer_compare_and_exchange (&mem->data, NULL, res))
57       break;
58
59     g_free (res);
60   }
61
62   GST_DEBUG ("%p: mapped %p", mem, res);
63
64   return res;
65 }
66
67 static gboolean
68 _my_vidmem_unmap (MyVidmem * mem)
69 {
70   GST_DEBUG ("%p: unmapped", mem);
71   return TRUE;
72 }
73
74 static void
75 _my_vidmem_free (MyVidmem * mem)
76 {
77   g_free (mem->data);
78   g_slice_free (MyVidmem, mem);
79   GST_DEBUG ("%p: freed", mem);
80 }
81
82 static MyVidmem *
83 _my_vidmem_share (MyVidmem * mem, gssize offset, gsize size)
84 {
85   MyVidmem *sub;
86   GstMemory *parent;
87
88   GST_DEBUG ("%p: share %" G_GSSIZE_FORMAT " %" G_GSIZE_FORMAT, mem, offset,
89       size);
90
91   /* find the real parent */
92   if ((parent = mem->mem.parent) == NULL)
93     parent = (GstMemory *) mem;
94
95   if (size == -1)
96     size = mem->mem.size - offset;
97
98   sub = g_slice_new (MyVidmem);
99   /* the shared memory is always readonly */
100   gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) |
101       GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent,
102       mem->mem.maxsize, mem->mem.align, mem->mem.offset + offset, size);
103
104   /* install pointer */
105   sub->data = _my_vidmem_map (mem, mem->mem.maxsize, GST_MAP_READ);
106
107   return sub;
108 }
109
110 static void
111 free_allocator (GstMiniObject * obj)
112 {
113   g_slice_free (GstAllocator, (GstAllocator *) obj);
114 }
115
116 void
117 my_vidmem_init (void)
118 {
119   static const GstMemoryInfo info = {
120     "MyVidmem",
121     (GstAllocatorAllocFunction) _my_alloc_alloc,
122     (GstMemoryMapFunction) _my_vidmem_map,
123     (GstMemoryUnmapFunction) _my_vidmem_unmap,
124     (GstMemoryFreeFunction) _my_vidmem_free,
125     (GstMemoryCopyFunction) NULL,
126     (GstMemoryShareFunction) _my_vidmem_share,
127     (GstMemoryIsSpanFunction) NULL,
128   };
129
130   _my_allocator = g_slice_new (GstAllocator);
131   gst_allocator_init (_my_allocator, 0, &info, free_allocator);
132
133   gst_allocator_register ("MyVidmem", gst_allocator_ref (_my_allocator));
134 }
135
136
137 GstMemory *
138 my_vidmem_alloc (guint format, guint width, guint height)
139 {
140   MyVidmem *mem;
141   gsize maxsize;
142
143   GST_DEBUG ("alloc frame format %u %ux%u", format, width, height);
144
145   maxsize = (GST_ROUND_UP_4 (width) * height);
146
147   mem = g_slice_new (MyVidmem);
148
149   gst_memory_init (GST_MEMORY_CAST (mem), 0, _my_allocator, NULL,
150       maxsize, 31, 0, maxsize);
151
152   mem->format = format;
153   mem->width = width;
154   mem->height = height;
155   mem->data = NULL;
156
157   return (GstMemory *) mem;
158 }
159
160 gboolean
161 my_is_vidmem (GstMemory * mem)
162 {
163   return mem->allocator == _my_allocator;
164 }
165
166 void
167 my_vidmem_get_format (GstMemory * mem, guint * format, guint * width,
168     guint * height)
169 {
170   MyVidmem *vmem = (MyVidmem *) mem;
171
172   *format = vmem->format;
173   *width = vmem->width;
174   *height = vmem->height;
175 }