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 static mfxFrameSurface1 *
40 gst_msdk_video_allocator_get_surface (GstAllocator * allocator)
42 mfxFrameInfo frame_info = { {0,}, 0, };
43 mfxFrameSurface1 *surface;
44 GstMsdkVideoAllocator *msdk_video_allocator =
45 GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
48 gst_msdk_context_get_surface_available (msdk_video_allocator->context,
49 msdk_video_allocator->alloc_response);
51 GST_ERROR ("failed to get surface available");
55 gst_msdk_set_mfx_frame_info_from_video_info (&frame_info,
56 &msdk_video_allocator->image_info);
58 surface->Info = frame_info;
64 gst_msdk_video_memory_get_surface_available (GstMemory * mem)
66 GstAllocator *allocator;
67 GstMsdkVideoMemory *msdk_mem;
69 g_return_val_if_fail (mem, FALSE);
70 g_return_val_if_fail (GST_IS_MSDK_VIDEO_MEMORY (mem), FALSE);
72 msdk_mem = GST_MSDK_VIDEO_MEMORY_CAST (mem);
73 allocator = mem->allocator;
74 msdk_mem->surface = gst_msdk_video_allocator_get_surface (allocator);
75 return msdk_mem->surface ? TRUE : FALSE;
79 * Every time releasing a gst buffer, we need to check the status of surface's lock,
80 * so that we could manage locked surfaces seperatedly in the context.
81 * Otherwise, we put the surface to the available list.
84 gst_msdk_video_memory_release_surface (GstMemory * mem)
86 GstMsdkVideoAllocator *msdk_video_allocator;
87 GstMsdkVideoMemory *msdk_mem;
89 g_return_if_fail (mem);
90 g_return_if_fail (GST_IS_MSDK_VIDEO_MEMORY (mem));
92 msdk_mem = GST_MSDK_VIDEO_MEMORY_CAST (mem);
93 msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (mem->allocator);
95 if (!msdk_mem->surface)
98 if (msdk_mem->surface->Data.Locked > 0)
99 gst_msdk_context_put_surface_locked (msdk_video_allocator->context,
100 msdk_video_allocator->alloc_response, msdk_mem->surface);
102 gst_msdk_context_put_surface_available (msdk_video_allocator->context,
103 msdk_video_allocator->alloc_response, msdk_mem->surface);
105 msdk_mem->surface = NULL;
110 gst_msdk_video_memory_new (GstAllocator * base_allocator)
112 GstMsdkVideoAllocator *allocator;
114 GstMsdkVideoMemory *mem;
116 g_return_val_if_fail (base_allocator, NULL);
117 g_return_val_if_fail (GST_IS_MSDK_VIDEO_ALLOCATOR (base_allocator), NULL);
119 allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (base_allocator);
121 mem = g_slice_new0 (GstMsdkVideoMemory);
125 mem->surface = gst_msdk_video_allocator_get_surface (base_allocator);
129 vip = &allocator->image_info;
130 gst_memory_init (&mem->parent_instance, GST_MEMORY_FLAG_NO_SHARE,
131 base_allocator, NULL, GST_VIDEO_INFO_SIZE (vip), 0, 0,
132 GST_VIDEO_INFO_SIZE (vip));
134 return GST_MEMORY_CAST (mem);
138 gst_video_meta_map_msdk_memory (GstVideoMeta * meta, guint plane,
139 GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags)
141 gboolean ret = FALSE;
142 GstAllocator *allocator;
143 GstMsdkVideoAllocator *msdk_video_allocator;
144 GstMsdkVideoMemory *mem =
145 GST_MSDK_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));
146 GstMsdkMemoryID *mem_id;
149 guint plane_id = plane;
151 g_return_val_if_fail (mem, FALSE);
153 allocator = GST_MEMORY_CAST (mem)->allocator;
154 msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
156 if (!GST_IS_MSDK_VIDEO_ALLOCATOR (allocator)) {
157 GST_WARNING ("The allocator is not MSDK video allocator");
162 GST_WARNING ("The surface is not allocated");
166 if ((flags & GST_MAP_WRITE) && mem->surface && mem->surface->Data.Locked) {
167 GST_WARNING ("The surface in memory %p is not still avaliable", mem);
172 gst_msdk_frame_lock (msdk_video_allocator->context,
173 mem->surface->Data.MemId, &mem->surface->Data);
177 mem_id = mem->surface->Data.MemId;
179 /* msdk doesn't support I420 format and we used YV12 internally
180 * So we need to swap U/V planes for mapping */
181 if (meta->format == GST_VIDEO_FORMAT_I420)
182 plane_id = plane ? (plane == 1 ? 2 : 1) : plane;
185 offset = mem_id->image.offsets[plane_id];
186 pitch = mem_id->image.pitches[plane_id];
188 /* TODO: This is just to avoid compile errors on Windows.
189 * Implement handling Windows-specific video-memory.
191 offset = mem_id->offset;
192 pitch = mem_id->pitch;
195 *data = mem->surface->Data.Y + offset;
199 ret = (*data != NULL);
205 gst_video_meta_unmap_msdk_memory (GstVideoMeta * meta, guint plane,
208 GstAllocator *allocator;
209 GstMsdkVideoAllocator *msdk_video_allocator;
210 GstMsdkVideoMemory *mem =
211 GST_MSDK_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));
213 g_return_val_if_fail (mem, FALSE);
215 allocator = GST_MEMORY_CAST (mem)->allocator;
216 msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
218 if (mem->mapped == 1)
219 gst_msdk_frame_unlock (msdk_video_allocator->context,
220 mem->surface->Data.MemId, &mem->surface->Data);
229 gst_msdk_video_memory_map_full (GstMemory * base_mem, GstMapInfo * info,
232 GstMsdkVideoMemory *const mem = GST_MSDK_VIDEO_MEMORY_CAST (base_mem);
233 GstAllocator *allocator = base_mem->allocator;
234 GstMsdkVideoAllocator *msdk_video_allocator =
235 GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
237 g_return_val_if_fail (mem, NULL);
240 GST_WARNING ("The surface is not allocated");
244 if ((info->flags & GST_MAP_WRITE) && mem->surface
245 && mem->surface->Data.Locked) {
246 GST_WARNING ("The surface in memory %p is not still avaliable", mem);
250 gst_msdk_frame_lock (msdk_video_allocator->context, mem->surface->Data.MemId,
251 &mem->surface->Data);
252 return mem->surface->Data.Y;
256 gst_msdk_video_memory_unmap (GstMemory * base_mem)
258 GstMsdkVideoMemory *const mem = GST_MSDK_VIDEO_MEMORY_CAST (base_mem);
259 GstAllocator *allocator = base_mem->allocator;
260 GstMsdkVideoAllocator *msdk_video_allocator =
261 GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
263 gst_msdk_frame_unlock (msdk_video_allocator->context,
264 mem->surface->Data.MemId, &mem->surface->Data);
267 /* GstMsdkVideoAllocator */
268 G_DEFINE_TYPE (GstMsdkVideoAllocator, gst_msdk_video_allocator,
272 gst_msdk_video_allocator_alloc (GstAllocator * allocator, gsize size,
273 GstAllocationParams * params)
275 return gst_msdk_video_memory_new (allocator);
279 gst_msdk_video_allocator_finalize (GObject * object)
281 GstMsdkVideoAllocator *allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (object);
283 gst_object_unref (allocator->context);
284 G_OBJECT_CLASS (gst_msdk_video_allocator_parent_class)->finalize (object);
288 gst_msdk_video_allocator_class_init (GstMsdkVideoAllocatorClass * klass)
290 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
291 GstAllocatorClass *const allocator_class = GST_ALLOCATOR_CLASS (klass);
293 object_class->finalize = gst_msdk_video_allocator_finalize;
295 allocator_class->alloc = gst_msdk_video_allocator_alloc;
299 gst_msdk_video_allocator_init (GstMsdkVideoAllocator * allocator)
301 GstAllocator *const base_allocator = GST_ALLOCATOR_CAST (allocator);
303 base_allocator->mem_type = GST_MSDK_VIDEO_MEMORY_NAME;
304 base_allocator->mem_map_full = gst_msdk_video_memory_map_full;
305 base_allocator->mem_unmap = gst_msdk_video_memory_unmap;
307 GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
311 gst_msdk_video_allocator_new (GstMsdkContext * context,
312 GstVideoInfo * image_info, mfxFrameAllocResponse * alloc_resp)
314 GstMsdkVideoAllocator *allocator;
316 g_return_val_if_fail (context != NULL, NULL);
317 g_return_val_if_fail (image_info != NULL, NULL);
319 allocator = g_object_new (GST_TYPE_MSDK_VIDEO_ALLOCATOR, NULL);
323 allocator->context = gst_object_ref (context);
324 allocator->image_info = *image_info;
325 allocator->alloc_response = alloc_resp;
327 return GST_ALLOCATOR_CAST (allocator);