2f4903950ab2ec8365b45750d66a198ca29c0a54
[platform/upstream/gstreamer.git] / sys / msdk / msdk.c
1 /* GStreamer Intel MSDK plugin
2  * Copyright (c) 2016, Oblong Industries, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *
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.
14  *
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.
18  *
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.
30  */
31
32 #include "msdk.h"
33 #include "gstmsdkvideomemory.h"
34 #include "gstmsdksystemmemory.h"
35
36 GST_DEBUG_CATEGORY_EXTERN (gst_msdk_debug);
37 #define GST_CAT_DEFAULT gst_msdk_debug
38
39 #define INVALID_INDEX         ((guint) -1)
40 #define GST_MSDK_ALIGNMENT_PADDING(num,padding) ((padding) - ((num) & ((padding) - 1)))
41
42 struct map
43 {
44   GstVideoFormat format;
45   mfxU16 mfx_chroma_format;
46   mfxU32 mfx_fourcc;
47 };
48
49 #define GST_VIDEO_INFO_TO_MFX_MAP(FORMAT, CHROMA, FOURCC) \
50     { GST_VIDEO_FORMAT_##FORMAT, MFX_CHROMAFORMAT_##CHROMA, MFX_FOURCC_##FOURCC }
51
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),
63 #endif
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),
69 #endif
70   {0, 0, 0}
71 };
72
73 const gchar *
74 msdk_status_to_string (mfxStatus status)
75 {
76   switch (status) {
77       /* no error */
78     case MFX_ERR_NONE:
79       return "no error";
80       /* reserved for unexpected errors */
81     case MFX_ERR_UNKNOWN:
82       return "unknown error";
83       /* error codes <0 */
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";
122       /* warnings >0 */
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:
130       return "SW is used";
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";
141     default:
142       break;
143   }
144   return "undefiend error";
145 }
146
147 void
148 msdk_close_session (mfxSession session)
149 {
150   mfxStatus status;
151
152   if (!session)
153     return;
154
155   status = MFXClose (session);
156   if (status != MFX_ERR_NONE)
157     GST_ERROR ("Close failed (%s)", msdk_status_to_string (status));
158 }
159
160 mfxSession
161 msdk_open_session (mfxIMPL impl)
162 {
163   mfxSession session = NULL;
164   mfxVersion version = { {1, 1}
165   };
166   mfxIMPL implementation;
167   mfxStatus status;
168
169   static const gchar *implementation_names[] = {
170     "AUTO", "SOFTWARE", "HARDWARE", "AUTO_ANY", "HARDWARE_ANY", "HARDWARE2",
171     "HARDWARE3", "HARDWARE4", "RUNTIME"
172   };
173
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));
178     goto failed;
179   }
180
181   status = MFXQueryIMPL (session, &implementation);
182   if (status != MFX_ERR_NONE) {
183     GST_ERROR ("Query implementation failed (%s)",
184         msdk_status_to_string (status));
185     goto failed;
186   }
187
188   status = MFXQueryVersion (session, &version);
189   if (status != MFX_ERR_NONE) {
190     GST_ERROR ("Query version failed (%s)", msdk_status_to_string (status));
191     goto failed;
192   }
193
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);
197
198   return session;
199
200 failed:
201   msdk_close_session (session);
202   return NULL;
203 }
204
205 gboolean
206 msdk_is_available (void)
207 {
208   mfxSession session = msdk_open_session (MFX_IMPL_AUTO_ANY);
209   if (!session) {
210     return FALSE;
211   }
212
213   msdk_close_session (session);
214   return TRUE;
215 }
216
217 void
218 gst_msdk_set_video_alignment (GstVideoInfo * info, guint alloc_w, guint alloc_h,
219     GstVideoAlignment * alignment)
220 {
221   guint i, width, height;
222   guint stride_align = 127;     /* 128-byte alignment */
223
224   width = GST_VIDEO_INFO_WIDTH (info);
225   height = GST_VIDEO_INFO_HEIGHT (info);
226
227   g_assert (alloc_w == 0 || alloc_w >= width);
228   g_assert (alloc_h == 0 || alloc_h >= height);
229
230   if (alloc_w == 0)
231     alloc_w = width;
232
233   if (alloc_h == 0)
234     alloc_h = height;
235
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 */
242
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;
246
247   alignment->padding_right = GST_ROUND_UP_16 (alloc_w) - width;
248   alignment->padding_bottom = GST_ROUND_UP_32 (alloc_h) - height;
249 }
250
251 static const struct map *
252 _map_lookup_format (GstVideoFormat format)
253 {
254   const struct map *m = gst_msdk_video_format_to_mfx_map;
255
256   for (; m->format != 0; m++) {
257     if (m->format == format)
258       return m;
259   }
260   return NULL;
261 }
262
263 gint
264 gst_msdk_get_mfx_chroma_from_format (GstVideoFormat format)
265 {
266   const struct map *const m = _map_lookup_format (format);
267
268   return m ? m->mfx_chroma_format : -1;
269 }
270
271 gint
272 gst_msdk_get_mfx_fourcc_from_format (GstVideoFormat format)
273 {
274   const struct map *const m = _map_lookup_format (format);
275
276   return m ? m->mfx_fourcc : -1;
277 }
278
279 void
280 gst_msdk_set_mfx_frame_info_from_video_info (mfxFrameInfo * mfx_info,
281     GstVideoInfo * info)
282 {
283   g_return_if_fail (info && mfx_info);
284
285   /* Use the first component in info to calculate mfx width / height */
286   mfx_info->Width =
287       GST_ROUND_UP_16 (GST_VIDEO_INFO_COMP_STRIDE (info,
288           0) / GST_VIDEO_INFO_COMP_PSTRIDE (info, 0));
289
290   if (GST_VIDEO_INFO_N_PLANES (info) > 1)
291     mfx_info->Height =
292         GST_ROUND_UP_32 (GST_VIDEO_INFO_COMP_OFFSET (info,
293             1) / GST_VIDEO_INFO_COMP_STRIDE (info, 0));
294   else
295     mfx_info->Height =
296         GST_ROUND_UP_32 (GST_VIDEO_INFO_SIZE (info) /
297         GST_VIDEO_INFO_COMP_STRIDE (info, 0));
298
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;
308   mfx_info->FourCC =
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));
312
313   switch (mfx_info->FourCC) {
314     case MFX_FOURCC_P010:
315 #if (MFX_VERSION >= 1027)
316     case MFX_FOURCC_Y210:
317 #endif
318       mfx_info->BitDepthLuma = 10;
319       mfx_info->BitDepthChroma = 10;
320       mfx_info->Shift = 1;
321
322       break;
323
324 #if (MFX_VERSION >= 1027)
325     case MFX_FOURCC_Y410:
326       mfx_info->BitDepthLuma = 10;
327       mfx_info->BitDepthChroma = 10;
328       mfx_info->Shift = 0;
329
330       break;
331 #endif
332
333     default:
334       break;
335   }
336
337   return;
338 }
339
340 gboolean
341 gst_msdk_is_msdk_buffer (GstBuffer * buf)
342 {
343   GstAllocator *allocator;
344   GstMemory *mem = gst_buffer_peek_memory (buf, 0);
345
346   allocator = GST_MEMORY_CAST (mem)->allocator;
347
348   if (allocator && (GST_IS_MSDK_VIDEO_ALLOCATOR (allocator) ||
349           GST_IS_MSDK_SYSTEM_ALLOCATOR (allocator) ||
350           GST_IS_MSDK_DMABUF_ALLOCATOR (allocator)))
351     return TRUE;
352   else
353     return FALSE;
354 }
355
356 mfxFrameSurface1 *
357 gst_msdk_get_surface_from_buffer (GstBuffer * buf)
358 {
359   GstAllocator *allocator;
360   GstMemory *mem = gst_buffer_peek_memory (buf, 0);
361
362   allocator = GST_MEMORY_CAST (mem)->allocator;
363
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"));
371   }
372
373   return NULL;
374 }
375
376 GstVideoFormat
377 gst_msdk_get_video_format_from_mfx_fourcc (mfxU32 fourcc)
378 {
379   const struct map *m = gst_msdk_video_format_to_mfx_map;
380
381   for (; m->mfx_fourcc != 0; m++) {
382     if (m->mfx_fourcc == fourcc)
383       return m->format;
384   }
385
386   return GST_VIDEO_FORMAT_UNKNOWN;
387 }
388
389 void
390 gst_msdk_update_mfx_frame_info_from_mfx_video_param (mfxFrameInfo * mfx_info,
391     mfxVideoParam * param)
392 {
393   mfx_info->BitDepthLuma = param->mfx.FrameInfo.BitDepthLuma;
394   mfx_info->BitDepthChroma = param->mfx.FrameInfo.BitDepthChroma;
395   mfx_info->Shift = param->mfx.FrameInfo.Shift;
396 }
397
398 void
399 gst_msdk_get_mfx_video_orientation_from_video_direction (guint value,
400     guint * mfx_mirror, guint * mfx_rotation)
401 {
402   *mfx_mirror = MFX_MIRRORING_DISABLED;
403   *mfx_rotation = MFX_ANGLE_0;
404
405   switch (value) {
406     case GST_VIDEO_ORIENTATION_IDENTITY:
407       *mfx_mirror = MFX_MIRRORING_DISABLED;
408       *mfx_rotation = MFX_ANGLE_0;
409       break;
410     case GST_VIDEO_ORIENTATION_HORIZ:
411       *mfx_mirror = MFX_MIRRORING_HORIZONTAL;
412       *mfx_rotation = MFX_ANGLE_0;
413       break;
414     case GST_VIDEO_ORIENTATION_VERT:
415       *mfx_mirror = MFX_MIRRORING_VERTICAL;
416       *mfx_rotation = MFX_ANGLE_0;
417       break;
418     case GST_VIDEO_ORIENTATION_90R:
419       *mfx_mirror = MFX_MIRRORING_DISABLED;
420       *mfx_rotation = MFX_ANGLE_90;
421       break;
422     case GST_VIDEO_ORIENTATION_180:
423       *mfx_mirror = MFX_MIRRORING_DISABLED;
424       *mfx_rotation = MFX_ANGLE_180;
425       break;
426     case GST_VIDEO_ORIENTATION_90L:
427       *mfx_mirror = MFX_MIRRORING_DISABLED;
428       *mfx_rotation = MFX_ANGLE_270;
429       break;
430     case GST_VIDEO_ORIENTATION_UL_LR:
431       *mfx_mirror = MFX_MIRRORING_HORIZONTAL;
432       *mfx_rotation = MFX_ANGLE_90;
433       break;
434     case GST_VIDEO_ORIENTATION_UR_LL:
435       *mfx_mirror = MFX_MIRRORING_VERTICAL;
436       *mfx_rotation = MFX_ANGLE_90;
437       break;
438     default:
439       break;
440   }
441 }