diff options
Diffstat (limited to 'src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp')
-rw-r--r-- | src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp | 434 |
1 files changed, 237 insertions, 197 deletions
diff --git a/src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp b/src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp index 96c7836cf..cc14cd419 100644 --- a/src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp +++ b/src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "evrd3dpresentengine_p.h" @@ -50,8 +14,7 @@ #include <d3d11_1.h> -#include <private/qrhi_p.h> -#include <private/qrhid3d11_p.h> +#include <rhi/qrhi.h> #if QT_CONFIG(opengl) # include <qopenglcontext.h> @@ -61,19 +24,18 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(qLcEvrD3DPresentEngine, "qt.multimedia.evrd3dpresentengine") +static Q_LOGGING_CATEGORY(qLcEvrD3DPresentEngine, "qt.multimedia.evrd3dpresentengine") class IMFSampleVideoBuffer: public QAbstractVideoBuffer { public: - IMFSampleVideoBuffer(QWindowsIUPointer<IDirect3DDevice9Ex> device, - IMFSample *sample, QRhi *rhi, QVideoFrame::HandleType type = QVideoFrame::NoHandle) + IMFSampleVideoBuffer(ComPtr<IDirect3DDevice9Ex> device, + const ComPtr<IMFSample> &sample, QRhi *rhi, QVideoFrame::HandleType type = QVideoFrame::NoHandle) : QAbstractVideoBuffer(type, rhi) , m_device(device) + , m_sample(sample) , m_mapMode(QVideoFrame::NotMapped) { - sample->AddRef(); - m_sample.reset(sample); } ~IMFSampleVideoBuffer() override @@ -95,24 +57,24 @@ public: return {}; } else { - QWindowsIUPointer<IMFMediaBuffer> buffer; - HRESULT hr = m_sample->GetBufferByIndex(0, buffer.address()); + ComPtr<IMFMediaBuffer> buffer; + HRESULT hr = m_sample->GetBufferByIndex(0, buffer.GetAddressOf()); if (FAILED(hr)) return {}; - QWindowsIUPointer<IDirect3DSurface9> surface; - hr = MFGetService(buffer.get(), MR_BUFFER_SERVICE, IID_IDirect3DSurface9, (void **)(surface.address())); + ComPtr<IDirect3DSurface9> surface; + hr = MFGetService(buffer.Get(), MR_BUFFER_SERVICE, IID_IDirect3DSurface9, (void **)(surface.GetAddressOf())); if (FAILED(hr)) return {}; if (FAILED(surface->GetDesc(&desc))) return {}; - if (FAILED(m_device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, m_memSurface.address(), nullptr))) + if (FAILED(m_device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, m_memSurface.GetAddressOf(), nullptr))) return {}; - if (FAILED(m_device->GetRenderTargetData(surface.get(), m_memSurface.get()))) { - m_memSurface.reset(); + if (FAILED(m_device->GetRenderTargetData(surface.Get(), m_memSurface.Get()))) { + m_memSurface.Reset(); return {}; } } @@ -142,76 +104,114 @@ public: } protected: - QWindowsIUPointer<IDirect3DDevice9Ex> m_device; - QWindowsIUPointer<IMFSample> m_sample; + ComPtr<IDirect3DDevice9Ex> m_device; + ComPtr<IMFSample> m_sample; private: - QWindowsIUPointer<IDirect3DSurface9> m_memSurface; + ComPtr<IDirect3DSurface9> m_memSurface; QVideoFrame::MapMode m_mapMode; }; +class QVideoFrameD3D11Textures: public QVideoFrameTextures +{ +public: + QVideoFrameD3D11Textures(std::unique_ptr<QRhiTexture> &&tex, ComPtr<ID3D11Texture2D> &&d3d11tex) + : m_tex(std::move(tex)) + , m_d3d11tex(std::move(d3d11tex)) + {} + + QRhiTexture *texture(uint plane) const override + { + return plane == 0 ? m_tex.get() : nullptr; + }; + +private: + std::unique_ptr<QRhiTexture> m_tex; + ComPtr<ID3D11Texture2D> m_d3d11tex; +}; + class D3D11TextureVideoBuffer: public IMFSampleVideoBuffer { public: - D3D11TextureVideoBuffer(QWindowsIUPointer<IDirect3DDevice9Ex> device, IMFSample *sample, - QWindowsIUPointer<ID3D11Texture2D> d2d11tex, QRhi *rhi) - : IMFSampleVideoBuffer(device, sample, rhi, QVideoFrame::RhiTextureHandle) - , m_d2d11tex(d2d11tex) + D3D11TextureVideoBuffer(ComPtr<IDirect3DDevice9Ex> device, const ComPtr<IMFSample> &sample, + HANDLE sharedHandle, QRhi *rhi) + : IMFSampleVideoBuffer(std::move(device), sample, rhi, QVideoFrame::RhiTextureHandle) + , m_sharedHandle(sharedHandle) {} - std::unique_ptr<QRhiTexture> texture(int plane) const override + std::unique_ptr<QVideoFrameTextures> mapTextures(QRhi *rhi) override { - if (!m_rhi || !m_d2d11tex || plane > 0) + if (!rhi || rhi->backend() != QRhi::D3D11) return {}; - D3D11_TEXTURE2D_DESC desc = {}; - m_d2d11tex->GetDesc(&desc); - QRhiTexture::Format format; - if (desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM) - format = QRhiTexture::BGRA8; - else if (desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM) - format = QRhiTexture::RGBA8; - else + + auto nh = static_cast<const QRhiD3D11NativeHandles*>(rhi->nativeHandles()); + if (!nh) + return {}; + + auto dev = reinterpret_cast<ID3D11Device *>(nh->dev); + if (!dev) return {}; - std::unique_ptr<QRhiTexture> tex(m_rhi->newTexture(format, QSize{int(desc.Width), int(desc.Height)}, 1, {})); - tex->createFrom({quint64(m_d2d11tex.get()), 0}); - return tex; + ComPtr<ID3D11Texture2D> d3d11tex; + HRESULT hr = dev->OpenSharedResource(m_sharedHandle, __uuidof(ID3D11Texture2D), (void**)(d3d11tex.GetAddressOf())); + if (SUCCEEDED(hr)) { + D3D11_TEXTURE2D_DESC desc = {}; + d3d11tex->GetDesc(&desc); + QRhiTexture::Format format; + if (desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM) + format = QRhiTexture::BGRA8; + else if (desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM) + format = QRhiTexture::RGBA8; + else + return {}; + + std::unique_ptr<QRhiTexture> tex(rhi->newTexture(format, QSize{int(desc.Width), int(desc.Height)}, 1, {})); + tex->createFrom({quint64(d3d11tex.Get()), 0}); + return std::make_unique<QVideoFrameD3D11Textures>(std::move(tex), std::move(d3d11tex)); + + } else { + qCDebug(qLcEvrD3DPresentEngine) << "Failed to obtain D3D11Texture2D from D3D9Texture2D handle"; + } + return {}; } private: - QWindowsIUPointer<ID3D11Texture2D> m_d2d11tex; + HANDLE m_sharedHandle = nullptr; }; #if QT_CONFIG(opengl) -class OpenGlVideoBuffer: public IMFSampleVideoBuffer +class QVideoFrameOpenGlTextures : public QVideoFrameTextures { + struct InterOpHandles { + GLuint textureName = 0; + HANDLE device = nullptr; + HANDLE texture = nullptr; + }; + public: - OpenGlVideoBuffer(QWindowsIUPointer<IDirect3DDevice9Ex> device, IMFSample *sample, - const WglNvDxInterop &wglNvDxInterop, HANDLE sharedHandle, QRhi *rhi) - : IMFSampleVideoBuffer(device, sample, rhi, QVideoFrame::RhiTextureHandle) - , m_sharedHandle(sharedHandle) - , m_wgl(wglNvDxInterop) - {} + Q_DISABLE_COPY(QVideoFrameOpenGlTextures); - ~OpenGlVideoBuffer() override - { - if (!m_d3dglHandle) - return; + QVideoFrameOpenGlTextures(std::unique_ptr<QRhiTexture> &&tex, const WglNvDxInterop &wgl, InterOpHandles &handles) + : m_tex(std::move(tex)) + , m_wgl(wgl) + , m_handles(handles) + {} + ~QVideoFrameOpenGlTextures() override { if (QOpenGLContext::currentContext()) { - if (m_glHandle) { - if (!m_wgl.wglDXUnlockObjectsNV(m_d3dglHandle, 1, &m_glHandle)) - qCDebug(qLcEvrD3DPresentEngine) << "Failed to unlock OpenGL texture"; - if (!m_wgl.wglDXUnregisterObjectNV(m_d3dglHandle, m_glHandle)) - qCDebug(qLcEvrD3DPresentEngine) << "Failed to unregister OpenGL texture"; - - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - if (funcs) - funcs->glDeleteTextures(1, &m_glTextureName); - else - qCDebug(qLcEvrD3DPresentEngine) << "Could not delete texture, OpenGL context functions missing"; - } - if (!m_wgl.wglDXCloseDeviceNV(m_d3dglHandle)) + if (!m_wgl.wglDXUnlockObjectsNV(m_handles.device, 1, &m_handles.texture)) + qCDebug(qLcEvrD3DPresentEngine) << "Failed to unlock OpenGL texture"; + + if (!m_wgl.wglDXUnregisterObjectNV(m_handles.device, m_handles.texture)) + qCDebug(qLcEvrD3DPresentEngine) << "Failed to unregister OpenGL texture"; + + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + if (funcs) + funcs->glDeleteTextures(1, &m_handles.textureName); + else + qCDebug(qLcEvrD3DPresentEngine) << "Could not delete texture, OpenGL context functions missing"; + + if (!m_wgl.wglDXCloseDeviceNV(m_handles.device)) qCDebug(qLcEvrD3DPresentEngine) << "Failed to close D3D-GL device"; } else { @@ -219,87 +219,106 @@ public: } } - void mapTextures() override + static std::unique_ptr<QVideoFrameOpenGlTextures> create(const WglNvDxInterop &wgl, QRhi *rhi, + IDirect3DDevice9Ex *device, IDirect3DTexture9 *texture, + HANDLE sharedHandle) { - if (!QOpenGLContext::currentContext()) - return; - - if (m_d3dglHandle) - return; - - QWindowsIUPointer<IMFMediaBuffer> buffer; - HRESULT hr = m_sample->GetBufferByIndex(0, buffer.address()); - if (FAILED(hr)) - return; - - QWindowsIUPointer<IDirect3DSurface9> surface; - hr = MFGetService(buffer.get(), MR_BUFFER_SERVICE, IID_IDirect3DSurface9, (void **)(surface.address())); - if (FAILED(hr)) - return; + if (!rhi || rhi->backend() != QRhi::OpenGLES2) + return {}; - hr = surface->GetContainer(IID_IDirect3DTexture9, (void **)m_texture.address()); - if (FAILED(hr)) - return; + if (!QOpenGLContext::currentContext()) + return {}; - m_d3dglHandle = m_wgl.wglDXOpenDeviceNV(m_device.get()); - if (!m_d3dglHandle) { - m_texture.reset(); + InterOpHandles handles = {}; + handles.device = wgl.wglDXOpenDeviceNV(device); + if (!handles.device) { qCDebug(qLcEvrD3DPresentEngine) << "Failed to open D3D device"; - return; + return {}; } - m_wgl.wglDXSetResourceShareHandleNV(m_texture.get(), m_sharedHandle); + wgl.wglDXSetResourceShareHandleNV(texture, sharedHandle); QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); if (funcs) { - funcs->glGenTextures(1, &m_glTextureName); - m_glHandle = m_wgl.wglDXRegisterObjectNV(m_d3dglHandle, m_texture.get(), m_glTextureName, - GL_TEXTURE_2D, WglNvDxInterop::WGL_ACCESS_READ_ONLY_NV); - if (m_glHandle) { - if (m_wgl.wglDXLockObjectsNV(m_d3dglHandle, 1, &m_glHandle)) - return; + funcs->glGenTextures(1, &handles.textureName); + handles.texture = wgl.wglDXRegisterObjectNV(handles.device, texture, handles.textureName, + GL_TEXTURE_2D, WglNvDxInterop::WGL_ACCESS_READ_ONLY_NV); + if (handles.texture) { + if (wgl.wglDXLockObjectsNV(handles.device, 1, &handles.texture)) { + D3DSURFACE_DESC desc; + texture->GetLevelDesc(0, &desc); + QRhiTexture::Format format; + if (desc.Format == D3DFMT_A8R8G8B8) + format = QRhiTexture::BGRA8; + else if (desc.Format == D3DFMT_A8B8G8R8) + format = QRhiTexture::RGBA8; + else + return {}; + + std::unique_ptr<QRhiTexture> tex(rhi->newTexture(format, QSize{int(desc.Width), int(desc.Height)}, 1, {})); + tex->createFrom({quint64(handles.textureName), 0}); + return std::make_unique<QVideoFrameOpenGlTextures>(std::move(tex), wgl, handles); + } qCDebug(qLcEvrD3DPresentEngine) << "Failed to lock OpenGL texture"; - m_wgl.wglDXUnregisterObjectNV(m_d3dglHandle, m_glHandle); - m_glHandle = nullptr; + wgl.wglDXUnregisterObjectNV(handles.device, handles.texture); } else { qCDebug(qLcEvrD3DPresentEngine) << "Could not register D3D9 texture in OpenGL"; } - funcs->glDeleteTextures(1, &m_glTextureName); - m_glTextureName = 0; + funcs->glDeleteTextures(1, &handles.textureName); } else { qCDebug(qLcEvrD3DPresentEngine) << "Failed generate texture names, OpenGL context functions missing"; } + return {}; } - std::unique_ptr<QRhiTexture> texture(int plane) const override + QRhiTexture *texture(uint plane) const override { - if (!m_rhi || !m_texture || plane > 0) - return {}; + return plane == 0 ? m_tex.get() : nullptr; + }; +private: + std::unique_ptr<QRhiTexture> m_tex; + WglNvDxInterop m_wgl; + InterOpHandles m_handles; +}; - D3DSURFACE_DESC desc; - m_texture->GetLevelDesc(0, &desc); - QRhiTexture::Format format; - if (desc.Format == D3DFMT_A8R8G8B8) - format = QRhiTexture::BGRA8; - else if (desc.Format == D3DFMT_A8B8G8R8) - format = QRhiTexture::RGBA8; - else - return {}; +class OpenGlVideoBuffer: public IMFSampleVideoBuffer +{ +public: + OpenGlVideoBuffer(ComPtr<IDirect3DDevice9Ex> device, const ComPtr<IMFSample> &sample, + const WglNvDxInterop &wglNvDxInterop, HANDLE sharedHandle, QRhi *rhi) + : IMFSampleVideoBuffer(std::move(device), sample, rhi, QVideoFrame::RhiTextureHandle) + , m_sharedHandle(sharedHandle) + , m_wgl(wglNvDxInterop) + {} + + std::unique_ptr<QVideoFrameTextures> mapTextures(QRhi *rhi) override + { + if (!m_texture) { + ComPtr<IMFMediaBuffer> buffer; + HRESULT hr = m_sample->GetBufferByIndex(0, buffer.GetAddressOf()); + if (FAILED(hr)) + return {}; + + ComPtr<IDirect3DSurface9> surface; + hr = MFGetService(buffer.Get(), MR_BUFFER_SERVICE, IID_IDirect3DSurface9, + (void **)(surface.GetAddressOf())); + if (FAILED(hr)) + return {}; - std::unique_ptr<QRhiTexture> tex(m_rhi->newTexture(format, QSize{int(desc.Width), int(desc.Height)}, 1, {})); - tex->createFrom({quint64(m_glTextureName), 0}); - return tex; + hr = surface->GetContainer(IID_IDirect3DTexture9, (void **)m_texture.GetAddressOf()); + if (FAILED(hr)) + return {}; + } + + return QVideoFrameOpenGlTextures::create(m_wgl, rhi, m_device.Get(), m_texture.Get(), m_sharedHandle); } private: - GLuint m_glTextureName = 0; - HANDLE m_d3dglHandle = nullptr; - HANDLE m_glHandle = nullptr; HANDLE m_sharedHandle = nullptr; WglNvDxInterop m_wgl; - QWindowsIUPointer<IDirect3DTexture9> m_texture; + ComPtr<IDirect3DTexture9> m_texture; }; #endif @@ -323,9 +342,9 @@ void D3DPresentEngine::setSink(QVideoSink *sink) m_sink = sink; releaseResources(); - m_device.reset(); - m_devices.reset(); - m_D3D9.reset(); + m_device.Reset(); + m_devices.Reset(); + m_D3D9.Reset(); if (!m_sink) return; @@ -343,10 +362,10 @@ void D3DPresentEngine::setSink(QVideoSink *sink) HRESULT D3DPresentEngine::initializeD3D() { - HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, m_D3D9.address()); + HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, m_D3D9.GetAddressOf()); if (SUCCEEDED(hr)) - hr = DXVA2CreateDirect3DDeviceManager9(&m_deviceResetToken, m_devices.address()); + hr = DXVA2CreateDirect3DDeviceManager9(&m_deviceResetToken, m_devices.GetAddressOf()); return hr; } @@ -391,8 +410,16 @@ static bool readWglNvDxInteropProc(WglNvDxInterop &f) return false; } - auto dc = ::GetDC(::GetShellWindow()); - if (!strstr(wglGetExtensionsStringARB(dc), "WGL_NV_DX_interop")) { + HWND hwnd = ::GetShellWindow(); + auto dc = ::GetDC(hwnd); + + const char *wglExtString = wglGetExtensionsStringARB(dc); + if (!wglExtString) + qCDebug(qLcEvrD3DPresentEngine) << "WGL extensions missing (wglGetExtensionsStringARB returned null)"; + + bool hasExtension = wglExtString && strstr(wglExtString, "WGL_NV_DX_interop"); + ReleaseDC(hwnd, dc); + if (!hasExtension) { qCDebug(qLcEvrD3DPresentEngine) << "WGL_NV_DX_interop missing"; return false; } @@ -407,6 +434,20 @@ static bool readWglNvDxInteropProc(WglNvDxInterop &f) } #endif +namespace { + +bool hwTextureRenderingEnabled() { + // add possibility for an user to opt-out HW video rendering + // using the same env. variable as for FFmpeg backend + static bool isDisableConversionSet = false; + static const int disableHwConversion = qEnvironmentVariableIntValue( + "QT_DISABLE_HW_TEXTURES_CONVERSION", &isDisableConversionSet); + + return !isDisableConversionSet || !disableHwConversion; +} + +} + HRESULT D3DPresentEngine::createD3DDevice() { if (!m_D3D9 || !m_devices) @@ -414,23 +455,26 @@ HRESULT D3DPresentEngine::createD3DDevice() m_useTextureRendering = false; UINT adapterID = 0; - QRhi *rhi = m_sink ? m_sink->rhi() : nullptr; - if (rhi) { - if (rhi->backend() == QRhi::D3D11) { - m_useTextureRendering = findD3D11AdapterID(*rhi, m_D3D9.get(), adapterID); + + if (hwTextureRenderingEnabled()) { + QRhi *rhi = m_sink ? m_sink->rhi() : nullptr; + if (rhi) { + if (rhi->backend() == QRhi::D3D11) { + m_useTextureRendering = findD3D11AdapterID(*rhi, m_D3D9.Get(), adapterID); #if QT_CONFIG(opengl) - } else if (rhi->backend() == QRhi::OpenGLES2) { - m_useTextureRendering = readWglNvDxInteropProc(m_wglNvDxInterop); + } else if (rhi->backend() == QRhi::OpenGLES2) { + m_useTextureRendering = readWglNvDxInteropProc(m_wglNvDxInterop); #endif + } else { + qCDebug(qLcEvrD3DPresentEngine) << "Not supported RHI backend type"; + } } else { - qCDebug(qLcEvrD3DPresentEngine) << "Not supported RHI backend type"; + qCDebug(qLcEvrD3DPresentEngine) << "No RHI associated with this sink"; } - } else { - qCDebug(qLcEvrD3DPresentEngine) << "No RHI associated with this sink"; - } - if (!m_useTextureRendering) - qCDebug(qLcEvrD3DPresentEngine) << "Could not find compatible RHI adapter, zero copy disabled"; + if (!m_useTextureRendering) + qCDebug(qLcEvrD3DPresentEngine) << "Could not find compatible RHI adapter, zero copy disabled"; + } D3DCAPS9 ddCaps; ZeroMemory(&ddCaps, sizeof(ddCaps)); @@ -458,7 +502,7 @@ HRESULT D3DPresentEngine::createD3DDevice() pp.Flags = D3DPRESENTFLAG_VIDEO; pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - QWindowsIUPointer<IDirect3DDevice9Ex> device; + ComPtr<IDirect3DDevice9Ex> device; hr = m_D3D9->CreateDeviceEx( adapterID, @@ -467,7 +511,7 @@ HRESULT D3DPresentEngine::createD3DDevice() vp | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, &pp, NULL, - device.address() + device.GetAddressOf() ); if (FAILED(hr)) return hr; @@ -476,7 +520,7 @@ HRESULT D3DPresentEngine::createD3DDevice() if (FAILED(hr)) return hr; - hr = m_devices->ResetDevice(device.get(), m_deviceResetToken); + hr = m_devices->ResetDevice(device.Get(), m_deviceResetToken); if (FAILED(hr)) return hr; @@ -486,7 +530,7 @@ HRESULT D3DPresentEngine::createD3DDevice() bool D3DPresentEngine::isValid() const { - return m_device.get() != nullptr; + return m_device.Get() != nullptr; } void D3DPresentEngine::releaseResources() @@ -502,7 +546,7 @@ HRESULT D3DPresentEngine::getService(REFGUID, REFIID riid, void** ppv) if (!m_devices) { hr = MF_E_UNSUPPORTED_SERVICE; } else { - *ppv = m_devices.get(); + *ppv = m_devices.Get(); m_devices->AddRef(); } } else { @@ -548,7 +592,9 @@ HRESULT D3DPresentEngine::checkFormat(D3DFORMAT format) return ok ? S_OK : D3DERR_NOTAVAILABLE; } -HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QList<IMFSample*> &videoSampleQueue) +HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, + QList<ComPtr<IMFSample>> &videoSampleQueue, + QSize frameSize) { if (!format || !m_device) return MF_E_UNEXPECTED; @@ -561,6 +607,11 @@ HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QList<IMFSamp if (FAILED(hr)) return hr; + if (frameSize.isValid() && !frameSize.isEmpty()) { + width = frameSize.width(); + height = frameSize.height(); + } + DWORD d3dFormat = 0; hr = qt_evr_getFourCC(format, &d3dFormat); if (FAILED(hr)) @@ -575,24 +626,24 @@ HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QList<IMFSamp for (int i = 0; i < PRESENTER_BUFFER_COUNT; i++) { // texture ref cnt is increased by GetSurfaceLevel()/MFCreateVideoSampleFromSurface() // below, so it will be destroyed only when the sample pool is released. - QWindowsIUPointer<IDirect3DTexture9> texture; + ComPtr<IDirect3DTexture9> texture; HANDLE sharedHandle = nullptr; - hr = m_device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)d3dFormat, D3DPOOL_DEFAULT, texture.address(), &sharedHandle); + hr = m_device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)d3dFormat, D3DPOOL_DEFAULT, texture.GetAddressOf(), &sharedHandle); if (FAILED(hr)) break; - QWindowsIUPointer<IDirect3DSurface9> surface; - hr = texture->GetSurfaceLevel(0, surface.address()); + ComPtr<IDirect3DSurface9> surface; + hr = texture->GetSurfaceLevel(0, surface.GetAddressOf()); if (FAILED(hr)) break; - QWindowsIUPointer<IMFSample> videoSample; - hr = MFCreateVideoSampleFromSurface(surface.get(), videoSample.address()); + ComPtr<IMFSample> videoSample; + hr = MFCreateVideoSampleFromSurface(surface.Get(), videoSample.GetAddressOf()); if (FAILED(hr)) break; - m_sampleTextureHandle[i] = {videoSample.get(), sharedHandle}; - videoSampleQueue.append(videoSample.release()); + m_sampleTextureHandle[i] = {videoSample.Get(), sharedHandle}; + videoSampleQueue.append(videoSample); } if (SUCCEEDED(hr)) { @@ -604,32 +655,21 @@ HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QList<IMFSamp return hr; } -QVideoFrame D3DPresentEngine::makeVideoFrame(IMFSample *sample) +QVideoFrame D3DPresentEngine::makeVideoFrame(const ComPtr<IMFSample> &sample) { if (!sample) return {}; HANDLE sharedHandle = nullptr; for (const auto &p : m_sampleTextureHandle) - if (p.first == sample) + if (p.first == sample.Get()) sharedHandle = p.second; QAbstractVideoBuffer *vb = nullptr; QRhi *rhi = m_sink ? m_sink->rhi() : nullptr; if (m_useTextureRendering && sharedHandle && rhi) { if (rhi->backend() == QRhi::D3D11) { - auto nh = static_cast<const QRhiD3D11NativeHandles*>(rhi->nativeHandles()); - if (nh) { - auto dev = reinterpret_cast<ID3D11Device *>(nh->dev); - if (dev) { - QWindowsIUPointer<ID3D11Texture2D> d3d11tex; - HRESULT hr = dev->OpenSharedResource(sharedHandle, __uuidof(ID3D11Texture2D), (void**)(d3d11tex.address())); - if (SUCCEEDED(hr)) - vb = new D3D11TextureVideoBuffer(m_device, sample, d3d11tex, rhi); - else - qCDebug(qLcEvrD3DPresentEngine) << "Failed to obtain D3D11Texture2D from D3D9Texture2D handle"; - } - } + vb = new D3D11TextureVideoBuffer(m_device, sample, sharedHandle, rhi); #if QT_CONFIG(opengl) } else if (rhi->backend() == QRhi::OpenGLES2) { vb = new OpenGlVideoBuffer(m_device, sample, m_wglNvDxInterop, sharedHandle, rhi); |