blob: ae2e1294915ba6bcf47e5c1df21f1d3166989b79 [file] [log] [blame]
Scott D Phillips71df82d2016-11-03 10:47:00 -07001/* 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
34GST_DEBUG_CATEGORY_EXTERN (gst_msdkenc_debug);
35#define GST_CAT_DEFAULT gst_msdkenc_debug
36
37#define INVALID_INDEX ((guint) -1)
38
39static inline guint
40msdk_get_free_surface_index (mfxFrameSurface1 * surfaces, guint size)
41{
42 if (surfaces) {
Sebastian Dröge5c99f9c2016-12-13 22:39:01 +020043 guint i;
44
45 for (i = 0; i < size; i++) {
Scott D Phillips71df82d2016-11-03 10:47:00 -070046 if (!surfaces[i].Data.Locked)
47 return i;
48 }
49 }
50
51 return INVALID_INDEX;
52}
53
54mfxFrameSurface1 *
55msdk_get_free_surface (mfxFrameSurface1 * surfaces, guint size)
56{
57 guint idx = INVALID_INDEX;
Sebastian Dröge5c99f9c2016-12-13 22:39:01 +020058 guint i;
Scott D Phillips71df82d2016-11-03 10:47:00 -070059
60 /* Poll the pool for a maximum of 20 milisecnds */
Sebastian Dröge5c99f9c2016-12-13 22:39:01 +020061 for (i = 0; i < 2000; i++) {
Scott D Phillips71df82d2016-11-03 10:47:00 -070062 idx = msdk_get_free_surface_index (surfaces, size);
63
64 if (idx != INVALID_INDEX)
65 break;
66
67 g_usleep (10);
68 }
69
70 return (idx == INVALID_INDEX ? NULL : &surfaces[idx]);
71}
72
73/* FIXME: Only NV12 is supported by now, add other YUV formats */
74void
75msdk_frame_to_surface (GstVideoFrame * frame, mfxFrameSurface1 * surface)
76{
77 guint8 *src, *dst;
78 guint sstride, dstride;
79 guint width, height;
Sebastian Dröge5c99f9c2016-12-13 22:39:01 +020080 guint i;
Scott D Phillips71df82d2016-11-03 10:47:00 -070081
82 if (!surface->Data.MemId) {
83 surface->Data.Y = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
84 surface->Data.UV = GST_VIDEO_FRAME_COMP_DATA (frame, 1);
85 surface->Data.Pitch = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
86 return;
87 }
88
89 /* Y Plane */
90 width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0);
91 height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0);
92 src = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
93 sstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
94 dst = surface->Data.Y;
95 dstride = surface->Data.Pitch;
96
Sebastian Dröge5c99f9c2016-12-13 22:39:01 +020097 for (i = 0; i < height; i++) {
Scott D Phillips71df82d2016-11-03 10:47:00 -070098 memcpy (dst, src, width);
99 src += sstride;
100 dst += dstride;
101 }
102
103 /* UV Plane */
104 height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 1);
105 src = GST_VIDEO_FRAME_COMP_DATA (frame, 1);
106 sstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1);
107 dst = surface->Data.UV;
108
Sebastian Dröge5c99f9c2016-12-13 22:39:01 +0200109 for (i = 0; i < height; i++) {
Scott D Phillips71df82d2016-11-03 10:47:00 -0700110 memcpy (dst, src, width);
111 src += sstride;
112 dst += dstride;
113 }
114}
115
116const gchar *
117msdk_status_to_string (mfxStatus status)
118{
119 switch (status) {
120 /* no error */
121 case MFX_ERR_NONE:
122 return "no error";
123 /* reserved for unexpected errors */
124 case MFX_ERR_UNKNOWN:
125 return "unknown error";
126 /* error codes <0 */
127 case MFX_ERR_NULL_PTR:
128 return "null pointer";
129 case MFX_ERR_UNSUPPORTED:
130 return "undeveloped feature";
131 case MFX_ERR_MEMORY_ALLOC:
132 return "failed to allocate memory";
133 case MFX_ERR_NOT_ENOUGH_BUFFER:
134 return "insufficient buffer at input/output";
135 case MFX_ERR_INVALID_HANDLE:
136 return "invalid handle";
137 case MFX_ERR_LOCK_MEMORY:
138 return "failed to lock the memory block";
139 case MFX_ERR_NOT_INITIALIZED:
140 return "member function called before initialization";
141 case MFX_ERR_NOT_FOUND:
142 return "the specified object is not found";
143 case MFX_ERR_MORE_DATA:
144 return "expect more data at input";
145 case MFX_ERR_MORE_SURFACE:
146 return "expect more surface at output";
147 case MFX_ERR_ABORTED:
148 return "operation aborted";
149 case MFX_ERR_DEVICE_LOST:
150 return "lose the HW acceleration device";
151 case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM:
152 return "incompatible video parameters";
153 case MFX_ERR_INVALID_VIDEO_PARAM:
154 return "invalid video parameters";
155 case MFX_ERR_UNDEFINED_BEHAVIOR:
156 return "undefined behavior";
157 case MFX_ERR_DEVICE_FAILED:
158 return "device operation failure";
159 case MFX_ERR_MORE_BITSTREAM:
160 return "expect more bitstream buffers at output";
161 case MFX_ERR_INCOMPATIBLE_AUDIO_PARAM:
162 return "incompatible audio parameters";
163 case MFX_ERR_INVALID_AUDIO_PARAM:
164 return "invalid audio parameters";
165 /* warnings >0 */
166 case MFX_WRN_IN_EXECUTION:
167 return "the previous asynchronous operation is in execution";
168 case MFX_WRN_DEVICE_BUSY:
169 return "the HW acceleration device is busy";
170 case MFX_WRN_VIDEO_PARAM_CHANGED:
171 return "the video parameters are changed during decoding";
172 case MFX_WRN_PARTIAL_ACCELERATION:
173 return "SW is used";
174 case MFX_WRN_INCOMPATIBLE_VIDEO_PARAM:
175 return "incompatible video parameters";
176 case MFX_WRN_VALUE_NOT_CHANGED:
177 return "the value is saturated based on its valid range";
178 case MFX_WRN_OUT_OF_RANGE:
179 return "the value is out of valid range";
180 case MFX_WRN_FILTER_SKIPPED:
181 return "one of requested filters has been skipped";
182 case MFX_WRN_INCOMPATIBLE_AUDIO_PARAM:
183 return "incompatible audio parameters";
184 default:
185 break;
186 }
187 return "undefiend error";
188}
189
190void
191msdk_close_session (mfxSession session)
192{
193 mfxStatus status;
194
195 if (!session)
196 return;
197
198 status = MFXClose (session);
199 if (status != MFX_ERR_NONE)
200 GST_ERROR ("Close failed (%s)", msdk_status_to_string (status));
201}
202
203mfxSession
204msdk_open_session (gboolean hardware)
205{
206 mfxSession session = NULL;
207 mfxVersion version = { {1, 1}
208 };
209 mfxIMPL implementation;
210 mfxStatus status;
211
212 static const gchar *implementation_names[] = {
213 "AUTO", "SOFTWARE", "HARDWARE", "AUTO_ANY", "HARDWARE_ANY", "HARDWARE2",
214 "HARDWARE3", "HARDWARE4", "RUNTIME"
215 };
216
217 status = MFXInit (hardware ? MFX_IMPL_HARDWARE_ANY : MFX_IMPL_SOFTWARE,
218 &version, &session);
219 if (status != MFX_ERR_NONE) {
220 GST_ERROR ("Intel Media SDK not available (%s)",
221 msdk_status_to_string (status));
222 goto failed;
223 }
224
225 MFXQueryIMPL (session, &implementation);
226 if (status != MFX_ERR_NONE) {
227 GST_ERROR ("Query implementation failed (%s)",
228 msdk_status_to_string (status));
229 goto failed;
230 }
231
232 MFXQueryVersion (session, &version);
233 if (status != MFX_ERR_NONE) {
234 GST_ERROR ("Query version failed (%s)", msdk_status_to_string (status));
235 goto failed;
236 }
237
238 GST_INFO ("MSDK implementation: 0x%04x (%s)", implementation,
239 implementation_names[MFX_IMPL_BASETYPE (implementation)]);
240 GST_INFO ("MSDK version: %d.%d", version.Major, version.Minor);
241
242 return session;
243
244failed:
245 msdk_close_session (session);
246 return NULL;
247}
248
249gboolean
250msdk_is_available (void)
251{
252 mfxSession session = msdk_open_session (FALSE);
253 if (!session) {
254 return FALSE;
255 }
256
257 msdk_close_session (session);
258 return TRUE;
259}