1 /* GStreamer Intel MSDK plugin
2 * Copyright (c) 2018, Intel Corporation
3 * Copyright (c) 2018, Igalia S.L.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * 3. Neither the name of the copyright holder nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGDECE
29 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "gstmsdkvideomemory.h"
37 #include "gstmsdkallocator.h"
39 #define GST_MSDK_BUFFER_SURFACE gst_msdk_buffer_surface_quark_get ()
41 gst_msdk_buffer_surface_quark_get (void)
45 if (g_once_init_enter (&g_quark)) {
46 gsize quark = (gsize) g_quark_from_static_string ("GstMsdkBufferSurface");
47 g_once_init_leave (&g_quark, quark);
52 static mfxFrameSurface1 *
53 gst_msdk_video_allocator_get_surface (GstAllocator * allocator)
55 mfxFrameInfo frame_info = { {0,}, 0, };
56 mfxFrameSurface1 *surface;
57 GstMsdkContext *context = NULL;
58 mfxFrameAllocResponse *resp = NULL;
59 GstVideoInfo *vinfo = NULL;
61 if (GST_IS_MSDK_VIDEO_ALLOCATOR (allocator)) {
62 context = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator)->context;
63 resp = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator)->alloc_response;
64 vinfo = &GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator)->image_info;
65 } else if (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator)) {
66 context = GST_MSDK_DMABUF_ALLOCATOR_CAST (allocator)->context;
67 resp = GST_MSDK_DMABUF_ALLOCATOR_CAST (allocator)->alloc_response;
68 vinfo = &GST_MSDK_DMABUF_ALLOCATOR_CAST (allocator)->image_info;
73 surface = gst_msdk_context_get_surface_available (context, resp);
75 GST_ERROR ("failed to get surface available");
79 gst_msdk_set_mfx_frame_info_from_video_info (&frame_info, vinfo);
80 surface->Info = frame_info;
86 gst_msdk_video_memory_get_surface_available (GstMemory * mem)
88 GstAllocator *allocator;
89 mfxFrameSurface1 *surface;
91 g_return_val_if_fail (mem, FALSE);
93 allocator = mem->allocator;
94 surface = gst_msdk_video_allocator_get_surface (allocator);
96 if (GST_IS_MSDK_VIDEO_ALLOCATOR (allocator)) {
97 GST_MSDK_VIDEO_MEMORY_CAST (mem)->surface = surface;
98 } else if (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator)) {
99 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem),
100 GST_MSDK_BUFFER_SURFACE, surface, NULL);
103 return surface ? TRUE : FALSE;
107 * Every time releasing a gst buffer, we need to check the status of surface's lock,
108 * so that we could manage locked surfaces seperatedly in the context.
109 * Otherwise, we put the surface to the available list.
112 gst_msdk_video_memory_release_surface (GstMemory * mem)
114 mfxFrameSurface1 *surface = NULL;
115 GstMsdkContext *context = NULL;
116 mfxFrameAllocResponse *alloc_response = NULL;
118 g_return_if_fail (mem);
120 if (GST_IS_MSDK_VIDEO_ALLOCATOR (mem->allocator)) {
121 surface = GST_MSDK_VIDEO_MEMORY_CAST (mem)->surface;
122 context = GST_MSDK_VIDEO_ALLOCATOR_CAST (mem->allocator)->context;
124 GST_MSDK_VIDEO_ALLOCATOR_CAST (mem->allocator)->alloc_response;
125 } else if (GST_IS_MSDK_DMABUF_ALLOCATOR (mem->allocator)) {
127 gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
128 GST_MSDK_BUFFER_SURFACE);
129 context = GST_MSDK_DMABUF_ALLOCATOR_CAST (mem->allocator)->context;
131 GST_MSDK_DMABUF_ALLOCATOR_CAST (mem->allocator)->alloc_response;
136 if (surface->Data.Locked > 0)
137 gst_msdk_context_put_surface_locked (context, alloc_response, surface);
139 gst_msdk_context_put_surface_available (context, alloc_response, surface);
141 if (GST_IS_MSDK_VIDEO_ALLOCATOR (mem->allocator))
142 GST_MSDK_VIDEO_MEMORY_CAST (mem)->surface = NULL;
143 else if (GST_IS_MSDK_DMABUF_ALLOCATOR (mem->allocator))
144 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem),
145 GST_MSDK_BUFFER_SURFACE, NULL, NULL);
151 gst_msdk_video_memory_new (GstAllocator * base_allocator)
153 GstMsdkVideoAllocator *allocator;
155 GstMsdkVideoMemory *mem;
157 g_return_val_if_fail (base_allocator, NULL);
158 g_return_val_if_fail (GST_IS_MSDK_VIDEO_ALLOCATOR (base_allocator), NULL);
160 allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (base_allocator);
162 mem = g_slice_new0 (GstMsdkVideoMemory);
166 mem->surface = gst_msdk_video_allocator_get_surface (base_allocator);
170 vip = &allocator->image_info;
171 gst_memory_init (&mem->parent_instance, GST_MEMORY_FLAG_NO_SHARE,
172 base_allocator, NULL, GST_VIDEO_INFO_SIZE (vip), 0, 0,
173 GST_VIDEO_INFO_SIZE (vip));
175 return GST_MEMORY_CAST (mem);
179 gst_video_meta_map_msdk_memory (GstVideoMeta * meta, guint plane,
180 GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags)
182 gboolean ret = FALSE;
183 GstAllocator *allocator;
184 GstMsdkVideoAllocator *msdk_video_allocator;
185 GstMsdkVideoMemory *mem =
186 GST_MSDK_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));
187 GstMsdkMemoryID *mem_id;
190 guint plane_id = plane;
192 g_return_val_if_fail (mem, FALSE);
194 allocator = GST_MEMORY_CAST (mem)->allocator;
195 msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
197 if (!GST_IS_MSDK_VIDEO_ALLOCATOR (allocator)) {
198 GST_WARNING ("The allocator is not MSDK video allocator");
203 GST_WARNING ("The surface is not allocated");
207 if ((flags & GST_MAP_WRITE) && mem->surface && mem->surface->Data.Locked) {
208 GST_WARNING ("The surface in memory %p is not still avaliable", mem);
213 gst_msdk_frame_lock (msdk_video_allocator->context,
214 mem->surface->Data.MemId, &mem->surface->Data);
218 mem_id = mem->surface->Data.MemId;
220 /* msdk doesn't support I420 format and we used YV12 internally
221 * So we need to swap U/V planes for mapping */
222 if (meta->format == GST_VIDEO_FORMAT_I420)
223 plane_id = plane ? (plane == 1 ? 2 : 1) : plane;
226 offset = mem_id->image.offsets[plane_id];
227 pitch = mem_id->image.pitches[plane_id];
229 /* TODO: This is just to avoid compile errors on Windows.
230 * Implement handling Windows-specific video-memory.
232 offset = mem_id->offset;
233 pitch = mem_id->pitch;
236 *data = mem->surface->Data.Y + offset;
240 ret = (*data != NULL);
246 gst_video_meta_unmap_msdk_memory (GstVideoMeta * meta, guint plane,
249 GstAllocator *allocator;
250 GstMsdkVideoAllocator *msdk_video_allocator;
251 GstMsdkVideoMemory *mem =
252 GST_MSDK_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));
254 g_return_val_if_fail (mem, FALSE);
256 allocator = GST_MEMORY_CAST (mem)->allocator;
257 msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
259 if (mem->mapped == 1)
260 gst_msdk_frame_unlock (msdk_video_allocator->context,
261 mem->surface->Data.MemId, &mem->surface->Data);
270 gst_msdk_video_memory_map_full (GstMemory * base_mem, GstMapInfo * info,
273 GstMsdkVideoMemory *const mem = GST_MSDK_VIDEO_MEMORY_CAST (base_mem);
274 GstAllocator *allocator = base_mem->allocator;
275 GstMsdkVideoAllocator *msdk_video_allocator =
276 GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
278 g_return_val_if_fail (mem, NULL);
281 GST_WARNING ("The surface is not allocated");
285 if ((info->flags & GST_MAP_WRITE) && mem->surface
286 && mem->surface->Data.Locked) {
287 GST_WARNING ("The surface in memory %p is not still avaliable", mem);
291 gst_msdk_frame_lock (msdk_video_allocator->context, mem->surface->Data.MemId,
292 &mem->surface->Data);
293 return mem->surface->Data.Y;
297 gst_msdk_video_memory_unmap (GstMemory * base_mem)
299 GstMsdkVideoMemory *const mem = GST_MSDK_VIDEO_MEMORY_CAST (base_mem);
300 GstAllocator *allocator = base_mem->allocator;
301 GstMsdkVideoAllocator *msdk_video_allocator =
302 GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
304 gst_msdk_frame_unlock (msdk_video_allocator->context,
305 mem->surface->Data.MemId, &mem->surface->Data);
308 /* GstMsdkVideoAllocator */
309 G_DEFINE_TYPE (GstMsdkVideoAllocator, gst_msdk_video_allocator,
313 gst_msdk_video_allocator_alloc (GstAllocator * allocator, gsize size,
314 GstAllocationParams * params)
316 return gst_msdk_video_memory_new (allocator);
320 gst_msdk_video_allocator_finalize (GObject * object)
322 GstMsdkVideoAllocator *allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (object);
324 gst_object_unref (allocator->context);
325 G_OBJECT_CLASS (gst_msdk_video_allocator_parent_class)->finalize (object);
329 gst_msdk_video_allocator_class_init (GstMsdkVideoAllocatorClass * klass)
331 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
332 GstAllocatorClass *const allocator_class = GST_ALLOCATOR_CLASS (klass);
334 object_class->finalize = gst_msdk_video_allocator_finalize;
336 allocator_class->alloc = gst_msdk_video_allocator_alloc;
340 gst_msdk_video_allocator_init (GstMsdkVideoAllocator * allocator)
342 GstAllocator *const base_allocator = GST_ALLOCATOR_CAST (allocator);
344 base_allocator->mem_type = GST_MSDK_VIDEO_MEMORY_NAME;
345 base_allocator->mem_map_full = gst_msdk_video_memory_map_full;
346 base_allocator->mem_unmap = gst_msdk_video_memory_unmap;
348 GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
352 gst_msdk_video_allocator_new (GstMsdkContext * context,
353 GstVideoInfo * image_info, mfxFrameAllocResponse * alloc_resp)
355 GstMsdkVideoAllocator *allocator;
357 g_return_val_if_fail (context != NULL, NULL);
358 g_return_val_if_fail (image_info != NULL, NULL);
360 allocator = g_object_new (GST_TYPE_MSDK_VIDEO_ALLOCATOR, NULL);
364 allocator->context = gst_object_ref (context);
365 allocator->image_info = *image_info;
366 allocator->alloc_response = alloc_resp;
368 return GST_ALLOCATOR_CAST (allocator);
371 /* GstMsdkDmaBufMemory */
373 gst_msdk_dmabuf_memory_new (GstAllocator * base_allocator)
376 mfxFrameSurface1 *surface;
378 g_return_val_if_fail (base_allocator, NULL);
379 g_return_val_if_fail (GST_IS_MSDK_DMABUF_ALLOCATOR (base_allocator), NULL);
381 surface = gst_msdk_video_allocator_get_surface (base_allocator);
385 return gst_msdk_dmabuf_memory_new_with_surface (base_allocator, surface);
392 gst_msdk_dmabuf_memory_new_with_surface (GstAllocator * allocator,
393 mfxFrameSurface1 * surface)
397 GstMsdkMemoryID *mem_id;
401 g_return_val_if_fail (allocator, NULL);
402 g_return_val_if_fail (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator), NULL);
404 mem_id = surface->Data.MemId;
405 fd = mem_id->info.handle;
406 size = mem_id->info.mem_size;
408 if (fd < 0 || (fd = dup (fd)) < 0) {
409 GST_ERROR ("Failed to get dmabuf handle");
413 mem = gst_dmabuf_allocator_alloc (allocator, fd, size);
415 GST_ERROR ("failed ! dmabuf fd: %d", fd);
419 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem),
420 GST_MSDK_BUFFER_SURFACE, surface, NULL);
428 /* GstMsdkDmaBufAllocator */
429 G_DEFINE_TYPE (GstMsdkDmaBufAllocator, gst_msdk_dmabuf_allocator,
430 GST_TYPE_DMABUF_ALLOCATOR);
433 gst_msdk_dmabuf_allocator_finalize (GObject * object)
435 GstMsdkDmaBufAllocator *allocator = GST_MSDK_DMABUF_ALLOCATOR_CAST (object);
437 gst_object_unref (allocator->context);
438 G_OBJECT_CLASS (gst_msdk_dmabuf_allocator_parent_class)->finalize (object);
442 gst_msdk_dmabuf_allocator_class_init (GstMsdkDmaBufAllocatorClass * klass)
444 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
446 object_class->finalize = gst_msdk_dmabuf_allocator_finalize;
450 gst_msdk_dmabuf_allocator_init (GstMsdkDmaBufAllocator * allocator)
452 GstAllocator *const base_allocator = GST_ALLOCATOR_CAST (allocator);
453 base_allocator->mem_type = GST_MSDK_DMABUF_MEMORY_NAME;
457 gst_msdk_dmabuf_allocator_new (GstMsdkContext * context,
458 GstVideoInfo * image_info, mfxFrameAllocResponse * alloc_resp)
460 GstMsdkDmaBufAllocator *allocator;
462 g_return_val_if_fail (context != NULL, NULL);
463 g_return_val_if_fail (image_info != NULL, NULL);
465 allocator = g_object_new (GST_TYPE_MSDK_DMABUF_ALLOCATOR, NULL);
469 allocator->context = gst_object_ref (context);
470 allocator->image_info = *image_info;
471 allocator->alloc_response = alloc_resp;
473 return GST_ALLOCATOR_CAST (allocator);