On Tue, 21 Apr 2020 at 11:26, Steve Lhomme <rob...@ycbcr.xyz> wrote: > On 2020-04-15 15:07, artem.ga...@gmail.com wrote: > > From: Artem Galin <artem.ga...@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.ga...@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@ffmpeg.org > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > > To unsubscribe, visit link above, or email > > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".