10#include <private/qvideotexturehelper_p.h>
11#include <private/qcomptr_p.h>
12#include <private/quniquehandle_p.h>
20#include <libavutil/hwcontext_d3d11va.h>
36 const ComPtr<ID3D11Device> rhiDevice =
static_cast<ID3D11Device *
>(native->dev);
38 ComPtr<ID3D11Device1> dev1;
39 if (rhiDevice.As(&dev1) != S_OK)
48bool TextureBridge::copyToSharedTex(ID3D11Device *dev, ID3D11DeviceContext *
ctx,
49 const ComPtr<ID3D11Texture2D> &tex, UINT
index,
58 if (m_srcMutex->AcquireSync(m_srcKey, INFINITE) != S_OK)
68 ctx->CopySubresourceRegion(m_srcTex.Get(), 0, 0, 0, 0, tex.Get(),
index, &crop);
70 m_srcMutex->ReleaseSync(m_destKey);
74ComPtr<ID3D11Texture2D> TextureBridge::copyFromSharedTex(
const ComPtr<ID3D11Device1> &dev,
75 const ComPtr<ID3D11DeviceContext> &
ctx)
77 if (!ensureDestTex(dev))
80 if (m_destMutex->AcquireSync(m_destKey, INFINITE) != S_OK)
83 ctx->CopySubresourceRegion(m_outputTex.Get(), 0, 0, 0, 0, m_destTex.Get(), 0,
nullptr);
85 m_destMutex->ReleaseSync(m_srcKey);
90bool TextureBridge::ensureDestTex(
const ComPtr<ID3D11Device1> &dev)
92 if (m_destDevice != dev) {
101 if (m_destDevice->OpenSharedResource1(m_sharedHandle.get(), IID_PPV_ARGS(&m_destTex)) != S_OK)
104 CD3D11_TEXTURE2D_DESC
desc{};
105 m_destTex->GetDesc(&desc);
108 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
110 if (m_destDevice->CreateTexture2D(&desc,
nullptr, m_outputTex.ReleaseAndGetAddressOf()) != S_OK)
113 if (m_destTex.As(&m_destMutex) != S_OK)
119bool TextureBridge::ensureSrcTex(ID3D11Device *dev,
const ComPtr<ID3D11Texture2D> &tex,
const QSize &
frameSize)
121 if (!isSrcInitialized(dev, tex,
frameSize))
127bool TextureBridge::isSrcInitialized(
const ID3D11Device *dev,
128 const ComPtr<ID3D11Texture2D> &tex,
135 ComPtr<ID3D11Device> texDevice;
136 m_srcTex->GetDevice(texDevice.GetAddressOf());
137 if (dev != texDevice.Get())
141 CD3D11_TEXTURE2D_DESC inputDesc{};
142 tex->GetDesc(&inputDesc);
144 CD3D11_TEXTURE2D_DESC currentDesc{};
145 m_srcTex->GetDesc(¤tDesc);
147 if (inputDesc.Format != currentDesc.Format)
153 if (currentDesc.Width !=
width || currentDesc.Height !=
height)
159bool TextureBridge::recreateSrc(ID3D11Device *dev,
const ComPtr<ID3D11Texture2D> &tex,
const QSize &
frameSize)
161 m_sharedHandle.close();
163 CD3D11_TEXTURE2D_DESC
desc{};
170 texDesc.MipLevels = 1;
171 texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
173 if (dev->CreateTexture2D(&texDesc,
nullptr, m_srcTex.ReleaseAndGetAddressOf()) != S_OK)
176 ComPtr<IDXGIResource1>
res;
177 if (m_srcTex.As(&
res) != S_OK)
181 res->CreateSharedHandle(
nullptr, DXGI_SHARED_RESOURCE_READ,
nullptr, &m_sharedHandle);
183 if (hr != S_OK || !m_sharedHandle)
186 if (m_srcTex.As(&m_srcMutex) != S_OK || !m_srcMutex)
190 m_destMutex =
nullptr;
198 : m_owner{ rhi }, m_tex(
std::move(tex))
206 return reinterpret_cast<qint64>(m_tex.Get());
210 QRhi *m_owner =
nullptr;
211 ComPtr<ID3D11Texture2D> m_tex;
214D3D11TextureConverter::D3D11TextureConverter(
QRhi *rhi)
215 : TextureConverterBackend(rhi), m_rhiDevice{ GetD3DDevice(rhi) }
220 m_rhiDevice->GetImmediateContext(m_rhiCtx.GetAddressOf());
223TextureSet *D3D11TextureConverter::getTextures(AVFrame *
frame)
228 if (!
frame || !
frame->hw_frames_ctx ||
frame->format != AV_PIX_FMT_D3D11)
231 const auto *fCtx =
reinterpret_cast<AVHWFramesContext *
>(
frame->hw_frames_ctx->data);
232 const auto *
ctx = fCtx->device_ctx;
234 if (!
ctx ||
ctx->type != AV_HWDEVICE_TYPE_D3D11VA)
237 const ComPtr<ID3D11Texture2D> ffmpegTex =
reinterpret_cast<ID3D11Texture2D *
>(
frame->data[0]);
242 const auto *avDeviceCtx =
static_cast<AVD3D11VADeviceContext *
>(
ctx->hwctx);
250 avDeviceCtx->lock(avDeviceCtx->lock_ctx);
251 QScopeGuard autoUnlock([&] { avDeviceCtx->unlock(avDeviceCtx->lock_ctx); });
256 if (!m_bridge.copyToSharedTex(avDeviceCtx->device, avDeviceCtx->device_context,
263 ComPtr<ID3D11Texture2D>
output = m_bridge.copyFromSharedTex(m_rhiDevice, m_rhiCtx);
268 return new D3D11TextureSet(rhi, std::move(
output));
274void D3D11TextureConverter::SetupDecoderTextures(AVCodecContext *
s)
285 constexpr qint32 framesHeldByRhi = 1;
286 constexpr qint32 framesHeldByQtEventLoop = 1;
287 s->extra_hw_frames = maxRenderQueueSize + framesHeldByRhi + framesHeldByQtEventLoop;
289 int ret = avcodec_get_hw_frames_parameters(
s,
s->hw_device_ctx, AV_PIX_FMT_D3D11,
292 qCDebug(qLcMediaFFmpegHWAccel) <<
"Failed to allocate HW frames context" <<
ret;
296 const auto *frames_ctx =
reinterpret_cast<const AVHWFramesContext *
>(
s->hw_frames_ctx->data);
297 auto *hwctx =
static_cast<AVD3D11VAFramesContext *
>(frames_ctx->hwctx);
298 hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
299 hwctx->BindFlags = D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE;
300 ret = av_hwframe_ctx_init(
s->hw_frames_ctx);
302 qCDebug(qLcMediaFFmpegHWAccel) <<
"Failed to initialize HW frames context" <<
ret;
303 av_buffer_unref(&
s->hw_frames_ctx);
qint64 textureHandle(QRhi *rhi, int) override
D3D11TextureSet(QRhi *rhi, ComPtr< ID3D11Texture2D > &&tex)
static qint32 maxQueueSize(QPlatformMediaPlayer::TrackType type)
\variable QRhiD3D11InitParams::enableDebugLayer
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Implementation backend() const
const QRhiNativeHandles * nativeHandles()
Combined button and popup list for selecting options.
ComPtr< ID3D11Device1 > GetD3DDevice(QRhi *rhi)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLint GLsizei GLsizei height
static constexpr QSize frameSize(const T &frame)
QT_BEGIN_NAMESPACE typedef uchar * output