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 G_DEFINE_TYPE (GstDmaBufAllocator, gst_dmabuf_allocator, GST_TYPE_FD_ALLOCATOR);
46
47 static gpointer
gst_dmabuf_mem_map(GstMemory * gmem,GstMapInfo * info,gsize maxsize)48 gst_dmabuf_mem_map (GstMemory * gmem, GstMapInfo * info, gsize maxsize)
49 {
50 GstAllocator *allocator = gmem->allocator;
51 gpointer ret;
52
53 #ifdef HAVE_LINUX_DMA_BUF_H
54 struct dma_buf_sync sync = { DMA_BUF_SYNC_START };
55
56 if (info->flags & GST_MAP_READ)
57 sync.flags |= DMA_BUF_SYNC_READ;
58
59 if (info->flags & GST_MAP_WRITE)
60 sync.flags |= DMA_BUF_SYNC_WRITE;
61 #endif
62
63 ret = allocator->mem_map (gmem, maxsize, info->flags);
64
65 #ifdef HAVE_LINUX_DMA_BUF_H
66 if (ret) {
67 if (ioctl (gst_fd_memory_get_fd (gmem), DMA_BUF_IOCTL_SYNC, &sync) < 0)
68 GST_WARNING_OBJECT (allocator, "Failed to synchronize DMABuf: %s (%i)",
69 g_strerror (errno), errno);
70 }
71 #endif
72
73 return ret;
74 }
75
76 static void
gst_dmabuf_mem_unmap(GstMemory * gmem,GstMapInfo * info)77 gst_dmabuf_mem_unmap (GstMemory * gmem, GstMapInfo * info)
78 {
79 GstAllocator *allocator = gmem->allocator;
80 #ifdef HAVE_LINUX_DMA_BUF_H
81 struct dma_buf_sync sync = { DMA_BUF_SYNC_END };
82
83 if (info->flags & GST_MAP_READ)
84 sync.flags |= DMA_BUF_SYNC_READ;
85
86 if (info->flags & GST_MAP_WRITE)
87 sync.flags |= DMA_BUF_SYNC_WRITE;
88
89 if (ioctl (gst_fd_memory_get_fd (gmem), DMA_BUF_IOCTL_SYNC, &sync) < 0)
90 GST_WARNING_OBJECT (allocator, "Failed to synchronize DMABuf: %s (%i)",
91 g_strerror (errno), errno);
92 #else
93 GST_WARNING_OBJECT (allocator, "Using DMABuf without synchronization.");
94 #endif
95
96 allocator->mem_unmap (gmem);
97 }
98
99 static void
gst_dmabuf_allocator_class_init(GstDmaBufAllocatorClass * klass)100 gst_dmabuf_allocator_class_init (GstDmaBufAllocatorClass * klass)
101 {
102 }
103
104 static void
gst_dmabuf_allocator_init(GstDmaBufAllocator * allocator)105 gst_dmabuf_allocator_init (GstDmaBufAllocator * allocator)
106 {
107 GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
108
109 alloc->mem_type = GST_ALLOCATOR_DMABUF;
110 alloc->mem_map_full = gst_dmabuf_mem_map;
111 alloc->mem_unmap_full = gst_dmabuf_mem_unmap;
112 }
113
114 /**
115 * gst_dmabuf_allocator_new:
116 *
117 * Return a new dmabuf allocator.
118 *
119 * Returns: (transfer full): a new dmabuf allocator, or NULL if the allocator
120 * isn't available. Use gst_object_unref() to release the allocator after
121 * usage
122 *
123 * Since: 1.2
124 */
125 GstAllocator *
gst_dmabuf_allocator_new(void)126 gst_dmabuf_allocator_new (void)
127 {
128 GstAllocator *alloc;
129
130 GST_DEBUG_CATEGORY_INIT (dmabuf_debug, "dmabuf", 0, "dmabuf memory");
131
132 alloc = g_object_new (GST_TYPE_DMABUF_ALLOCATOR, NULL);
133 gst_object_ref_sink (alloc);
134
135 return alloc;
136 }
137
138 /**
139 * gst_dmabuf_allocator_alloc:
140 * @allocator: allocator to be used for this memory
141 * @fd: dmabuf file descriptor
142 * @size: memory size
143 *
144 * Return a %GstMemory that wraps a dmabuf file descriptor.
145 *
146 * Returns: (transfer full): a GstMemory based on @allocator.
147 * When the buffer will be released dmabuf allocator will close the @fd.
148 * The memory is only mmapped on gst_buffer_map() request.
149 *
150 * Since: 1.2
151 */
152 GstMemory *
gst_dmabuf_allocator_alloc(GstAllocator * allocator,gint fd,gsize size)153 gst_dmabuf_allocator_alloc (GstAllocator * allocator, gint fd, gsize size)
154 {
155 g_return_val_if_fail (GST_IS_DMABUF_ALLOCATOR (allocator), NULL);
156
157 return gst_fd_allocator_alloc (allocator, fd, size, GST_FD_MEMORY_FLAG_NONE);
158 }
159
160 /**
161 * gst_dmabuf_allocator_alloc_with_flags:
162 * @allocator: allocator to be used for this memory
163 * @fd: dmabuf file descriptor
164 * @size: memory size
165 * @flags: extra #GstFdMemoryFlags
166 *
167 * Return a %GstMemory that wraps a dmabuf file descriptor.
168 *
169 * Returns: (transfer full): a GstMemory based on @allocator.
170 *
171 * When the buffer will be released the allocator will close the @fd unless
172 * the %GST_FD_MEMORY_FLAG_DONT_CLOSE flag is specified.
173 * The memory is only mmapped on gst_buffer_mmap() request.
174 *
175 * Since: 1.16
176 */
177 GstMemory *
gst_dmabuf_allocator_alloc_with_flags(GstAllocator * allocator,gint fd,gsize size,GstFdMemoryFlags flags)178 gst_dmabuf_allocator_alloc_with_flags (GstAllocator * allocator, gint fd,
179 gsize size, GstFdMemoryFlags flags)
180 {
181 g_return_val_if_fail (GST_IS_DMABUF_ALLOCATOR (allocator), NULL);
182
183 return gst_fd_allocator_alloc (allocator, fd, size, flags);
184 }
185
186 /**
187 * gst_dmabuf_memory_get_fd:
188 * @mem: the memory to get the file descriptor
189 *
190 * Return the file descriptor associated with @mem.
191 *
192 * Returns: the file descriptor associated with the memory, or -1. The file
193 * descriptor is still owned by the GstMemory. Use dup to take a copy
194 * if you intend to use it beyond the lifetime of this GstMemory.
195 *
196 * Since: 1.2
197 */
198 gint
gst_dmabuf_memory_get_fd(GstMemory * mem)199 gst_dmabuf_memory_get_fd (GstMemory * mem)
200 {
201 g_return_val_if_fail (gst_is_dmabuf_memory (mem), -1);
202
203 return gst_fd_memory_get_fd (mem);
204 }
205
206 /**
207 * gst_is_dmabuf_memory:
208 * @mem: the memory to be check
209 *
210 * Check if @mem is dmabuf memory.
211 *
212 * Returns: %TRUE if @mem is dmabuf memory, otherwise %FALSE
213 *
214 * Since: 1.2
215 */
216 gboolean
gst_is_dmabuf_memory(GstMemory * mem)217 gst_is_dmabuf_memory (GstMemory * mem)
218 {
219 g_return_val_if_fail (mem != NULL, FALSE);
220
221 return GST_IS_DMABUF_ALLOCATOR (mem->allocator);
222 }
223