onnxruntime
353 строки · 12.5 Кб
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License.
3
4#include "lib/Api.Image/pch.h"5#include "inc/ImageConversionHelpers.h"6
7#include <winrt/Windows.Graphics.DirectX.Direct3D11.h>8
9using namespace Microsoft::WRL;10using namespace Windows::Graphics::DirectX::Direct3D11;11
12static LUID GetLUIDFromDirect3DSurface(const wgdx::Direct3D11::IDirect3DSurface& surface) {13ComPtr<ID3D11Device> spDx11Device;14ComPtr<IDirect3DDxgiInterfaceAccess> spDxgiInterfaceAccess;15ComPtr<ID3D11Texture2D> spDx11Texture2D;16ComPtr<IDXGIDevice> spDXGIDevice;17ComPtr<IDXGIAdapter> spDXGIAdapter;18DXGI_ADAPTER_DESC adapterDesc = {0};19
20spDxgiInterfaceAccess = surface.as<IDirect3DDxgiInterfaceAccess>().get();21WINML_THROW_IF_FAILED(spDxgiInterfaceAccess->GetInterface(IID_PPV_ARGS(&spDx11Texture2D)));22spDx11Texture2D->GetDevice(&spDx11Device);23WINML_THROW_IF_FAILED(spDx11Device->QueryInterface(IID_PPV_ARGS(&spDXGIDevice)));24WINML_THROW_IF_FAILED(spDXGIDevice->GetAdapter(&spDXGIAdapter));25WINML_THROW_IF_FAILED(spDXGIAdapter->GetDesc(&adapterDesc));26
27return adapterDesc.AdapterLuid;28}
29
30static HRESULT GetVideoFrameInfo(31_In_ const wm::IVideoFrame& inputVideoFrame,32_Out_ DWORD& format,33_Out_ int& width,34_Out_ int& height,35_Out_ LUID& luid36) {37wgdx::Direct3D11::IDirect3DSurface spInputSurface = inputVideoFrame.Direct3DSurface();38if (spInputSurface != nullptr) {39wgdx::Direct3D11::Direct3DSurfaceDescription description;40description = spInputSurface.Description();41format = (DWORD)description.Format;42width = description.Width;43height = description.Height;44luid = GetLUIDFromDirect3DSurface(spInputSurface);45} else {46wgi::SoftwareBitmap spInputSoftwareBitmap = inputVideoFrame.SoftwareBitmap();47if (spInputSoftwareBitmap != nullptr) {48format = (DWORD)spInputSoftwareBitmap.BitmapPixelFormat();49height = spInputSoftwareBitmap.PixelHeight();50width = spInputSoftwareBitmap.PixelWidth();51luid.HighPart = luid.LowPart = 0;52} else {53return E_INVALIDARG;54}55}56return S_OK;57}
58
59void _winmli::ConvertVideoFrameToVideoFrame(60_In_ const wm::IVideoFrame& inputVideoFrame,61_In_ const wgi::BitmapBounds& inputBounds,62_In_ UINT32 outputWidth,63_In_ UINT32 outputHeight,64_Inout_ wm::VideoFrame& pOutputVideoFrame65) {66wgi::BitmapBounds outputBounds = {0, 0, outputWidth, outputHeight};67
68wgi::SoftwareBitmap spInputSoftwareBitmap = inputVideoFrame.SoftwareBitmap();69wgdx::Direct3D11::IDirect3DSurface spInputDirect3DSurface = inputVideoFrame.Direct3DSurface();70
71// only one of softwarebitmap or direct3Dsurface should be non-null72if ((spInputSoftwareBitmap == nullptr && spInputDirect3DSurface == nullptr) ||73(spInputSoftwareBitmap != nullptr && spInputDirect3DSurface != nullptr)) {74WINML_THROW_HR(E_INVALIDARG);75}76
77auto pInputVideoFrame2 = inputVideoFrame.as<wm::IVideoFrame2>();78pInputVideoFrame2.CopyToAsync(pOutputVideoFrame, inputBounds, outputBounds).get();79}
80
81bool _winmli::SoftwareBitmapFormatSupported(const wgi::SoftwareBitmap& softwareBitmap) {82assert(softwareBitmap != nullptr);83
84switch (softwareBitmap.BitmapPixelFormat()) {85case wgi::BitmapPixelFormat::Bgra8:86case wgi::BitmapPixelFormat::Rgba8:87case wgi::BitmapPixelFormat::Gray8:88return true;89}90
91return false;92}
93
94bool _winmli::DirectXPixelFormatSupported(wgdx::DirectXPixelFormat format) {95switch (format) {96case wgdx::DirectXPixelFormat::B8G8R8X8UIntNormalized:97case wgdx::DirectXPixelFormat::B8G8R8A8UIntNormalized:98case wgdx::DirectXPixelFormat::R8G8B8A8UIntNormalized:99case wgdx::DirectXPixelFormat::R8UIntNormalized:100return true;101}102
103return false;104}
105
106bool _winmli::FormatSupportedForUAV(_In_ ID3D12Device1* device, _In_ DXGI_FORMAT format) {107assert(device != nullptr);108
109D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport = {format};110HRESULT hr = device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &formatSupport, sizeof(formatSupport));111
112return SUCCEEDED(hr) && (formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW);113}
114
115// This helper method uses the input parameters do determine if a conversion is necessary
116// A conversion is not necessary if
117// 1. input bounds cover the entire input bitmap/surface (else we are cropping)
118// 2. desired output size is equal to input size (else we are resizing)
119// 3. (mapping softwarebitmap to softwarebitmap) OR (mapping from d3dsurface to d3dsurface AND the two surfaces are on the same device)
120// 4. the input is already in the desired format (BGRA8/B8G8R8X8UIntNormalized)
121bool _winmli::NeedsVideoFrameConversion(122_In_ const wm::IVideoFrame& inputVideoFrame,123_In_ LUID outputLuid,124_In_ const wgi::BitmapBounds& inputBounds,125_In_ UINT32 outputWidth,126_In_ UINT32 outputHeight
127) {128bool bNeedConversion = false;129HRESULT hr = S_OK;130
131DWORD format = 0;132int width = 0, height = 0;133LUID luid;134
135if (FAILED((hr = GetVideoFrameInfo(inputVideoFrame, format, width, height, luid)))) {136bNeedConversion = true;137} else if (((int)inputBounds.Width != outputWidth) || (inputBounds.X != 0) ||138((int)inputBounds.Height != outputHeight) || (inputBounds.Y != 0) ||139(inputVideoFrame == nullptr)) // Check crop140{141bNeedConversion = true;142} else if (luid.HighPart != outputLuid.HighPart || luid.LowPart != outputLuid.LowPart) {143bNeedConversion = true;144} else if (static_cast<uint32_t>(width) != outputWidth || static_cast<uint32_t>(height) != outputHeight) {145bNeedConversion = true;146} else if (outputLuid.HighPart != 0 || outputLuid.LowPart != 0) {147if (format != (DWORD)wgdx::DirectXPixelFormat::B8G8R8X8UIntNormalized) {148bNeedConversion = true;149}150} else {151if (format != (DWORD)wgi::BitmapPixelFormat::Bgra8) {152bNeedConversion = true;153}154}155
156TraceLoggingWrite(157winml_trace_logging_provider,158"InputVideoFrame",159TraceLoggingKeyword(WINML_PROVIDER_KEYWORD_DEFAULT),160TraceLoggingBool(bNeedConversion, "Convert"),161TraceLoggingHexInt32(hr, "HRESULT"),162TraceLoggingInt32(width, "iWidth"),163TraceLoggingInt32(outputWidth, "oWidth"),164TraceLoggingInt32(height, "iHeight"),165TraceLoggingInt32(outputWidth, "oHeight"),166TraceLoggingHexInt64(*((ULONGLONG*)&luid), "iLuid"),167TraceLoggingHexInt64(*((ULONGLONG*)&outputLuid), "oLuid"),168TraceLoggingHexInt32(format, "iFormat"),169TraceLoggingInt32(inputBounds.X, "rX"),170TraceLoggingInt32(inputBounds.Y, "rY"),171TraceLoggingInt32(inputBounds.Width, "rW"),172TraceLoggingInt32(inputBounds.Height, "rH")173);174
175return bNeedConversion;176}
177
178_winml::ImageTensorChannelType _winmli::GetChannelTypeFromSoftwareBitmap(const wgi::SoftwareBitmap& softwareBitmap) {179assert(softwareBitmap != nullptr);180
181switch (softwareBitmap.BitmapPixelFormat()) {182case wgi::BitmapPixelFormat::Bgra8:183return _winml::kImageTensorChannelTypeBGR8;184case wgi::BitmapPixelFormat::Rgba8:185return _winml::kImageTensorChannelTypeRGB8;186case wgi::BitmapPixelFormat::Gray8:187return _winml::kImageTensorChannelTypeGRAY8;188}189
190WINML_THROW_HR(E_INVALIDARG);191}
192
193wgi::BitmapPixelFormat _winmli::GetBitmapPixelFormatFromChannelType(_winml::ImageTensorChannelType channelType) {194switch (channelType) {195case _winml::kImageTensorChannelTypeBGR8:196return wgi::BitmapPixelFormat::Bgra8;197case _winml::kImageTensorChannelTypeRGB8:198return wgi::BitmapPixelFormat::Rgba8;199case _winml::kImageTensorChannelTypeGRAY8:200return wgi::BitmapPixelFormat::Gray8;201}202
203WINML_THROW_HR(E_INVALIDARG);204}
205
206_winml::ImageTensorChannelType _winmli::GetChannelTypeFromDirect3DSurface(207const wgdx::Direct3D11::IDirect3DSurface& direct3DSurface208) {209assert(direct3DSurface != nullptr);210
211switch (direct3DSurface.Description().Format) {212case wgdx::DirectXPixelFormat::B8G8R8A8UIntNormalized:213case wgdx::DirectXPixelFormat::B8G8R8X8UIntNormalized:214return _winml::kImageTensorChannelTypeBGR8;215
216case wgdx::DirectXPixelFormat::R8G8B8A8UIntNormalized:217return _winml::kImageTensorChannelTypeRGB8;218
219case wgdx::DirectXPixelFormat::R8UIntNormalized:220return _winml::kImageTensorChannelTypeGRAY8;221}222
223WINML_THROW_HR(E_INVALIDARG);224}
225
226wgdx::DirectXPixelFormat _winmli::GetDirectXPixelFormatFromDXGIFormat(DXGI_FORMAT dxgiFormat) {227switch (dxgiFormat) {228case DXGI_FORMAT_B8G8R8A8_UNORM:229return wgdx::DirectXPixelFormat::B8G8R8A8UIntNormalized;230case DXGI_FORMAT_B8G8R8X8_UNORM:231return wgdx::DirectXPixelFormat::B8G8R8X8UIntNormalized;232case DXGI_FORMAT_R8G8B8A8_UNORM:233return wgdx::DirectXPixelFormat::R8G8B8A8UIntNormalized;234case DXGI_FORMAT_R8_UNORM:235return wgdx::DirectXPixelFormat::R8UIntNormalized;236}237
238WINML_THROW_HR(E_INVALIDARG);239}
240
241DXGI_FORMAT _winmli::GetDXGIFormatFromDirectXPixelFormat(_In_ wgdx::DirectXPixelFormat directXPixelFormat) {242switch (directXPixelFormat) {243case wgdx::DirectXPixelFormat::B8G8R8A8UIntNormalized:244return DXGI_FORMAT_B8G8R8A8_UNORM;245case wgdx::DirectXPixelFormat::B8G8R8X8UIntNormalized:246return DXGI_FORMAT_B8G8R8X8_UNORM;247case wgdx::DirectXPixelFormat::R8G8B8A8UIntNormalized:248return DXGI_FORMAT_R8G8B8A8_UNORM;249case wgdx::DirectXPixelFormat::R8UIntNormalized:250return DXGI_FORMAT_R8_UNORM;251}252
253WINML_THROW_HR(E_INVALIDARG);254}
255
256wgdx::DirectXPixelFormat _winmli::GetDirectXPixelFormatFromChannelType(_In_ _winml::ImageTensorChannelType channelType257) {258switch (channelType) {259case _winml::kImageTensorChannelTypeBGR8:260return wgdx::DirectXPixelFormat::B8G8R8A8UIntNormalized;261case _winml::kImageTensorChannelTypeRGB8:262return wgdx::DirectXPixelFormat::R8G8B8A8UIntNormalized;263case _winml::kImageTensorChannelTypeGRAY8:264return wgdx::DirectXPixelFormat::R8UIntNormalized;265}266
267WINML_THROW_HR(E_INVALIDARG);268}
269
270wgdx::Direct3D11::IDirect3DDevice _winmli::GetDeviceFromDirect3DSurface(271const wgdx::Direct3D11::IDirect3DSurface& d3dSurface272) {273assert(d3dSurface != nullptr);274
275ComPtr<ID3D11Texture2D> spDx11Texture2D;276ComPtr<IDirect3DDxgiInterfaceAccess> spDxgiInterfaceAccess = d3dSurface.as<IDirect3DDxgiInterfaceAccess>().get();277WINML_THROW_IF_FAILED(spDxgiInterfaceAccess->GetInterface(IID_PPV_ARGS(&spDx11Texture2D)));278
279ComPtr<ID3D11Device> spDx11Device;280spDx11Texture2D->GetDevice(&spDx11Device);281
282ComPtr<IDXGIDevice> spDXGIDevice;283WINML_THROW_IF_FAILED(spDx11Device->QueryInterface(IID_PPV_ARGS(&spDXGIDevice)));284
285ComPtr<::IInspectable> spInspectable;286WINML_THROW_IF_FAILED(CreateDirect3D11DeviceFromDXGIDevice(spDXGIDevice.Get(), &spInspectable));287
288wgdx::Direct3D11::IDirect3DDevice d3dDevice;289WINML_THROW_IF_FAILED(spInspectable->QueryInterface(290winrt::guid_of<wgdx::Direct3D11::IDirect3DDevice>(), reinterpret_cast<void**>(winrt::put_abi(d3dDevice))291));292
293return d3dDevice;294}
295
296bool _winmli::TexturesHaveSameDevice(_In_ ID3D11Texture2D* pTexture1, _In_ ID3D11Texture2D* pTexture2) {297if (pTexture1 && pTexture2) {298ComPtr<ID3D11Device> spDevice1;299pTexture1->GetDevice(&spDevice1);300
301ComPtr<ID3D11Device> spDevice2;302pTexture2->GetDevice(&spDevice2);303
304return spDevice1.Get() == spDevice2.Get();305}306
307return false;308}
309
310bool _winmli::TextureIsOnDevice(_In_ ID3D11Texture2D* pTexture, _In_ ID3D11Device* pDevice) {311if (pTexture && pDevice) {312ComPtr<ID3D11Device> spDevice1;313pTexture->GetDevice(&spDevice1);314
315return spDevice1.Get() == pDevice;316}317
318return false;319}
320
321ComPtr<ID3D11Texture2D> _winmli::GetTextureFromDirect3DSurface(const wgdx::Direct3D11::IDirect3DSurface& d3dSurface) {322auto spDxgiInterfaceAccess = d3dSurface.as<IDirect3DDxgiInterfaceAccess>();323ComPtr<ID3D11Texture2D> d3d11Texture;324WINML_THROW_IF_FAILED(spDxgiInterfaceAccess->GetInterface(IID_PPV_ARGS(&d3d11Texture)));325
326return d3d11Texture;327}
328
329bool _winmli::VideoFramesHaveSameDimensions(const wm::IVideoFrame& videoFrame1, const wm::IVideoFrame& videoFrame2) {330if (videoFrame1 && videoFrame2) {331auto desc1 = videoFrame1.Direct3DSurface().Description();332auto desc2 = videoFrame2.Direct3DSurface().Description();333
334return desc1.Width == desc2.Width && desc1.Height == desc2.Height;335}336
337return false;338}
339
340bool _winmli::VideoFramesHaveSameDevice(const wm::IVideoFrame& videoFrame1, const wm::IVideoFrame& videoFrame2) {341if (videoFrame1 && videoFrame2) {342ComPtr<ID3D11Texture2D> spTexture1 = _winmli::GetTextureFromDirect3DSurface(videoFrame1.Direct3DSurface());343ComPtr<ID3D11Texture2D> spTexture2 = _winmli::GetTextureFromDirect3DSurface(videoFrame2.Direct3DSurface());344
345ComPtr<ID3D11Device> spDevice1, spDevice2;346spTexture1->GetDevice(&spDevice1);347spTexture2->GetDevice(&spDevice2);348
349return spDevice1.Get() == spDevice2.Get();350}351
352return false;353}
354