1 /* GStreamer dmabuf allocator
2 * Copyright (C) 2013 Linaro SA
3 * Author: Benjamin Gaignard <benjamin.gaignard@linaro.org> for Linaro.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for mordetails.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "gstfdmemory.h"
26 #include "gstdmabuf.h"
27
28 /**
29 * SECTION:gstdmabuf
30 * @title: GstDmaBufAllocator
31 * @short_description: Memory wrapper for Linux dmabuf memory
32 * @see_also: #GstMemory
33 *
34 * Since: 1.2
35 */
36
37 #ifdef HAVE_LINUX_DMA_BUF_H
38 #include <sys/ioctl.h>
39 #include <linux/dma-buf.h>
40 #endif
41
42 GST_DEBUG_CATEGORY_STATIC (dmabuf_debug);
43 #define GST_CAT_DEFAULT dmabuf_debug
44
45 #define _do_init \
46 GST_DEBUG_CATEGORY_INIT (dmabuf_debug, \
47 "dmabuf", 0, "dmabuf memory");
48
49 G_DEFINE_TYPE_WITH_CODE (GstDmaBufAllocator, gst_dmabuf_allocator,
50 GST_TYPE_FD_ALLOCATOR, _do_init);
51
52 static gpointer
gst_dmabuf_mem_map(GstMemory * gmem,GstMapInfo * info,gsize maxsize)53 gst_dmabuf_mem_map (GstMemory * gmem, GstMapInfo * info, gsize maxsize)
54 {
55 GstAllocator *allocator = gmem->allocator;
56 gpointer ret;
57
58 #ifdef HAVE_LINUX_DMA_BUF_H
59 struct dma_buf_sync sync = { DMA_BUF_SYNC_START };
60
61 if (info->flags & GST_MAP_READ)
62 sync.flags |= DMA_BUF_SYNC_READ;
63
64 if (info->flags & GST_MAP_WRITE)
65 sync.flags |= DMA_BUF_SYNC_WRITE;
66 #endif
67
68 ret = allocator->mem_map (gmem, maxsize, info->flags);
69
70 #ifdef HAVE_LINUX_DMA_BUF_H
71 if (ret) {
72 if (ioctl (gst_fd_memory_get_fd (gmem), DMA_BUF_IOCTL_SYNC, &sync) < 0)
73 GST_WARNING_OBJECT (allocator, "Failed to synchronize DMABuf: %s (%i)",
74 g_strerror (errno), errno);
75 }
76 #endif
77
78 return ret;
79 }
80
81 static void
gst_dmabuf_mem_unmap(GstMemory * gmem,GstMapInfo * info)82 gst_dmabuf_mem_unmap (GstMemory * gmem, GstMapInfo * info)
83 {
84 GstAllocator *allocator = gmem->allocator;
85 #ifdef HAVE_LINUX_DMA_BUF_H
86 struct dma_buf_sync sync = { DMA_BUF_SYNC_END };
87
88 if (info->flags & GST_MAP_READ)
89 sync.flags |= DMA_BUF_SYNC_READ;
90
91 if (info->flags & GST_MAP_WRITE)
92 sync.flags |= DMA_BUF_SYNC_WRITE;
93
94 if (ioctl (gst_fd_memory_get_fd (gmem), DMA_BUF_IOCTL_SYNC, &sync) < 0)
95 GST_WARNING_OBJECT (allocator, "Failed to synchronize DMABuf: %s (%i)",
96 g_strerror (errno), errno);
97 #else
98 GST_WARNING_OBJECT (allocator, "Using DMABuf without synchronization.");
99 #endif
100
101 allocator->mem_unmap (gmem);
102 }
103
104 static void
gst_dmabuf_allocator_class_init(GstDmaBufAllocatorClass * klass)105 gst_dmabuf_allocator_class_init (GstDmaBufAllocatorClass * klass)
106 {
107 }
108
109 static void
gst_dmabuf_allocator_init(GstDmaBufAllocator * allocator)110 gst_dmabuf_allocator_init (GstDmaBufAllocator * allocator)
111 {
112 GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
113
114 alloc->mem_type = GST_ALLOCATOR_DMABUF;
115 alloc->mem_map_full = gst_dmabuf_mem_map;
116 alloc->mem_unmap_full = gst_dmabuf_mem_unmap;
117 }
118
119 /**
120 * gst_dmabuf_allocator_new:
121 *
122 * Return a new dmabuf allocator.
123 *
124 * Returns: (transfer full): a new dmabuf allocator, or NULL if the allocator
125 * isn't available. Use gst_object_unref() to release the allocator after
126 * usage
127 *
128 * Since: 1.2
129 */
130 GstAllocator *
gst_dmabuf_allocator_new(void)131 gst_dmabuf_allocator_new (void)
132 {
133 GstAllocator *alloc;
134
135 alloc = g_object_new (GST_TYPE_DMABUF_ALLOCATOR, NULL);
136 gst_object_ref_sink (alloc);
137
138 return alloc;
139 }
140
141 /**
142 * gst_dmabuf_allocator_alloc:
143 * @allocator: allocator to be used for this memory
144 * @fd: dmabuf file descriptor
145 * @size: memory size
146 *
147 * Return a %GstMemory that wraps a dmabuf file descriptor.
148 *
149 * Returns: (transfer full): a GstMemory based on @allocator.
150 * When the buffer will be released dmabuf allocator will close the @fd.
151 * The memory is only mmapped on gst_buffer_map() request.
152 *
153 * Since: 1.2
154 */
155 GstMemory *
gst_dmabuf_allocator_alloc(GstAllocator * allocator,gint fd,gsize size)156 gst_dmabuf_allocator_alloc (GstAllocator * allocator, gint fd, gsize size)
157 {
158 g_return_val_if_fail (GST_IS_DMABUF_ALLOCATOR (allocator), NULL);
159
160 return gst_fd_allocator_alloc (allocator, fd, size, GST_FD_MEMORY_FLAG_NONE);
161 }
162
163 /**
164 * gst_dmabuf_allocator_alloc_with_flags:
165 * @allocator: allocator to be used for this memory
166 * @fd: dmabuf file descriptor
167 * @size: memory size
168 * @flags: extra #GstFdMemoryFlags
169 *
170 * Return a %GstMemory that wraps a dmabuf file descriptor.
171 *
172 * Returns: (transfer full): a GstMemory based on @allocator.
173 *
174 * When the buffer will be released the allocator will close the @fd unless
175 * the %GST_FD_MEMORY_FLAG_DONT_CLOSE flag is specified.
176 * The memory is only mmapped on gst_buffer_mmap() request.
177 *
178 * Since: 1.16
179 */
180 GstMemory *
gst_dmabuf_allocator_alloc_with_flags(GstAllocator * allocator,gint fd,gsize size,GstFdMemoryFlags flags)181 gst_dmabuf_allocator_alloc_with_flags (GstAllocator * allocator, gint fd,
182 gsize size, GstFdMemoryFlags flags)
183 {
184 g_return_val_if_fail (GST_IS_DMABUF_ALLOCATOR (allocator), NULL);
185
186 return gst_fd_allocator_alloc (allocator, fd, size, flags);
187 }
188
189 /**
190 * gst_dmabuf_memory_get_fd:
191 * @mem: the memory to get the file descriptor
192 *
193 * Return the file descriptor associated with @mem.
194 *
195 * Returns: the file descriptor associated with the memory, or -1. The file
196 * descriptor is still owned by the GstMemory. Use dup to take a copy
197 * if you intend to use it beyond the lifetime of this GstMemory.
198 *
199 * Since: 1.2
200 */
201 gint
gst_dmabuf_memory_get_fd(GstMemory * mem)202 gst_dmabuf_memory_get_fd (GstMemory * mem)
203 {
204 g_return_val_if_fail (gst_is_dmabuf_memory (mem), -1);
205
206 return gst_fd_memory_get_fd (mem);
207 }
208
209 /**
210 * gst_is_dmabuf_memory:
211 * @mem: the memory to be check
212 *
213 * Check if @mem is dmabuf memory.
214 *
215 * Returns: %TRUE if @mem is dmabuf memory, otherwise %FALSE
216 *
217 * Since: 1.2
218 */
219 gboolean
gst_is_dmabuf_memory(GstMemory * mem)220 gst_is_dmabuf_memory (GstMemory * mem)
221 {
222 g_return_val_if_fail (mem != NULL, FALSE);
223
224 return GST_IS_DMABUF_ALLOCATOR (mem->allocator);
225 }
226