[FFmpeg-devel] [PATCH v2 4/4] libavutil/qsv: enabling d3d11va support

Artem Galin artem.galin at gmail.com
Wed Apr 22 21:38:19 EEST 2020


On Tue, 21 Apr 2020 at 11:26, Steve Lhomme <robux4 at ycbcr.xyz> wrote:

> On 2020-04-15 15:07, artem.galin at gmail.com wrote:
> > From: Artem Galin <artem.galin at intel.com>
> >
> > Makes selection of d3d11va device type by default and over DirectX 9,
> > which is still supported but requires explicit selection.
> > This enables usage of non-powered/headless GPU, better HDR support.
> > Pool of resources is allocated as one texture with array of slices.
>
> I'm all for it ;)
>
Great :)

>
> > Added d3d11va device selection by vendor id.
> > Example: --init_hw_device d3d11va:,vendor=0x8086
> >
> > DirectX 9 usage.
> > Example: --init_hw_device qsv:hw,child_device_type=dxva2
>
> Same remark as before on the possible uninitialized handle_type.
>
Agreed.

>
> > Signed-off-by: Artem Galin <artem.galin at intel.com>
> > ---
> >   libavutil/hwcontext_d3d11va.c |  82 +++++++-
> >   libavutil/hwcontext_d3d11va.h |   8 +
> >   libavutil/hwcontext_qsv.c     | 339 +++++++++++++++++++++++++++++-----
> >   3 files changed, 371 insertions(+), 58 deletions(-)
> >
> > diff --git a/libavutil/hwcontext_d3d11va.c
> b/libavutil/hwcontext_d3d11va.c
> > index c8ae58f908..9d7615eb55 100644
> > --- a/libavutil/hwcontext_d3d11va.c
> > +++ b/libavutil/hwcontext_d3d11va.c
> > @@ -72,7 +72,7 @@ static av_cold void load_functions(void)
> >   }
> >
> >   typedef struct D3D11VAFramesContext {
> > -    int nb_surfaces_used;
> > +    int nb_surfaces;
>
> Probably better as a size_t
>
Agreed.

>
> >       DXGI_FORMAT format;
> >
> > @@ -112,6 +112,8 @@ static void d3d11va_frames_uninit(AVHWFramesContext
> *ctx)
> >       if (s->staging_texture)
> >           ID3D11Texture2D_Release(s->staging_texture);
> >       s->staging_texture = NULL;
> > +
> > +    av_freep(&frames_hwctx->texture_infos);
> >   }
> >
> >   static int d3d11va_frames_get_constraints(AVHWDeviceContext *ctx,
> > @@ -152,8 +154,9 @@ static void free_texture(void *opaque, uint8_t *data)
> >       av_free(data);
> >   }
> >
> > -static AVBufferRef *wrap_texture_buf(ID3D11Texture2D *tex, int index)
> > +static AVBufferRef *wrap_texture_buf(AVHWFramesContext *ctx,
> ID3D11Texture2D *tex, int index)
> >   {
> > +    AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
> >       AVBufferRef *buf;
> >       AVD3D11FrameDescriptor *desc = av_mallocz(sizeof(*desc));
> >       if (!desc) {
> > @@ -161,6 +164,10 @@ static AVBufferRef
> *wrap_texture_buf(ID3D11Texture2D *tex, int index)
> >           return NULL;
> >       }
> >
> > +    frames_hwctx->texture_infos[frames_hwctx->nb_surfaces_used].texture
> = tex;
> > +    frames_hwctx->texture_infos[frames_hwctx->nb_surfaces_used].index =
> index;
> > +    frames_hwctx->nb_surfaces_used++;
> > +
> >       desc->texture = tex;
> >       desc->index   = index;
> >
> > @@ -199,13 +206,12 @@ static AVBufferRef
> *d3d11va_alloc_single(AVHWFramesContext *ctx)
> >           return NULL;
> >       }
> >
> > -    return wrap_texture_buf(tex, 0);
> > +    return wrap_texture_buf(ctx, tex, 0);
> >   }
> >
> >   static AVBufferRef *d3d11va_pool_alloc(void *opaque, int size)
> >   {
> >       AVHWFramesContext        *ctx = (AVHWFramesContext*)opaque;
> > -    D3D11VAFramesContext       *s = ctx->internal->priv;
> >       AVD3D11VAFramesContext *hwctx = ctx->hwctx;
> >       D3D11_TEXTURE2D_DESC  texDesc;
> >
> > @@ -214,13 +220,13 @@ static AVBufferRef *d3d11va_pool_alloc(void
> *opaque, int size)
> >
> >       ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc);
> >
> > -    if (s->nb_surfaces_used >= texDesc.ArraySize) {
> > +    if (hwctx->nb_surfaces_used >= texDesc.ArraySize) {
> >           av_log(ctx, AV_LOG_ERROR, "Static surface pool size
> exceeded.\n");
> >           return NULL;
> >       }
> >
> >       ID3D11Texture2D_AddRef(hwctx->texture);
> > -    return wrap_texture_buf(hwctx->texture, s->nb_surfaces_used++);
> > +    return wrap_texture_buf(ctx, hwctx->texture,
> hwctx->nb_surfaces_used);
> >   }
> >
> >   static int d3d11va_frames_init(AVHWFramesContext *ctx)
> > @@ -267,7 +273,7 @@ static int d3d11va_frames_init(AVHWFramesContext
> *ctx)
> >               av_log(ctx, AV_LOG_ERROR, "User-provided texture has
> mismatching parameters\n");
> >               return AVERROR(EINVAL);
> >           }
> > -    } else if (texDesc.ArraySize > 0) {
> > +    } else if (!(texDesc.BindFlags & D3D11_BIND_RENDER_TARGET) &&
> texDesc.ArraySize > 0) {
> >           hr = ID3D11Device_CreateTexture2D(device_hwctx->device,
> &texDesc, NULL, &hwctx->texture);
> >           if (FAILED(hr)) {
> >               av_log(ctx, AV_LOG_ERROR, "Could not create the texture
> (%lx)\n", (long)hr);
> > @@ -275,6 +281,12 @@ static int d3d11va_frames_init(AVHWFramesContext
> *ctx)
> >           }
> >       }
> >
> > +    hwctx->texture_infos = av_mallocz_array(ctx->initial_pool_size,
> sizeof(*hwctx->texture_infos));
> > +    if (!hwctx->texture_infos)
> > +        return AVERROR(ENOMEM);
> > +
> > +    s->nb_surfaces = ctx->initial_pool_size;
> > +
> >       ctx->internal->pool_internal =
> av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor),
> >                                                           ctx,
> d3d11va_pool_alloc, NULL);
> >       if (!ctx->internal->pool_internal)
> > @@ -511,15 +523,56 @@ static void
> d3d11va_device_uninit(AVHWDeviceContext *hwdev)
> >       }
> >   }
> >
> > +static int d3d11va_device_find_adapter_by_vendor_id(AVHWDeviceContext
> *ctx, UINT creationFlags, char *vendor)
> > +{
> > +    HRESULT hr;
> > +    IDXGIAdapter *adapter = NULL;
> > +    int adapter_id = 0;
> > +    IDXGIFactory2 *factory;
> > +    long int vendor_id = strtol(vendor, NULL, 0);
> > +    hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&factory);
> > +    while (IDXGIFactory2_EnumAdapters(factory, adapter_id++, &adapter)
> != DXGI_ERROR_NOT_FOUND) {
> > +        ID3D11Device* device = NULL;
> > +        DXGI_ADAPTER_DESC adapter_desc;
> > +
> > +        hr = mD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL,
> creationFlags, NULL, 0, D3D11_SDK_VERSION, &device, NULL, NULL);
> > +        if (FAILED(hr)) {
> > +            av_log(ctx, AV_LOG_ERROR, "D3D11CreateDevice returned
> error\n");
> > +            continue;
> > +        }
> > +
> > +        hr = IDXGIAdapter2_GetDesc(adapter, &adapter_desc);
> > +        if (FAILED(hr)) {
> > +            av_log(ctx, AV_LOG_ERROR, "IDXGIAdapter2_GetDesc returned
> error\n");
> > +            continue;
> > +        }
> > +
> > +        if (device)
> > +            ID3D11Device_Release(device);
> > +
> > +        if (adapter)
> > +            IDXGIAdapter_Release(adapter);
> > +
> > +        if (adapter_desc.VendorId == vendor_id) {
> > +            IDXGIFactory2_Release(factory);
> > +            return adapter_id - 1;
> > +        }
> > +    }
> > +    IDXGIFactory2_Release(factory);
> > +    return -1;
> > +}
> > +
> >   static int d3d11va_device_create(AVHWDeviceContext *ctx, const char
> *device,
> >                                    AVDictionary *opts, int flags)
> >   {
> >       AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
> >
> >       HRESULT hr;
> > +    AVDictionaryEntry *e;
> >       IDXGIAdapter           *pAdapter = NULL;
> >       ID3D10Multithread      *pMultithread;
> >       UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
> > +    int adapter = -1;
> >       int is_debug       = !!av_dict_get(opts, "debug", NULL, 0);
> >       int ret;
> >
> > @@ -539,11 +592,23 @@ static int d3d11va_device_create(AVHWDeviceContext
> *ctx, const char *device,
> >           return AVERROR_UNKNOWN;
> >       }
> >
> > +    e = av_dict_get(opts, "vendor", NULL, 0);
> > +    if (e) {
>
> Not sure where "vendor" is defined but maybe it's possible to read it as
> an integer directly ? The you can pass the integer directly to
> d3d11va_device_find_adapter_by_vendor_id().
>
I can extract value from dictionary and convert to int, then pass integer
value to the function.

>
> > +        adapter = d3d11va_device_find_adapter_by_vendor_id(ctx,
> creationFlags, e ? e->value : NULL);
> > +        if (adapter < 0) {
> > +            av_log(ctx, AV_LOG_ERROR, "Failed to find d3d11va adapter
> by vendor id %s\n", e ? e->value : NULL);
> > +            return AVERROR_UNKNOWN;
> > +        }
> > +    }
> > +
> >       if (device) {
> > +        adapter = atoi(device);
> > +    }
> > +
> > +    if (adapter >= 0) {
> >           IDXGIFactory2 *pDXGIFactory;
> >           hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void
> **)&pDXGIFactory);
> >           if (SUCCEEDED(hr)) {
> > -            int adapter = atoi(device);
> >               if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory,
> adapter, &pAdapter)))
> >                   pAdapter = NULL;
> >               IDXGIFactory2_Release(pDXGIFactory);
> > @@ -568,6 +633,7 @@ static int d3d11va_device_create(AVHWDeviceContext
> *ctx, const char *device,
> >           return AVERROR_UNKNOWN;
> >       }
> >
> > +    av_log(ctx, AV_LOG_VERBOSE, "Using D3D11 device.\n");
> >       hr = ID3D11Device_QueryInterface(device_hwctx->device,
> &IID_ID3D10Multithread, (void **)&pMultithread);
> >       if (SUCCEEDED(hr)) {
> >           ID3D10Multithread_SetMultithreadProtected(pMultithread, TRUE);
> > diff --git a/libavutil/hwcontext_d3d11va.h
> b/libavutil/hwcontext_d3d11va.h
> > index 9f91e9b1b6..4312fe0b62 100644
> > --- a/libavutil/hwcontext_d3d11va.h
> > +++ b/libavutil/hwcontext_d3d11va.h
> > @@ -39,6 +39,11 @@
> >   #include <d3d11.h>
> >   #include <stdint.h>
> >
> > +typedef struct D3D11TextureInfo {
> > +    ID3D11Texture2D *texture;
> > +    int index;
>
> Probably better as a size_t
>
> Agreed

> > +} D3D11TextureInfo;
> > +
> >   /**
> >    * This struct is allocated as AVHWDeviceContext.hwctx
> >    */
> > @@ -164,6 +169,9 @@ typedef struct AVD3D11VAFramesContext {
> >        * This field is ignored/invalid if a user-allocated texture is
> provided.
> >        */
> >       UINT MiscFlags;
> > +
> > +    D3D11TextureInfo *texture_infos;
> > +    int nb_surfaces_used;
> >   } AVD3D11VAFramesContext;
> >
> >   #endif /* AVUTIL_HWCONTEXT_D3D11VA_H */
> > diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
> > index b1b67400de..1bc02c41eb 100644
> > --- a/libavutil/hwcontext_qsv.c
> > +++ b/libavutil/hwcontext_qsv.c
> > @@ -27,9 +27,13 @@
> >   #include <pthread.h>
> >   #endif
> >
> > +#define COBJMACROS
> >   #if CONFIG_VAAPI
> >   #include "hwcontext_vaapi.h"
> >   #endif
> > +#if CONFIG_D3D11VA
> > +#include "hwcontext_d3d11va.h"
> > +#endif
> >   #if CONFIG_DXVA2
> >   #include "hwcontext_dxva2.h"
> >   #endif
> > @@ -44,6 +48,8 @@
> >   #include "pixdesc.h"
> >   #include "time.h"
> >
> > +#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
> > +
> >   typedef struct QSVDevicePriv {
> >       AVBufferRef *child_device_ctx;
> >   } QSVDevicePriv;
> > @@ -70,6 +76,7 @@ typedef struct QSVFramesContext {
> >
> >       AVBufferRef *child_frames_ref;
> >       mfxFrameSurface1 *surfaces_internal;
> > +    mfxHDLPair *handle_pairs_internal;
> >       int             nb_surfaces_used;
> >
> >       // used in the frame allocator for non-opaque surfaces
> > @@ -89,6 +96,9 @@ static const struct {
> >   #if CONFIG_VAAPI
> >       { MFX_HANDLE_VA_DISPLAY,          AV_HWDEVICE_TYPE_VAAPI,
> AV_PIX_FMT_VAAPI },
> >   #endif
> > +#if CONFIG_D3D11VA
> > +    { MFX_HANDLE_D3D11_DEVICE,        AV_HWDEVICE_TYPE_D3D11VA,
> AV_PIX_FMT_D3D11 },
> > +#endif
> >   #if CONFIG_DXVA2
> >       { MFX_HANDLE_D3D9_DEVICE_MANAGER, AV_HWDEVICE_TYPE_DXVA2,
> AV_PIX_FMT_DXVA2_VLD },
> >   #endif
> > @@ -115,29 +125,32 @@ static uint32_t qsv_fourcc_from_pix_fmt(enum
> AVPixelFormat pix_fmt)
> >       return 0;
> >   }
> >
> > +#if CONFIG_D3D11VA
> > +static uint32_t qsv_get_d3d11va_bind_flags(int mem_type)
> > +{
> > +    uint32_t bind_flags = 0;
> > +
> > +    if ((mem_type & MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET) &&
> (mem_type & MFX_MEMTYPE_INTERNAL_FRAME))
> > +        bind_flags = D3D11_BIND_DECODER | D3D11_BIND_VIDEO_ENCODER;
> > +    else
> > +        bind_flags = D3D11_BIND_DECODER;
> > +
> > +    if ((MFX_MEMTYPE_FROM_VPPOUT & mem_type) ||
> (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & mem_type))
> > +        bind_flags = D3D11_BIND_RENDER_TARGET;
> > +
> > +    return bind_flags;
> > +}
> > +#endif
> > +
> >   static int qsv_device_init(AVHWDeviceContext *ctx)
> >   {
> >       AVQSVDeviceContext *hwctx = ctx->hwctx;
> >       QSVDeviceContext       *s = ctx->internal->priv;
> > +    mfxHandleType handle_type = MFX_HANDLE_D3D11_DEVICE;
> >
> >       mfxStatus err;
> >       int i;
> >
> > -    for (i = 0; supported_handle_types[i].handle_type; i++) {
> > -        err = MFXVideoCORE_GetHandle(hwctx->session,
> supported_handle_types[i].handle_type,
> > -                                     &s->handle);
> > -        if (err == MFX_ERR_NONE) {
> > -            s->handle_type       =
> supported_handle_types[i].handle_type;
> > -            s->child_device_type =
> supported_handle_types[i].device_type;
> > -            s->child_pix_fmt     = supported_handle_types[i].pix_fmt;
> > -            break;
> > -        }
> > -    }
> > -    if (!s->handle) {
> > -        av_log(ctx, AV_LOG_VERBOSE, "No supported hw handle could be
> retrieved "
> > -               "from the session\n");
> > -    }
> > -
> >       err = MFXQueryIMPL(hwctx->session, &s->impl);
> >       if (err == MFX_ERR_NONE)
> >           err = MFXQueryVersion(hwctx->session, &s->ver);
> > @@ -146,6 +159,31 @@ static int qsv_device_init(AVHWDeviceContext *ctx)
> >           return AVERROR_UNKNOWN;
> >       }
> >
> > +    if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(s->impl)) {
> > +        handle_type = MFX_HANDLE_D3D11_DEVICE;
> > +    } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(s->impl)) {
> > +        handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
> > +    } else if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(s->impl)) {
> > +        handle_type = MFX_HANDLE_VA_DISPLAY;
> > +    }
> > +
> > +    for (i = 0; supported_handle_types[i].handle_type; i++) {
>
> This loop it not needed given the next line.
>
This particular loop is different from you commented before. This is needed
to extract pix_fmt and device_type.
Can you suggest better solution?


>
> > +        if (supported_handle_types[i].handle_type == handle_type) {
> > +            err = MFXVideoCORE_GetHandle(hwctx->session,
> supported_handle_types[i].handle_type,
> > +                                        &s->handle);
> > +            if (err == MFX_ERR_NONE) {
> > +                s->handle_type       =
> supported_handle_types[i].handle_type;
> > +                s->child_device_type =
> supported_handle_types[i].device_type;
> > +                s->child_pix_fmt     =
> supported_handle_types[i].pix_fmt;
> > +                break;
> > +            }
> > +        }
> > +    }
> > +    if (!s->handle) {
> > +        av_log(ctx, AV_LOG_VERBOSE, "No supported hw handle could be
> retrieved "
> > +               "from the session\n");
> > +    }
> > +
> >       return 0;
> >   }
> >
> > @@ -175,6 +213,7 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx)
> >       av_freep(&s->mem_ids);
> >       av_freep(&s->surface_ptrs);
> >       av_freep(&s->surfaces_internal);
> > +    av_freep(&s->handle_pairs_internal);
> >       av_buffer_unref(&s->child_frames_ref);
> >   }
> >
> > @@ -190,6 +229,8 @@ static AVBufferRef *qsv_pool_alloc(void *opaque, int
> size)
> >
> >       if (s->nb_surfaces_used < hwctx->nb_surfaces) {
> >           s->nb_surfaces_used++;
> > +        av_buffer_create((uint8_t*)(s->handle_pairs_internal +
> s->nb_surfaces_used - 1),
> > +                                sizeof(*s->handle_pairs_internal),
> qsv_pool_release_dummy, NULL, 0);
> >           return av_buffer_create((uint8_t*)(s->surfaces_internal +
> s->nb_surfaces_used - 1),
> >                                   sizeof(*hwctx->surfaces),
> qsv_pool_release_dummy, NULL, 0);
> >       }
> > @@ -229,6 +270,13 @@ static int qsv_init_child_ctx(AVHWFramesContext
> *ctx)
> >           child_device_hwctx->display = (VADisplay)device_priv->handle;
> >       }
> >   #endif
> > +#if CONFIG_D3D11VA
> > +    if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
> > +        AVD3D11VADeviceContext *child_device_hwctx =
> child_device_ctx->hwctx;
> > +        ID3D11Device_AddRef((ID3D11Device*)device_priv->handle);
> > +        child_device_hwctx->device = (ID3D11Device*)device_priv->handle;
> > +    }
> > +#endif
> >   #if CONFIG_DXVA2
> >       if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
> >           AVDXVA2DeviceContext *child_device_hwctx =
> child_device_ctx->hwctx;
> > @@ -255,6 +303,16 @@ static int qsv_init_child_ctx(AVHWFramesContext
> *ctx)
> >       child_frames_ctx->width             = FFALIGN(ctx->width, 16);
> >       child_frames_ctx->height            = FFALIGN(ctx->height, 16);
> >
> > +#if CONFIG_D3D11VA
> > +    if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
> > +        AVD3D11VAFramesContext *child_frames_hwctx =
> child_frames_ctx->hwctx;
> > +        if (hwctx->frame_type == 0)
> > +            hwctx->frame_type =
> MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
> > +        if (hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
> > +            child_frames_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
> > +        child_frames_hwctx->BindFlags =
> qsv_get_d3d11va_bind_flags(hwctx->frame_type);
> > +    }
> > +#endif
> >   #if CONFIG_DXVA2
> >       if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
> >           AVDXVA2FramesContext *child_frames_hwctx =
> child_frames_ctx->hwctx;
> > @@ -279,11 +337,33 @@ static int qsv_init_child_ctx(AVHWFramesContext
> *ctx)
> >           hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
> >       }
> >   #endif
> > +#if CONFIG_D3D11VA
> > +    if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
> > +        AVD3D11VAFramesContext *child_frames_hwctx =
> child_frames_ctx->hwctx;
> > +        for (i = 0; i < ctx->initial_pool_size; i++) {
> > +            s->handle_pairs_internal[i].first =
> (mfxMemId)child_frames_hwctx->texture_infos[i].texture;
> > +            if(child_frames_hwctx->BindFlags &
> D3D11_BIND_RENDER_TARGET) {
> > +                s->handle_pairs_internal[i].second =
> (mfxMemId)MFX_INFINITE;
> > +            } else {
> > +                s->handle_pairs_internal[i].second =
> (mfxMemId)child_frames_hwctx->texture_infos[i].index;
> > +            }
> > +            s->surfaces_internal[i].Data.MemId =
> (mfxMemId)&s->handle_pairs_internal[i];
> > +        }
> > +        if (child_frames_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
> > +            hwctx->frame_type |=
> MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
> > +        } else {
> > +            hwctx->frame_type |=
> MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
> > +        }
> > +    }
> > +#endif
> >   #if CONFIG_DXVA2
> >       if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
> >           AVDXVA2FramesContext *child_frames_hwctx =
> child_frames_ctx->hwctx;
> > -        for (i = 0; i < ctx->initial_pool_size; i++)
> > -            s->surfaces_internal[i].Data.MemId =
> (mfxMemId)child_frames_hwctx->surfaces[i];
> > +        for (i = 0; i < ctx->initial_pool_size; i++) {
> > +            s->handle_pairs_internal[i].first =
> (mfxMemId)child_frames_hwctx->surfaces[i];
> > +            s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
> > +            s->surfaces_internal[i].Data.MemId =
> (mfxMemId)&s->handle_pairs_internal[i];
> > +        }
> >           if (child_frames_hwctx->surface_type ==
> DXVA2_VideoProcessorRenderTarget)
> >               hwctx->frame_type =
> MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
> >           else
> > @@ -348,6 +428,11 @@ static int qsv_init_pool(AVHWFramesContext *ctx,
> uint32_t fourcc)
> >           return AVERROR(EINVAL);
> >       }
> >
> > +    s->handle_pairs_internal = av_mallocz_array(ctx->initial_pool_size,
> > +
> sizeof(*s->handle_pairs_internal));
> > +    if (!s->handle_pairs_internal)
> > +        return AVERROR(ENOMEM);
> > +
> >       s->surfaces_internal = av_mallocz_array(ctx->initial_pool_size,
> >
>  sizeof(*s->surfaces_internal));
> >       if (!s->surfaces_internal)
> > @@ -421,7 +506,17 @@ static mfxStatus frame_unlock(mfxHDL pthis,
> mfxMemId mid, mfxFrameData *ptr)
> >
> >   static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
> >   {
> > +#if CONFIG_VAAPI
> >       *hdl = mid;
> > +#else
> > +    mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
> > +    mfxHDLPair *pair_src = (mfxHDLPair*)mid;
> > +
> > +    pair_dst->first = pair_src->first;
> > +
> > +    if (pair_src->second != (mfxMemId)MFX_INFINITE)
> > +        pair_dst->second = pair_src->second;
> > +#endif
> >       return MFX_ERR_NONE;
> >   }
> >
> > @@ -621,6 +716,18 @@ static int qsv_frames_derive_from(AVHWFramesContext
> *dst_ctx,
> >           }
> >           break;
> >   #endif
> > +#if CONFIG_D3D11VA
> > +    case AV_HWDEVICE_TYPE_D3D11VA:
> > +        {
> > +            AVD3D11VAFramesContext *dst_hwctx = dst_ctx->hwctx;
> > +            mfxHDLPair *pair =
> (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId;
> > +            dst_hwctx->texture = (ID3D11Texture2D*)pair->first;
> > +            if (src_hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
> > +                dst_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
> > +            dst_hwctx->BindFlags =
> qsv_get_d3d11va_bind_flags(src_hwctx->frame_type);
> > +        }
> > +        break;
> > +#endif
> >   #if CONFIG_DXVA2
> >       case AV_HWDEVICE_TYPE_DXVA2:
> >           {
> > @@ -629,9 +736,10 @@ static int qsv_frames_derive_from(AVHWFramesContext
> *dst_ctx,
> >
> sizeof(*dst_hwctx->surfaces));
> >               if (!dst_hwctx->surfaces)
> >                   return AVERROR(ENOMEM);
> > -            for (i = 0; i < src_hwctx->nb_surfaces; i++)
> > -                dst_hwctx->surfaces[i] =
> > -
> (IDirect3DSurface9*)src_hwctx->surfaces[i].Data.MemId;
> > +            for (i = 0; i < src_hwctx->nb_surfaces; i++) {
> > +                mfxHDLPair *pair =
> (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId;
> > +                dst_hwctx->surfaces[i] =
> (IDirect3DSurface9*)pair->first;
> > +            }
> >               dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
> >               if (src_hwctx->frame_type ==
> MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
> >                   dst_hwctx->surface_type =
> DXVA2_VideoDecoderRenderTarget;
> > @@ -668,10 +776,21 @@ static int qsv_map_from(AVHWFramesContext *ctx,
> >           child_data =
> (uint8_t*)(intptr_t)*(VASurfaceID*)surf->Data.MemId;
> >           break;
> >   #endif
> > +#if CONFIG_D3D11VA
> > +    case AV_HWDEVICE_TYPE_D3D11VA:
> > +    {
> > +        mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
> > +        child_data = pair->first;
> > +        break;
> > +    }
> > +#endif
> >   #if CONFIG_DXVA2
> >       case AV_HWDEVICE_TYPE_DXVA2:
> > -        child_data = surf->Data.MemId;
> > +    {
> > +        mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
> > +        child_data = pair->first;
> >           break;
> > +    }
> >   #endif
> >       default:
> >           return AVERROR(ENOSYS);
> > @@ -685,7 +804,14 @@ static int qsv_map_from(AVHWFramesContext *ctx,
> >
> >           dst->width   = src->width;
> >           dst->height  = src->height;
> > -        dst->data[3] = child_data;
> > +
> > +       if (child_frames_ctx->device_ctx->type ==
> AV_HWDEVICE_TYPE_D3D11VA) {
> > +            mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
> > +            dst->data[0] = pair->first;
> > +            dst->data[1] = pair->second;
> > +        } else {
> > +            dst->data[3] = child_data;
> > +        }
> >
> >           return 0;
> >       }
> > @@ -708,7 +834,14 @@ static int qsv_map_from(AVHWFramesContext *ctx,
> >       dummy->format        = child_frames_ctx->format;
> >       dummy->width         = src->width;
> >       dummy->height        = src->height;
> > -    dummy->data[3]       = child_data;
> > +
> > +    if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA)
> {
> > +        mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
> > +        dummy->data[0] = pair->first;
> > +        dummy->data[1] = pair->second;
> > +    } else {
> > +        dummy->data[3] = child_data;
> > +    }
> >
> >       ret = av_hwframe_map(dst, dummy, flags);
> >
> > @@ -954,6 +1087,12 @@ static int qsv_frames_derive_to(AVHWFramesContext
> *dst_ctx,
> >       AVQSVFramesContext *dst_hwctx = dst_ctx->hwctx;
> >       int i;
> >
> > +    if (src_ctx->initial_pool_size == 0) {
> > +        av_log(dst_ctx, AV_LOG_ERROR, "Only fixed-size pools can be "
> > +            "mapped to QSV frames.\n");
> > +        return AVERROR(EINVAL);
> > +    }
> > +
> >       switch (src_ctx->device_ctx->type) {
> >   #if CONFIG_VAAPI
> >       case AV_HWDEVICE_TYPE_VAAPI:
> > @@ -972,6 +1111,36 @@ static int qsv_frames_derive_to(AVHWFramesContext
> *dst_ctx,
> >           }
> >           break;
> >   #endif
> > +#if CONFIG_D3D11VA
> > +    case AV_HWDEVICE_TYPE_D3D11VA:
> > +        {
> > +            AVD3D11VAFramesContext *src_hwctx = src_ctx->hwctx;
> > +            s->handle_pairs_internal =
> av_mallocz_array(src_ctx->initial_pool_size,
> sizeof(*s->handle_pairs_internal));
> > +            if (!s->handle_pairs_internal)
> > +                return AVERROR(ENOMEM);
> > +            s->surfaces_internal =
> av_mallocz_array(src_ctx->initial_pool_size,
> > +
> sizeof(*s->surfaces_internal));
> > +            if (!s->surfaces_internal)
> > +                return AVERROR(ENOMEM);
> > +            for (i = 0; i < src_ctx->initial_pool_size; i++) {
> > +                qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
> > +                s->handle_pairs_internal[i].first =
> (mfxMemId)src_hwctx->texture_infos[i].texture;
> > +                if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
> > +                    s->handle_pairs_internal[i].second =
> (mfxMemId)MFX_INFINITE;
> > +                } else {
> > +                    s->handle_pairs_internal[i].second =
> (mfxMemId)src_hwctx->texture_infos[i].index;
> > +                }
> > +                s->surfaces_internal[i].Data.MemId =
> (mfxMemId)&s->handle_pairs_internal[i];
> > +            }
> > +            dst_hwctx->nb_surfaces = src_ctx->initial_pool_size;
> > +            if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
> > +                dst_hwctx->frame_type |=
> MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
> > +            } else {
> > +                dst_hwctx->frame_type |=
> MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
> > +            }
> > +        }
> > +        break;
> > +#endif
> >   #if CONFIG_DXVA2
> >       case AV_HWDEVICE_TYPE_DXVA2:
> >           {
> > @@ -982,7 +1151,9 @@ static int qsv_frames_derive_to(AVHWFramesContext
> *dst_ctx,
> >                   return AVERROR(ENOMEM);
> >               for (i = 0; i < src_hwctx->nb_surfaces; i++) {
> >                   qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
> > -                s->surfaces_internal[i].Data.MemId =
> (mfxMemId)src_hwctx->surfaces[i];
> > +                s->handle_pairs_internal[i].first =
> (mfxMemId)src_hwctx->surfaces[i];
> > +                s->handle_pairs_internal[i].second =
> (mfxMemId)MFX_INFINITE;
> > +                s->surfaces_internal[i].Data.MemId =
> (mfxMemId)&s->handle_pairs_internal[i];
> >               }
> >               dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
> >               if (src_hwctx->surface_type ==
> DXVA2_VideoProcessorRenderTarget)
> > @@ -1005,21 +1176,43 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx,
> >                         AVFrame *dst, const AVFrame *src, int flags)
> >   {
> >       AVQSVFramesContext *hwctx = dst_ctx->hwctx;
> > -    int i, err;
> > +    int i, err, index = -1;
> >
> > -    for (i = 0; i < hwctx->nb_surfaces; i++) {
> > +    for (i = 0; i < hwctx->nb_surfaces && index < 0; i++) {
> > +        switch(src->format) {
> >   #if CONFIG_VAAPI
> > -        if (*(VASurfaceID*)hwctx->surfaces[i].Data.MemId ==
> > -            (VASurfaceID)(uintptr_t)src->data[3])
> > +        case AV_PIX_FMT_VAAPI:
> > +            if (*(VASurfaceID*)hwctx->surfaces[i].Data.MemId ==
> > +                (VASurfaceID)(uintptr_t)src->data[3])
> > +                index = i;
> >               break;
> >   #endif
> > +#if CONFIG_D3D11VA
> > +        case AV_PIX_FMT_D3D11:
> > +        {
> > +            mfxHDLPair *pair =
> (mfxHDLPair*)hwctx->surfaces[i].Data.MemId;
> > +            if ((ID3D11Texture2D*)pair->first ==
> > +                (ID3D11Texture2D*)(uintptr_t)src->data[0]
>
> I don't think the ID3D11Texture2D* cast is needed for the comparison.
>
Agreed

>
> > +                && pair->second == (mfxMemId)src->data[1]) {
> > +                index = i;
> > +                break;
> > +            }
> > +        }
> > +#endif
> >   #if CONFIG_DXVA2
> > -        if ((IDirect3DSurface9*)hwctx->surfaces[i].Data.MemId ==
> > -            (IDirect3DSurface9*)(uintptr_t)src->data[3])
> > -            break;
> > +        case AV_PIX_FMT_DXVA2_VLD:
> > +        {
> > +            mfxHDLPair *pair =
> (mfxHDLPair*)hwctx->surfaces[i].Data.MemId;
> > +            if ((IDirect3DSurface9*)pair->first ==
> > +                (IDirect3DSurface9*)(uintptr_t)src->data[3]) {
>
> I don't think the IDirect3DSurface9* is needed for the comparison.
>
Agreed

>
> > +                index = i;
> > +                break;
> > +            }
> > +        }
> >   #endif
> > +        }
> >       }
> > -    if (i >= hwctx->nb_surfaces) {
> > +    if (index < 0) {
> >           av_log(dst_ctx, AV_LOG_ERROR, "Trying to map from a surface
> which "
> >                  "is not in the mapped frames context.\n");
> >           return AVERROR(EINVAL);
> > @@ -1032,7 +1225,7 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx,
> >
> >       dst->width   = src->width;
> >       dst->height  = src->height;
> > -    dst->data[3] = (uint8_t*)&hwctx->surfaces[i];
> > +    dst->data[3] = (uint8_t*)&hwctx->surfaces[index];
> >
> >       return 0;
> >   }
> > @@ -1074,7 +1267,7 @@ static void qsv_device_free(AVHWDeviceContext *ctx)
> >       av_freep(&priv);
> >   }
> >
> > -static mfxIMPL choose_implementation(const char *device)
> > +static mfxIMPL choose_implementation(const char *device, enum
> AVHWDeviceType child_device_type)
> >   {
> >       static const struct {
> >           const char *name;
> > @@ -1103,6 +1296,10 @@ static mfxIMPL choose_implementation(const char
> *device)
> >               impl = strtol(device, NULL, 0);
> >       }
> >
> > +    if ( (child_device_type == AV_HWDEVICE_TYPE_D3D11VA) && (impl !=
> MFX_IMPL_SOFTWARE) ) {
> > +        impl |= MFX_IMPL_VIA_D3D11;
> > +    }
> > +
> >       return impl;
> >   }
> >
> > @@ -1129,6 +1326,15 @@ static int
> qsv_device_derive_from_child(AVHWDeviceContext *ctx,
> >           }
> >           break;
> >   #endif
> > +#if CONFIG_D3D11VA
> > +    case AV_HWDEVICE_TYPE_D3D11VA:
> > +        {
> > +            AVD3D11VADeviceContext *child_device_hwctx =
> child_device_ctx->hwctx;
> > +            handle_type = MFX_HANDLE_D3D11_DEVICE;
> > +            handle = (mfxHDL)child_device_hwctx->device;
> > +        }
> > +        break;
> > +#endif
> >   #if CONFIG_DXVA2
> >       case AV_HWDEVICE_TYPE_DXVA2:
> >           {
> > @@ -1191,7 +1397,9 @@ fail:
> >   static int qsv_device_derive(AVHWDeviceContext *ctx,
> >                                AVHWDeviceContext *child_device_ctx, int
> flags)
> >   {
> > -    return qsv_device_derive_from_child(ctx, MFX_IMPL_HARDWARE_ANY,
> > +    mfxIMPL impl;
> > +    impl = choose_implementation("hw_any", child_device_ctx->type);
> > +    return qsv_device_derive_from_child(ctx, impl,
> >                                           child_device_ctx, flags);
> >   }
> >
> > @@ -1214,35 +1422,66 @@ static int qsv_device_create(AVHWDeviceContext
> *ctx, const char *device,
> >       ctx->user_opaque = priv;
> >       ctx->free        = qsv_device_free;
> >
> > -    e = av_dict_get(opts, "child_device", NULL, 0);
> > -
> > -    child_device_opts = NULL;
> > -    if (CONFIG_VAAPI) {
> > +    e = av_dict_get(opts, "child_device_type", NULL, 0);
> > +    if (e) {
> > +        child_device_type = av_hwdevice_find_type_by_name(e ? e->value
> : NULL);
> > +        if (child_device_type == AV_HWDEVICE_TYPE_NONE) {
> > +            av_log(ctx, AV_LOG_ERROR, "Unknown child device type "
> > +                   "\"%s\".\n", e ? e->value : NULL);
> > +            return AVERROR(EINVAL);
> > +        }
> > +    } else if (CONFIG_VAAPI) {
> >           child_device_type = AV_HWDEVICE_TYPE_VAAPI;
> > -        // libmfx does not actually implement VAAPI properly, rather it
> > -        // depends on the specific behaviour of a matching iHD driver
> when
> > -        // used on recent Intel hardware.  Set options to the VAAPI
> device
> > -        // creation so that we should pick a usable setup by default if
> > -        // possible, even when multiple devices and drivers are
> available.
> > -        av_dict_set(&child_device_opts, "kernel_driver", "i915", 0);
> > -        av_dict_set(&child_device_opts, "driver",        "iHD",  0);
> > -    } else if (CONFIG_DXVA2)
> > +    } else if (CONFIG_D3D11VA) {
> > +        child_device_type = AV_HWDEVICE_TYPE_D3D11VA;
> > +    } else if (CONFIG_DXVA2) {
> >           child_device_type = AV_HWDEVICE_TYPE_DXVA2;
> > -    else {
> > +    } else {
> >           av_log(ctx, AV_LOG_ERROR, "No supported child device type is
> enabled\n");
> >           return AVERROR(ENOSYS);
> >       }
> >
> > +    child_device_opts = NULL;
> > +    switch (child_device_type) {
> > +#if CONFIG_VAAPI
> > +    case AV_HWDEVICE_TYPE_VAAPI:
> > +        {
> > +            // libmfx does not actually implement VAAPI properly,
> rather it
> > +            // depends on the specific behaviour of a matching iHD
> driver when
> > +            // used on recent Intel hardware.  Set options to the VAAPI
> device
> > +            // creation so that we should pick a usable setup by
> default if
> > +            // possible, even when multiple devices and drivers are
> available.
> > +            av_dict_set(&child_device_opts, "kernel_driver", "i915", 0);
> > +            av_dict_set(&child_device_opts, "driver",        "iHD",  0);
> > +        }
> > +        break;
> > +#endif
> > +#if CONFIG_D3D11VA
> > +    case AV_HWDEVICE_TYPE_D3D11VA:
> > +        break;
> > +#endif
> > +#if CONFIG_DXVA2
> > +    case AV_HWDEVICE_TYPE_DXVA2:
> > +        break;
> > +#endif
> > +    default:
> > +        {
> > +            av_log(ctx, AV_LOG_ERROR, "No supported child device type
> is enabled\n");
> > +            return AVERROR(ENOSYS);
> > +        }
> > +        break;
> > +    }
> > +
> > +    e = av_dict_get(opts, "child_device", NULL, 0);
> >       ret = av_hwdevice_ctx_create(&priv->child_device_ctx,
> child_device_type,
> >                                    e ? e->value : NULL,
> child_device_opts, 0);
> > -
> >       av_dict_free(&child_device_opts);
> >       if (ret < 0)
> >           return ret;
> >
> >       child_device = (AVHWDeviceContext*)priv->child_device_ctx->data;
> >
> > -    impl = choose_implementation(device);
> > +    impl = choose_implementation(device, child_device_type);
> >
> >       return qsv_device_derive_from_child(ctx, impl, child_device, 0);
> >   }
> > --
> > 2.26.0
> >
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel at ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
> >
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".


More information about the ffmpeg-devel mailing list