From patchwork Thu Jul 22 10:56:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: galinart X-Patchwork-Id: 29007 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a5d:965a:0:0:0:0:0 with SMTP id d26csp411416ios; Thu, 22 Jul 2021 04:03:29 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwvPW+/QO6+egQa/agNaVqCDB9j7UCt1LmnF6QEc/zVXvgveSKzchGau/whH7vNlNdrxvsA X-Received: by 2002:a17:906:6b1b:: with SMTP id q27mr42148865ejr.169.1626951809506; Thu, 22 Jul 2021 04:03:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1626951809; cv=none; d=google.com; s=arc-20160816; b=TjY81DFsVNr5WzZKqlc0Vf8DywwLeYuh99Ki7DSfUeayyyDM0rZxLIyWsi/7enkSA3 ZmtSf6SUDLeccX0kHtT/oKsTLBh0DD8vNmYaknNiG92Jbb1TchJdvQMBWZfc1Mhx27q5 QIRXdAbvF/92JzBrBUIp22jNb2u03bTu4uZ+WmjfCIP/7vwV/gk9rGjXvP37GII6hI3p Kzq3UKPPgUHJYjxRD94P+VmMB00ACzalfICslowzQPxyTz/egsqtEqc5P54OL9/bxk1M A7bVxdUkfHOAStvcUm/rw7Xu1DAWLUDEIGSayynuaCphX9p2pZpStkHIF064+SD1Ut0K KYvQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=QOYoleaqnocOIoO/L221J5NEvcJpBHBzHXYKtcIqSAY=; b=AwWdNlGipmDuURqX8+fsEuluh5ljvRQGkGEEVvozGf93FbQX6JcCoM1TPvw3DMbT3W w3SG54xBTWSUEleBoW7SKWw4c8A8u8mEhrG+BVuKhbrU9VuFOAMn6VYGdHInaYzBTalb Nz67sYKq7xaksWPtj74XYtZESPgLXtx2skSwf8sFTW3d2KENHvVZISIqyfhEUqW75q4l Lx4jaxx0+Vxzu0/DEdXdYRJP6P6TAg+6C7RemxZtJaJkXQmZFwvncpiuCgwKinvPRxxk WQ/YfvJKe5eqCrY0wbR3nBcb7y+Taisu5/rbqaDJFsCQ+6/cXwDPm5X7OxHKwvXg2Anl bpsw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=X2HtfLox; 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 l5si32104692edv.367.2021.07.22.04.03.05; Thu, 22 Jul 2021 04:03:29 -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=X2HtfLox; 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 9638468A7ED; Thu, 22 Jul 2021 14:03:00 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f50.google.com (mail-ed1-f50.google.com [209.85.208.50]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4244168A380 for ; Thu, 22 Jul 2021 14:02:48 +0300 (EEST) Received: by mail-ed1-f50.google.com with SMTP id k27so6250919edk.9; Thu, 22 Jul 2021 04:02:48 -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=wPDkangqmk1fXMbFREEnvDIGdRHcz9+N17k/d6T0BVE=; b=X2HtfLoxagUOjz2yDVItH5MHMs0OnURbzlB6eib2pVdmSU8SKGdDE/6gKKtV62VYXE jCidJUptY3bhaxQgHZ/Fj9ZTfIIZAv10hq65Bg5SU7qJG6HEuA5VrdXz1H6hJxwkTKkW IpZvNKvtfxr4rcX7WYdzFjKpXASiQ0sxVQ/ZBDO4sUIQ+a2iTfxesYUAdJXbDmT/zaRD cJnbwch+SzfcibQ2NJafI3dZWKk9VWuPD46NYywoNl9P363Y7YXB6XF2tpT2hfpB3hQu sOJsiR5WgNk/BVS/3jaQus2HPqytpBsZhlTdpoXWmA+PFgMlqBN3/qgCJy+C8GFSb4fG nwtQ== 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=wPDkangqmk1fXMbFREEnvDIGdRHcz9+N17k/d6T0BVE=; b=mQvrJKAbYz2ufRBuqXRMCJSKTg809Bkaku7mTfmDGCxj/ARhpsrpJx+6ofOzXEuDGk 7TeWY/wvLeyM3nV2JuFnrtIk3zN9GTYxn9NPntiKs7XLxWqVz9jwT7hAHA9p91l7QFkn 0hDxzqxQUe6ocvU2SPKeK/85uq0+Y2l10T4JQUJzO3Jt6b7hwqbV4TK/eweOJV7Fa/FR vBmTrq1GO1MF+2E4y+iyWCvaWl00Q2zSdC8VsSCW1CDQiX/Lp/NINcMLRKDRfhTpp0wp spTcyH/Ql6fKEOzqegeOyQZr+rIPvk0q57A4vcOeR2de+OKOSv/FFUto9fatTPsUc2cq y3Og== X-Gm-Message-State: AOAM530XFQfqlQgu8ubIZDg3lWvHzkiDeb3n0wQevMGsG3B1HhOVC3Wh Bg1IsPr0CmTosc98Mb8X6vlGaVwaxkvFcnTT X-Received: by 2002:a19:7110:: with SMTP id m16mr28774918lfc.125.1626951410116; Thu, 22 Jul 2021 03:56:50 -0700 (PDT) Received: from localhost.localdomain (37-144-244-78.broadband.corbina.ru. [37.144.244.78]) by smtp.googlemail.com with ESMTPSA id z4sm1951236lfh.2.2021.07.22.03.56.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Jul 2021 03:56:49 -0700 (PDT) From: Artem Galin To: ffmpeg-devel@ffmpeg.org, ffmpeg-devep@ffmpeg.org Date: Thu, 22 Jul 2021 11:56:29 +0100 Message-Id: <20210722105635.48075-2-artem.galin@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210722105635.48075-1-artem.galin@gmail.com> References: <20210722105635.48075-1-artem.galin@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/8] libavutil/hwcontext_qsv: supporting d3d11va device type X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 0zV8PsCTivCm From: Artem Galin This enables usage of non-powered/headless GPU, better HDR support. Pool of resources is allocated as one texture with array of slices. Signed-off-by: Artem Galin --- libavutil/hwcontext_qsv.c | 323 +++++++++++++++++++++++++++++++------- 1 file changed, 262 insertions(+), 61 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 08a6e0ee1c..95170323d9 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 @@ -48,6 +52,8 @@ (MFX_VERSION_MAJOR > (MAJOR) || \ MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR)) +#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) + typedef struct QSVDevicePriv { AVBufferRef *child_device_ctx; } QSVDevicePriv; @@ -74,6 +80,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 @@ -85,20 +92,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; @@ -131,24 +124,11 @@ 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) @@ -158,6 +138,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; } @@ -187,6 +202,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); } @@ -202,6 +218,8 @@ static AVBufferRef *qsv_pool_alloc(void *opaque, size_t 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); } @@ -241,6 +259,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; @@ -267,6 +292,17 @@ 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 & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) + child_frames_hwctx->BindFlags = D3D11_BIND_RENDER_TARGET; + else + child_frames_hwctx->BindFlags = D3D11_BIND_DECODER; + if (hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE) + child_frames_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED; + } +#endif #if CONFIG_DXVA2 if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx; @@ -286,16 +322,41 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx) #if CONFIG_VAAPI if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) { AVVAAPIFramesContext *child_frames_hwctx = child_frames_ctx->hwctx; - for (i = 0; i < ctx->initial_pool_size; i++) - s->surfaces_internal[i].Data.MemId = child_frames_hwctx->surface_ids + i; + for (i = 0; i < ctx->initial_pool_size; i++) { + s->handle_pairs_internal[i].first = child_frames_hwctx->surface_ids + i; + s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE; + s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i]; + } 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; + 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)i; + } + 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 @@ -360,6 +421,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) @@ -433,7 +499,13 @@ static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) { - *hdl = mid; + 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; return MFX_ERR_NONE; } @@ -626,13 +698,29 @@ static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx, sizeof(*dst_hwctx->surface_ids)); if (!dst_hwctx->surface_ids) return AVERROR(ENOMEM); - for (i = 0; i < src_hwctx->nb_surfaces; i++) - dst_hwctx->surface_ids[i] = - *(VASurfaceID*)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->surface_ids[i] = *(VASurfaceID*)pair->first; + } dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces; } 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; + if (src_hwctx->frame_type == MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET) + dst_hwctx->BindFlags = D3D11_BIND_DECODER; + else + dst_hwctx->BindFlags = D3D11_BIND_RENDER_TARGET; + } + break; +#endif #if CONFIG_DXVA2 case AV_HWDEVICE_TYPE_DXVA2: { @@ -641,9 +729,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; @@ -677,13 +766,27 @@ static int qsv_map_from(AVHWFramesContext *ctx, switch (child_frames_ctx->device_ctx->type) { #if CONFIG_VAAPI case AV_HWDEVICE_TYPE_VAAPI: - child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)surf->Data.MemId; + { + mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId; + child_data = pair->first; 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); @@ -697,7 +800,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; } @@ -720,7 +830,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); @@ -978,35 +1095,81 @@ 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: { AVVAAPIFramesContext *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_hwctx->nb_surfaces, sizeof(*s->surfaces_internal)); if (!s->surfaces_internal) 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 = src_hwctx->surface_ids + i; + s->handle_pairs_internal[i].first = src_hwctx->surface_ids + 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; dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; } 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; + 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)i; + } + 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: { AVDXVA2FramesContext *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_hwctx->nb_surfaces, sizeof(*s->surfaces_internal)); if (!s->surfaces_internal) 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) @@ -1029,21 +1192,44 @@ 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]) - break; + case AV_PIX_FMT_VAAPI: + { + mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId; + if (pair->first == 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); @@ -1056,7 +1242,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; } @@ -1098,7 +1284,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; @@ -1127,6 +1313,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; } @@ -1153,6 +1343,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: { @@ -1216,7 +1415,9 @@ static int qsv_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *child_device_ctx, AVDictionary *opts, 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); } @@ -1267,7 +1468,7 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, 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); }