From patchwork Fri Apr 13 09:21:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kravchenko X-Patchwork-Id: 8434 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.1.70 with SMTP id c67csp546805jad; Fri, 13 Apr 2018 02:21:45 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+EBdsdS+3562C9pSW2DkRGi4O8+UiPp0knEa27Wm+/AasuxyqAYUzoltwyBwnzXrk8XLA/ X-Received: by 10.223.187.138 with SMTP id q10mr2888837wrg.62.1523611305279; Fri, 13 Apr 2018 02:21:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523611305; cv=none; d=google.com; s=arc-20160816; b=iNz7Zf/vVbxjhg2YI6RcDeTxTwd4Jvn9NPVlE7vghZEbBjoCcDHiHivMRIKhJCz16T l/2MaCtHbSrnuK0cox3XwZm6b4nhzswXtc0+3mPyxdgZTN8ikZrnYiLIubSzaORkurDN GbSH9FarsGZobI1556VQkgxmJtRu9O3w3jHQgP+jB3U7AV4YuUmtdNzotD5ZqxHTTnGQ vbGsnSPa4lHSZXhJtCCOJfJm5VBOpmVoY7RtU0EG4uOsmfn/2qKw5Z36XzHWzw9EBtUF lxNDvMCIleydujPVqyz1SCtIFVOlwqED8GAinYtSz5EiQHb2ILu9XDdmcBx7JS06K08F uBzw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to:arc-authentication-results; bh=ezPXoX0ubm2zdVvIXBwaJB5ZrBan37YHtXJ92G1hl4I=; b=iT14Jd8XEaRH5vu7E/gGQHucqUEunLN6qnPhQWilO+iQNlGvH3MaE38RXLn36EvRE7 PxeLXjcqaqKm+S8IEf3S/DWqxTIVX3S7EpPfKfnou2cAgWXRShpKFQ0wuyirLmrdD4KP +0LBMSI1G8Puf4Ue6wAV+JXFN46Kae2kAxnNRzG3YUApQg/xwfRZvNjQFb0U3d5LSz5M TtpX182pv6RXl/Nwzwd0vJCm2SOAdxrmqiXZaeNjxHTn9JXtrzrN6YgPgKNiB4dNmYTr KQ6FUuDlIW/2FWVECzFJE4pI0ym8E4OM0wwhXzEyZ0AVaaMWrTIg09nL2137RJKkc/uB BrGg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=SZit1h5X; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id o45si1186188wrf.359.2018.04.13.02.21.44; Fri, 13 Apr 2018 02:21:45 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=SZit1h5X; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5D97C689F3D; Fri, 13 Apr 2018 12:21:17 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf0-f54.google.com (mail-lf0-f54.google.com [209.85.215.54]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 236CA689BC3 for ; Fri, 13 Apr 2018 12:21:11 +0300 (EEST) Received: by mail-lf0-f54.google.com with SMTP id v207-v6so11633635lfa.10 for ; Fri, 13 Apr 2018 02:21:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=3BeA+CSP7+IsYfyPQSyffKoU4zwRZbI6qwpkAncw61s=; b=SZit1h5XSF3iWLoYLytwnS2bLOzXBfw1Kk+tTIqqRQeWDp1xNnJJMNTjQi1NyOZpKo n9RkQ82hJZv7PPBV0RQArS6+JPV8FmXgTf+OoWOVf4ABQXpavzYICWTr90YjLlkR+51c tex3a8Pq7FedI74Tvmf/wQyhcwZivetlQv7DcU8upCCiFUNQvR2uENDMNRQa9OFDDS8l 7Vu+h1ZMSMKT6ZOrgQlAVGhSCSnbGT0uxqVNJ7cFSKMP4cHaKLoYnqdGHafDDMXXPEo8 3yufrLvFpYtp3MKGTiqtyDkIqoVu9XKIQP2fnS4ZwiaXkVaWiyZAfy8YAQAb8TJlYk9d QSNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=3BeA+CSP7+IsYfyPQSyffKoU4zwRZbI6qwpkAncw61s=; b=j97NFTKB4h67dlUJCyr+AkCTKhXDKVURobaj5glyXQBQaj1qIJitS0mWihVjyLQxIp K8yFa1h95kX56/g1GvXnSM/rXk0VuIOQACHEc/CZMlGMLSqV70L3AZcp3orDxbvKP877 fpagXYepIIG7xkzsblK5+8aWrGLrAcd5aedJ9mCd4gP/buuDafOlRNoxr5HNaI5oUhFN zF2X/N146LIA6/zLNbh2deQmEWW4jv2Hcg0Pjn5ijfumMiL22geINWHk263Lu7Yiz8Rq qYTV5Fsur644pNrbEWfWbwAiGRG1sBsOjxj7QQkW0xZnuMAGK+BKoTobJfTF3hP4qOU3 kdAw== X-Gm-Message-State: ALQs6tDepvP9iRheuUxb+kZ2aU5IzTCIJV3kBlNvEb8PeXdb00X641vp JurL464cC98otJQM02aok/+F2OT5 X-Received: by 2002:a19:6d03:: with SMTP id i3-v6mr7553411lfc.34.1523611294754; Fri, 13 Apr 2018 02:21:34 -0700 (PDT) Received: from localhost.localdomain ([188.227.65.188]) by smtp.gmail.com with ESMTPSA id n18-v6sm1128244lfh.87.2018.04.13.02.21.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 13 Apr 2018 02:21:34 -0700 (PDT) From: Alexander Kravchenko To: ffmpeg-devel@ffmpeg.org Date: Fri, 13 Apr 2018 12:21:12 +0300 Message-Id: <20180413092112.20468-1-akravchenko188@gmail.com> X-Mailer: git-send-email 2.16.2.windows.1 Subject: [FFmpeg-devel] [PATCH] lavc/amfenc: DXVA2 textures support implementation by AMF encoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Alexander Kravchenko MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This patch contains DXVA2 textures support implementation by AMF encoder (in addition of D3D11 textures) Samples of usage: DXVA2 decoder -> dxva2_vld texture -> AMF Encoder: ffmpeg -hwaccel dxva2 -hwaccel_output_format dxva2_vld -extra_hw_frames 16 -i input.mp4 -an -c:v h264_amf out.mkv D3D11va decoder -> d3d11 texture -> AMF Encoder: ffmpeg -hwaccel d3d11va -hwaccel_output_format d3d11 -extra_hw_frames 16 -i input.mp4 -an -c:v h264_amf out.mkv --- Sending updated patch (Fixes according Mark's review): > > --- > ^ > (When adding commentary which isn't part of the commit message to an email please place it after this line so that it doesn't end up in the commit message.) Done here, hopefully correctly > > { AV_PIX_FMT_D3D11, AMF_SURFACE_NV12 }, > > + { AV_PIX_FMT_DXVA2_VLD, AMF_SURFACE_NV12 }, > > As with D3D11, this isn't necessarily true. This was ignored before, but do you have any plan for how P010 (and others?) will be handled here? removed HW types from format map, and added logic reading pixel format from avctx->sw_pix_fmt in case if avctx->pix_fmt is HWACCEL type > +static void get_dx9_device_from_devmgr(IDirect3DDeviceManager9 *devmgr, IDirect3DDevice9 **device, void *avcl) { > ... > Might be cleaner using an error return rather than the null device? Fixed > Everything using D3D9 types needs to be inside CONFIG_DXVA2 Fixed > Passing NULL here will make this case succeed in cases where it shouldn't, I think? Agree, fixed > Tbh I don't think this fallback case should exist at all, it should just fail. > Is there any use-case for having it? The user passed a DXVA2 frames context on a > non-AMD device and expects it to work with that hardware input, this fallback makes > it kindof work with at least two copies in a way which is likely to be very slow. > Even if the user does want to do that, it would be better for them to do it explicitly > to ensure that they aware of the problem. (We don't automatically do this in any other case.) Agree, fixed > Spurious whitespace. Fixed in changed blocks/functions > Tested on Windows 7, works well. > Unlike with D3D11 the OpenCL interop works properly as well, > so e.g. -vf 'hwmap=derive_device=opencl,convolution_opencl=0 1 0 1 -4 1 0 1 0,hwmap=derive_device=dxva2:reverse=1:extra_hw_frames=16' as encoder input works too. Could you send the samples (or link if they are published, I will add to my tests and will check OpenCL interop with D3D11) libavcodec/amfenc.c | 158 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 126 insertions(+), 32 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index b9418b6791..7cdf17a972 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -24,6 +24,9 @@ #if CONFIG_D3D11VA #include "libavutil/hwcontext_d3d11va.h" #endif +#if CONFIG_DXVA2 +#include "libavutil/hwcontext_dxva2.h" +#endif #include "libavutil/mem.h" #include "libavutil/pixdesc.h" #include "libavutil/time.h" @@ -50,6 +53,9 @@ const enum AVPixelFormat ff_amf_pix_fmts[] = { AV_PIX_FMT_YUV420P, #if CONFIG_D3D11VA AV_PIX_FMT_D3D11, +#endif +#if CONFIG_DXVA2 + AV_PIX_FMT_DXVA2_VLD, #endif AV_PIX_FMT_NONE }; @@ -68,7 +74,6 @@ static const FormatMap format_map[] = { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, { AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P }, { AV_PIX_FMT_YUYV422, AMF_SURFACE_YUY2 }, - { AV_PIX_FMT_D3D11, AMF_SURFACE_NV12 }, }; @@ -152,6 +157,26 @@ static int amf_load_library(AVCodecContext *avctx) return 0; } +#if CONFIG_DXVA2 +static HRESULT get_dx9_device_from_devmgr(IDirect3DDeviceManager9 *devmgr, IDirect3DDevice9 **device, void *avcl) +{ + HRESULT hr; + HANDLE device_handle; + + if (SUCCEEDED(hr = devmgr->lpVtbl->OpenDeviceHandle(devmgr, &device_handle))) { + if (SUCCEEDED(hr = devmgr->lpVtbl->LockDevice(devmgr, device_handle, device, FALSE))) { + devmgr->lpVtbl->UnlockDevice(devmgr, device_handle, FALSE); + } else { + av_log(avcl, AV_LOG_INFO, "Failed to lock device handle for Direct3D9 device: %lx.\n", (unsigned long)hr); + } + devmgr->lpVtbl->CloseDeviceHandle(devmgr, device_handle); + } else { + av_log(avcl, AV_LOG_INFO, "Failed to open device handle for Direct3D9 device: %lx.\n", (unsigned long)hr); + } + return hr; +} +#endif + static int amf_init_context(AVCodecContext *avctx) { AmfContext *ctx = avctx->priv_data; @@ -177,34 +202,61 @@ static int amf_init_context(AVCodecContext *avctx) res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res); // try to reuse existing DX device -#if CONFIG_D3D11VA if (avctx->hw_frames_ctx) { - AVHWFramesContext *device_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - if (device_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { - if (amf_av_to_amf_format(device_ctx->sw_format) != AMF_SURFACE_UNKNOWN) { - if (device_ctx->device_ctx->hwctx) { - AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->device_ctx->hwctx; + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; + if (amf_av_to_amf_format(frames_ctx->sw_format) != AMF_SURFACE_UNKNOWN) { + if (frames_ctx->device_ctx->hwctx) { +#if CONFIG_D3D11VA + if (frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { + AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)frames_ctx->device_ctx->hwctx; res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1); if (res == AMF_OK) { ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); if (!ctx->hw_frames_ctx) { return AVERROR(ENOMEM); } - if (device_ctx->initial_pool_size > 0) - ctx->hwsurfaces_in_queue_max = device_ctx->initial_pool_size - 1; + if (frames_ctx->initial_pool_size > 0) + ctx->hwsurfaces_in_queue_max = frames_ctx->initial_pool_size - 1; } else { - if(res == AMF_NOT_SUPPORTED) - av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n"); + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D11 device which doesn't have D3D11VA interface\n"); else - av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has non-AMD device, switching to default\n"); + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has non-AMD device\n"); + return AVERROR(ENODEV); } } - } else { - av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has format not uspported by AMF, switching to default\n"); +#endif +#if CONFIG_DXVA2 + if (frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { + AVDXVA2DeviceContext *device_dxva2 = (AVDXVA2DeviceContext *)frames_ctx->device_ctx->hwctx; + IDirect3DDevice9 *device_dx9 = NULL; + if(SUCCEEDED(get_dx9_device_from_devmgr(device_dxva2->devmgr, &device_dx9, avctx))) { + res = ctx->context->pVtbl->InitDX9(ctx->context, device_dx9); + device_dx9->lpVtbl->Release(device_dx9); + if (res == AMF_OK) { + ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); + if (!ctx->hw_frames_ctx) { + return AVERROR(ENOMEM); + } + if (frames_ctx->initial_pool_size > 0) + ctx->hwsurfaces_in_queue_max = frames_ctx->initial_pool_size - 1; + } else { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D device which doesn't have DXVA2 interface\n"); + else + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has non-AMD device\n"); + return AVERROR(ENODEV); + } + } + } +#endif } + } else { + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has format not uspported by AMF\n"); } } else if (avctx->hw_device_ctx) { - AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data); + AVHWDeviceContext *device_ctx = (AVHWDeviceContext *)(avctx->hw_device_ctx->data); +#if CONFIG_D3D11VA if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { if (device_ctx->hwctx) { AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->hwctx; @@ -216,19 +268,42 @@ static int amf_init_context(AVCodecContext *avctx) } } else { if (res == AMF_NOT_SUPPORTED) - av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n"); + av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has D3D11 device which doesn't have D3D11VA interface\n"); else - av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has non-AMD device, switching to default\n"); + av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has non-AMD device\n"); + return AVERROR(ENODEV); + } + } + } +#endif +#if CONFIG_DXVA2 + if (device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { + AVDXVA2DeviceContext *device_dxva2 = (AVDXVA2DeviceContext *)device_ctx->hwctx; + IDirect3DDevice9 *device_dx9 = NULL; + if(SUCCEEDED(get_dx9_device_from_devmgr(device_dxva2->devmgr, &device_dx9, avctx))) { + res = ctx->context->pVtbl->InitDX9(ctx->context, device_dx9); + device_dx9->lpVtbl->Release(device_dx9); + if (res == AMF_OK) { + ctx->hw_device_ctx = av_buffer_ref(avctx->hw_device_ctx); + if (!ctx->hw_device_ctx) { + return AVERROR(ENOMEM); + } + } else { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has D3D device which doesn't have DXVA2 interface\n"); + else + av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has non-AMD device\n"); + return AVERROR(ENODEV); } } } - } #endif + } if (!ctx->hw_frames_ctx && !ctx->hw_device_ctx) { res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1); if (res != AMF_OK) { res = ctx->context->pVtbl->InitDX9(ctx->context, NULL); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "InitDX9() failed with error %d\n", res); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENODEV), "InitDX9() failed with error %d\n", res); } } return 0; @@ -239,6 +314,7 @@ static int amf_init_encoder(AVCodecContext *avctx) AmfContext *ctx = avctx->priv_data; const wchar_t *codec_id = NULL; AMF_RESULT res = AMF_OK; + enum AVPixelFormat pix_fmt; switch (avctx->codec->id) { case AV_CODEC_ID_H264: @@ -252,8 +328,13 @@ static int amf_init_encoder(AVCodecContext *avctx) } AMF_RETURN_IF_FALSE(ctx, codec_id != NULL, AVERROR(EINVAL), "Codec %d is not supported\n", avctx->codec->id); - ctx->format = amf_av_to_amf_format(avctx->pix_fmt); - AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), "Format %d is not supported\n", avctx->pix_fmt); + if(is_hwaccel_pix_fmt(avctx->pix_fmt)) { + pix_fmt = avctx->sw_pix_fmt; + } else { + pix_fmt = avctx->pix_fmt; + } + ctx->format = amf_av_to_amf_format(pix_fmt); + AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), "Format %d is not supported\n", pix_fmt); res = ctx->factory->pVtbl->CreateComponent(ctx->factory, ctx->context, codec_id, &ctx->encoder); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res); @@ -555,22 +636,35 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) // check if the same hw_frames_ctx as used in initialization (ctx->hw_frames_ctx && frame->hw_frames_ctx->data == ctx->hw_frames_ctx->data) || // check if the same hw_device_ctx as used in initialization - (ctx->hw_device_ctx && ((AVHWFramesContext*)frame->hw_frames_ctx->data)->device_ctx == - (AVHWDeviceContext*)ctx->hw_device_ctx->data) + (ctx->hw_device_ctx && ((AVHWFramesContext *)frame->hw_frames_ctx->data)->device_ctx == + (AVHWDeviceContext *)ctx->hw_device_ctx->data) )) { AMFBuffer *frame_ref_storage_buffer; - #if CONFIG_D3D11VA - static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } }; - ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture - int index = (int)(size_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use - texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index); + if (((AVHWFramesContext *)frame->hw_frames_ctx->data)->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { + static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } }; + + ID3D11Texture2D *texture = (ID3D11Texture2D *)frame->data[0]; // actual texture + int index = (int)(size_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use + texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index); - res = ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res); + res = ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res); - // input HW surfaces can be vertically aligned by 16; tell AMF the real size - surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height); + // input HW surfaces can be vertically aligned by 16; tell AMF the real size + surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height); + } +#endif +#if CONFIG_DXVA2 + if (((AVHWFramesContext *)frame->hw_frames_ctx->data)->device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { + IDirect3DSurface9 *texture = (IDirect3DSurface9 *)frame->data[3]; // actual texture + + res = ctx->context->pVtbl->CreateSurfaceFromDX9Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res); + + // input HW surfaces can be vertically aligned by 16; tell AMF the real size + surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height); + } #endif frame_ref_storage_buffer = amf_create_buffer_with_frame_ref(frame, ctx->context);