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 "gstmsdkcontext.h"
34 #ifndef _WIN32
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <xf86drm.h>
38 #include <va/va_drm.h>
39 #include <gudev/gudev.h>
40 #endif
41
42 GST_DEBUG_CATEGORY_STATIC (gst_debug_msdkcontext);
43 #define GST_CAT_DEFAULT gst_debug_msdkcontext
44
45 struct _GstMsdkContextPrivate
46 {
47 MsdkSession session;
48 GList *cached_alloc_responses;
49 gboolean hardware;
50 gboolean has_frame_allocator;
51 GstMsdkContextJobType job_type;
52 gint shared_async_depth;
53 GMutex mutex;
54 GList *child_session_list;
55 GstMsdkContext *parent_context;
56 #ifndef _WIN32
57 gint fd;
58 VADisplay dpy;
59 #endif
60 };
61
62 #define gst_msdk_context_parent_class parent_class
63 G_DEFINE_TYPE_WITH_CODE (GstMsdkContext, gst_msdk_context, GST_TYPE_OBJECT,
64 G_ADD_PRIVATE (GstMsdkContext)
65 GST_DEBUG_CATEGORY_INIT (gst_debug_msdkcontext, "msdkcontext", 0,
66 "MSDK Context"));
67
68 #ifndef _WIN32
69
70 static gint
get_device_id(void)71 get_device_id (void)
72 {
73 GUdevClient *client = NULL;
74 GUdevEnumerator *e = NULL;
75 GList *devices, *l;
76 GUdevDevice *dev, *parent;
77 const gchar *devnode_path;
78 const gchar *devnode_files[2] = { "renderD[0-9]*", "card[0-9]*" };
79 int fd = -1, i;
80 const gchar *user_choice = g_getenv ("GST_MSDK_DRM_DEVICE");
81
82 if (user_choice) {
83 if (g_str_has_prefix (user_choice, "/dev/dri/"))
84 fd = open (user_choice, O_RDWR | O_CLOEXEC);
85
86 if (fd >= 0) {
87 drmVersionPtr drm_version = drmGetVersion (fd);
88
89 if (!drm_version || strncmp (drm_version->name, "i915", 4)) {
90 GST_ERROR ("The specified device isn't an Intel device");
91 drmFreeVersion (drm_version);
92 close (fd);
93 fd = -1;
94 } else {
95 GST_DEBUG ("Opened the specified drm device %s", user_choice);
96 drmFreeVersion (drm_version);
97 }
98 } else {
99 GST_ERROR ("The specified device isn't a valid drm device");
100 }
101
102 return fd;
103 }
104
105 client = g_udev_client_new (NULL);
106 if (!client)
107 goto done;
108
109 e = g_udev_enumerator_new (client);
110 if (!e)
111 goto done;
112
113 g_udev_enumerator_add_match_subsystem (e, "drm");
114 for (i = 0; i < 2; i++) {
115 g_udev_enumerator_add_match_name (e, devnode_files[i]);
116 devices = g_udev_enumerator_execute (e);
117
118 for (l = devices; l != NULL; l = l->next) {
119 dev = (GUdevDevice *) l->data;
120
121 parent = g_udev_device_get_parent (dev);
122 if (strcmp (g_udev_device_get_subsystem (parent), "pci") != 0 ||
123 strcmp (g_udev_device_get_driver (parent), "i915") != 0) {
124 g_object_unref (parent);
125 continue;
126 }
127 g_object_unref (parent);
128
129 devnode_path = g_udev_device_get_device_file (dev);
130 fd = open (devnode_path, O_RDWR | O_CLOEXEC);
131 if (fd < 0)
132 continue;
133 GST_DEBUG ("Opened the drm device node %s", devnode_path);
134 break;
135 }
136
137 g_list_foreach (devices, (GFunc) gst_object_unref, NULL);
138 g_list_free (devices);
139 if (fd >= 0)
140 goto done;
141 }
142
143 done:
144 if (e)
145 g_object_unref (e);
146 if (client)
147 g_object_unref (client);
148
149 return fd;
150 }
151
152
153 static gboolean
gst_msdk_context_use_vaapi(GstMsdkContext * context)154 gst_msdk_context_use_vaapi (GstMsdkContext * context)
155 {
156 gint fd;
157 gint maj_ver, min_ver;
158 VADisplay va_dpy = NULL;
159 VAStatus va_status;
160 mfxStatus status;
161 GstMsdkContextPrivate *priv = context->priv;
162
163 fd = get_device_id ();
164 if (fd < 0) {
165 GST_WARNING ("Couldn't find a valid drm device node");
166 return FALSE;
167 }
168
169 va_dpy = vaGetDisplayDRM (fd);
170 if (!va_dpy) {
171 GST_ERROR ("Couldn't get a VA DRM display");
172 goto failed;
173 }
174
175 va_status = vaInitialize (va_dpy, &maj_ver, &min_ver);
176 if (va_status != VA_STATUS_SUCCESS) {
177 GST_ERROR ("Couldn't initialize VA DRM display");
178 goto failed;
179 }
180
181 status = MFXVideoCORE_SetHandle (priv->session.session, MFX_HANDLE_VA_DISPLAY,
182 (mfxHDL) va_dpy);
183 if (status != MFX_ERR_NONE) {
184 GST_ERROR ("Setting VAAPI handle failed (%s)",
185 msdk_status_to_string (status));
186 goto failed;
187 }
188
189 priv->fd = fd;
190 priv->dpy = va_dpy;
191
192 return TRUE;
193
194 failed:
195 if (va_dpy)
196 vaTerminate (va_dpy);
197 close (fd);
198 return FALSE;
199 }
200 #endif
201
202 static gboolean
gst_msdk_context_open(GstMsdkContext * context,gboolean hardware,GstMsdkContextJobType job_type)203 gst_msdk_context_open (GstMsdkContext * context, gboolean hardware,
204 GstMsdkContextJobType job_type)
205 {
206 mfxU16 codename;
207 GstMsdkContextPrivate *priv = context->priv;
208 MsdkSession msdk_session;
209
210 priv->job_type = job_type;
211 priv->hardware = hardware;
212
213 msdk_session =
214 msdk_open_session (hardware ? MFX_IMPL_HARDWARE_ANY : MFX_IMPL_SOFTWARE);
215 priv->session = msdk_session;
216 if (!priv->session.session)
217 goto failed;
218
219 #ifndef _WIN32
220 priv->fd = -1;
221
222 if (hardware) {
223 if (!gst_msdk_context_use_vaapi (context))
224 goto failed;
225 }
226 #endif
227
228 codename = msdk_get_platform_codename (priv->session.session);
229
230 if (codename != MFX_PLATFORM_UNKNOWN)
231 GST_INFO ("Detected MFX platform with device code %d", codename);
232 else
233 GST_WARNING ("Unknown MFX platform");
234
235 return TRUE;
236
237 failed:
238 return FALSE;
239 }
240
241 static void
gst_msdk_context_init(GstMsdkContext * context)242 gst_msdk_context_init (GstMsdkContext * context)
243 {
244 GstMsdkContextPrivate *priv = gst_msdk_context_get_instance_private (context);
245
246 context->priv = priv;
247
248 g_mutex_init (&priv->mutex);
249 }
250
251 static void
release_child_session(gpointer session)252 release_child_session (gpointer session)
253 {
254 mfxStatus status;
255
256 mfxSession _session = session;
257 status = MFXDisjoinSession (_session);
258 if (status != MFX_ERR_NONE)
259 GST_WARNING ("failed to disjoin (%s)", msdk_status_to_string (status));
260 msdk_close_mfx_session (_session);
261 }
262
263 static void
gst_msdk_context_finalize(GObject * obj)264 gst_msdk_context_finalize (GObject * obj)
265 {
266 GstMsdkContext *context = GST_MSDK_CONTEXT_CAST (obj);
267 GstMsdkContextPrivate *priv = context->priv;
268
269 /* child sessions will be closed when the parent session is closed */
270 if (priv->parent_context) {
271 gst_object_unref (priv->parent_context);
272 goto done;
273 } else
274 g_list_free_full (priv->child_session_list, release_child_session);
275
276 msdk_close_session (&priv->session);
277 g_mutex_clear (&priv->mutex);
278
279 #ifndef _WIN32
280 if (priv->dpy)
281 vaTerminate (priv->dpy);
282 if (priv->fd >= 0)
283 close (priv->fd);
284 #endif
285
286 done:
287 G_OBJECT_CLASS (parent_class)->finalize (obj);
288 }
289
290 static void
gst_msdk_context_class_init(GstMsdkContextClass * klass)291 gst_msdk_context_class_init (GstMsdkContextClass * klass)
292 {
293 GObjectClass *const g_object_class = G_OBJECT_CLASS (klass);
294
295 g_object_class->finalize = gst_msdk_context_finalize;
296 }
297
298 GstMsdkContext *
gst_msdk_context_new(gboolean hardware,GstMsdkContextJobType job_type)299 gst_msdk_context_new (gboolean hardware, GstMsdkContextJobType job_type)
300 {
301 GstMsdkContext *obj = g_object_new (GST_TYPE_MSDK_CONTEXT, NULL);
302
303 if (obj && !gst_msdk_context_open (obj, hardware, job_type)) {
304 if (obj)
305 gst_object_unref (obj);
306 return NULL;
307 }
308
309 return obj;
310 }
311
312 GstMsdkContext *
gst_msdk_context_new_with_parent(GstMsdkContext * parent)313 gst_msdk_context_new_with_parent (GstMsdkContext * parent)
314 {
315 mfxStatus status;
316 GstMsdkContext *obj = g_object_new (GST_TYPE_MSDK_CONTEXT, NULL);
317 GstMsdkContextPrivate *priv = obj->priv;
318 GstMsdkContextPrivate *parent_priv = parent->priv;
319 mfxVersion version;
320 mfxIMPL impl;
321 MsdkSession child_msdk_session;
322 mfxHandleType handle_type = 0;
323 mfxHDL handle = NULL;
324
325 status = MFXQueryIMPL (parent_priv->session.session, &impl);
326
327 if (status == MFX_ERR_NONE)
328 status = MFXQueryVersion (parent_priv->session.session, &version);
329
330 if (status != MFX_ERR_NONE) {
331 GST_ERROR ("Failed to query the session attributes (%s)",
332 msdk_status_to_string (status));
333 g_object_unref (obj);
334 return NULL;
335 }
336
337 if (MFX_IMPL_VIA_VAAPI == (0x0f00 & (impl)))
338 handle_type = MFX_HANDLE_VA_DISPLAY;
339
340 if (handle_type) {
341 status =
342 MFXVideoCORE_GetHandle (parent_priv->session.session, handle_type,
343 &handle);
344
345 if (status != MFX_ERR_NONE || !handle) {
346 GST_ERROR ("Failed to get session handle (%s)",
347 msdk_status_to_string (status));
348 g_object_unref (obj);
349 return NULL;
350 }
351 }
352
353 child_msdk_session.loader = parent_priv->session.loader;
354 child_msdk_session.session = NULL;
355 status = msdk_init_msdk_session (impl, &version, &child_msdk_session);
356
357 if (status != MFX_ERR_NONE) {
358 GST_ERROR ("Failed to create a child mfx session (%s)",
359 msdk_status_to_string (status));
360 g_object_unref (obj);
361 return NULL;
362 }
363
364 if (handle) {
365 status =
366 MFXVideoCORE_SetHandle (child_msdk_session.session, handle_type,
367 handle);
368
369 if (status != MFX_ERR_NONE) {
370 GST_ERROR ("Failed to set a HW handle (%s)",
371 msdk_status_to_string (status));
372 MFXClose (child_msdk_session.session);
373 g_object_unref (obj);
374 return NULL;
375 }
376 }
377 #if (MFX_VERSION >= 1025)
378 status =
379 MFXJoinSession (parent_priv->session.session, child_msdk_session.session);
380
381 if (status != MFX_ERR_NONE) {
382 GST_ERROR ("Failed to join two sessions (%s)",
383 msdk_status_to_string (status));
384 MFXClose (child_msdk_session.session);
385 g_object_unref (obj);
386 return NULL;
387 }
388 #endif
389
390 /* Set loader to NULL for child session */
391 priv->session.loader = NULL;
392 priv->session.session = child_msdk_session.session;
393 priv->hardware = parent_priv->hardware;
394 priv->job_type = parent_priv->job_type;
395 parent_priv->child_session_list =
396 g_list_prepend (parent_priv->child_session_list, priv->session.session);
397 #ifndef _WIN32
398 priv->dpy = parent_priv->dpy;
399 priv->fd = parent_priv->fd;
400 #endif
401 priv->parent_context = gst_object_ref (parent);
402
403 return obj;
404 }
405
406 mfxSession
gst_msdk_context_get_session(GstMsdkContext * context)407 gst_msdk_context_get_session (GstMsdkContext * context)
408 {
409 return context->priv->session.session;
410 }
411
412 gpointer
gst_msdk_context_get_handle(GstMsdkContext * context)413 gst_msdk_context_get_handle (GstMsdkContext * context)
414 {
415 #ifndef _WIN32
416 return context->priv->dpy;
417 #else
418 return NULL;
419 #endif
420 }
421
422 gint
gst_msdk_context_get_fd(GstMsdkContext * context)423 gst_msdk_context_get_fd (GstMsdkContext * context)
424 {
425 #ifndef _WIN32
426 return context->priv->fd;
427 #else
428 return -1;
429 #endif
430 }
431
432 static gint
_find_response(gconstpointer resp,gconstpointer comp_resp)433 _find_response (gconstpointer resp, gconstpointer comp_resp)
434 {
435 GstMsdkAllocResponse *cached_resp = (GstMsdkAllocResponse *) resp;
436 mfxFrameAllocResponse *_resp = (mfxFrameAllocResponse *) comp_resp;
437
438 return cached_resp ? cached_resp->response.mids != _resp->mids : -1;
439 }
440
441 static inline gboolean
_requested_frame_size_is_equal_or_lower(mfxFrameAllocRequest * _req,GstMsdkAllocResponse * cached_resp)442 _requested_frame_size_is_equal_or_lower (mfxFrameAllocRequest * _req,
443 GstMsdkAllocResponse * cached_resp)
444 {
445 if (((_req->Type & MFX_MEMTYPE_EXPORT_FRAME) &&
446 _req->Info.Width == cached_resp->request.Info.Width &&
447 _req->Info.Height == cached_resp->request.Info.Height) ||
448 (!(_req->Type & MFX_MEMTYPE_EXPORT_FRAME) &&
449 _req->Info.Width <= cached_resp->request.Info.Width &&
450 _req->Info.Height <= cached_resp->request.Info.Height))
451 return TRUE;
452
453 return FALSE;
454 }
455
456 static gint
_find_request(gconstpointer resp,gconstpointer req)457 _find_request (gconstpointer resp, gconstpointer req)
458 {
459 GstMsdkAllocResponse *cached_resp = (GstMsdkAllocResponse *) resp;
460 mfxFrameAllocRequest *_req = (mfxFrameAllocRequest *) req;
461
462 /* Confirm if it's under the size of the cached response */
463 if (_req->NumFrameSuggested <= cached_resp->request.NumFrameSuggested &&
464 _requested_frame_size_is_equal_or_lower (_req, cached_resp))
465 return _req->Type & cached_resp->
466 request.Type & MFX_MEMTYPE_FROM_DECODE ? 0 : -1;
467
468 return -1;
469 }
470
471 GstMsdkAllocResponse *
gst_msdk_context_get_cached_alloc_responses(GstMsdkContext * context,mfxFrameAllocResponse * resp)472 gst_msdk_context_get_cached_alloc_responses (GstMsdkContext * context,
473 mfxFrameAllocResponse * resp)
474 {
475 GstMsdkContextPrivate *priv = context->priv;
476 GList *l =
477 g_list_find_custom (priv->cached_alloc_responses, resp, _find_response);
478
479 if (l)
480 return l->data;
481 else
482 return NULL;
483 }
484
485 GstMsdkAllocResponse *
gst_msdk_context_get_cached_alloc_responses_by_request(GstMsdkContext * context,mfxFrameAllocRequest * req)486 gst_msdk_context_get_cached_alloc_responses_by_request (GstMsdkContext *
487 context, mfxFrameAllocRequest * req)
488 {
489 GstMsdkContextPrivate *priv = context->priv;
490 GList *l =
491 g_list_find_custom (priv->cached_alloc_responses, req, _find_request);
492
493 if (l)
494 return l->data;
495 else
496 return NULL;
497 }
498
499 static void
create_surfaces(GstMsdkContext * context,GstMsdkAllocResponse * resp)500 create_surfaces (GstMsdkContext * context, GstMsdkAllocResponse * resp)
501 {
502 gint i;
503 mfxMemId *mem_id;
504 mfxFrameSurface1 *surface;
505
506 for (i = 0; i < resp->response.NumFrameActual; i++) {
507 mem_id = resp->response.mids[i];
508 surface = (mfxFrameSurface1 *) g_slice_new0 (mfxFrameSurface1);
509 if (!surface) {
510 GST_ERROR ("failed to allocate surface");
511 break;
512 }
513 surface->Data.MemId = mem_id;
514 resp->surfaces_avail = g_list_prepend (resp->surfaces_avail, surface);
515 }
516 }
517
518 static void
free_surface(gpointer surface)519 free_surface (gpointer surface)
520 {
521 g_slice_free1 (sizeof (mfxFrameSurface1), surface);
522 }
523
524 static void
remove_surfaces(GstMsdkContext * context,GstMsdkAllocResponse * resp)525 remove_surfaces (GstMsdkContext * context, GstMsdkAllocResponse * resp)
526 {
527 g_list_free_full (resp->surfaces_used, free_surface);
528 g_list_free_full (resp->surfaces_avail, free_surface);
529 g_list_free_full (resp->surfaces_locked, free_surface);
530 }
531
532 void
gst_msdk_context_add_alloc_response(GstMsdkContext * context,GstMsdkAllocResponse * resp)533 gst_msdk_context_add_alloc_response (GstMsdkContext * context,
534 GstMsdkAllocResponse * resp)
535 {
536 context->priv->cached_alloc_responses =
537 g_list_prepend (context->priv->cached_alloc_responses, resp);
538
539 create_surfaces (context, resp);
540 }
541
542 gboolean
gst_msdk_context_remove_alloc_response(GstMsdkContext * context,mfxFrameAllocResponse * resp)543 gst_msdk_context_remove_alloc_response (GstMsdkContext * context,
544 mfxFrameAllocResponse * resp)
545 {
546 GstMsdkAllocResponse *msdk_resp;
547 GstMsdkContextPrivate *priv = context->priv;
548 GList *l =
549 g_list_find_custom (priv->cached_alloc_responses, resp, _find_response);
550
551 if (!l)
552 return FALSE;
553
554 msdk_resp = l->data;
555
556 remove_surfaces (context, msdk_resp);
557
558 g_slice_free1 (sizeof (GstMsdkAllocResponse), msdk_resp);
559 priv->cached_alloc_responses =
560 g_list_delete_link (priv->cached_alloc_responses, l);
561
562 return TRUE;
563 }
564
565 static gboolean
check_surfaces_available(GstMsdkContext * context,GstMsdkAllocResponse * resp)566 check_surfaces_available (GstMsdkContext * context, GstMsdkAllocResponse * resp)
567 {
568 GList *l;
569 mfxFrameSurface1 *surface = NULL;
570 GstMsdkContextPrivate *priv = context->priv;
571 gboolean ret = FALSE;
572
573 g_mutex_lock (&priv->mutex);
574 for (l = resp->surfaces_locked; l;) {
575 surface = l->data;
576 l = l->next;
577 if (!surface->Data.Locked) {
578 resp->surfaces_locked = g_list_remove (resp->surfaces_locked, surface);
579 resp->surfaces_avail = g_list_prepend (resp->surfaces_avail, surface);
580 ret = TRUE;
581 }
582 }
583 g_mutex_unlock (&priv->mutex);
584
585 return ret;
586 }
587
588 /*
589 * There are 3 lists here in GstMsdkContext as the following:
590 * 1. surfaces_avail : surfaces which are free and unused anywhere
591 * 2. surfaces_used : surfaces coupled with a gst buffer and being used now.
592 * 3. surfaces_locked : surfaces still locked even after the gst buffer is released.
593 *
594 * Note that they need to be protected by mutex to be thread-safe.
595 */
596
597 mfxFrameSurface1 *
gst_msdk_context_get_surface_available(GstMsdkContext * context,mfxFrameAllocResponse * resp)598 gst_msdk_context_get_surface_available (GstMsdkContext * context,
599 mfxFrameAllocResponse * resp)
600 {
601 GList *l;
602 mfxFrameSurface1 *surface = NULL;
603 GstMsdkAllocResponse *msdk_resp =
604 gst_msdk_context_get_cached_alloc_responses (context, resp);
605 gint retry = 0;
606 GstMsdkContextPrivate *priv = context->priv;
607
608 retry:
609 g_mutex_lock (&priv->mutex);
610 for (l = msdk_resp->surfaces_avail; l;) {
611 surface = l->data;
612 l = l->next;
613 if (!surface->Data.Locked) {
614 msdk_resp->surfaces_avail =
615 g_list_remove (msdk_resp->surfaces_avail, surface);
616 msdk_resp->surfaces_used =
617 g_list_prepend (msdk_resp->surfaces_used, surface);
618 break;
619 }
620 }
621 g_mutex_unlock (&priv->mutex);
622
623 /*
624 * If a msdk context is shared by multiple msdk elements,
625 * upstream msdk element sometimes needs to wait for a gst buffer
626 * to be released in downstream.
627 *
628 * Poll the pool for a maximum of 20 millisecond.
629 *
630 * FIXME: Is there any better way to handle this case?
631 */
632 if (!surface && retry < 20) {
633 /* If there's no surface available, find unlocked surfaces in the locked list,
634 * take it back to the available list and then search again.
635 */
636 check_surfaces_available (context, msdk_resp);
637 retry++;
638 g_usleep (1000);
639 goto retry;
640 }
641
642 return surface;
643 }
644
645 void
gst_msdk_context_put_surface_locked(GstMsdkContext * context,mfxFrameAllocResponse * resp,mfxFrameSurface1 * surface)646 gst_msdk_context_put_surface_locked (GstMsdkContext * context,
647 mfxFrameAllocResponse * resp, mfxFrameSurface1 * surface)
648 {
649 GstMsdkContextPrivate *priv = context->priv;
650 GstMsdkAllocResponse *msdk_resp =
651 gst_msdk_context_get_cached_alloc_responses (context, resp);
652
653 g_mutex_lock (&priv->mutex);
654 if (!g_list_find (msdk_resp->surfaces_locked, surface)) {
655 msdk_resp->surfaces_used =
656 g_list_remove (msdk_resp->surfaces_used, surface);
657 msdk_resp->surfaces_locked =
658 g_list_prepend (msdk_resp->surfaces_locked, surface);
659 }
660 g_mutex_unlock (&priv->mutex);
661 }
662
663 void
gst_msdk_context_put_surface_available(GstMsdkContext * context,mfxFrameAllocResponse * resp,mfxFrameSurface1 * surface)664 gst_msdk_context_put_surface_available (GstMsdkContext * context,
665 mfxFrameAllocResponse * resp, mfxFrameSurface1 * surface)
666 {
667 GstMsdkContextPrivate *priv = context->priv;
668 GstMsdkAllocResponse *msdk_resp =
669 gst_msdk_context_get_cached_alloc_responses (context, resp);
670
671 g_mutex_lock (&priv->mutex);
672 if (!g_list_find (msdk_resp->surfaces_avail, surface)) {
673 msdk_resp->surfaces_used =
674 g_list_remove (msdk_resp->surfaces_used, surface);
675 msdk_resp->surfaces_avail =
676 g_list_prepend (msdk_resp->surfaces_avail, surface);
677 }
678 g_mutex_unlock (&priv->mutex);
679 }
680
681 GstMsdkContextJobType
gst_msdk_context_get_job_type(GstMsdkContext * context)682 gst_msdk_context_get_job_type (GstMsdkContext * context)
683 {
684 return context->priv->job_type;
685 }
686
687 void
gst_msdk_context_add_job_type(GstMsdkContext * context,GstMsdkContextJobType job_type)688 gst_msdk_context_add_job_type (GstMsdkContext * context,
689 GstMsdkContextJobType job_type)
690 {
691 context->priv->job_type |= job_type;
692 }
693
694 gint
gst_msdk_context_get_shared_async_depth(GstMsdkContext * context)695 gst_msdk_context_get_shared_async_depth (GstMsdkContext * context)
696 {
697 return context->priv->shared_async_depth;
698 }
699
700 void
gst_msdk_context_add_shared_async_depth(GstMsdkContext * context,gint async_depth)701 gst_msdk_context_add_shared_async_depth (GstMsdkContext * context,
702 gint async_depth)
703 {
704 context->priv->shared_async_depth += async_depth;
705 }
706
707 void
gst_msdk_context_set_frame_allocator(GstMsdkContext * context,mfxFrameAllocator * allocator)708 gst_msdk_context_set_frame_allocator (GstMsdkContext * context,
709 mfxFrameAllocator * allocator)
710 {
711 GstMsdkContextPrivate *priv = context->priv;
712
713 g_mutex_lock (&priv->mutex);
714
715 if (!priv->has_frame_allocator) {
716 mfxStatus status;
717
718 status = MFXVideoCORE_SetFrameAllocator (priv->session.session, allocator);
719
720 if (status != MFX_ERR_NONE)
721 GST_ERROR ("Failed to set frame allocator");
722 else
723 priv->has_frame_allocator = 1;
724 }
725
726 g_mutex_unlock (&priv->mutex);
727 }
728