1 /* GStreamer Intel MSDK plugin
2 * Copyright (c) 2016, Oblong Industries, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "gstmsdkvideomemory.h"
34 #include "gstmsdksystemmemory.h"
36 GST_DEBUG_CATEGORY_EXTERN (gst_msdk_debug);
37 #define GST_CAT_DEFAULT gst_msdk_debug
39 #define INVALID_INDEX ((guint) -1)
40 #define GST_MSDK_ALIGNMENT_PADDING(num,padding) ((padding) - ((num) & ((padding) - 1)))
44 GstVideoFormat format;
45 mfxU16 mfx_chroma_format;
49 #define GST_VIDEO_INFO_TO_MFX_MAP(FORMAT, CHROMA, FOURCC) \
50 { GST_VIDEO_FORMAT_##FORMAT, MFX_CHROMAFORMAT_##CHROMA, MFX_FOURCC_##FOURCC }
52 static const struct map gst_msdk_video_format_to_mfx_map[] = {
53 GST_VIDEO_INFO_TO_MFX_MAP (NV12, YUV420, NV12),
54 GST_VIDEO_INFO_TO_MFX_MAP (YV12, YUV420, YV12),
55 GST_VIDEO_INFO_TO_MFX_MAP (I420, YUV420, YV12),
56 GST_VIDEO_INFO_TO_MFX_MAP (P010_10LE, YUV420, P010),
57 GST_VIDEO_INFO_TO_MFX_MAP (YUY2, YUV422, YUY2),
58 GST_VIDEO_INFO_TO_MFX_MAP (UYVY, YUV422, UYVY),
59 GST_VIDEO_INFO_TO_MFX_MAP (BGRA, YUV444, RGB4),
60 GST_VIDEO_INFO_TO_MFX_MAP (BGRx, YUV444, RGB4),
61 #if (MFX_VERSION >= 1028)
62 GST_VIDEO_INFO_TO_MFX_MAP (RGB16, YUV444, RGB565),
64 GST_VIDEO_INFO_TO_MFX_MAP (VUYA, YUV444, AYUV),
65 GST_VIDEO_INFO_TO_MFX_MAP (BGR10A2_LE, YUV444, A2RGB10),
66 #if (MFX_VERSION >= 1027)
67 GST_VIDEO_INFO_TO_MFX_MAP (Y210, YUV422, Y210),
68 GST_VIDEO_INFO_TO_MFX_MAP (Y410, YUV444, Y410),
70 #if (MFX_VERSION >= 1031)
71 /* P016 is used for semi-planar 12 bits format in MSDK */
72 GST_VIDEO_INFO_TO_MFX_MAP (P012_LE, YUV420, P016),
73 /* Y216 is used for 12bit 4:2:2 format in MSDK */
74 GST_VIDEO_INFO_TO_MFX_MAP (Y212_LE, YUV422, Y216),
75 /* Y416 is used for 12bit 4:4:4:4 format in MSDK */
76 GST_VIDEO_INFO_TO_MFX_MAP (Y412_LE, YUV444, Y416),
78 #if (MFX_VERSION >=2004)
79 GST_VIDEO_INFO_TO_MFX_MAP (RGBP, YUV444, RGBP),
80 GST_VIDEO_INFO_TO_MFX_MAP (BGRP, YUV444, BGRP),
86 msdk_status_to_string (mfxStatus status)
92 /* reserved for unexpected errors */
94 return "unknown error";
96 case MFX_ERR_NULL_PTR:
97 return "null pointer";
98 case MFX_ERR_UNSUPPORTED:
99 return "undeveloped feature";
100 case MFX_ERR_MEMORY_ALLOC:
101 return "failed to allocate memory";
102 case MFX_ERR_NOT_ENOUGH_BUFFER:
103 return "insufficient buffer at input/output";
104 case MFX_ERR_INVALID_HANDLE:
105 return "invalid handle";
106 case MFX_ERR_LOCK_MEMORY:
107 return "failed to lock the memory block";
108 case MFX_ERR_NOT_INITIALIZED:
109 return "member function called before initialization";
110 case MFX_ERR_NOT_FOUND:
111 return "the specified object is not found";
112 case MFX_ERR_MORE_DATA:
113 return "expect more data at input";
114 case MFX_ERR_MORE_SURFACE:
115 return "expect more surface at output";
116 case MFX_ERR_ABORTED:
117 return "operation aborted";
118 case MFX_ERR_DEVICE_LOST:
119 return "lose the HW acceleration device";
120 case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM:
121 return "incompatible video parameters";
122 case MFX_ERR_INVALID_VIDEO_PARAM:
123 return "invalid video parameters";
124 case MFX_ERR_UNDEFINED_BEHAVIOR:
125 return "undefined behavior";
126 case MFX_ERR_DEVICE_FAILED:
127 return "device operation failure";
128 case MFX_ERR_MORE_BITSTREAM:
129 return "expect more bitstream buffers at output";
130 #if (MFX_VERSION < 2000)
131 case MFX_ERR_INCOMPATIBLE_AUDIO_PARAM:
132 return "incompatible audio parameters";
133 case MFX_ERR_INVALID_AUDIO_PARAM:
134 return "invalid audio parameters";
137 case MFX_WRN_IN_EXECUTION:
138 return "the previous asynchronous operation is in execution";
139 case MFX_WRN_DEVICE_BUSY:
140 return "the HW acceleration device is busy";
141 case MFX_WRN_VIDEO_PARAM_CHANGED:
142 return "the video parameters are changed during decoding";
143 case MFX_WRN_PARTIAL_ACCELERATION:
145 case MFX_WRN_INCOMPATIBLE_VIDEO_PARAM:
146 return "incompatible video parameters";
147 case MFX_WRN_VALUE_NOT_CHANGED:
148 return "the value is saturated based on its valid range";
149 case MFX_WRN_OUT_OF_RANGE:
150 return "the value is out of valid range";
151 case MFX_WRN_FILTER_SKIPPED:
152 return "one of requested filters has been skipped";
153 #if (MFX_VERSION < 2000)
154 case MFX_WRN_INCOMPATIBLE_AUDIO_PARAM:
155 return "incompatible audio parameters";
160 return "undefined error";
164 msdk_get_platform_codename (mfxSession session)
166 mfxU16 codename = MFX_PLATFORM_UNKNOWN;
168 #if (MFX_VERSION >= 1019)
171 mfxPlatform platform = { 0 };
172 status = MFXVideoCORE_QueryPlatform (session, &platform);
173 if (MFX_ERR_NONE == status)
174 codename = platform.CodeName;
181 #if (MFX_VERSION >= 2000)
184 msdk_init_msdk_session (mfxIMPL impl, mfxVersion * pver,
185 MsdkSession * msdk_session)
187 mfxStatus sts = MFX_ERR_NONE;
188 mfxLoader loader = NULL;
189 mfxSession session = NULL;
190 uint32_t impl_idx = 0;
192 mfxVariant impl_value;
194 loader = msdk_session->loader;
199 GST_INFO ("Use the Intel oneVPL SDK to create MFX session");
202 GST_WARNING ("Failed to create a MFX loader");
203 return MFX_ERR_UNKNOWN;
206 /* Create configurations for implementation */
207 cfg = MFXCreateConfig (loader);
210 GST_ERROR ("Failed to create a MFX configuration");
212 return MFX_ERR_UNKNOWN;
215 impl_value.Type = MFX_VARIANT_TYPE_U32;
216 impl_value.Data.U32 =
218 MFX_IMPL_SOFTWARE) ? MFX_IMPL_TYPE_SOFTWARE : MFX_IMPL_TYPE_HARDWARE;
220 MFXSetConfigFilterProperty (cfg,
221 (const mfxU8 *) "mfxImplDescription.Impl", impl_value);
223 if (sts != MFX_ERR_NONE) {
224 GST_ERROR ("Failed to add an additional MFX configuration (%s)",
225 msdk_status_to_string (sts));
230 impl_value.Type = MFX_VARIANT_TYPE_U32;
231 impl_value.Data.U32 = pver->Version;
233 MFXSetConfigFilterProperty (cfg,
234 (const mfxU8 *) "mfxImplDescription.ApiVersion.Version", impl_value);
236 if (sts != MFX_ERR_NONE) {
237 GST_ERROR ("Failed to add an additional MFX configuration (%s)",
238 msdk_status_to_string (sts));
245 /* Enumerate all implementations */
246 mfxImplDescription *impl_desc;
248 sts = MFXEnumImplementations (loader, impl_idx,
249 MFX_IMPLCAPS_IMPLDESCSTRUCTURE, (mfxHDL *) & impl_desc);
251 /* Failed to find an available implementation */
252 if (sts == MFX_ERR_NOT_FOUND)
254 else if (sts != MFX_ERR_NONE) {
259 sts = MFXCreateSession (loader, impl_idx, &session);
260 MFXDispReleaseImplDescription (loader, impl_desc);
262 if (sts == MFX_ERR_NONE)
268 if (sts != MFX_ERR_NONE) {
269 GST_ERROR ("Failed to create a MFX session (%s)",
270 msdk_status_to_string (sts));
272 if (!msdk_session->loader)
278 msdk_session->session = session;
279 msdk_session->loader = loader;
287 msdk_init_msdk_session (mfxIMPL impl, mfxVersion * pver,
288 MsdkSession * msdk_session)
291 mfxSession session = NULL;
292 mfxInitParam init_par = { impl, *pver };
294 GST_INFO ("Use the " MFX_API_SDK " to create MFX session");
296 #if (MFX_VERSION >= 1025)
297 init_par.GPUCopy = 1;
300 status = MFXInitEx (init_par, &session);
302 if (status != MFX_ERR_NONE) {
303 GST_WARNING ("Failed to initialize a MFX session (%s)",
304 msdk_status_to_string (status));
308 msdk_session->session = session;
309 msdk_session->loader = NULL;
315 GstMFXUnload (mfxLoader loader)
317 g_assert (loader == NULL);
323 msdk_close_mfx_session (mfxSession session)
330 status = MFXClose (session);
331 if (status != MFX_ERR_NONE)
332 GST_ERROR ("Close failed (%s)", msdk_status_to_string (status));
336 msdk_close_session (MsdkSession * msdk_session)
338 msdk_close_mfx_session (msdk_session->session);
339 MFXUnload (msdk_session->loader);
343 msdk_open_session (mfxIMPL impl)
345 mfxSession session = NULL;
346 mfxVersion version = { {1, 1}
348 mfxIMPL implementation;
350 MsdkSession msdk_session;
352 static const gchar *implementation_names[] = {
353 "AUTO", "SOFTWARE", "HARDWARE", "AUTO_ANY", "HARDWARE_ANY", "HARDWARE2",
354 "HARDWARE3", "HARDWARE4", "RUNTIME"
357 msdk_session.session = NULL;
358 msdk_session.loader = NULL;
359 status = msdk_init_msdk_session (impl, &version, &msdk_session);
361 if (status != MFX_ERR_NONE)
364 session = msdk_session.session;
366 status = MFXQueryIMPL (session, &implementation);
367 if (status != MFX_ERR_NONE) {
368 GST_ERROR ("Query implementation failed (%s)",
369 msdk_status_to_string (status));
373 status = MFXQueryVersion (session, &version);
374 if (status != MFX_ERR_NONE) {
375 GST_ERROR ("Query version failed (%s)", msdk_status_to_string (status));
379 GST_INFO ("MFX implementation: 0x%04x (%s)", implementation,
380 implementation_names[MFX_IMPL_BASETYPE (implementation)]);
381 GST_INFO ("MFX version: %d.%d", version.Major, version.Minor);
386 msdk_close_session (&msdk_session);
387 msdk_session.session = NULL;
388 msdk_session.loader = NULL;
393 msdk_is_available (void)
395 /* Make sure we can create GstMsdkContext instance (the job type is not used actually) */
396 GstMsdkContext *msdk_context = gst_msdk_context_new (1, GST_MSDK_JOB_DECODER);
402 gst_object_unref (msdk_context);
407 gst_msdk_set_video_alignment (GstVideoInfo * info, guint alloc_w, guint alloc_h,
408 GstVideoAlignment * alignment)
410 guint i, width, height;
411 guint stride_align = 127; /* 128-byte alignment */
413 width = GST_VIDEO_INFO_WIDTH (info);
414 height = GST_VIDEO_INFO_HEIGHT (info);
416 g_assert (alloc_w == 0 || alloc_w >= width);
417 g_assert (alloc_h == 0 || alloc_h >= height);
425 /* PitchAlignment is set to 64 bytes in the media driver for the following formats */
426 if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_BGRA ||
427 GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_BGRx ||
428 GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_BGR10A2_LE ||
429 GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_RGB16)
430 stride_align = 63; /* 64-byte alignment */
432 gst_video_alignment_reset (alignment);
433 for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++)
434 alignment->stride_align[i] = stride_align;
436 alignment->padding_right = GST_ROUND_UP_16 (alloc_w) - width;
437 alignment->padding_bottom = GST_ROUND_UP_32 (alloc_h) - height;
440 static const struct map *
441 _map_lookup_format (GstVideoFormat format)
443 const struct map *m = gst_msdk_video_format_to_mfx_map;
445 for (; m->format != 0; m++) {
446 if (m->format == format)
453 gst_msdk_get_mfx_chroma_from_format (GstVideoFormat format)
455 const struct map *const m = _map_lookup_format (format);
457 return m ? m->mfx_chroma_format : -1;
461 gst_msdk_get_mfx_fourcc_from_format (GstVideoFormat format)
463 const struct map *const m = _map_lookup_format (format);
465 return m ? m->mfx_fourcc : -1;
469 gst_msdk_set_mfx_frame_info_from_video_info (mfxFrameInfo * mfx_info,
472 g_return_if_fail (info && mfx_info);
474 /* Use the first component in info to calculate mfx width / height */
476 GST_ROUND_UP_16 (GST_VIDEO_INFO_COMP_STRIDE (info,
477 0) / GST_VIDEO_INFO_COMP_PSTRIDE (info, 0));
479 if (GST_VIDEO_INFO_N_PLANES (info) > 1)
481 GST_ROUND_UP_32 (GST_VIDEO_INFO_COMP_OFFSET (info,
482 1) / GST_VIDEO_INFO_COMP_STRIDE (info, 0));
485 GST_ROUND_UP_32 (GST_VIDEO_INFO_SIZE (info) /
486 GST_VIDEO_INFO_COMP_STRIDE (info, 0));
488 mfx_info->CropW = GST_VIDEO_INFO_WIDTH (info);
489 mfx_info->CropH = GST_VIDEO_INFO_HEIGHT (info);
490 mfx_info->FrameRateExtN = GST_VIDEO_INFO_FPS_N (info);
491 mfx_info->FrameRateExtD = GST_VIDEO_INFO_FPS_D (info);
492 mfx_info->AspectRatioW = GST_VIDEO_INFO_PAR_N (info);
493 mfx_info->AspectRatioH = GST_VIDEO_INFO_PAR_D (info);
494 mfx_info->PicStruct =
495 !GST_VIDEO_INFO_IS_INTERLACED (info) ? MFX_PICSTRUCT_PROGRESSIVE :
496 MFX_PICSTRUCT_UNKNOWN;
498 gst_msdk_get_mfx_fourcc_from_format (GST_VIDEO_INFO_FORMAT (info));
499 mfx_info->ChromaFormat =
500 gst_msdk_get_mfx_chroma_from_format (GST_VIDEO_INFO_FORMAT (info));
502 switch (mfx_info->FourCC) {
503 case MFX_FOURCC_P010:
504 #if (MFX_VERSION >= 1027)
505 case MFX_FOURCC_Y210:
507 mfx_info->BitDepthLuma = 10;
508 mfx_info->BitDepthChroma = 10;
513 #if (MFX_VERSION >= 1027)
514 case MFX_FOURCC_Y410:
515 mfx_info->BitDepthLuma = 10;
516 mfx_info->BitDepthChroma = 10;
522 #if (MFX_VERSION >= 1031)
523 case MFX_FOURCC_P016:
524 case MFX_FOURCC_Y216:
525 case MFX_FOURCC_Y416:
526 mfx_info->BitDepthLuma = 12;
527 mfx_info->BitDepthChroma = 12;
541 gst_msdk_is_msdk_buffer (GstBuffer * buf)
543 GstAllocator *allocator;
544 GstMemory *mem = gst_buffer_peek_memory (buf, 0);
546 allocator = GST_MEMORY_CAST (mem)->allocator;
548 if (allocator && (GST_IS_MSDK_VIDEO_ALLOCATOR (allocator) ||
549 GST_IS_MSDK_SYSTEM_ALLOCATOR (allocator) ||
550 GST_IS_MSDK_DMABUF_ALLOCATOR (allocator)))
557 gst_msdk_get_surface_from_buffer (GstBuffer * buf)
559 GstAllocator *allocator;
560 GstMemory *mem = gst_buffer_peek_memory (buf, 0);
562 allocator = GST_MEMORY_CAST (mem)->allocator;
564 if (GST_IS_MSDK_VIDEO_ALLOCATOR (allocator))
565 return GST_MSDK_VIDEO_MEMORY_CAST (mem)->surface;
566 else if (GST_IS_MSDK_SYSTEM_ALLOCATOR (allocator))
567 return GST_MSDK_SYSTEM_MEMORY_CAST (mem)->surface;
568 else if (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator)) {
569 return gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
570 g_quark_from_static_string ("GstMsdkBufferSurface"));
577 gst_msdk_get_video_format_from_mfx_fourcc (mfxU32 fourcc)
579 const struct map *m = gst_msdk_video_format_to_mfx_map;
581 for (; m->mfx_fourcc != 0; m++) {
582 if (m->mfx_fourcc == fourcc)
586 return GST_VIDEO_FORMAT_UNKNOWN;
590 gst_msdk_update_mfx_frame_info_from_mfx_video_param (mfxFrameInfo * mfx_info,
591 mfxVideoParam * param)
593 mfx_info->BitDepthLuma = param->mfx.FrameInfo.BitDepthLuma;
594 mfx_info->BitDepthChroma = param->mfx.FrameInfo.BitDepthChroma;
595 mfx_info->Shift = param->mfx.FrameInfo.Shift;
599 gst_msdk_get_mfx_video_orientation_from_video_direction (guint value,
600 guint * mfx_mirror, guint * mfx_rotation)
602 *mfx_mirror = MFX_MIRRORING_DISABLED;
603 *mfx_rotation = MFX_ANGLE_0;
606 case GST_VIDEO_ORIENTATION_IDENTITY:
607 *mfx_mirror = MFX_MIRRORING_DISABLED;
608 *mfx_rotation = MFX_ANGLE_0;
610 case GST_VIDEO_ORIENTATION_HORIZ:
611 *mfx_mirror = MFX_MIRRORING_HORIZONTAL;
612 *mfx_rotation = MFX_ANGLE_0;
614 case GST_VIDEO_ORIENTATION_VERT:
615 *mfx_mirror = MFX_MIRRORING_VERTICAL;
616 *mfx_rotation = MFX_ANGLE_0;
618 case GST_VIDEO_ORIENTATION_90R:
619 *mfx_mirror = MFX_MIRRORING_DISABLED;
620 *mfx_rotation = MFX_ANGLE_90;
622 case GST_VIDEO_ORIENTATION_180:
623 *mfx_mirror = MFX_MIRRORING_DISABLED;
624 *mfx_rotation = MFX_ANGLE_180;
626 case GST_VIDEO_ORIENTATION_90L:
627 *mfx_mirror = MFX_MIRRORING_DISABLED;
628 *mfx_rotation = MFX_ANGLE_270;
630 case GST_VIDEO_ORIENTATION_UL_LR:
631 *mfx_mirror = MFX_MIRRORING_HORIZONTAL;
632 *mfx_rotation = MFX_ANGLE_90;
634 case GST_VIDEO_ORIENTATION_UR_LL:
635 *mfx_mirror = MFX_MIRRORING_VERTICAL;
636 *mfx_rotation = MFX_ANGLE_90;
644 gst_msdk_load_plugin (mfxSession session, const mfxPluginUID * uid,
645 mfxU32 version, const gchar * plugin)
647 #if (MFX_VERSION < 2000)
650 status = MFXVideoUSER_Load (session, uid, version);
652 if (status == MFX_ERR_UNDEFINED_BEHAVIOR) {
653 GST_WARNING ("Media SDK Plugin for %s has been loaded", plugin);
654 } else if (status < MFX_ERR_NONE) {
655 GST_ERROR ("Media SDK Plugin for %s load failed (%s)", plugin,
656 msdk_status_to_string (status));
658 } else if (status > MFX_ERR_NONE) {
659 GST_WARNING ("Media SDK Plugin for %s load warning: %s", plugin,
660 msdk_status_to_string (status));