• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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