diff mbox series

[FFmpeg-devel,v10,10/13] lavu/hwcontext_qsv: make qsv hwdevice works with oneVPL

Message ID 20220712062735.20339-11-haihao.xiang@intel.com
State New
Headers show
Series make QSV works with the Intel's oneVPL | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Xiang, Haihao July 12, 2022, 6:27 a.m. UTC
From: Haihao Xiang <haihao.xiang@intel.com>

In oneVPL, MFXLoad() and MFXCreateSession() are required to create a
workable mfx session[1]

Add config filters for D3D9/D3D11 session (galinart)

The default device is changed to d3d11va for oneVPL when both d3d11va
and dxva2 are enabled on Microsoft Windows

This is in preparation for oneVPL support

[1] https://spec.oneapi.io/versions/latest/elements/oneVPL/source/programming_guide/VPL_prg_session.html#onevpl-dispatcher

Co-authored-by: galinart <artem.galin@intel.com>
Signed-off-by: galinart <artem.galin@intel.com>
Signed-off-by: Haihao Xiang <haihao.xiang@intel.com>
---
 libavutil/hwcontext_qsv.c | 530 +++++++++++++++++++++++++++++++++++---
 1 file changed, 492 insertions(+), 38 deletions(-)

Comments

Anton Khirnov July 18, 2022, 1:02 p.m. UTC | #1
Quoting Xiang, Haihao (2022-07-12 08:27:32)
> +static int qsv_va_update_config(void *ctx, mfxHDL handle, mfxConfig cfg)
> +{
> +#if CONFIG_VAAPI
> +#if VA_CHECK_VERSION(1, 5, 0)
> +#define LOCAL_VADISPLAYPCIID VADisplayPCIID
> +#else
> +#define LOCAL_VADISPLAYPCIID 21
> +#endif
> +    mfxStatus sts;
> +    VADisplay dpy = handle;
> +    VAStatus vas;
> +    VADisplayAttribute attr = {
> +        .type = LOCAL_VADISPLAYPCIID
> +    };
> +    mfxVariant impl_value;
> +
> +    vas = vaGetDisplayAttributes(dpy, &attr, 1);
> +    if (vas == VA_STATUS_SUCCESS && attr.flags != VA_DISPLAY_ATTRIB_NOT_SUPPORTED) {
> +        impl_value.Type = MFX_VARIANT_TYPE_U16;
> +        impl_value.Data.U16 = (attr.value & 0xFFFF);
> +        sts = MFXSetConfigFilterProperty(cfg,
> +                                         (const mfxU8 *)"mfxExtendedDeviceId.DeviceID", impl_value);
> +        if (sts != MFX_ERR_NONE) {
> +            av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
> +                   "DeviceID property: %d.\n", sts);
> +            goto fail;
> +        }
> +    } else
> +        av_log(ctx, AV_LOG_WARNING, "Cannot get device id from the driver, the default "
> +               "MFX implementation will be loaded for this device. Please consider to "
> +               "upgrade the driver to support VAAPI 1.5.0. \n");

I would still prefer to fail here. The user requested a specific device,
disregarding that request is evil.
Xiang, Haihao July 19, 2022, 7:18 a.m. UTC | #2
On Mon, 2022-07-18 at 15:02 +0200, Anton Khirnov wrote:
> Quoting Xiang, Haihao (2022-07-12 08:27:32)
> > +static int qsv_va_update_config(void *ctx, mfxHDL handle, mfxConfig cfg)
> > +{
> > +#if CONFIG_VAAPI
> > +#if VA_CHECK_VERSION(1, 5, 0)
> > +#define LOCAL_VADISPLAYPCIID VADisplayPCIID
> > +#else
> > +#define LOCAL_VADISPLAYPCIID 21
> > +#endif
> > +    mfxStatus sts;
> > +    VADisplay dpy = handle;
> > +    VAStatus vas;
> > +    VADisplayAttribute attr = {
> > +        .type = LOCAL_VADISPLAYPCIID
> > +    };
> > +    mfxVariant impl_value;
> > +
> > +    vas = vaGetDisplayAttributes(dpy, &attr, 1);
> > +    if (vas == VA_STATUS_SUCCESS && attr.flags !=
> > VA_DISPLAY_ATTRIB_NOT_SUPPORTED) {
> > +        impl_value.Type = MFX_VARIANT_TYPE_U16;
> > +        impl_value.Data.U16 = (attr.value & 0xFFFF);
> > +        sts = MFXSetConfigFilterProperty(cfg,
> > +                                         (const mfxU8
> > *)"mfxExtendedDeviceId.DeviceID", impl_value);
> > +        if (sts != MFX_ERR_NONE) {
> > +            av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
> > +                   "DeviceID property: %d.\n", sts);
> > +            goto fail;
> > +        }
> > +    } else
> > +        av_log(ctx, AV_LOG_WARNING, "Cannot get device id from the driver,
> > the default "
> > +               "MFX implementation will be loaded for this device. Please
> > consider to "
> > +               "upgrade the driver to support VAAPI 1.5.0. \n");
> 
> I would still prefer to fail here. The user requested a specific device,
> disregarding that request is evil.

Thanks for the comment. There is only one available device for most users, so
the default one and the given one from user should be the same, otherwise it
won't work. I don't want to make them in trouble if they don't have a driver to
support the new interface. However I agree with you it is a little evil to
ignore the request. I'll update the patch to return error here. 

Regards
Haihao
Xiang, Haihao July 20, 2022, 8:42 a.m. UTC | #3
On Tue, 2022-07-19 at 07:18 +0000, Xiang, Haihao wrote:
> On Mon, 2022-07-18 at 15:02 +0200, Anton Khirnov wrote:
> > Quoting Xiang, Haihao (2022-07-12 08:27:32)
> > > +static int qsv_va_update_config(void *ctx, mfxHDL handle, mfxConfig cfg)
> > > +{
> > > +#if CONFIG_VAAPI
> > > +#if VA_CHECK_VERSION(1, 5, 0)
> > > +#define LOCAL_VADISPLAYPCIID VADisplayPCIID
> > > +#else
> > > +#define LOCAL_VADISPLAYPCIID 21
> > > +#endif
> > > +    mfxStatus sts;
> > > +    VADisplay dpy = handle;
> > > +    VAStatus vas;
> > > +    VADisplayAttribute attr = {
> > > +        .type = LOCAL_VADISPLAYPCIID
> > > +    };
> > > +    mfxVariant impl_value;
> > > +
> > > +    vas = vaGetDisplayAttributes(dpy, &attr, 1);
> > > +    if (vas == VA_STATUS_SUCCESS && attr.flags !=
> > > VA_DISPLAY_ATTRIB_NOT_SUPPORTED) {
> > > +        impl_value.Type = MFX_VARIANT_TYPE_U16;
> > > +        impl_value.Data.U16 = (attr.value & 0xFFFF);
> > > +        sts = MFXSetConfigFilterProperty(cfg,
> > > +                                         (const mfxU8
> > > *)"mfxExtendedDeviceId.DeviceID", impl_value);
> > > +        if (sts != MFX_ERR_NONE) {
> > > +            av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
> > > +                   "DeviceID property: %d.\n", sts);
> > > +            goto fail;
> > > +        }
> > > +    } else
> > > +        av_log(ctx, AV_LOG_WARNING, "Cannot get device id from the
> > > driver,
> > > the default "
> > > +               "MFX implementation will be loaded for this device. Please
> > > consider to "
> > > +               "upgrade the driver to support VAAPI 1.5.0. \n");
> > 
> > I would still prefer to fail here. The user requested a specific device,
> > disregarding that request is evil.
> 
> Thanks for the comment. There is only one available device for most users, so
> the default one and the given one from user should be the same, otherwise it
> won't work. I don't want to make them in trouble if they don't have a driver
> to
> support the new interface. However I agree with you it is a little evil to
> ignore the request. I'll update the patch to return error here. 
> 

Fixed in v11, 

Thanks
Haihao
Soft Works July 21, 2022, 8:30 p.m. UTC | #4
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Xiang, Haihao
> Sent: Tuesday, July 19, 2022 9:19 AM
> To: anton@khirnov.net; ffmpeg-devel@ffmpeg.org
> Cc: Galin, Artem <artem.galin@intel.com>
> Subject: Re: [FFmpeg-devel] [PATCH v10 10/13] lavu/hwcontext_qsv:
> make qsv hwdevice works with oneVPL
> 
> On Mon, 2022-07-18 at 15:02 +0200, Anton Khirnov wrote:
> > Quoting Xiang, Haihao (2022-07-12 08:27:32)
> > > +static int qsv_va_update_config(void *ctx, mfxHDL handle,
> mfxConfig cfg)
> > > +{
> > > +#if CONFIG_VAAPI
> > > +#if VA_CHECK_VERSION(1, 5, 0)
> > > +#define LOCAL_VADISPLAYPCIID VADisplayPCIID
> > > +#else
> > > +#define LOCAL_VADISPLAYPCIID 21
> > > +#endif
> > > +    mfxStatus sts;
> > > +    VADisplay dpy = handle;
> > > +    VAStatus vas;
> > > +    VADisplayAttribute attr = {
> > > +        .type = LOCAL_VADISPLAYPCIID
> > > +    };
> > > +    mfxVariant impl_value;
> > > +
> > > +    vas = vaGetDisplayAttributes(dpy, &attr, 1);
> > > +    if (vas == VA_STATUS_SUCCESS && attr.flags !=
> > > VA_DISPLAY_ATTRIB_NOT_SUPPORTED) {
> > > +        impl_value.Type = MFX_VARIANT_TYPE_U16;
> > > +        impl_value.Data.U16 = (attr.value & 0xFFFF);
> > > +        sts = MFXSetConfigFilterProperty(cfg,
> > > +                                         (const mfxU8
> > > *)"mfxExtendedDeviceId.DeviceID", impl_value);
> > > +        if (sts != MFX_ERR_NONE) {
> > > +            av_log(ctx, AV_LOG_ERROR, "Error adding a MFX
> configuration"
> > > +                   "DeviceID property: %d.\n", sts);
> > > +            goto fail;
> > > +        }
> > > +    } else
> > > +        av_log(ctx, AV_LOG_WARNING, "Cannot get device id from
> the driver,
> > > the default "
> > > +               "MFX implementation will be loaded for this
> device. Please
> > > consider to "
> > > +               "upgrade the driver to support VAAPI 1.5.0. \n");
> >
> > I would still prefer to fail here. The user requested a specific
> device,
> > disregarding that request is evil.
> 
> Thanks for the comment. There is only one available device for most
> users, so
> the default one and the given one from user should be the same,
> otherwise it
> won't work. I don't want to make them in trouble if they don't have a
> driver to
> support the new interface. However I agree with you it is a little
> evil to
> ignore the request. I'll update the patch to return error here.

I'm not a fan of that kind of automagic behavior. Quick success 
experiences are surely desirable in general, but we also need to 
consider the effects of such behavior - in this case, that would
mean: It doesn't really matter what a user specifies for the parameter,
because it will always work anyway.

In turn, users may start to think that their wrong command with the 
wrong ID would be right, and then, in a subsequent command
use that wrong ID again in different context, where it might fail,
while in turn maximizing confusion.

When it is possible to internally retrieve potentially valid 
values, why not output something useful like: "XXID failed, you
might want to try A, B or C" (or similar)?

Kind regards,
softworkz
Xiang, Haihao July 22, 2022, 2:54 a.m. UTC | #5
On Thu, 2022-07-21 at 20:30 +0000, Soft Works wrote:
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Xiang, Haihao
> > Sent: Tuesday, July 19, 2022 9:19 AM
> > To: anton@khirnov.net; ffmpeg-devel@ffmpeg.org
> > Cc: Galin, Artem <artem.galin@intel.com>
> > Subject: Re: [FFmpeg-devel] [PATCH v10 10/13] lavu/hwcontext_qsv:
> > make qsv hwdevice works with oneVPL
> > 
> > On Mon, 2022-07-18 at 15:02 +0200, Anton Khirnov wrote:
> > > Quoting Xiang, Haihao (2022-07-12 08:27:32)
> > > > +static int qsv_va_update_config(void *ctx, mfxHDL handle,
> > 
> > mfxConfig cfg)
> > > > +{
> > > > +#if CONFIG_VAAPI
> > > > +#if VA_CHECK_VERSION(1, 5, 0)
> > > > +#define LOCAL_VADISPLAYPCIID VADisplayPCIID
> > > > +#else
> > > > +#define LOCAL_VADISPLAYPCIID 21
> > > > +#endif
> > > > +    mfxStatus sts;
> > > > +    VADisplay dpy = handle;
> > > > +    VAStatus vas;
> > > > +    VADisplayAttribute attr = {
> > > > +        .type = LOCAL_VADISPLAYPCIID
> > > > +    };
> > > > +    mfxVariant impl_value;
> > > > +
> > > > +    vas = vaGetDisplayAttributes(dpy, &attr, 1);
> > > > +    if (vas == VA_STATUS_SUCCESS && attr.flags !=
> > > > VA_DISPLAY_ATTRIB_NOT_SUPPORTED) {
> > > > +        impl_value.Type = MFX_VARIANT_TYPE_U16;
> > > > +        impl_value.Data.U16 = (attr.value & 0xFFFF);
> > > > +        sts = MFXSetConfigFilterProperty(cfg,
> > > > +                                         (const mfxU8
> > > > *)"mfxExtendedDeviceId.DeviceID", impl_value);
> > > > +        if (sts != MFX_ERR_NONE) {
> > > > +            av_log(ctx, AV_LOG_ERROR, "Error adding a MFX
> > 
> > configuration"
> > > > +                   "DeviceID property: %d.\n", sts);
> > > > +            goto fail;
> > > > +        }
> > > > +    } else
> > > > +        av_log(ctx, AV_LOG_WARNING, "Cannot get device id from
> > 
> > the driver,
> > > > the default "
> > > > +               "MFX implementation will be loaded for this
> > 
> > device. Please
> > > > consider to "
> > > > +               "upgrade the driver to support VAAPI 1.5.0. \n");
> > > 
> > > I would still prefer to fail here. The user requested a specific
> > 
> > device,
> > > disregarding that request is evil.
> > 
> > Thanks for the comment. There is only one available device for most
> > users, so
> > the default one and the given one from user should be the same,
> > otherwise it
> > won't work. I don't want to make them in trouble if they don't have a
> > driver to
> > support the new interface. However I agree with you it is a little
> > evil to
> > ignore the request. I'll update the patch to return error here.
> 
> I'm not a fan of that kind of automagic behavior. Quick success 
> experiences are surely desirable in general, but we also need to 
> consider the effects of such behavior - in this case, that would
> mean: It doesn't really matter what a user specifies for the parameter,
> because it will always work anyway.
> 
> In turn, users may start to think that their wrong command with the 
> wrong ID would be right, and then, in a subsequent command
> use that wrong ID again in different context, where it might fail,
> while in turn maximizing confusion.
> 
> When it is possible to internally retrieve potentially valid 
> values, why not output something useful like: "XXID failed, you
> might want to try A, B or C" (or similar)?

Agree, and this is fixed in the new version.

Thanks
Haihao
diff mbox series

Patch

diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 21a2a805f8..9b0c255cf4 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -49,6 +49,7 @@ 
 #include "pixdesc.h"
 #include "time.h"
 #include "imgutils.h"
+#include "avassert.h"
 
 #define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
     (MFX_VERSION_MAJOR > (MAJOR) ||         \
@@ -58,6 +59,12 @@ 
 #define QSV_ONEVPL       QSV_VERSION_ATLEAST(2, 0)
 #define QSV_HAVE_OPAQUE  !QSV_ONEVPL
 
+#if QSV_ONEVPL
+#include <mfxdispatcher.h>
+#else
+#define MFXUnload(a) do { } while(0)
+#endif
+
 typedef struct QSVDevicePriv {
     AVBufferRef *child_device_ctx;
 } QSVDevicePriv;
@@ -619,6 +626,435 @@  static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
     return MFX_ERR_NONE;
 }
 
+#if QSV_ONEVPL
+
+static int qsv_d3d11_update_config(void *ctx, mfxHDL handle, mfxConfig cfg)
+{
+#if CONFIG_D3D11VA
+    mfxStatus sts;
+    IDXGIAdapter *pDXGIAdapter;
+    DXGI_ADAPTER_DESC adapterDesc;
+    IDXGIDevice *pDXGIDevice = NULL;
+    HRESULT hr;
+    ID3D11Device *device = handle;
+    mfxVariant impl_value;
+
+    hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void**)&pDXGIDevice);
+    if (SUCCEEDED(hr)) {
+        hr = IDXGIDevice_GetAdapter(pDXGIDevice, &pDXGIAdapter);
+        if (FAILED(hr)) {
+            av_log(ctx, AV_LOG_ERROR, "Error IDXGIDevice_GetAdapter %d\n", hr);
+            goto fail;
+        }
+
+        hr = IDXGIAdapter_GetDesc(pDXGIAdapter, &adapterDesc);
+        if (FAILED(hr)) {
+            av_log(ctx, AV_LOG_ERROR, "Error IDXGIAdapter_GetDesc %d\n", hr);
+            goto fail;
+        }
+    } else {
+        av_log(ctx, AV_LOG_ERROR, "Error ID3D11Device_QueryInterface %d\n", hr);
+        goto fail;
+    }
+
+    impl_value.Type = MFX_VARIANT_TYPE_U16;
+    impl_value.Data.U16 = adapterDesc.DeviceId;
+    sts = MFXSetConfigFilterProperty(cfg,
+                                     (const mfxU8 *)"mfxExtendedDeviceId.DeviceID", impl_value);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
+               "DeviceID property: %d.\n", sts);
+        goto fail;
+    }
+
+    impl_value.Type = MFX_VARIANT_TYPE_PTR;
+    impl_value.Data.Ptr = &adapterDesc.AdapterLuid;
+    sts = MFXSetConfigFilterProperty(cfg,
+                                     (const mfxU8 *)"mfxExtendedDeviceId.DeviceLUID", impl_value);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
+               "DeviceLUID property: %d.\n", sts);
+        goto fail;
+    }
+
+    impl_value.Type = MFX_VARIANT_TYPE_U32;
+    impl_value.Data.U32 = 0x0001;
+    sts = MFXSetConfigFilterProperty(cfg,
+                                     (const mfxU8 *)"mfxExtendedDeviceId.LUIDDeviceNodeMask", impl_value);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
+               "LUIDDeviceNodeMask property: %d.\n", sts);
+        goto fail;
+    }
+
+    return 0;
+
+fail:
+#endif
+    return AVERROR_UNKNOWN;
+}
+
+static int qsv_d3d9_update_config(void *ctx, mfxHDL handle, mfxConfig cfg)
+{
+    int ret = AVERROR_UNKNOWN;
+#if CONFIG_DXVA2
+    mfxStatus sts;
+    IDirect3DDeviceManager9* devmgr = handle;
+    IDirect3DDevice9Ex *device = NULL;
+    HANDLE device_handle = 0;
+    IDirect3D9Ex *d3d9ex = NULL;
+    LUID luid;
+    D3DDEVICE_CREATION_PARAMETERS params;
+    HRESULT hr;
+    mfxVariant impl_value;
+
+    hr = IDirect3DDeviceManager9_OpenDeviceHandle(devmgr, &device_handle);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Error OpenDeviceHandle %d\n", hr);
+        goto fail;
+    }
+
+    hr = IDirect3DDeviceManager9_LockDevice(devmgr, device_handle, &device, TRUE);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Error LockDevice %d\n", hr);
+        goto fail;
+    }
+
+    hr = IDirect3DDevice9Ex_GetCreationParameters(device, &params);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Error IDirect3DDevice9_GetCreationParameters %d\n", hr);
+        goto unlock;
+    }
+
+    hr = IDirect3DDevice9Ex_GetDirect3D(device, &d3d9ex);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Error IDirect3DDevice9Ex_GetAdapterLUID %d\n", hr);
+        goto unlock;
+    }
+
+    hr = IDirect3D9Ex_GetAdapterLUID(d3d9ex, params.AdapterOrdinal, &luid);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Error IDirect3DDevice9Ex_GetAdapterLUID %d\n", hr);
+        goto unlock;
+    }
+
+    impl_value.Type = MFX_VARIANT_TYPE_PTR;
+    impl_value.Data.Ptr = &luid;
+    sts = MFXSetConfigFilterProperty(cfg,
+                                     (const mfxU8 *)"mfxExtendedDeviceId.DeviceLUID", impl_value);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
+               "DeviceLUID property: %d.\n", sts);
+        goto unlock;
+    }
+
+    ret = 0;
+
+unlock:
+    IDirect3DDeviceManager9_UnlockDevice(devmgr, device_handle, FALSE);
+fail:
+#endif
+    return ret;
+}
+
+static int qsv_va_update_config(void *ctx, mfxHDL handle, mfxConfig cfg)
+{
+#if CONFIG_VAAPI
+#if VA_CHECK_VERSION(1, 5, 0)
+#define LOCAL_VADISPLAYPCIID VADisplayPCIID
+#else
+#define LOCAL_VADISPLAYPCIID 21
+#endif
+    mfxStatus sts;
+    VADisplay dpy = handle;
+    VAStatus vas;
+    VADisplayAttribute attr = {
+        .type = LOCAL_VADISPLAYPCIID
+    };
+    mfxVariant impl_value;
+
+    vas = vaGetDisplayAttributes(dpy, &attr, 1);
+    if (vas == VA_STATUS_SUCCESS && attr.flags != VA_DISPLAY_ATTRIB_NOT_SUPPORTED) {
+        impl_value.Type = MFX_VARIANT_TYPE_U16;
+        impl_value.Data.U16 = (attr.value & 0xFFFF);
+        sts = MFXSetConfigFilterProperty(cfg,
+                                         (const mfxU8 *)"mfxExtendedDeviceId.DeviceID", impl_value);
+        if (sts != MFX_ERR_NONE) {
+            av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
+                   "DeviceID property: %d.\n", sts);
+            goto fail;
+        }
+    } else
+        av_log(ctx, AV_LOG_WARNING, "Cannot get device id from the driver, the default "
+               "MFX implementation will be loaded for this device. Please consider to "
+               "upgrade the driver to support VAAPI 1.5.0. \n");
+
+    return 0;
+
+fail:
+#endif
+    return AVERROR_UNKNOWN;
+}
+
+static int qsv_new_mfx_loader(void *ctx,
+                              mfxHDL handle,
+                              mfxHandleType handle_type,
+                              mfxIMPL implementation,
+                              mfxVersion *pver,
+                              void **ploader)
+{
+    mfxStatus sts;
+    mfxLoader loader = NULL;
+    mfxConfig cfg;
+    mfxVariant impl_value;
+
+    *ploader = NULL;
+    loader = MFXLoad();
+    if (!loader) {
+        av_log(ctx, AV_LOG_ERROR, "Error creating a MFX loader\n");
+        goto fail;
+    }
+
+    /* Create configurations for implementation */
+    cfg = MFXCreateConfig(loader);
+    if (!cfg) {
+        av_log(ctx, AV_LOG_ERROR, "Error creating a MFX configuration\n");
+        goto fail;
+    }
+
+    impl_value.Type = MFX_VARIANT_TYPE_U32;
+    impl_value.Data.U32 = (implementation == MFX_IMPL_SOFTWARE) ?
+        MFX_IMPL_TYPE_SOFTWARE : MFX_IMPL_TYPE_HARDWARE;
+    sts = MFXSetConfigFilterProperty(cfg,
+                                     (const mfxU8 *)"mfxImplDescription.Impl", impl_value);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration "
+               "property: %d.\n", sts);
+        goto fail;
+    }
+
+    impl_value.Type = MFX_VARIANT_TYPE_U32;
+    impl_value.Data.U32 = pver->Version;
+    sts = MFXSetConfigFilterProperty(cfg,
+                                     (const mfxU8 *)"mfxImplDescription.ApiVersion.Version",
+                                     impl_value);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration "
+               "property: %d.\n", sts);
+        goto fail;
+    }
+
+    impl_value.Type = MFX_VARIANT_TYPE_U16;
+    impl_value.Data.U16 = 0x8086; // Intel device only
+    sts = MFXSetConfigFilterProperty(cfg,
+                                     (const mfxU8 *)"mfxExtendedDeviceId.VendorID", impl_value);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
+               "VendorID property: %d.\n", sts);
+        goto fail;
+    }
+
+    if (MFX_HANDLE_VA_DISPLAY == handle_type) {
+        if (handle && qsv_va_update_config(ctx, handle, cfg))
+            goto fail;
+
+        impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_VAAPI;
+    } else if (MFX_HANDLE_D3D9_DEVICE_MANAGER == handle_type) {
+        if (handle && qsv_d3d9_update_config(ctx, handle, cfg))
+            goto fail;
+
+        impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_D3D9;
+    } else {
+        if (handle && qsv_d3d11_update_config(ctx, handle, cfg))
+            goto fail;
+
+        impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_D3D11;
+    }
+
+    impl_value.Type = MFX_VARIANT_TYPE_U32;
+    sts = MFXSetConfigFilterProperty(cfg,
+                                     (const mfxU8 *)"mfxImplDescription.AccelerationMode", impl_value);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
+               "AccelerationMode property: %d.\n", sts);
+        goto fail;
+    }
+
+    *ploader = loader;
+
+    return 0;
+
+fail:
+    if (loader)
+        MFXUnload(loader);
+
+    return AVERROR_UNKNOWN;
+}
+
+static int qsv_create_mfx_session_from_loader(void *ctx, mfxLoader loader, mfxSession *psession)
+{
+    mfxStatus sts;
+    mfxSession session = NULL;
+    uint32_t impl_idx = 0;
+    mfxVersion ver;
+
+    while (1) {
+        /* Enumerate all implementations */
+        mfxImplDescription *impl_desc;
+
+        sts = MFXEnumImplementations(loader, impl_idx,
+                                     MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
+                                     (mfxHDL *)&impl_desc);
+        /* Failed to find an available implementation */
+        if (sts == MFX_ERR_NOT_FOUND)
+            break;
+        else if (sts != MFX_ERR_NONE) {
+            impl_idx++;
+            continue;
+        }
+
+        sts = MFXCreateSession(loader, impl_idx, &session);
+        MFXDispReleaseImplDescription(loader, impl_desc);
+        if (sts == MFX_ERR_NONE)
+            break;
+
+        impl_idx++;
+    }
+
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error creating a MFX session: %d.\n", sts);
+        goto fail;
+    }
+
+    sts = MFXQueryVersion(session, &ver);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error querying a MFX session: %d.\n", sts);
+        goto fail;
+    }
+
+    av_log(ctx, AV_LOG_VERBOSE, "Initialize MFX session: implementation "
+           "version is %d.%d\n", ver.Major, ver.Minor);
+
+    *psession = session;
+
+    return 0;
+
+fail:
+    if (session)
+        MFXClose(session);
+
+    return AVERROR_UNKNOWN;
+}
+
+static int qsv_create_mfx_session(void *ctx,
+                                  mfxHDL handle,
+                                  mfxHandleType handle_type,
+                                  mfxIMPL implementation,
+                                  mfxVersion *pver,
+                                  mfxSession *psession,
+                                  void **ploader)
+{
+    mfxLoader loader = NULL;
+
+    av_log(ctx, AV_LOG_VERBOSE,
+           "Use Intel(R) oneVPL to create MFX session, API version is "
+           "%d.%d, the required implementation version is %d.%d\n",
+           MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
+
+    if (handle_type != MFX_HANDLE_VA_DISPLAY &&
+        handle_type != MFX_HANDLE_D3D9_DEVICE_MANAGER &&
+        handle_type != MFX_HANDLE_D3D11_DEVICE) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Invalid MFX device handle type\n");
+        return AVERROR(EXDEV);
+    }
+
+    *psession = NULL;
+
+    if (!*ploader) {
+        if (qsv_new_mfx_loader(ctx, handle, handle_type, implementation, pver, (void **)&loader))
+            goto fail;
+
+        av_assert0(loader);
+    } else
+        loader = *ploader;      // Use the input mfxLoader to create mfx session
+
+    if (qsv_create_mfx_session_from_loader(ctx, loader, psession))
+        goto fail;
+
+    if (!*ploader)
+        *ploader = loader;
+
+    return 0;
+
+fail:
+    if (!*ploader && loader)
+        MFXUnload(loader);
+
+    return AVERROR_UNKNOWN;
+}
+
+#else
+
+static int qsv_create_mfx_session(void *ctx,
+                                  mfxHDL handle,
+                                  mfxHandleType handle_type,
+                                  mfxIMPL implementation,
+                                  mfxVersion *pver,
+                                  mfxSession *psession,
+                                  void **ploader)
+{
+    mfxVersion ver;
+    mfxStatus sts;
+    mfxSession session = NULL;
+
+    av_log(ctx, AV_LOG_VERBOSE,
+           "Use Intel(R) Media SDK to create MFX session, API version is "
+           "%d.%d, the required implementation version is %d.%d\n",
+           MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
+
+    *ploader = NULL;
+    *psession = NULL;
+    ver = *pver;
+    sts = MFXInit(implementation, &ver, &session);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
+               "%d.\n", sts);
+        goto fail;
+    }
+
+    sts = MFXQueryVersion(session, &ver);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error querying an MFX session: "
+               "%d.\n", sts);
+        goto fail;
+    }
+
+    av_log(ctx, AV_LOG_VERBOSE, "Initialize MFX session: implementation "
+           "version is %d.%d\n", ver.Major, ver.Minor);
+
+    MFXClose(session);
+
+    sts = MFXInit(implementation, &ver, &session);
+    if (sts != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
+               "%d.\n", sts);
+        goto fail;
+    }
+
+    *psession = session;
+
+    return 0;
+
+fail:
+    if (session)
+        MFXClose(session);
+
+    return AVERROR_UNKNOWN;
+}
+
+#endif
+
 static int qsv_init_internal_session(AVHWFramesContext *ctx,
                                      mfxSession *session, int upload)
 {
@@ -637,29 +1073,36 @@  static int qsv_init_internal_session(AVHWFramesContext *ctx,
 
     mfxVideoParam par;
     mfxStatus err;
+    int                   ret = AVERROR_UNKNOWN;
+    AVQSVDeviceContext *hwctx = ctx->device_ctx->hwctx;
+    /* hwctx->loader is non-NULL for oneVPL user and NULL for non-oneVPL user */
+    void             **loader = &hwctx->loader;
 
 #if QSV_HAVE_OPAQUE
     QSVFramesContext              *s = ctx->internal->priv;
     opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
 #endif
 
-    err = MFXInit(device_priv->impl, &device_priv->ver, session);
-    if (err != MFX_ERR_NONE) {
-        av_log(ctx, AV_LOG_ERROR, "Error initializing an internal session\n");
-        return AVERROR_UNKNOWN;
-    }
+    ret = qsv_create_mfx_session(ctx, device_priv->handle, device_priv->handle_type,
+                                 device_priv->impl, &device_priv->ver, session, loader);
+    if (ret)
+        goto fail;
 
     if (device_priv->handle) {
         err = MFXVideoCORE_SetHandle(*session, device_priv->handle_type,
                                      device_priv->handle);
-        if (err != MFX_ERR_NONE)
-            return AVERROR_UNKNOWN;
+        if (err != MFX_ERR_NONE) {
+            ret = AVERROR_UNKNOWN;
+            goto fail;
+        }
     }
 
     if (!opaque) {
         err = MFXVideoCORE_SetFrameAllocator(*session, &frame_allocator);
-        if (err != MFX_ERR_NONE)
-            return AVERROR_UNKNOWN;
+        if (err != MFX_ERR_NONE) {
+            ret = AVERROR_UNKNOWN;
+            goto fail;
+        }
     }
 
     memset(&par, 0, sizeof(par));
@@ -695,11 +1138,20 @@  static int qsv_init_internal_session(AVHWFramesContext *ctx,
     if (err != MFX_ERR_NONE) {
         av_log(ctx, AV_LOG_VERBOSE, "Error opening the internal VPP session."
                "Surface upload/download will not be possible\n");
-        MFXClose(*session);
-        *session = NULL;
+
+        ret = AVERROR_UNKNOWN;
+        goto fail;
     }
 
     return 0;
+
+fail:
+    if (*session)
+        MFXClose(*session);
+
+    *session = NULL;
+
+    return ret;
 }
 
 static int qsv_frames_init(AVHWFramesContext *ctx)
@@ -1456,6 +1908,8 @@  static void qsv_device_free(AVHWDeviceContext *ctx)
     if (hwctx->session)
         MFXClose(hwctx->session);
 
+    if (hwctx->loader)
+        MFXUnload(hwctx->loader);
     av_buffer_unref(&priv->child_device_ctx);
     av_freep(&priv);
 }
@@ -1545,34 +1999,10 @@  static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
         goto fail;
     }
 
-    err = MFXInit(implementation, &ver, &hwctx->session);
-    if (err != MFX_ERR_NONE) {
-        av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
-               "%d.\n", err);
-        ret = AVERROR_UNKNOWN;
+    ret = qsv_create_mfx_session(ctx, handle, handle_type, implementation, &ver,
+                                 &hwctx->session, &hwctx->loader);
+    if (ret)
         goto fail;
-    }
-
-    err = MFXQueryVersion(hwctx->session, &ver);
-    if (err != MFX_ERR_NONE) {
-        av_log(ctx, AV_LOG_ERROR, "Error querying an MFX session: %d.\n", err);
-        ret = AVERROR_UNKNOWN;
-        goto fail;
-    }
-
-    av_log(ctx, AV_LOG_VERBOSE,
-           "Initialize MFX session: API version is %d.%d, implementation version is %d.%d\n",
-           MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor);
-
-    MFXClose(hwctx->session);
-
-    err = MFXInit(implementation, &ver, &hwctx->session);
-    if (err != MFX_ERR_NONE) {
-        av_log(ctx, AV_LOG_ERROR,
-               "Error initializing an MFX session: %d.\n", err);
-        ret = AVERROR_UNKNOWN;
-        goto fail;
-    }
 
     err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle);
     if (err != MFX_ERR_NONE) {
@@ -1587,6 +2017,12 @@  static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
 fail:
     if (hwctx->session)
         MFXClose(hwctx->session);
+
+    if (hwctx->loader)
+        MFXUnload(hwctx->loader);
+
+    hwctx->session = NULL;
+    hwctx->loader = NULL;
     return ret;
 }
 
@@ -1629,6 +2065,16 @@  static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
         }
     } else if (CONFIG_VAAPI) {
         child_device_type = AV_HWDEVICE_TYPE_VAAPI;
+#if QSV_ONEVPL
+    } else if (CONFIG_D3D11VA) {  // Use D3D11 by default if d3d11va is enabled
+        av_log(ctx, AV_LOG_VERBOSE,
+               "Defaulting child_device_type to AV_HWDEVICE_TYPE_D3D11VA for oneVPL."
+               "Please explicitly set child device type via \"-init_hw_device\" "
+               "option if needed.\n");
+        child_device_type = AV_HWDEVICE_TYPE_D3D11VA;
+    } else if (CONFIG_DXVA2) {
+        child_device_type = AV_HWDEVICE_TYPE_DXVA2;
+#else
     } else if (CONFIG_DXVA2) {
         av_log(NULL, AV_LOG_WARNING,
                 "WARNING: defaulting child_device_type to AV_HWDEVICE_TYPE_DXVA2 for compatibility "
@@ -1637,6 +2083,7 @@  static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
         child_device_type = AV_HWDEVICE_TYPE_DXVA2;
     } else if (CONFIG_D3D11VA) {
         child_device_type = AV_HWDEVICE_TYPE_D3D11VA;
+#endif
     } else {
         av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n");
         return AVERROR(ENOSYS);
@@ -1663,6 +2110,13 @@  static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
 #endif
 #if CONFIG_DXVA2
     case AV_HWDEVICE_TYPE_DXVA2:
+#if QSV_ONEVPL
+        {
+            av_log(ctx, AV_LOG_VERBOSE,
+                   "d3d11va is not available or child device type is set to dxva2 "
+                   "explicitly for oneVPL.\n");
+        }
+#endif
         break;
 #endif
     default: