qsv: Update SDK version to v2022.2.4
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / qsv / plugin.cpp
1 /* GStreamer
2  * Copyright (C) 2021 Seungha Yang <seungha@centricular.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 /**
25  * plugin-qsv:
26  *
27  * Since: 1.22
28  */
29
30 #include <gst/gst.h>
31 #include <mfx.h>
32 #include "gstqsvav1enc.h"
33 #include "gstqsvh264dec.h"
34 #include "gstqsvh264enc.h"
35 #include "gstqsvh265dec.h"
36 #include "gstqsvh265enc.h"
37 #include "gstqsvjpegenc.h"
38 #include "gstqsvvp9enc.h"
39 #include "gstqsvutils.h"
40 #include <string.h>
41
42 #ifdef G_OS_WIN32
43 #define WIN32_LEAN_AND_MEAN
44 #include <windows.h>
45 #include <versionhelpers.h>
46 #include <gst/d3d11/gstd3d11.h>
47 #else
48 #include <gst/va/gstva.h>
49 #endif
50
51 GST_DEBUG_CATEGORY (gst_qsv_debug);
52 GST_DEBUG_CATEGORY (gst_qsv_allocator_debug);
53
54 #define GST_CAT_DEFAULT gst_qsv_debug
55
56 #ifdef G_OS_WIN32
57 #define MFX_ACCEL_MODE MFX_ACCEL_MODE_VIA_D3D11
58 #else
59 #define MFX_ACCEL_MODE MFX_ACCEL_MODE_VIA_VAAPI
60 #endif
61
62 #ifdef G_OS_WIN32
63 static mfxSession
64 create_session_with_platform_device (mfxLoader loader,
65     mfxImplDescription * desc, guint impl_index, GstObject ** d3d11_device,
66     GList ** devices)
67 {
68   mfxSession session = nullptr;
69   mfxStatus status;
70   GstD3D11Device *selected = nullptr;
71   GList *list = *devices;
72   GList *iter;
73   mfxU16 device_id = 0;
74
75   *d3d11_device = nullptr;
76
77   status = MFXCreateSession (loader, impl_index, &session);
78   if (status != MFX_ERR_NONE) {
79     GST_WARNING ("Failed to create session with index %d, %d (%s)",
80         impl_index, QSV_STATUS_ARGS (status));
81     return nullptr;
82   }
83
84   if (desc->ApiVersion.Major >= 2 ||
85       (desc->ApiVersion.Major == 1 && desc->ApiVersion.Minor >= 19)) {
86     mfxPlatform platform;
87
88     memset (&platform, 0, sizeof (mfxPlatform));
89
90     if (MFXVideoCORE_QueryPlatform (session, &platform) == MFX_ERR_NONE) {
91       device_id = platform.DeviceId;
92
93       /* XXX: re-create session, MFXVideoCORE_QueryPlatform() may cause
94        * later MFXVideoCORE_SetHandle() call failed with
95        * MFX_ERR_UNDEFINED_BEHAVIOR error */
96       g_clear_pointer (&session, MFXClose);
97
98       status = MFXCreateSession (loader, impl_index, &session);
99       if (status != MFX_ERR_NONE) {
100         GST_WARNING ("Failed to re-create session with index %d, %d (%s)",
101             impl_index, QSV_STATUS_ARGS (status));
102         return nullptr;
103       }
104     }
105   }
106
107   if (device_id) {
108     for (iter = list; iter; iter = g_list_next (iter)) {
109       GstD3D11Device *dev = GST_D3D11_DEVICE (iter->data);
110       guint dev_id;
111
112       g_object_get (dev, "device-id", &dev_id, nullptr);
113       if (dev_id == (guint) device_id) {
114         selected = dev;
115         list = g_list_delete_link (list, iter);
116         break;
117       }
118     }
119   }
120
121   if (!selected) {
122     /* Unknown device id, pick the first device */
123     selected = GST_D3D11_DEVICE (list->data);
124     list = g_list_delete_link (list, list);
125   }
126
127   *devices = list;
128
129   status = MFXVideoCORE_SetHandle (session, MFX_HANDLE_D3D11_DEVICE,
130       gst_d3d11_device_get_device_handle (selected));
131   if (status != MFX_ERR_NONE) {
132     GST_WARNING ("Failed to set d3d11 device handle, %d (%s)",
133         QSV_STATUS_ARGS (status));
134     gst_object_unref (selected);
135     MFXClose (session);
136
137     return nullptr;
138   }
139
140   *d3d11_device = GST_OBJECT (selected);
141
142   return session;
143 }
144 #else
145 static mfxSession
146 create_session_with_platform_device (mfxLoader loader,
147     mfxImplDescription * desc, guint impl_index, GstObject ** va_display,
148     GList ** devices)
149 {
150   mfxSession session = nullptr;
151   mfxStatus status;
152   GstVaDisplay *selected;
153   GList *list = *devices;
154
155   *va_display = nullptr;
156
157   status = MFXCreateSession (loader, impl_index, &session);
158   if (status != MFX_ERR_NONE) {
159     GST_WARNING ("Failed to create session with index %d, %d (%s)",
160         impl_index, QSV_STATUS_ARGS (status));
161     return nullptr;
162   }
163
164   /* XXX: what's the relation between implementation index and VA display ?
165    * Pick the first available device for now */
166   selected = GST_VA_DISPLAY (list->data);
167   list = g_list_delete_link (list, list);
168   *devices = list;
169
170   status = MFXVideoCORE_SetHandle (session, MFX_HANDLE_VA_DISPLAY,
171       gst_va_display_get_va_dpy (selected));
172   if (status != MFX_ERR_NONE) {
173     GST_WARNING ("Failed to set display handle, %d (%s)",
174         QSV_STATUS_ARGS (status));
175     gst_object_unref (selected);
176     MFXClose (session);
177
178     return nullptr;
179   }
180
181   *va_display = GST_OBJECT (selected);
182
183   return session;
184 }
185 #endif
186
187 static void
188 plugin_deinit (gpointer data)
189 {
190   gst_qsv_deinit ();
191 }
192
193 static gboolean
194 plugin_init (GstPlugin * plugin)
195 {
196   mfxLoader loader;
197   guint i = 0;
198   GList *platform_devices = nullptr;
199
200 #ifdef G_OS_WIN32
201   /* D3D11 Video API is supported since Windows 8.
202    * Do we want to support old OS (Windows 7 for example) with D3D9 ?? */
203   if (!IsWindows8OrGreater ())
204     return TRUE;
205 #endif
206
207   GST_DEBUG_CATEGORY_INIT (gst_qsv_debug, "qsv", 0, "Intel Quick Sync Video");
208   GST_DEBUG_CATEGORY_INIT (gst_qsv_allocator_debug,
209       "qsvallocator", 0, "qsvallocator");
210
211   loader = gst_qsv_get_loader ();
212   if (!loader)
213     return TRUE;
214
215   platform_devices = gst_qsv_get_platform_devices ();
216   if (!platform_devices) {
217     gst_qsv_deinit ();
218     return TRUE;
219   }
220
221   GST_INFO ("Found %d platform devices", g_list_length (platform_devices));
222
223   do {
224     mfxStatus status = MFX_ERR_NONE;
225     mfxSession session = nullptr;
226     mfxImplDescription *desc = nullptr;
227     GstObject *device = nullptr;
228
229     status = MFXEnumImplementations (loader,
230         i, MFX_IMPLCAPS_IMPLDESCSTRUCTURE, (mfxHDL *) & desc);
231
232     if (status != MFX_ERR_NONE)
233       break;
234
235     if ((desc->Impl & MFX_IMPL_TYPE_HARDWARE) == 0)
236       goto next;
237
238     if ((desc->AccelerationMode & MFX_ACCEL_MODE) == 0)
239       goto next;
240
241     session = create_session_with_platform_device (loader, desc, i, &device,
242         &platform_devices);
243     if (!session)
244       goto next;
245
246     gst_qsv_h264_dec_register (plugin, GST_RANK_MARGINAL, i, device, session);
247     gst_qsv_h265_dec_register (plugin, GST_RANK_MARGINAL, i, device, session);
248
249     gst_qsv_h264_enc_register (plugin, GST_RANK_NONE, i, device, session);
250     gst_qsv_h265_enc_register (plugin, GST_RANK_NONE, i, device, session);
251     gst_qsv_jpeg_enc_register (plugin, GST_RANK_NONE, i, device, session);
252     gst_qsv_vp9_enc_register (plugin, GST_RANK_NONE, i, device, session);
253     gst_qsv_av1_enc_register (plugin, GST_RANK_NONE, i, device, session);
254
255   next:
256     MFXDispReleaseImplDescription (loader, desc);
257     g_clear_pointer (&session, MFXClose);
258     gst_clear_object (&device);
259     i++;
260
261     /* What's the possible maximum number of impl/device ? */
262   } while (i < 16 && platform_devices != nullptr);
263
264   if (platform_devices)
265     g_list_free_full (platform_devices, (GDestroyNotify) gst_object_unref);
266
267   g_object_set_data_full (G_OBJECT (plugin), "plugin-qsv-shutdown",
268       (gpointer) "shutdown-data", (GDestroyNotify) plugin_deinit);
269
270   return TRUE;
271 }
272
273 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
274     GST_VERSION_MINOR,
275     qsv,
276     "Intel Quick Sync Video plugin",
277     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)