From patchwork Fri Apr 24 14:52:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: galinart X-Patchwork-Id: 19219 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 7E73B44A6E0 for ; Fri, 24 Apr 2020 18:26:38 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5DCA368C0FA; Fri, 24 Apr 2020 18:26:38 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ej1-f67.google.com (mail-ej1-f67.google.com [209.85.218.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E7FBA68BB17 for ; Fri, 24 Apr 2020 18:26:31 +0300 (EEST) Received: by mail-ej1-f67.google.com with SMTP id pg17so7783466ejb.9 for ; Fri, 24 Apr 2020 08:26:31 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=uhd7ptCTQ7ijucpHx34AJDraOhurHQh7/oyUXZQY3Ho=; b=ipz7eNFuDkO1nvydlRncLAwm4hXvJFy14xuWp/I+4iUud1X9P8CSIVEsoDYWNF0/Bd 5XsDolmBQLymfu2zyvsB4d3L4t9IxXH/zzPOMC0b6jxDNQATsMwbS6mnZQkzt0chkEJj PXfIvWPXdKLR5wGDopDRCzUoOhwkKpqYeZrKXTQaGs9sY1d0nWfTPLNPb3vcIcHpTpnQ ui+beONSP7NHpomHVjyqieOiEGbhn2EmcBFToulje/9ZMBd15x1TWJY724MUo9CuANfh oU1K9/uWK8CXlJtPbRxiVo1zJ6wDtlA/grezhgB6iyEEpOUUyUm6zbMfl/KiNqCtEOqH KmvQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=uhd7ptCTQ7ijucpHx34AJDraOhurHQh7/oyUXZQY3Ho=; b=C+pHICaxiHlxd5ZpWWewtRLBKGc6yDfG3pau0qtY1ap5PNGWYuNed1+o68yWcLzCxz sDOzmft/kSmAaS+JsFog+ZG7GDVg1xFzFqqDz6gAGzY8uB3fdhd5WqjnP3jzWlawMWkx oxcUSJpdRCscc47dOyHh+PMp+bpFzuOStScqjWvJsrdr2ZZtIdaxKEE3pC1efyGWKkd3 2cNvccXVVcX3UdAV12+ob50pNZJmiZlYrKCIebKGe3u70pKekfR5eDLsH62KZz5sUQRm CbWygKWtDll5rQMJsr08gQUpOa/Nv/nzN5l2szZqYqxwd9UgXVpjdt1ZhG3qyKZcnWXl UnwQ== X-Gm-Message-State: AGi0PuYFRFd9JlcXArRBxOPmwfpGAtfFrguU3qgGk7qVLtN/Re/pLldl IG5biR+4JVSiv1GwIzX+eUpcAUnNTIo= X-Google-Smtp-Source: APiQypKTafDnkzO2Iq9fD5xKSvlWHOapbjIWYcRewGBhN01ocg/1B/u9jCtIVmhMIy7vJjXfmpCjqg== X-Received: by 2002:adf:e5c8:: with SMTP id a8mr12539558wrn.56.1587740043023; Fri, 24 Apr 2020 07:54:03 -0700 (PDT) Received: from localhost.localdomain ([2a02:c7d:3e2e:7400:d810:daa5:1027:e125]) by smtp.googlemail.com with ESMTPSA id p190sm3180552wmp.38.2020.04.24.07.54.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Apr 2020 07:54:02 -0700 (PDT) From: artem.galin@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Fri, 24 Apr 2020 15:52:16 +0100 Message-Id: <20200424145219.54067-1-artem.galin@gmail.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200415130741.27263-1-artem.galin@gmail.com> References: <20200415130741.27263-1-artem.galin@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 1/4] fftools/qsv: enabling d3d11va/dxva2 device selection 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: Artem Galin , robux4@ycbcr.xyz Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Artem Galin child_device_type argument is responsible for selection. Usage examples: -init_hw_device qsv:hw,child_device_type=d3d11va -init_hw_device qsv:hw,child_device_type=dxva2 Signed-off-by: Artem Galin --- fftools/ffmpeg_opt.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 680f0f1dfb..de5bc51bee 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -565,7 +565,17 @@ static int opt_init_hw_device(void *optctx, const char *opt, const char *arg) printf("\n"); exit_program(0); } else { - return hw_device_init_from_string(arg, NULL); + HWDevice *dev; + int err; + if (!arg) + return AVERROR(ENOMEM); + err = hw_device_init_from_string(arg, &dev); + if (err < 0) + return err; + hw_device_ctx = av_buffer_ref(dev->device_ref); + if (!hw_device_ctx) + return AVERROR(ENOMEM); + return 0; } } From patchwork Fri Apr 24 14:52:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: galinart X-Patchwork-Id: 19214 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id A9C6F44A379 for ; Fri, 24 Apr 2020 17:54:21 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 81C8E68BFB1; Fri, 24 Apr 2020 17:54:21 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id DA57C68BF81 for ; Fri, 24 Apr 2020 17:54:14 +0300 (EEST) Received: by mail-wr1-f67.google.com with SMTP id k13so11209351wrw.7 for ; Fri, 24 Apr 2020 07:54:14 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=Oj24E9wN1F2/LAGJHbR4DuwbpvtSapXZZyBn2hejP6o=; b=mCJNngfRTWldRbmGcFTeW1E2enQROoFsvagwUIqJClzCJYBVmGKp1SBMUcXVET2Son gF06Ojg70EcnF1aRHGFw7Yer0okpDKQ6oIjmBWw4IC59bkWc8ix6Go53kuJ23V9mnWxs ZvICl+igqApQPfUW6eb9pIQ+bCmZ6bPPR90DxumfV3bZ5Se4NQ3I9MxnDvGgV9qDY20g VBaJFR+sLYdSGUZjixB/SAz9p/pfwGvYVZ0RNmOftuVAqvqa5NL4pW0JO/iGFSOOMZyx FEgFgAFEQZWtkzthJ+44mGWspntQRwq4qV2/IhznLdYKz4LZf+yvGcAjnyxiBqqS319F k38A== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=Oj24E9wN1F2/LAGJHbR4DuwbpvtSapXZZyBn2hejP6o=; b=I1cnJlVuu+QKhiGeMPvb00AL8/w2nS2I1zHNYXHkUvBXRnr6qikhnUekfElR7OQI+H xwqFoVD0Vy1WmcXOVShUDcAEoEcVZ3bYafrr5UVlx2gOtsoFkysytMRlOwyHTCsEb1SI IODpIoWrl8kaFUeE72ToENeYlqko1g2Ccet+n4OSGoqQEw8NghVsowy45Xvm+jDqrSss rD/v+FWjPWhyAuLJcrBy5cOGOnuN/fkV08xcyVRPVXpd3V+VJ7ktmgpa+9l/RBVF9Guc u3cuZjTrU456iDYe1zNS9wgHJBilXpi/5rfYmxF8MsOepI1kwNq72YyewYjRWrvaVrG2 JZxw== X-Gm-Message-State: AGi0PuY9UnFtfLsXb2X6xtSYlZfTrYyZnSNAuQnDsRNPtNdQBqgZzH1P kg3Xzy3FE0TXPRUBW6TRKBfa2QtJC8s= X-Google-Smtp-Source: APiQypK+rwrK5He40VZysrkgtH4F7Ztnjn/Kmjn7MZR5M3z2vbgr4wJroT8VDppdIUtVbIQ6khQDHA== X-Received: by 2002:adf:e5c8:: with SMTP id a8mr12540525wrn.56.1587740054105; Fri, 24 Apr 2020 07:54:14 -0700 (PDT) Received: from localhost.localdomain ([2a02:c7d:3e2e:7400:d810:daa5:1027:e125]) by smtp.googlemail.com with ESMTPSA id p190sm3180552wmp.38.2020.04.24.07.54.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Apr 2020 07:54:13 -0700 (PDT) From: artem.galin@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Fri, 24 Apr 2020 15:52:17 +0100 Message-Id: <20200424145219.54067-2-artem.galin@gmail.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200424145219.54067-1-artem.galin@gmail.com> References: <20200415130741.27263-1-artem.galin@gmail.com> <20200424145219.54067-1-artem.galin@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 2/4] libavfilter/qsvvpp: enabling d3d11va support 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: Artem Galin , robux4@ycbcr.xyz Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Artem Galin Adding DX11 relevant device type checks and adjusting callback with proper MediaSDK pair type support. Signed-off-by: Artem Galin --- libavfilter/qsvvpp.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index 8d5ff2eb65..f74b504990 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -36,6 +36,7 @@ MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) #define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME) #define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY) +#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) typedef struct QSVFrame { AVFrame *frame; @@ -68,12 +69,6 @@ struct QSVVPPContext { int nb_ext_buffers; }; -static const mfxHandleType handle_types[] = { - MFX_HANDLE_VA_DISPLAY, - MFX_HANDLE_D3D9_DEVICE_MANAGER, - MFX_HANDLE_D3D11_DEVICE, -}; - static const AVRational default_tb = { 1, 90000 }; /* functions for frameAlloc */ @@ -129,7 +124,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; } @@ -451,7 +456,7 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) s->out_mem_mode = IS_OPAQUE_MEMORY(s->in_mem_mode) ? MFX_MEMTYPE_OPAQUE_FRAME : - MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; + MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT; out_frames_ctx = (AVHWFramesContext *)out_frames_ref->data; out_frames_hwctx = out_frames_ctx->hwctx; @@ -497,14 +502,18 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) return AVERROR_UNKNOWN; } - for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) { - ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle); - if (ret == MFX_ERR_NONE) { - handle_type = handle_types[i]; - break; - } + if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) { + handle_type = MFX_HANDLE_VA_DISPLAY; + } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) { + handle_type = MFX_HANDLE_D3D11_DEVICE; + } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) { + handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; + } else { + av_log(avctx, AV_LOG_ERROR, "Error unsupported handle type\n"); + return AVERROR_UNKNOWN; } + ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle); if (ret != MFX_ERR_NONE) { av_log(avctx, AV_LOG_ERROR, "Error getting the session handle\n"); return AVERROR_UNKNOWN; From patchwork Fri Apr 24 14:52:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: galinart X-Patchwork-Id: 19216 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 489CF449C9C for ; Fri, 24 Apr 2020 17:59:56 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1ED8368BFEF; Fri, 24 Apr 2020 17:59:56 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 402C668B619 for ; Fri, 24 Apr 2020 17:59:49 +0300 (EEST) Received: by mail-wm1-f68.google.com with SMTP id u16so11135971wmc.5 for ; Fri, 24 Apr 2020 07:59:49 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=aDNO738MyIF4mWFVBYVa1lQkN7M/M3zewnrA3+QLKiM=; b=FyOkaAZSJ6+juFBGXLvCPc2/V/2Ba5Oi7k9m2X5daHlm50QRvoMbW2ogUxtOZh0/8W wEHaWc5a+4dwGvptoU2mCHYvyKB7qv8kyF8IfX5BQsMRBjv2P+bfhIQz0AcyEy148jbY gwZSZwQJJ6BUPOyDi3cq/ZvmfLFn8LjggBRC4maJzVSjo+Bdy4LdBa3X7ZviX9dFXefq 2CUY6OTJSgF9WweAUcxKHbVr7p1PHVls0JFLtAOHqYiXBPpno70Xh7IoZGjV9+qtWOoZ AgWRDi9HhbJxfk09L8fzLuVNKaKCwWsx7Dad0Kib+pzWhnqf2ACM3Zdk6pciwT8aebM7 DJCQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=aDNO738MyIF4mWFVBYVa1lQkN7M/M3zewnrA3+QLKiM=; b=g53EochuypndUL+lY2s57j07qioUKMUmJMpk4laTfmp0yy00QXHDilTB8vgoi3EqAW +safEIywbfZqfIVlZhPoZTY+bzxOhyUEjzkGVhmeazyYLyApjRi7ORxbCMP76ErXXKRL stwTi4UVPez7uoW68UHmHmudfNRDqM+CAaY/cBVoKgvB0bigZOgbSQSY0apQiO8v8e/v HUToYjI2sJCOUq3Lccb8C2kR2B1CSajZphW+HDwznuhyMaWdmDb2DYAi+54Og6nkdFgs aeW1RrvwIyvNqxIF4KbLl+92yGtmTmS17pfXr4tGSaGilgZGCGlcAxQGrn8hGgzWapE0 3DfQ== X-Gm-Message-State: AGi0PuZz0CYDcjb1LMZcfZ5QGDz1TCqWjrvXln8Zv9zBfcw2Bezv12Jo ZH9xMFWuj0BTOZ0PxKC5FqG0r/YjnHA= X-Google-Smtp-Source: APiQypJB2X/eBdrqim2aFd2XEixYMUhSVP4mrlq/4tL44ToBk0fVX3e8RFkqxHr6QCVt7KesfK0tHA== X-Received: by 2002:a1c:b144:: with SMTP id a65mr11304786wmf.54.1587740056361; Fri, 24 Apr 2020 07:54:16 -0700 (PDT) Received: from localhost.localdomain ([2a02:c7d:3e2e:7400:d810:daa5:1027:e125]) by smtp.googlemail.com with ESMTPSA id p190sm3180552wmp.38.2020.04.24.07.54.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Apr 2020 07:54:15 -0700 (PDT) From: artem.galin@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Fri, 24 Apr 2020 15:52:18 +0100 Message-Id: <20200424145219.54067-3-artem.galin@gmail.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200424145219.54067-1-artem.galin@gmail.com> References: <20200415130741.27263-1-artem.galin@gmail.com> <20200424145219.54067-1-artem.galin@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 3/4] libavcodec/qsv: enabling d3d11va support, added mfxhdlpair 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: Artem Galin , robux4@ycbcr.xyz Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Artem Galin Adding DX11 relevant device type checks and adjusting callbacks with proper MediaSDK pair type support. Extending structure for proper MediaSDK pair type support. Signed-off-by: Artem Galin --- libavcodec/qsv.c | 66 +++++++++++++++++++++++++++++++-------- libavcodec/qsv_internal.h | 1 + 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index db98c75073..35e62417f6 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -36,6 +36,8 @@ #include "avcodec.h" #include "qsv_internal.h" +#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) + #if QSV_VERSION_ATLEAST(1, 12) #include "mfx/mfxvp8.h" #endif @@ -221,8 +223,15 @@ int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame) int i; for (i = 0; i < ctx->nb_mids; i++) { QSVMid *mid = &ctx->mids[i]; +#if CONFIG_VAAPI if (mid->handle == frame->surface.Data.MemId) return i; +#else + mfxHDLPair *pair = (mfxHDLPair*)frame->surface.Data.MemId; + if ((mid->handle_pair.first == pair->first) && + (mid->handle_pair.second == pair->second)) + return i; +#endif } return AVERROR_BUG; } @@ -362,7 +371,11 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs) int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, const char *load_plugins, int gpu_copy) { +#if CONFIG_D3D11VA + mfxIMPL impl = MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11; +#else mfxIMPL impl = MFX_IMPL_AUTO_ANY; +#endif mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } }; mfxInitParam init_par = { MFX_IMPL_AUTO_ANY }; @@ -449,11 +462,19 @@ static AVBufferRef *qsv_create_mids(AVBufferRef *hw_frames_ref) return NULL; } +#if CONFIG_VAAPI for (i = 0; i < nb_surfaces; i++) { QSVMid *mid = &mids[i]; mid->handle = frames_hwctx->surfaces[i].Data.MemId; mid->hw_frames_ref = hw_frames_ref1; } +#else + for (i = 0; i < nb_surfaces; i++) { + QSVMid *mid = &mids[i]; + mid->handle_pair = *((mfxHDLPair*)frames_hwctx->surfaces[i].Data.MemId); + mid->hw_frames_ref = hw_frames_ref1; + } +#endif return mids_buf; } @@ -628,7 +649,11 @@ static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) goto fail; qsv_mid->surf.Info = hw_frames_hwctx->surfaces[0].Info; +#if CONFIG_VAAPI qsv_mid->surf.Data.MemId = qsv_mid->handle; +#else + qsv_mid->surf.Data.MemId = &qsv_mid->handle_pair; +#endif /* map the data to the system memory */ ret = av_hwframe_map(qsv_mid->locked_frame, qsv_mid->hw_frame, @@ -661,7 +686,17 @@ static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) { QSVMid *qsv_mid = (QSVMid*)mid; +#if CONFIG_VAAPI *hdl = qsv_mid->handle; +#else + mfxHDLPair *pair_dst = (mfxHDLPair*)hdl; + mfxHDLPair *pair_src = (mfxHDLPair*)&qsv_mid->handle_pair; + + pair_dst->first = pair_src->first; + + if (pair_src->second != (mfxMemId)MFX_INFINITE) + pair_dst->second = pair_src->second; +#endif return MFX_ERR_NONE; } @@ -669,24 +704,19 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, AVBufferRef *device_ref, const char *load_plugins, int gpu_copy) { - static const mfxHandleType handle_types[] = { - MFX_HANDLE_VA_DISPLAY, - MFX_HANDLE_D3D9_DEVICE_MANAGER, - MFX_HANDLE_D3D11_DEVICE, - }; AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data; AVQSVDeviceContext *device_hwctx = device_ctx->hwctx; mfxSession parent_session = device_hwctx->session; mfxInitParam init_par = { MFX_IMPL_AUTO_ANY }; mfxHDL handle = NULL; + int hw_handle_supported = 0; mfxSession session; mfxVersion ver; mfxIMPL impl; mfxHandleType handle_type; mfxStatus err; - - int i, ret; + int ret; err = MFXQueryIMPL(parent_session, &impl); if (err == MFX_ERR_NONE) @@ -695,13 +725,23 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, return ff_qsv_print_error(avctx, err, "Error querying the session attributes"); - for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) { - err = MFXVideoCORE_GetHandle(parent_session, handle_types[i], &handle); - if (err == MFX_ERR_NONE) { - handle_type = handle_types[i]; - break; + if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) { + handle_type = MFX_HANDLE_VA_DISPLAY; + hw_handle_supported = 1; + } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) { + handle_type = MFX_HANDLE_D3D11_DEVICE; + hw_handle_supported = 1; + } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) { + handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; + hw_handle_supported = 1; + } + + if (hw_handle_supported) { + err = MFXVideoCORE_GetHandle(parent_session, handle_type, &handle); + if (err != MFX_ERR_NONE) { + return ff_qsv_print_error(avctx, err, + "Error getting handle session"); } - handle = NULL; } if (!handle) { av_log(avctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved " diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index 6489836a67..7a4a66e9d6 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -61,6 +61,7 @@ typedef struct QSVMid { AVBufferRef *hw_frames_ref; mfxHDL handle; + mfxHDLPair handle_pair; AVFrame *locked_frame; AVFrame *hw_frame; From patchwork Fri Apr 24 14:52:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: galinart X-Patchwork-Id: 19215 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id DDB1B44A379 for ; Fri, 24 Apr 2020 17:54:26 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BF7B068BFF1; Fri, 24 Apr 2020 17:54:26 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 817DB68BEF7 for ; Fri, 24 Apr 2020 17:54:20 +0300 (EEST) Received: by mail-wm1-f41.google.com with SMTP id e26so10805483wmk.5 for ; Fri, 24 Apr 2020 07:54:20 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=WyH63qtwCjKhcbYxMQRoPTCdiCrBWANFDr4tf1Hulwg=; b=WlGMLyNMJgYkOiXooeOSecJbX3PzHizQRE74gx/EAtEy9T8DZnxB3sVz/2jQ+ZDceR mgWC4ZGJtFlbj61gl2lsazx4zC8BkUAqjdZ9SG6J9NR/IEPwQtXT3/w1Br0lcz/gRpZk 7vR6zeXaEkBJW/CmxQcU+f4X0/wR2VksxtKTD7TVPAChOw03T+FHzkPFO0hoeVHCaa+W U9GjhMG3FffK6beg9Gx7sOd4BWtkz8R3giftputOPuWGujl11eV2LcMycyTb/CINqsOe XukNnGhQCgvU8KWMWO/due+zY1NYgKs0wOkPX98ovsfB7pJn7oer6tSTn6DaOFf6d/0Y x8gQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=WyH63qtwCjKhcbYxMQRoPTCdiCrBWANFDr4tf1Hulwg=; b=d+UGNnxzZNLH7PqQ3HCfkdD6k+WDW9+FloxRt+B5q4MMsNbKZZhJfrZqjP9YJZvCXJ 2wslt/A5eJfpNgyN+HU7DGVaHMFPKX81ECRUaaDegaD6u7IcfJW0GViCRYqOyejMV27+ zsJpLLUb0lYSGeGUt3i1/Bxgp4o1vqksq4KApJ2g+e15bPdOaWSz6UlFj+Jo9GkufyI/ 4HAfxulhYUcckOPq1KKRFuZ4fFG0AJ8rcyX4u90b653aK2aTmFsLIjHEKQud0NJL0do5 EFBHQh/5JLJhEom60ZNofr2bvnmCIHySNH4sXnPmSCE76uXz+gzLOjIunWg8g1De2sFt jgAA== X-Gm-Message-State: AGi0PubOs7sVHoaqKOwCUBz01egspb9d7RwTlaUszeAQZKvyoQLMNa8i EQ/ugmuL7BkvwmIsIe1CSZXiMhYvP14= X-Google-Smtp-Source: APiQypKxM5rfz2romBGDLFp+fj0W2jzH5n7O8WyvhKIeQ5hJcTPLvr8O3s8gDevaurjigE3blmgIaw== X-Received: by 2002:a1c:59c3:: with SMTP id n186mr3765554wmb.24.1587740059020; Fri, 24 Apr 2020 07:54:19 -0700 (PDT) Received: from localhost.localdomain ([2a02:c7d:3e2e:7400:d810:daa5:1027:e125]) by smtp.googlemail.com with ESMTPSA id p190sm3180552wmp.38.2020.04.24.07.54.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Apr 2020 07:54:18 -0700 (PDT) From: artem.galin@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Fri, 24 Apr 2020 15:52:19 +0100 Message-Id: <20200424145219.54067-4-artem.galin@gmail.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200424145219.54067-1-artem.galin@gmail.com> References: <20200415130741.27263-1-artem.galin@gmail.com> <20200424145219.54067-1-artem.galin@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 4/4] libavutil/qsv: enabling d3d11va support 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: Artem Galin , robux4@ycbcr.xyz Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Artem Galin 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. 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 Signed-off-by: Artem Galin --- libavutil/hwcontext_d3d11va.c | 82 +++++++- libavutil/hwcontext_d3d11va.h | 8 + libavutil/hwcontext_qsv.c | 363 +++++++++++++++++++++++++++------- 3 files changed, 379 insertions(+), 74 deletions(-) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index c8ae58f908..c5e127aadb 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; + size_t nb_surfaces; 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,55 @@ static void d3d11va_device_uninit(AVHWDeviceContext *hwdev) } } +static int d3d11va_device_find_adapter_by_vendor_id(AVHWDeviceContext *ctx, UINT creationFlags, long int vendor_id) +{ + HRESULT hr; + IDXGIAdapter *adapter = NULL; + int adapter_id = 0; + IDXGIFactory2 *factory; + 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 +591,24 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, return AVERROR_UNKNOWN; } + e = av_dict_get(opts, "vendor", NULL, 0); + if (e) { + long int vendor_id = strtol(e->value, NULL, 0); + adapter = d3d11va_device_find_adapter_by_vendor_id(ctx, creationFlags, vendor_id); + 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..f3def15bea 100644 --- a/libavutil/hwcontext_d3d11va.h +++ b/libavutil/hwcontext_d3d11va.h @@ -39,6 +39,11 @@ #include #include +typedef struct D3D11TextureInfo { + ID3D11Texture2D *texture; + size_t index; +} 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; + size_t nb_surfaces_used; } AVD3D11VAFramesContext; #endif /* AVUTIL_HWCONTEXT_D3D11VA_H */ diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index b1b67400de..3a9c3f8ff0 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -27,9 +27,13 @@ #include #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 @@ -81,20 +88,6 @@ typedef struct QSVFramesContext { mfxExtBuffer *ext_buffers[1]; } QSVFramesContext; -static const struct { - mfxHandleType handle_type; - enum AVHWDeviceType device_type; - enum AVPixelFormat pix_fmt; -} supported_handle_types[] = { -#if CONFIG_VAAPI - { MFX_HANDLE_VA_DISPLAY, AV_HWDEVICE_TYPE_VAAPI, AV_PIX_FMT_VAAPI }, -#endif -#if CONFIG_DXVA2 - { MFX_HANDLE_D3D9_DEVICE_MANAGER, AV_HWDEVICE_TYPE_DXVA2, AV_PIX_FMT_DXVA2_VLD }, -#endif - { 0 }, -}; - static const struct { enum AVPixelFormat pix_fmt; uint32_t fourcc; @@ -115,28 +108,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; - + int hw_handle_supported = 0; + mfxHandleType handle_type; + enum AVHWDeviceType device_type; + enum AVPixelFormat pix_fmt; 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) @@ -146,6 +143,41 @@ static int qsv_device_init(AVHWDeviceContext *ctx) return AVERROR_UNKNOWN; } + if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(s->impl)) { +#if CONFIG_VAAPI + handle_type = MFX_HANDLE_VA_DISPLAY; + device_type = AV_HWDEVICE_TYPE_VAAPI; + pix_fmt = AV_PIX_FMT_VAAPI; + hw_handle_supported = 1; +#endif + } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(s->impl)) { +#if CONFIG_D3D11VA + handle_type = MFX_HANDLE_D3D11_DEVICE; + device_type = AV_HWDEVICE_TYPE_D3D11VA; + pix_fmt = AV_PIX_FMT_D3D11; + hw_handle_supported = 1; +#endif + } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(s->impl)) { +#if CONFIG_DXVA2 + handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; + device_type = AV_HWDEVICE_TYPE_DXVA2; + pix_fmt = AV_PIX_FMT_DXVA2_VLD; + hw_handle_supported = 1; +#endif + } + + if (hw_handle_supported) { + err = MFXVideoCORE_GetHandle(hwctx->session, handle_type, &s->handle); + if (err == MFX_ERR_NONE) { + s->handle_type = handle_type; + s->child_device_type = device_type; + s->child_pix_fmt = pix_fmt; + } + } + if (!s->handle) { + av_log(ctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved " + "from the session\n"); + } return 0; } @@ -175,6 +207,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 +223,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 +264,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 +297,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 +331,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 +422,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 +500,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 +710,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 +730,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 +770,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 +798,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 +828,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 +1081,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 +1105,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 +1145,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 +1170,41 @@ 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 (pair->first == src->data[0] + && pair->second == 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 (pair->first == src->data[3]) { + 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 +1217,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 +1259,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 +1288,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 +1318,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 +1389,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 +1414,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); }