• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <va/va.h>
34 #include <va/va_drmcommon.h>
35 #include "gstmsdkallocator.h"
36 #include "gstmsdkallocator_libva.h"
37 #include "msdk_libva.h"
38 
39 mfxStatus
gst_msdk_frame_alloc(mfxHDL pthis,mfxFrameAllocRequest * req,mfxFrameAllocResponse * resp)40 gst_msdk_frame_alloc (mfxHDL pthis, mfxFrameAllocRequest * req,
41     mfxFrameAllocResponse * resp)
42 {
43   VAStatus va_status;
44   mfxStatus status = MFX_ERR_NONE;
45   gint i;
46   guint format;
47   guint va_fourcc = 0;
48   VASurfaceID *surfaces = NULL;
49   VASurfaceAttrib attrib;
50   mfxMemId *mids = NULL;
51   GstMsdkContext *context = (GstMsdkContext *) pthis;
52   GstMsdkMemoryID *msdk_mids = NULL;
53   GstMsdkAllocResponse *msdk_resp = NULL;
54   mfxU32 fourcc = req->Info.FourCC;
55   mfxU16 surfaces_num = req->NumFrameSuggested;
56 
57   if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
58     GstMsdkAllocResponse *cached =
59         gst_msdk_context_get_cached_alloc_responses_by_request (context, req);
60     if (cached) {
61       /* check if enough frames were allocated */
62       if (req->NumFrameSuggested > cached->response->NumFrameActual)
63         return MFX_ERR_MEMORY_ALLOC;
64 
65       *resp = *cached->response;
66       return MFX_ERR_NONE;
67     }
68   }
69 
70   /* The VA API does not define any surface types and the application can use either
71    * MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET or
72    * MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET to indicate data in video memory.
73    */
74   if (!(req->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET |
75               MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)))
76     return MFX_ERR_UNSUPPORTED;
77 
78   va_fourcc = gst_msdk_get_va_fourcc_from_mfx_fourcc (fourcc);
79 
80   msdk_mids =
81       (GstMsdkMemoryID *) g_slice_alloc0 (surfaces_num *
82       sizeof (GstMsdkMemoryID));
83   mids = (mfxMemId *) g_slice_alloc0 (surfaces_num * sizeof (mfxMemId));
84   surfaces =
85       (VASurfaceID *) g_slice_alloc0 (surfaces_num * sizeof (VASurfaceID));
86   msdk_resp =
87       (GstMsdkAllocResponse *) g_slice_alloc0 (sizeof (GstMsdkAllocResponse));
88 
89   if (va_fourcc != VA_FOURCC_P208) {
90     attrib.type = VASurfaceAttribPixelFormat;
91     attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
92     attrib.value.type = VAGenericValueTypeInteger;
93     attrib.value.value.i = va_fourcc;
94 
95     format =
96         gst_msdk_get_va_rt_format_from_mfx_rt_format (req->Info.ChromaFormat);
97 
98     if (format == VA_RT_FORMAT_YUV420 && va_fourcc == VA_FOURCC_P010)
99       format = VA_RT_FORMAT_YUV420_10;
100 
101 #if VA_CHECK_VERSION(1, 4, 1)
102     if (format == VA_RT_FORMAT_YUV444 && va_fourcc == VA_FOURCC_A2R10G10B10)
103       format = VA_RT_FORMAT_RGB32_10;
104 #endif
105 
106     va_status = vaCreateSurfaces (gst_msdk_context_get_handle (context),
107         format,
108         req->Info.Width, req->Info.Height, surfaces, surfaces_num, &attrib, 1);
109 
110     status = gst_msdk_get_mfx_status_from_va_status (va_status);
111     if (status != MFX_ERR_NONE) {
112       GST_WARNING ("failed to create VA surface");
113       return status;
114     }
115 
116     for (i = 0; i < surfaces_num; i++) {
117       /* Get dmabuf handle if MFX_MEMTYPE_EXPORT_FRAME */
118       if (req->Type & MFX_MEMTYPE_EXPORT_FRAME) {
119         msdk_mids[i].info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
120         va_status =
121             vaDeriveImage (gst_msdk_context_get_handle (context), surfaces[i],
122             &msdk_mids[i].image);
123         status = gst_msdk_get_mfx_status_from_va_status (va_status);
124 
125         if (MFX_ERR_NONE != status) {
126           GST_ERROR ("failed to derive image");
127           return status;
128         }
129 
130         va_status =
131             vaAcquireBufferHandle (gst_msdk_context_get_handle (context),
132             msdk_mids[i].image.buf, &msdk_mids[i].info);
133         status = gst_msdk_get_mfx_status_from_va_status (va_status);
134 
135         if (MFX_ERR_NONE != status) {
136           GST_ERROR ("failed to get dmabuf handle");
137           va_status = vaDestroyImage (gst_msdk_context_get_handle (context),
138               msdk_mids[i].image.image_id);
139           if (va_status == VA_STATUS_SUCCESS) {
140             msdk_mids[i].image.image_id = VA_INVALID_ID;
141             msdk_mids[i].image.buf = VA_INVALID_ID;
142           }
143         }
144       } else {
145         /* useful to check the image mapping state later */
146         msdk_mids[i].image.image_id = VA_INVALID_ID;
147         msdk_mids[i].image.buf = VA_INVALID_ID;
148       }
149 
150       msdk_mids[i].surface = &surfaces[i];
151       mids[i] = (mfxMemId *) & msdk_mids[i];
152     }
153   } else {
154     /* This is requested from the driver when h265 encoding.
155      * These buffers will be used inside the driver and released by
156      * gst_msdk_frame_free functions. Application doesn't need to handle these buffers.
157      *
158      * See https://github.com/Intel-Media-SDK/samples/issues/13 for more details.
159      */
160     VAContextID context_id = req->AllocId;
161     gint width32 = 32 * ((req->Info.Width + 31) >> 5);
162     gint height32 = 32 * ((req->Info.Height + 31) >> 5);
163     guint64 codedbuf_size = (width32 * height32) * 400LL / (16 * 16);
164 
165     for (i = 0; i < surfaces_num; i++) {
166       VABufferID coded_buf;
167 
168       va_status = vaCreateBuffer (gst_msdk_context_get_handle (context),
169           context_id, VAEncCodedBufferType, codedbuf_size, 1, NULL, &coded_buf);
170 
171       status = gst_msdk_get_mfx_status_from_va_status (va_status);
172       if (status < MFX_ERR_NONE) {
173         GST_ERROR ("failed to create buffer");
174         return status;
175       }
176 
177       surfaces[i] = coded_buf;
178       msdk_mids[i].surface = &surfaces[i];
179       msdk_mids[i].fourcc = fourcc;
180       mids[i] = (mfxMemId *) & msdk_mids[i];
181     }
182   }
183 
184   resp->mids = mids;
185   resp->NumFrameActual = surfaces_num;
186 
187   msdk_resp->response = resp;
188   msdk_resp->mem_ids = mids;
189   msdk_resp->request = *req;
190 
191   gst_msdk_context_add_alloc_response (context, msdk_resp);
192 
193   return status;
194 }
195 
196 mfxStatus
gst_msdk_frame_free(mfxHDL pthis,mfxFrameAllocResponse * resp)197 gst_msdk_frame_free (mfxHDL pthis, mfxFrameAllocResponse * resp)
198 {
199   GstMsdkContext *context = (GstMsdkContext *) pthis;
200   VAStatus va_status = VA_STATUS_SUCCESS;
201   mfxStatus status;
202   GstMsdkMemoryID *mem_id;
203   VADisplay dpy;
204   gint i;
205 
206   if (!gst_msdk_context_remove_alloc_response (context, resp))
207     return MFX_ERR_NONE;
208 
209   mem_id = resp->mids[0];
210   dpy = gst_msdk_context_get_handle (context);
211 
212   if (mem_id->fourcc != MFX_FOURCC_P8) {
213     /* Make sure that all the vaImages are destroyed */
214     for (i = 0; i < resp->NumFrameActual; i++) {
215       GstMsdkMemoryID *mem = resp->mids[i];
216 
217       /* Release dmabuf handle if used */
218       if (mem->info.mem_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME)
219         vaReleaseBufferHandle (dpy, mem->image.buf);
220 
221       if (mem->image.image_id != VA_INVALID_ID &&
222           vaDestroyImage (dpy, mem->image.image_id) == VA_STATUS_SUCCESS) {
223         mem_id->image.image_id = VA_INVALID_ID;
224         mem_id->image.buf = VA_INVALID_ID;
225       }
226     }
227 
228     va_status =
229         vaDestroySurfaces (dpy, (VASurfaceID *) mem_id->surface,
230         resp->NumFrameActual);
231   } else {
232     VASurfaceID *surfaces = mem_id->surface;
233 
234     for (i = 0; i < resp->NumFrameActual; i++) {
235       va_status = vaDestroyBuffer (dpy, surfaces[i]);
236     }
237   }
238 
239   g_slice_free1 (resp->NumFrameActual * sizeof (VASurfaceID), mem_id->surface);
240   g_slice_free1 (resp->NumFrameActual * sizeof (GstMsdkMemoryID), mem_id);
241   g_slice_free1 (resp->NumFrameActual * sizeof (mfxMemId), resp->mids);
242 
243   status = gst_msdk_get_mfx_status_from_va_status (va_status);
244   return status;
245 }
246 
247 mfxStatus
gst_msdk_frame_lock(mfxHDL pthis,mfxMemId mid,mfxFrameData * data)248 gst_msdk_frame_lock (mfxHDL pthis, mfxMemId mid, mfxFrameData * data)
249 {
250   GstMsdkContext *context = (GstMsdkContext *) pthis;
251   VAStatus va_status;
252   mfxStatus status;
253   mfxU8 *buf = NULL;
254   VASurfaceID *va_surface;
255   VADisplay dpy;
256   GstMsdkMemoryID *mem_id;
257 
258   mem_id = (GstMsdkMemoryID *) mid;
259   va_surface = mem_id->surface;
260   dpy = gst_msdk_context_get_handle (context);
261 
262   if (mem_id->info.mem_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME) {
263     GST_WARNING ("Couldn't map the buffer since dmabuf is already in use");
264     return MFX_ERR_LOCK_MEMORY;
265   }
266 
267   if (mem_id->fourcc != MFX_FOURCC_P8) {
268     va_status = vaDeriveImage (dpy, *va_surface, &mem_id->image);
269     status = gst_msdk_get_mfx_status_from_va_status (va_status);
270 
271     if (status != MFX_ERR_NONE) {
272       GST_WARNING ("failed to derive image");
273       return status;
274     }
275 
276     va_status = vaMapBuffer (dpy, mem_id->image.buf, (void **) &buf);
277     status = gst_msdk_get_mfx_status_from_va_status (va_status);
278 
279     if (status != MFX_ERR_NONE) {
280       GST_WARNING ("failed to map");
281       if (vaDestroyImage (dpy, mem_id->image.image_id) == VA_STATUS_SUCCESS) {
282         mem_id->image.image_id = VA_INVALID_ID;
283         mem_id->image.buf = VA_INVALID_ID;
284       }
285       return status;
286     }
287 
288     switch (mem_id->image.format.fourcc) {
289       case VA_FOURCC_NV12:
290       case VA_FOURCC_P010:
291         data->Pitch = mem_id->image.pitches[0];
292         data->Y = buf + mem_id->image.offsets[0];
293         data->UV = buf + mem_id->image.offsets[1];
294         break;
295       case VA_FOURCC_YV12:
296         data->Pitch = mem_id->image.pitches[0];
297         data->Y = buf + mem_id->image.offsets[0];
298         data->U = buf + mem_id->image.offsets[2];
299         data->V = buf + mem_id->image.offsets[1];
300         break;
301       case VA_FOURCC_YUY2:
302         data->Pitch = mem_id->image.pitches[0];
303         data->Y = buf + mem_id->image.offsets[0];
304         data->U = data->Y + 1;
305         data->V = data->Y + 3;
306         break;
307       case VA_FOURCC_UYVY:
308         data->Pitch = mem_id->image.pitches[0];
309         data->Y = buf + mem_id->image.offsets[0];
310         data->U = data->U + 1;
311         data->V = data->U + 2;
312         break;
313       case VA_FOURCC_ARGB:
314         data->Pitch = mem_id->image.pitches[0];
315         data->R = buf + mem_id->image.offsets[0];
316         data->G = data->R + 1;
317         data->B = data->R + 2;
318         data->A = data->R + 3;
319         break;
320 #if (MFX_VERSION >= 1028)
321       case VA_FOURCC_RGB565:
322         data->Pitch = mem_id->image.pitches[0];
323         data->R = buf + mem_id->image.offsets[0];
324         data->G = data->R;
325         data->B = data->R;
326         break;
327 #endif
328       case VA_FOURCC_AYUV:
329         data->PitchHigh = (mfxU16) (mem_id->image.pitches[0] / (1 << 16));
330         data->PitchLow = (mfxU16) (mem_id->image.pitches[0] % (1 << 16));
331         data->V = buf + mem_id->image.offsets[0];
332         data->U = data->V + 1;
333         data->Y = data->V + 2;
334         data->A = data->V + 3;
335         break;
336 #if VA_CHECK_VERSION(1, 4, 1)
337       case VA_FOURCC_A2R10G10B10:
338         data->Pitch = mem_id->image.pitches[0];
339         data->R = buf + mem_id->image.offsets[0];
340         data->G = data->R;
341         data->B = data->R;
342         data->A = data->R;
343         break;
344 #endif
345       default:
346         g_assert_not_reached ();
347         break;
348     }
349   } else {
350     VACodedBufferSegment *coded_buffer_segment;
351     va_status =
352         vaMapBuffer (dpy, *va_surface, (void **) (&coded_buffer_segment));
353     status = gst_msdk_get_mfx_status_from_va_status (va_status);
354     if (MFX_ERR_NONE == status)
355       data->Y = (mfxU8 *) coded_buffer_segment->buf;
356   }
357 
358   return status;
359 }
360 
361 mfxStatus
gst_msdk_frame_unlock(mfxHDL pthis,mfxMemId mid,mfxFrameData * ptr)362 gst_msdk_frame_unlock (mfxHDL pthis, mfxMemId mid, mfxFrameData * ptr)
363 {
364   GstMsdkContext *context = (GstMsdkContext *) pthis;
365   VAStatus va_status;
366   mfxStatus status;
367   VADisplay dpy;
368   GstMsdkMemoryID *mem_id;
369 
370   mem_id = (GstMsdkMemoryID *) mid;
371   dpy = gst_msdk_context_get_handle (context);
372 
373   if (mem_id->fourcc != MFX_FOURCC_P8) {
374     vaUnmapBuffer (dpy, mem_id->image.buf);
375     va_status = vaDestroyImage (dpy, mem_id->image.image_id);
376 
377     if (va_status == VA_STATUS_SUCCESS) {
378       mem_id->image.image_id = VA_INVALID_ID;
379       mem_id->image.buf = VA_INVALID_ID;
380     }
381   } else {
382     va_status = vaUnmapBuffer (dpy, *(mem_id->surface));
383   }
384 
385   status = gst_msdk_get_mfx_status_from_va_status (va_status);
386 
387   return status;
388 }
389 
390 mfxStatus
gst_msdk_frame_get_hdl(mfxHDL pthis,mfxMemId mid,mfxHDL * hdl)391 gst_msdk_frame_get_hdl (mfxHDL pthis, mfxMemId mid, mfxHDL * hdl)
392 {
393   GstMsdkMemoryID *mem_id;
394 
395   if (!hdl || !mid)
396     return MFX_ERR_INVALID_HANDLE;
397 
398   mem_id = mid;
399   *hdl = mem_id->surface;
400 
401   return MFX_ERR_NONE;
402 }
403 
404 void
gst_msdk_set_frame_allocator(GstMsdkContext * context)405 gst_msdk_set_frame_allocator (GstMsdkContext * context)
406 {
407   mfxFrameAllocator gst_msdk_frame_allocator = {
408     .pthis = context,
409     .Alloc = gst_msdk_frame_alloc,
410     .Lock = gst_msdk_frame_lock,
411     .Unlock = gst_msdk_frame_unlock,
412     .GetHDL = gst_msdk_frame_get_hdl,
413     .Free = gst_msdk_frame_free,
414   };
415 
416   gst_msdk_context_set_frame_allocator (context, &gst_msdk_frame_allocator);
417 }
418 
419 gboolean
gst_msdk_get_dmabuf_info_from_surface(mfxFrameSurface1 * surface,gint * handle,gsize * size)420 gst_msdk_get_dmabuf_info_from_surface (mfxFrameSurface1 * surface,
421     gint * handle, gsize * size)
422 {
423   GstMsdkMemoryID *mem_id;
424   g_return_val_if_fail (surface, FALSE);
425 
426   mem_id = (GstMsdkMemoryID *) surface->Data.MemId;
427   if (handle)
428     *handle = mem_id->info.handle;
429   if (size)
430     *size = mem_id->info.mem_size;
431 
432   return TRUE;
433 }
434 
435 gboolean
gst_msdk_export_dmabuf_to_vasurface(GstMsdkContext * context,GstVideoInfo * vinfo,gint fd,VASurfaceID * surface_id)436 gst_msdk_export_dmabuf_to_vasurface (GstMsdkContext * context,
437     GstVideoInfo * vinfo, gint fd, VASurfaceID * surface_id)
438 {
439   GstVideoFormat format;
440   guint width, height, size, i;
441   unsigned long extbuf_handle;
442   guint va_fourcc = 0, va_chroma = 0;
443   VASurfaceAttrib attribs[2], *attrib;
444   VASurfaceAttribExternalBuffers extbuf;
445   VAStatus va_status;
446   mfxStatus status = MFX_ERR_NONE;
447 
448   g_return_val_if_fail (context != NULL, FALSE);
449   g_return_val_if_fail (vinfo != NULL, FALSE);
450   g_return_val_if_fail (fd >= 0, FALSE);
451 
452   extbuf_handle = (guintptr) (fd);
453 
454   format = GST_VIDEO_INFO_FORMAT (vinfo);
455   width = GST_VIDEO_INFO_WIDTH (vinfo);
456   height = GST_VIDEO_INFO_HEIGHT (vinfo);
457   size = GST_VIDEO_INFO_SIZE (vinfo);
458 
459   /* Fixme: Move to common format handling util */
460   switch (format) {
461     case GST_VIDEO_FORMAT_NV12:
462       va_chroma = VA_RT_FORMAT_YUV420;
463       va_fourcc = VA_FOURCC_NV12;
464       break;
465     case GST_VIDEO_FORMAT_BGRA:
466       va_chroma = VA_RT_FORMAT_YUV444;
467       va_fourcc = VA_FOURCC_BGRA;
468       break;
469     case GST_VIDEO_FORMAT_YUY2:
470       va_chroma = VA_RT_FORMAT_YUV422;
471       va_fourcc = VA_FOURCC_YUY2;
472       break;
473     case GST_VIDEO_FORMAT_P010_10LE:
474       va_chroma = VA_RT_FORMAT_YUV420_10;
475       va_fourcc = VA_FOURCC_P010;
476       break;
477     case GST_VIDEO_FORMAT_UYVY:
478       va_chroma = VA_RT_FORMAT_YUV422;
479       va_fourcc = VA_FOURCC_UYVY;
480       break;
481 #if (MFX_VERSION >= 1028)
482     case GST_VIDEO_FORMAT_RGB16:
483       va_chroma = VA_RT_FORMAT_RGB16;
484       va_fourcc = VA_FOURCC_RGB565;
485       break;
486 #endif
487     case GST_VIDEO_FORMAT_VUYA:
488       va_chroma = VA_RT_FORMAT_YUV444;
489       va_fourcc = VA_FOURCC_AYUV;
490       break;
491 #if VA_CHECK_VERSION(1, 4, 1)
492     case GST_VIDEO_FORMAT_BGR10A2_LE:
493       va_chroma = VA_RT_FORMAT_RGB32_10;
494       va_fourcc = VA_FOURCC_A2R10G10B10;
495       break;
496 #endif
497     default:
498       goto error_unsupported_format;
499   }
500 
501   /* Fill the VASurfaceAttribExternalBuffers */
502   extbuf.pixel_format = va_fourcc;
503   extbuf.width = width;
504   extbuf.height = height;
505   extbuf.data_size = size;
506   extbuf.num_planes = GST_VIDEO_INFO_N_PLANES (vinfo);
507   for (i = 0; i < extbuf.num_planes; i++) {
508     extbuf.pitches[i] = GST_VIDEO_INFO_PLANE_STRIDE (vinfo, i);
509     extbuf.offsets[i] = GST_VIDEO_INFO_PLANE_OFFSET (vinfo, i);
510   }
511   extbuf.buffers = (uintptr_t *) & extbuf_handle;
512   extbuf.num_buffers = 1;
513   extbuf.flags = 0;
514   extbuf.private_data = NULL;
515 
516   /* Fill the Surface Attributes */
517   attrib = attribs;
518   attrib->type = VASurfaceAttribMemoryType;
519   attrib->flags = VA_SURFACE_ATTRIB_SETTABLE;
520   attrib->value.type = VAGenericValueTypeInteger;
521   attrib->value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
522   attrib++;
523   attrib->type = VASurfaceAttribExternalBufferDescriptor;
524   attrib->flags = VA_SURFACE_ATTRIB_SETTABLE;
525   attrib->value.type = VAGenericValueTypePointer;
526   attrib->value.value.p = &extbuf;
527   attrib++;
528 
529   va_status = vaCreateSurfaces (gst_msdk_context_get_handle (context),
530       va_chroma, width, height, surface_id, 1, attribs, attrib - attribs);
531   status = gst_msdk_get_mfx_status_from_va_status (va_status);
532   if (status != MFX_ERR_NONE)
533     goto error_create_surface;
534 
535   return TRUE;
536 
537 error_unsupported_format:
538   {
539     GST_ERROR ("Unsupported Video format %s, Can't export dmabuf to vaSurface",
540         gst_video_format_to_string (format));
541     return FALSE;
542   }
543 error_create_surface:
544   {
545     GST_ERROR ("Failed to create the VASurface from DRM_PRIME FD");
546     return FALSE;
547   }
548 }
549 
550 /**
551  * gst_msdk_replace_mfx_memid:
552  * This method replace the internal VA Suface in mfxSurface with a new one
553  *
554  * Caution: Not a thread-safe routine, this method is here to work around
555  * the dmabuf-import use case with dynamic memID replacement where msdk
556  * originally Inited with fake memIDs.
557  *
558  * Don't use anywhere else unless you really know what you are doing!
559  */
560 gboolean
gst_msdk_replace_mfx_memid(GstMsdkContext * context,mfxFrameSurface1 * mfx_surface,VASurfaceID surface_id)561 gst_msdk_replace_mfx_memid (GstMsdkContext * context,
562     mfxFrameSurface1 * mfx_surface, VASurfaceID surface_id)
563 {
564   GstMsdkMemoryID *msdk_mid = NULL;
565   VADisplay dpy;
566   VASurfaceID *old_surface_id;
567   VAStatus va_status;
568   mfxStatus status = MFX_ERR_NONE;
569 
570   g_return_val_if_fail (mfx_surface != NULL, FALSE);
571   g_return_val_if_fail (context != NULL, FALSE);
572 
573   msdk_mid = (GstMsdkMemoryID *) mfx_surface->Data.MemId;
574   dpy = gst_msdk_context_get_handle (context);
575 
576   /* Destory the underlined VAImage if already mapped */
577   if (msdk_mid->image.image_id != VA_INVALID_ID
578       && msdk_mid->image.buf != VA_INVALID_ID) {
579     status =
580         gst_msdk_frame_unlock ((mfxHDL) context, (mfxMemId) msdk_mid, NULL);
581     if (status != MFX_ERR_NONE)
582       goto error_destroy_va_image;
583   }
584 
585   /* Destroy the associated VASurface */
586   old_surface_id = msdk_mid->surface;
587   if (*old_surface_id != VA_INVALID_ID) {
588     va_status = vaDestroySurfaces (dpy, old_surface_id, 1);
589     status = gst_msdk_get_mfx_status_from_va_status (va_status);
590     if (status != MFX_ERR_NONE)
591       goto error_destroy_va_surface;
592   }
593 
594   *msdk_mid->surface = surface_id;
595 
596   return TRUE;
597 
598 error_destroy_va_image:
599   {
600     GST_ERROR ("Failed to Destroy the VAImage");
601     return FALSE;
602   }
603 error_destroy_va_surface:
604   {
605     GST_ERROR ("Failed to Destroy the VASurfaceID %x", *old_surface_id);
606     return FALSE;
607   }
608 }
609