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 ;)

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.

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

      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().

+        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

+} 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.

+        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.

+                && 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.

+                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".

Reply via email to