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),
74 msdk_status_to_string (mfxStatus status)
80 /* reserved for unexpected errors */
82 return "unknown error";
84 case MFX_ERR_NULL_PTR:
85 return "null pointer";
86 case MFX_ERR_UNSUPPORTED:
87 return "undeveloped feature";
88 case MFX_ERR_MEMORY_ALLOC:
89 return "failed to allocate memory";
90 case MFX_ERR_NOT_ENOUGH_BUFFER:
91 return "insufficient buffer at input/output";
92 case MFX_ERR_INVALID_HANDLE:
93 return "invalid handle";
94 case MFX_ERR_LOCK_MEMORY:
95 return "failed to lock the memory block";
96 case MFX_ERR_NOT_INITIALIZED:
97 return "member function called before initialization";
98 case MFX_ERR_NOT_FOUND:
99 return "the specified object is not found";
100 case MFX_ERR_MORE_DATA:
101 return "expect more data at input";
102 case MFX_ERR_MORE_SURFACE:
103 return "expect more surface at output";
104 case MFX_ERR_ABORTED:
105 return "operation aborted";
106 case MFX_ERR_DEVICE_LOST:
107 return "lose the HW acceleration device";
108 case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM:
109 return "incompatible video parameters";
110 case MFX_ERR_INVALID_VIDEO_PARAM:
111 return "invalid video parameters";
112 case MFX_ERR_UNDEFINED_BEHAVIOR:
113 return "undefined behavior";
114 case MFX_ERR_DEVICE_FAILED:
115 return "device operation failure";
116 case MFX_ERR_MORE_BITSTREAM:
117 return "expect more bitstream buffers at output";
118 case MFX_ERR_INCOMPATIBLE_AUDIO_PARAM:
119 return "incompatible audio parameters";
120 case MFX_ERR_INVALID_AUDIO_PARAM:
121 return "invalid audio parameters";
123 case MFX_WRN_IN_EXECUTION:
124 return "the previous asynchronous operation is in execution";
125 case MFX_WRN_DEVICE_BUSY:
126 return "the HW acceleration device is busy";
127 case MFX_WRN_VIDEO_PARAM_CHANGED:
128 return "the video parameters are changed during decoding";
129 case MFX_WRN_PARTIAL_ACCELERATION:
131 case MFX_WRN_INCOMPATIBLE_VIDEO_PARAM:
132 return "incompatible video parameters";
133 case MFX_WRN_VALUE_NOT_CHANGED:
134 return "the value is saturated based on its valid range";
135 case MFX_WRN_OUT_OF_RANGE:
136 return "the value is out of valid range";
137 case MFX_WRN_FILTER_SKIPPED:
138 return "one of requested filters has been skipped";
139 case MFX_WRN_INCOMPATIBLE_AUDIO_PARAM:
140 return "incompatible audio parameters";
144 return "undefined error";
148 msdk_close_session (mfxSession session)
155 status = MFXClose (session);
156 if (status != MFX_ERR_NONE)
157 GST_ERROR ("Close failed (%s)", msdk_status_to_string (status));
161 msdk_open_session (mfxIMPL impl)
163 mfxSession session = NULL;
164 mfxVersion version = { {1, 1}
166 mfxIMPL implementation;
169 static const gchar *implementation_names[] = {
170 "AUTO", "SOFTWARE", "HARDWARE", "AUTO_ANY", "HARDWARE_ANY", "HARDWARE2",
171 "HARDWARE3", "HARDWARE4", "RUNTIME"
174 status = MFXInit (impl, &version, &session);
175 if (status != MFX_ERR_NONE) {
176 GST_ERROR ("Intel Media SDK not available (%s)",
177 msdk_status_to_string (status));
181 status = MFXQueryIMPL (session, &implementation);
182 if (status != MFX_ERR_NONE) {
183 GST_ERROR ("Query implementation failed (%s)",
184 msdk_status_to_string (status));
188 status = MFXQueryVersion (session, &version);
189 if (status != MFX_ERR_NONE) {
190 GST_ERROR ("Query version failed (%s)", msdk_status_to_string (status));
194 GST_INFO ("MSDK implementation: 0x%04x (%s)", implementation,
195 implementation_names[MFX_IMPL_BASETYPE (implementation)]);
196 GST_INFO ("MSDK version: %d.%d", version.Major, version.Minor);
201 msdk_close_session (session);
206 msdk_is_available (void)
208 mfxSession session = msdk_open_session (MFX_IMPL_AUTO_ANY);
213 msdk_close_session (session);
218 gst_msdk_set_video_alignment (GstVideoInfo * info, guint alloc_w, guint alloc_h,
219 GstVideoAlignment * alignment)
221 guint i, width, height;
222 guint stride_align = 127; /* 128-byte alignment */
224 width = GST_VIDEO_INFO_WIDTH (info);
225 height = GST_VIDEO_INFO_HEIGHT (info);
227 g_assert (alloc_w == 0 || alloc_w >= width);
228 g_assert (alloc_h == 0 || alloc_h >= height);
236 /* PitchAlignment is set to 64 bytes in the media driver for the following formats */
237 if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_BGRA ||
238 GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_BGRx ||
239 GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_BGR10A2_LE ||
240 GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_RGB16)
241 stride_align = 63; /* 64-byte alignment */
243 gst_video_alignment_reset (alignment);
244 for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++)
245 alignment->stride_align[i] = stride_align;
247 alignment->padding_right = GST_ROUND_UP_16 (alloc_w) - width;
248 alignment->padding_bottom = GST_ROUND_UP_32 (alloc_h) - height;
251 static const struct map *
252 _map_lookup_format (GstVideoFormat format)
254 const struct map *m = gst_msdk_video_format_to_mfx_map;
256 for (; m->format != 0; m++) {
257 if (m->format == format)
264 gst_msdk_get_mfx_chroma_from_format (GstVideoFormat format)
266 const struct map *const m = _map_lookup_format (format);
268 return m ? m->mfx_chroma_format : -1;
272 gst_msdk_get_mfx_fourcc_from_format (GstVideoFormat format)
274 const struct map *const m = _map_lookup_format (format);
276 return m ? m->mfx_fourcc : -1;
280 gst_msdk_set_mfx_frame_info_from_video_info (mfxFrameInfo * mfx_info,
283 g_return_if_fail (info && mfx_info);
285 /* Use the first component in info to calculate mfx width / height */
287 GST_ROUND_UP_16 (GST_VIDEO_INFO_COMP_STRIDE (info,
288 0) / GST_VIDEO_INFO_COMP_PSTRIDE (info, 0));
290 if (GST_VIDEO_INFO_N_PLANES (info) > 1)
292 GST_ROUND_UP_32 (GST_VIDEO_INFO_COMP_OFFSET (info,
293 1) / GST_VIDEO_INFO_COMP_STRIDE (info, 0));
296 GST_ROUND_UP_32 (GST_VIDEO_INFO_SIZE (info) /
297 GST_VIDEO_INFO_COMP_STRIDE (info, 0));
299 mfx_info->CropW = GST_VIDEO_INFO_WIDTH (info);
300 mfx_info->CropH = GST_VIDEO_INFO_HEIGHT (info);
301 mfx_info->FrameRateExtN = GST_VIDEO_INFO_FPS_N (info);
302 mfx_info->FrameRateExtD = GST_VIDEO_INFO_FPS_D (info);
303 mfx_info->AspectRatioW = GST_VIDEO_INFO_PAR_N (info);
304 mfx_info->AspectRatioH = GST_VIDEO_INFO_PAR_D (info);
305 mfx_info->PicStruct =
306 !GST_VIDEO_INFO_IS_INTERLACED (info) ? MFX_PICSTRUCT_PROGRESSIVE :
307 MFX_PICSTRUCT_UNKNOWN;
309 gst_msdk_get_mfx_fourcc_from_format (GST_VIDEO_INFO_FORMAT (info));
310 mfx_info->ChromaFormat =
311 gst_msdk_get_mfx_chroma_from_format (GST_VIDEO_INFO_FORMAT (info));
313 switch (mfx_info->FourCC) {
314 case MFX_FOURCC_P010:
315 #if (MFX_VERSION >= 1027)
316 case MFX_FOURCC_Y210:
318 mfx_info->BitDepthLuma = 10;
319 mfx_info->BitDepthChroma = 10;
324 #if (MFX_VERSION >= 1027)
325 case MFX_FOURCC_Y410:
326 mfx_info->BitDepthLuma = 10;
327 mfx_info->BitDepthChroma = 10;
341 gst_msdk_is_msdk_buffer (GstBuffer * buf)
343 GstAllocator *allocator;
344 GstMemory *mem = gst_buffer_peek_memory (buf, 0);
346 allocator = GST_MEMORY_CAST (mem)->allocator;
348 if (allocator && (GST_IS_MSDK_VIDEO_ALLOCATOR (allocator) ||
349 GST_IS_MSDK_SYSTEM_ALLOCATOR (allocator) ||
350 GST_IS_MSDK_DMABUF_ALLOCATOR (allocator)))
357 gst_msdk_get_surface_from_buffer (GstBuffer * buf)
359 GstAllocator *allocator;
360 GstMemory *mem = gst_buffer_peek_memory (buf, 0);
362 allocator = GST_MEMORY_CAST (mem)->allocator;
364 if (GST_IS_MSDK_VIDEO_ALLOCATOR (allocator))
365 return GST_MSDK_VIDEO_MEMORY_CAST (mem)->surface;
366 else if (GST_IS_MSDK_SYSTEM_ALLOCATOR (allocator))
367 return GST_MSDK_SYSTEM_MEMORY_CAST (mem)->surface;
368 else if (GST_IS_MSDK_DMABUF_ALLOCATOR (allocator)) {
369 return gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
370 g_quark_from_static_string ("GstMsdkBufferSurface"));
377 gst_msdk_get_video_format_from_mfx_fourcc (mfxU32 fourcc)
379 const struct map *m = gst_msdk_video_format_to_mfx_map;
381 for (; m->mfx_fourcc != 0; m++) {
382 if (m->mfx_fourcc == fourcc)
386 return GST_VIDEO_FORMAT_UNKNOWN;
390 gst_msdk_update_mfx_frame_info_from_mfx_video_param (mfxFrameInfo * mfx_info,
391 mfxVideoParam * param)
393 mfx_info->BitDepthLuma = param->mfx.FrameInfo.BitDepthLuma;
394 mfx_info->BitDepthChroma = param->mfx.FrameInfo.BitDepthChroma;
395 mfx_info->Shift = param->mfx.FrameInfo.Shift;
399 gst_msdk_get_mfx_video_orientation_from_video_direction (guint value,
400 guint * mfx_mirror, guint * mfx_rotation)
402 *mfx_mirror = MFX_MIRRORING_DISABLED;
403 *mfx_rotation = MFX_ANGLE_0;
406 case GST_VIDEO_ORIENTATION_IDENTITY:
407 *mfx_mirror = MFX_MIRRORING_DISABLED;
408 *mfx_rotation = MFX_ANGLE_0;
410 case GST_VIDEO_ORIENTATION_HORIZ:
411 *mfx_mirror = MFX_MIRRORING_HORIZONTAL;
412 *mfx_rotation = MFX_ANGLE_0;
414 case GST_VIDEO_ORIENTATION_VERT:
415 *mfx_mirror = MFX_MIRRORING_VERTICAL;
416 *mfx_rotation = MFX_ANGLE_0;
418 case GST_VIDEO_ORIENTATION_90R:
419 *mfx_mirror = MFX_MIRRORING_DISABLED;
420 *mfx_rotation = MFX_ANGLE_90;
422 case GST_VIDEO_ORIENTATION_180:
423 *mfx_mirror = MFX_MIRRORING_DISABLED;
424 *mfx_rotation = MFX_ANGLE_180;
426 case GST_VIDEO_ORIENTATION_90L:
427 *mfx_mirror = MFX_MIRRORING_DISABLED;
428 *mfx_rotation = MFX_ANGLE_270;
430 case GST_VIDEO_ORIENTATION_UL_LR:
431 *mfx_mirror = MFX_MIRRORING_HORIZONTAL;
432 *mfx_rotation = MFX_ANGLE_90;
434 case GST_VIDEO_ORIENTATION_UR_LL:
435 *mfx_mirror = MFX_MIRRORING_VERTICAL;
436 *mfx_rotation = MFX_ANGLE_90;