msdk: Avoid build failures on Windows until d3d allocator is implemented
[platform/upstream/gstreamer.git] / sys / msdk / gstmsdkvideomemory.c
1 /* GStreamer Intel MSDK plugin
2  * Copyright (c) 2018, Intel Corporation
3  * Copyright (c) 2018, Igalia S.L.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  *    this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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.
31  */
32
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <va/va.h>
36 #include "gstmsdkvideomemory.h"
37 #include "gstmsdkallocator.h"
38
39 static gboolean
40 ensure_data (GstMsdkVideoMemory * mem, GstMsdkVideoAllocator * allocator)
41 {
42   GstMsdkMemoryID *mem_id;
43   GstMsdkAllocResponse *resp =
44       gst_msdk_context_get_cached_alloc_responses (allocator->context,
45       allocator->alloc_response);
46
47   if (!resp) {
48     GST_WARNING ("failed to get allocation response");
49     return FALSE;
50   }
51
52   mem_id = (GstMsdkMemoryID *) resp->mem_ids[resp->num_used_memory++];
53   mem->surface->Data.MemId = mem_id;
54
55   return TRUE;
56 }
57
58 static mfxFrameSurface1 *
59 gst_msdk_video_allocator_create_surface (GstAllocator * allocator)
60 {
61   mfxFrameInfo frame_info = { {0,}, 0, };
62   mfxFrameSurface1 *surface;
63   GstMsdkVideoAllocator *msdk_video_allocator =
64       GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
65
66   surface = (mfxFrameSurface1 *) g_slice_new0 (mfxFrameSurface1);
67
68   if (!surface) {
69     GST_ERROR ("failed to allocate surface");
70     return NULL;
71   }
72
73   gst_msdk_set_mfx_frame_info_from_video_info (&frame_info,
74       &msdk_video_allocator->image_info);
75
76   surface->Info = frame_info;
77
78   return surface;
79 }
80
81 GstMemory *
82 gst_msdk_video_memory_new (GstAllocator * base_allocator)
83 {
84   GstMsdkVideoAllocator *allocator;
85   GstVideoInfo *vip;
86   GstMsdkVideoMemory *mem;
87
88   g_return_val_if_fail (base_allocator, NULL);
89   g_return_val_if_fail (GST_IS_MSDK_VIDEO_ALLOCATOR (base_allocator), NULL);
90
91   allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (base_allocator);
92
93   mem = g_slice_new0 (GstMsdkVideoMemory);
94   if (!mem)
95     return NULL;
96
97   mem->surface = gst_msdk_video_allocator_create_surface (base_allocator);
98
99   vip = &allocator->image_info;
100   gst_memory_init (&mem->parent_instance, GST_MEMORY_FLAG_NO_SHARE,
101       base_allocator, NULL, GST_VIDEO_INFO_SIZE (vip), 0, 0,
102       GST_VIDEO_INFO_SIZE (vip));
103
104   if (!ensure_data (mem, allocator))
105     return FALSE;
106
107   return GST_MEMORY_CAST (mem);
108 }
109
110 gboolean
111 gst_video_meta_map_msdk_memory (GstVideoMeta * meta, guint plane,
112     GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags)
113 {
114   gboolean ret = FALSE;
115   GstAllocator *allocator;
116   GstMsdkVideoAllocator *msdk_video_allocator;
117   GstMsdkVideoMemory *mem =
118       GST_MSDK_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));
119   GstMsdkMemoryID *mem_id;
120   guint offset = 0;
121   gint pitch = 0;
122
123   g_return_val_if_fail (mem, FALSE);
124
125   allocator = GST_MEMORY_CAST (mem)->allocator;
126   msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
127
128   if (!GST_IS_MSDK_VIDEO_ALLOCATOR (allocator)) {
129     GST_WARNING ("The allocator is not MSDK video allocator");
130     return FALSE;
131   }
132
133   if (!mem->surface) {
134     GST_WARNING ("The surface is not allocated");
135     return FALSE;
136   }
137
138   if ((flags & GST_MAP_WRITE) && mem->surface && mem->surface->Data.Locked) {
139     GST_WARNING ("The surface in memory %p is not still avaliable", mem);
140     return FALSE;
141   }
142
143   if (!mem->mapped) {
144     gst_msdk_frame_lock (msdk_video_allocator->context,
145         mem->surface->Data.MemId, &mem->surface->Data);
146   }
147
148   mem->mapped++;
149   mem_id = mem->surface->Data.MemId;
150
151 #ifndef _WIN32
152   offset = mem_id->image.offsets[plane];
153   pitch = mem_id->image.pitches[plane];
154 #else
155   /* TODO: This is just to avoid compile errors on Windows.
156    * Implement handling Windows-specific video-memory.
157    */
158   offset = mem_id->offset;
159   pitch = mem_id->pitch;
160 #endif
161
162   *data = mem->surface->Data.Y + offset;
163   *stride = pitch;
164
165   info->flags = flags;
166   ret = (*data != NULL);
167
168   return ret;
169 }
170
171 gboolean
172 gst_video_meta_unmap_msdk_memory (GstVideoMeta * meta, guint plane,
173     GstMapInfo * info)
174 {
175   GstAllocator *allocator;
176   GstMsdkVideoAllocator *msdk_video_allocator;
177   GstMsdkVideoMemory *mem =
178       GST_MSDK_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));
179
180   g_return_val_if_fail (mem, FALSE);
181
182   allocator = GST_MEMORY_CAST (mem)->allocator;
183   msdk_video_allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
184
185   if (mem->mapped == 1)
186     gst_msdk_frame_unlock (msdk_video_allocator->context,
187         mem->surface->Data.MemId, &mem->surface->Data);
188
189   mem->mapped--;
190
191   return TRUE;
192 }
193
194
195 static gpointer
196 gst_msdk_video_memory_map_full (GstMemory * base_mem, GstMapInfo * info,
197     gsize maxsize)
198 {
199   GstMsdkVideoMemory *const mem = GST_MSDK_VIDEO_MEMORY_CAST (base_mem);
200   GstAllocator *allocator = base_mem->allocator;
201   GstMsdkVideoAllocator *msdk_video_allocator =
202       GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
203
204   g_return_val_if_fail (mem, NULL);
205
206   if (!mem->surface) {
207     GST_WARNING ("The surface is not allocated");
208     return FALSE;
209   }
210
211   if ((info->flags & GST_MAP_WRITE) && mem->surface
212       && mem->surface->Data.Locked) {
213     GST_WARNING ("The surface in memory %p is not still avaliable", mem);
214     return FALSE;
215   }
216
217   gst_msdk_frame_lock (msdk_video_allocator->context, mem->surface->Data.MemId,
218       &mem->surface->Data);
219   return mem->surface->Data.Y;
220 }
221
222 static void
223 gst_msdk_video_memory_unmap (GstMemory * base_mem)
224 {
225   GstMsdkVideoMemory *const mem = GST_MSDK_VIDEO_MEMORY_CAST (base_mem);
226   GstAllocator *allocator = base_mem->allocator;
227   GstMsdkVideoAllocator *msdk_video_allocator =
228       GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
229
230   gst_msdk_frame_unlock (msdk_video_allocator->context,
231       mem->surface->Data.MemId, &mem->surface->Data);
232 }
233
234 /* GstMsdkVideoAllocator */
235 G_DEFINE_TYPE (GstMsdkVideoAllocator, gst_msdk_video_allocator,
236     GST_TYPE_ALLOCATOR);
237
238 static GstMemory *
239 gst_msdk_video_allocator_alloc (GstAllocator * allocator, gsize size,
240     GstAllocationParams * params)
241 {
242   return gst_msdk_video_memory_new (allocator);
243 }
244
245 static void
246 gst_msdk_video_allocator_free (GstAllocator * allocator, GstMemory * memory)
247 {
248   GstMsdkVideoAllocator *msdk_video_allocator =
249       GST_MSDK_VIDEO_ALLOCATOR_CAST (allocator);
250   GstMsdkAllocResponse *resp =
251       gst_msdk_context_get_cached_alloc_responses
252       (msdk_video_allocator->context, msdk_video_allocator->alloc_response);
253
254   if (resp)
255     resp->num_used_memory--;
256 }
257
258 static void
259 gst_msdk_video_allocator_finalize (GObject * object)
260 {
261   GstMsdkVideoAllocator *allocator = GST_MSDK_VIDEO_ALLOCATOR_CAST (object);
262
263   gst_object_unref (allocator->context);
264   G_OBJECT_CLASS (gst_msdk_video_allocator_parent_class)->finalize (object);
265 }
266
267 static void
268 gst_msdk_video_allocator_class_init (GstMsdkVideoAllocatorClass * klass)
269 {
270   GObjectClass *const object_class = G_OBJECT_CLASS (klass);
271   GstAllocatorClass *const allocator_class = GST_ALLOCATOR_CLASS (klass);
272
273   object_class->finalize = gst_msdk_video_allocator_finalize;
274
275   allocator_class->alloc = gst_msdk_video_allocator_alloc;
276   allocator_class->free = gst_msdk_video_allocator_free;
277 }
278
279 static void
280 gst_msdk_video_allocator_init (GstMsdkVideoAllocator * allocator)
281 {
282   GstAllocator *const base_allocator = GST_ALLOCATOR_CAST (allocator);
283
284   base_allocator->mem_type = GST_MSDK_VIDEO_MEMORY_NAME;
285   base_allocator->mem_map_full = gst_msdk_video_memory_map_full;
286   base_allocator->mem_unmap = gst_msdk_video_memory_unmap;
287
288   GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
289 }
290
291 GstAllocator *
292 gst_msdk_video_allocator_new (GstMsdkContext * context,
293     GstVideoInfo * image_info, mfxFrameAllocResponse * alloc_resp)
294 {
295   GstMsdkVideoAllocator *allocator;
296
297   g_return_val_if_fail (context != NULL, NULL);
298   g_return_val_if_fail (image_info != NULL, NULL);
299
300   allocator = g_object_new (GST_TYPE_MSDK_VIDEO_ALLOCATOR, NULL);
301   if (!allocator)
302     return NULL;
303
304   allocator->context = gst_object_ref (context);
305   allocator->image_info = *image_info;
306   allocator->alloc_response = alloc_resp;
307
308   return GST_ALLOCATOR_CAST (allocator);
309 }