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.
38 #include "gstmsdkvideomemory.h"
39 #include "gstmsdkallocator.h"
41 #define GST_MSDK_BUFFER_SURFACE gst_msdk_buffer_surface_quark_get ()
43 gst_msdk_buffer_surface_quark_get (void)
47 if (g_once_init_enter (&g_quark)) {
48 gsize quark = (gsize) g_quark_from_static_string ("GstMsdkBufferSurface");
49 g_once_init_leave (&g_quark, quark);
54 static mfxFrameSurface1 *
55 gst_msdk_video_allocator_get_surface (GstAllocator * allocator)
57 mfxFrameInfo frame_info = { {0,}, 0, };
58 mfxFrameSurface1 *surface;
59 GstMsdkContext *context = NULL;
60 mfxFrameAllocResponse *resp = NULL;
61 GstVideoInfo *vinfo = NULL;
63 if (GST_IS_MSDK_VIDEO_ALLOCATOR (allocator)) {
64 context = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator)->context;
65 resp = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator)->alloc_response;
66 vinfo = &GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator)->image_info;
67 } else if (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator)) {
68 context = GST_MSDK_DMABUF_ALLOCATOR_CAST (allocator)->context;
69 resp = GST_MSDK_DMABUF_ALLOCATOR_CAST (allocator)->alloc_response;
70 vinfo = &GST_MSDK_DMABUF_ALLOCATOR_CAST (allocator)->image_info;
75 surface = gst_msdk_context_get_surface_available (context, resp);
77 GST_ERROR ("failed to get surface available");
81 gst_msdk_set_mfx_frame_info_from_video_info (&frame_info, vinfo);
82 surface->Info = frame_info;
88 gst_msdk_video_memory_get_surface_available (GstMemory * mem)
90 GstAllocator *allocator;
91 mfxFrameSurface1 *surface;
93 g_return_val_if_fail (mem, FALSE);
95 allocator = mem->allocator;
96 surface = gst_msdk_video_allocator_get_surface (allocator);
98 if (GST_IS_MSDK_VIDEO_ALLOCATOR (allocator)) {
99 GST_MSDK_VIDEO_MEMORY_CAST (mem)->surface = surface;
100 } else if (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator)) {
101 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem),
102 GST_MSDK_BUFFER_SURFACE, surface, NULL);
105 return surface ? TRUE : FALSE;
109 * Every time releasing a gst buffer, we need to check the status of surface's lock,
110 * so that we could manage locked surfaces seperatedly in the context.
111 * Otherwise, we put the surface to the available list.
114 gst_msdk_video_memory_release_surface (GstMemory * mem)
116 mfxFrameSurface1 *surface = NULL;
117 GstMsdkContext *context = NULL;
118 mfxFrameAllocResponse *alloc_response = NULL;
120 g_return_if_fail (mem);
122 if (GST_IS_MSDK_VIDEO_ALLOCATOR (mem->allocator)) {
123 surface = GST_MSDK_VIDEO_MEMORY_CAST (mem)->surface;
124 context = GST_MSDK_VIDEO_ALLOCATOR_CAST (mem->allocator)->context;
126 GST_MSDK_VIDEO_ALLOCATOR_CAST (mem->allocator)->alloc_response;
127 } else if (GST_IS_MSDK_DMABUF_ALLOCATOR (mem->allocator)) {
129 gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
130 GST_MSDK_BUFFER_SURFACE);
131 context = GST_MSDK_DMABUF_ALLOCATOR_CAST (mem->allocator)->context;
133 GST_MSDK_DMABUF_ALLOCATOR_CAST (mem->allocator)->alloc_response;
138 if (surface->Data.Locked > 0)
139 gst_msdk_context_put_surface_locked (context, alloc_response, surface);
141 gst_msdk_context_put_surface_available (context, alloc_response, surface);
143 if (GST_IS_MSDK_VIDEO_ALLOCATOR (mem->allocator))
144 GST_MSDK_VIDEO_MEMORY_CAST (mem)->surface = NULL;
145 else if (GST_IS_MSDK_DMABUF_ALLOCATOR (mem->allocator))
146 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem),
147 GST_MSDK_BUFFER_SURFACE, NULL, NULL);
153 gst_msdk_video_memory_new (GstAllocator * base_allocator)
155 GstMsdkVideoAllocator *allocator;
157 GstMsdkVideoMemory *mem;
159 g_return_val_if_fail (base_allocator, NULL);
160 g_return_val_if_fail (GST_IS_MSDK_VIDEO_ALLOCATOR (base_allocator), NULL);
162 allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (base_allocator);
164 mem = g_slice_new0 (GstMsdkVideoMemory);
168 mem->surface = gst_msdk_video_allocator_get_surface (base_allocator);
170 g_slice_free (GstMsdkVideoMemory, mem);
174 vip = &allocator->image_info;
175 gst_memory_init (&mem->parent_instance, 0,
176 base_allocator, NULL, GST_VIDEO_INFO_SIZE (vip), 0, 0,
177 GST_VIDEO_INFO_SIZE (vip));
179 return GST_MEMORY_CAST (mem);
183 gst_video_meta_map_msdk_memory (GstVideoMeta * meta, guint plane,
184 GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags)
186 gboolean ret = FALSE;
187 GstAllocator *allocator;
188 GstMsdkVideoAllocator *msdk_video_allocator;
189 GstMsdkVideoMemory *mem =
190 GST_MSDK_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));
191 GstMsdkMemoryID *mem_id;
194 guint plane_id = plane;
196 g_return_val_if_fail (mem, FALSE);
198 allocator = GST_MEMORY_CAST (mem)->allocator;
199 msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
201 if (!GST_IS_MSDK_VIDEO_ALLOCATOR (allocator)) {
202 GST_WARNING ("The allocator is not MSDK video allocator");
207 GST_WARNING ("The surface is not allocated");
211 if ((flags & GST_MAP_WRITE) && mem->surface && mem->surface->Data.Locked) {
212 GST_WARNING ("The surface in memory %p is not still avaliable", mem);
217 gst_msdk_frame_lock (msdk_video_allocator->context,
218 mem->surface->Data.MemId, &mem->surface->Data);
222 mem_id = mem->surface->Data.MemId;
224 /* msdk doesn't support I420 format and we used YV12 internally
225 * So we need to swap U/V planes for mapping */
226 if (meta->format == GST_VIDEO_FORMAT_I420)
227 plane_id = plane ? (plane == 1 ? 2 : 1) : plane;
230 offset = mem_id->image.offsets[plane_id];
231 pitch = mem_id->image.pitches[plane_id];
233 /* TODO: This is just to avoid compile errors on Windows.
234 * Implement handling Windows-specific video-memory.
236 offset = mem_id->offset;
237 pitch = mem_id->pitch;
240 /* The first channel in memory is V for GST_VIDEO_FORMAT_VUYA */
241 if (meta->format == GST_VIDEO_FORMAT_VUYA)
242 *data = mem->surface->Data.V + offset;
243 else if (meta->format == GST_VIDEO_FORMAT_Y410)
244 *data = mem->surface->Data.U + offset; /* Data.Y410 */
246 *data = mem->surface->Data.Y + offset;
250 ret = (*data != NULL);
256 gst_video_meta_unmap_msdk_memory (GstVideoMeta * meta, guint plane,
259 GstAllocator *allocator;
260 GstMsdkVideoAllocator *msdk_video_allocator;
261 GstMsdkVideoMemory *mem =
262 GST_MSDK_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));
264 g_return_val_if_fail (mem, FALSE);
266 allocator = GST_MEMORY_CAST (mem)->allocator;
267 msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
269 if (mem->mapped == 1)
270 gst_msdk_frame_unlock (msdk_video_allocator->context,
271 mem->surface->Data.MemId, &mem->surface->Data);
280 gst_msdk_video_memory_map_full (GstMemory * base_mem, GstMapInfo * info,
283 GstMsdkVideoMemory *const mem = GST_MSDK_VIDEO_MEMORY_CAST (base_mem);
284 GstAllocator *allocator = base_mem->allocator;
285 GstMsdkVideoAllocator *msdk_video_allocator =
286 GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
288 g_return_val_if_fail (mem, NULL);
291 GST_WARNING ("The surface is not allocated");
295 if ((info->flags & GST_MAP_WRITE) && mem->surface
296 && mem->surface->Data.Locked) {
297 GST_WARNING ("The surface in memory %p is not still avaliable", mem);
301 gst_msdk_frame_lock (msdk_video_allocator->context, mem->surface->Data.MemId,
302 &mem->surface->Data);
303 return mem->surface->Data.Y;
307 gst_msdk_video_memory_unmap (GstMemory * base_mem)
309 GstMsdkVideoMemory *const mem = GST_MSDK_VIDEO_MEMORY_CAST (base_mem);
310 GstAllocator *allocator = base_mem->allocator;
311 GstMsdkVideoAllocator *msdk_video_allocator =
312 GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
314 gst_msdk_frame_unlock (msdk_video_allocator->context,
315 mem->surface->Data.MemId, &mem->surface->Data);
319 gst_msdk_video_memory_copy (GstMemory * base_mem, gssize offset, gssize size)
323 GstMsdkVideoAllocator *msdk_video_allocator;
325 GstMapInfo src_map, dst_map;
327 /* FIXME: can we consider offset and size here ? */
328 copy = gst_msdk_video_memory_new (base_mem->allocator);
331 GST_ERROR_OBJECT (base_mem->allocator, "Failed to create new video memory");
335 msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (base_mem->allocator);
337 info = &msdk_video_allocator->image_info;
338 mem_size = GST_VIDEO_INFO_SIZE (info);
340 gst_memory_map (base_mem, &src_map, GST_MAP_READ);
341 gst_memory_map (copy, &dst_map, GST_MAP_WRITE);
343 memcpy (dst_map.data, src_map.data, mem_size);
344 gst_memory_unmap (copy, &dst_map);
345 gst_memory_unmap (base_mem, &src_map);
350 /* GstMsdkVideoAllocator */
351 G_DEFINE_TYPE (GstMsdkVideoAllocator, gst_msdk_video_allocator,
355 gst_msdk_video_allocator_alloc (GstAllocator * allocator, gsize size,
356 GstAllocationParams * params)
358 return gst_msdk_video_memory_new (allocator);
362 gst_msdk_video_allocator_finalize (GObject * object)
364 GstMsdkVideoAllocator *allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (object);
366 gst_object_unref (allocator->context);
367 G_OBJECT_CLASS (gst_msdk_video_allocator_parent_class)->finalize (object);
371 gst_msdk_video_allocator_free (GstAllocator * allocator, GstMemory * base_mem)
373 GstMsdkVideoMemory *const mem = GST_MSDK_VIDEO_MEMORY_CAST (base_mem);
375 g_slice_free (GstMsdkVideoMemory, mem);
379 gst_msdk_video_allocator_class_init (GstMsdkVideoAllocatorClass * klass)
381 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
382 GstAllocatorClass *const allocator_class = GST_ALLOCATOR_CLASS (klass);
384 object_class->finalize = gst_msdk_video_allocator_finalize;
386 allocator_class->alloc = gst_msdk_video_allocator_alloc;
387 allocator_class->free = gst_msdk_video_allocator_free;
391 gst_msdk_video_allocator_init (GstMsdkVideoAllocator * allocator)
393 GstAllocator *const base_allocator = GST_ALLOCATOR_CAST (allocator);
395 base_allocator->mem_type = GST_MSDK_VIDEO_MEMORY_NAME;
396 base_allocator->mem_map_full = gst_msdk_video_memory_map_full;
397 base_allocator->mem_unmap = gst_msdk_video_memory_unmap;
398 base_allocator->mem_copy = gst_msdk_video_memory_copy;
400 GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
404 gst_msdk_video_allocator_new (GstMsdkContext * context,
405 GstVideoInfo * image_info, mfxFrameAllocResponse * alloc_resp)
407 GstMsdkVideoAllocator *allocator;
409 g_return_val_if_fail (context != NULL, NULL);
410 g_return_val_if_fail (image_info != NULL, NULL);
412 allocator = g_object_new (GST_TYPE_MSDK_VIDEO_ALLOCATOR, NULL);
416 allocator->context = gst_object_ref (context);
417 allocator->image_info = *image_info;
418 allocator->alloc_response = alloc_resp;
420 return GST_ALLOCATOR_CAST (allocator);
423 /* GstMsdkDmaBufMemory */
425 gst_msdk_dmabuf_memory_new (GstAllocator * base_allocator)
428 mfxFrameSurface1 *surface;
430 g_return_val_if_fail (base_allocator, NULL);
431 g_return_val_if_fail (GST_IS_MSDK_DMABUF_ALLOCATOR (base_allocator), NULL);
433 surface = gst_msdk_video_allocator_get_surface (base_allocator);
437 return gst_msdk_dmabuf_memory_new_with_surface (base_allocator, surface);
444 gst_msdk_dmabuf_memory_new_with_surface (GstAllocator * allocator,
445 mfxFrameSurface1 * surface)
449 GstMsdkMemoryID *mem_id;
453 g_return_val_if_fail (allocator, NULL);
454 g_return_val_if_fail (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator), NULL);
456 mem_id = surface->Data.MemId;
457 fd = mem_id->info.handle;
458 size = mem_id->info.mem_size;
460 if (fd < 0 || (fd = dup (fd)) < 0) {
461 GST_ERROR ("Failed to get dmabuf handle");
465 mem = gst_dmabuf_allocator_alloc (allocator, fd, size);
467 GST_ERROR ("failed ! dmabuf fd: %d", fd);
472 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem),
473 GST_MSDK_BUFFER_SURFACE, surface, NULL);
481 /* GstMsdkDmaBufAllocator */
482 G_DEFINE_TYPE (GstMsdkDmaBufAllocator, gst_msdk_dmabuf_allocator,
483 GST_TYPE_DMABUF_ALLOCATOR);
486 gst_msdk_dmabuf_allocator_finalize (GObject * object)
488 GstMsdkDmaBufAllocator *allocator = GST_MSDK_DMABUF_ALLOCATOR_CAST (object);
490 gst_object_unref (allocator->context);
491 G_OBJECT_CLASS (gst_msdk_dmabuf_allocator_parent_class)->finalize (object);
495 gst_msdk_dmabuf_allocator_class_init (GstMsdkDmaBufAllocatorClass * klass)
497 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
499 object_class->finalize = gst_msdk_dmabuf_allocator_finalize;
503 gst_msdk_dmabuf_allocator_init (GstMsdkDmaBufAllocator * allocator)
505 GstAllocator *const base_allocator = GST_ALLOCATOR_CAST (allocator);
506 base_allocator->mem_type = GST_MSDK_DMABUF_MEMORY_NAME;
510 gst_msdk_dmabuf_allocator_new (GstMsdkContext * context,
511 GstVideoInfo * image_info, mfxFrameAllocResponse * alloc_resp)
513 GstMsdkDmaBufAllocator *allocator;
515 g_return_val_if_fail (context != NULL, NULL);
516 g_return_val_if_fail (image_info != NULL, NULL);
518 allocator = g_object_new (GST_TYPE_MSDK_DMABUF_ALLOCATOR, NULL);
522 allocator->context = gst_object_ref (context);
523 allocator->image_info = *image_info;
524 allocator->alloc_response = alloc_resp;
526 return GST_ALLOCATOR_CAST (allocator);