8#include <QtMultimedia/qvideoframeformat.h>
9#include <QtMultimedia/private/qvideotexturehelper_p.h>
11#include <QtGui/rhi/qrhi.h>
12#include <QtCore/qloggingcategory.h>
13#include <QtCore/private/qcomptr_p.h>
15#include <libavutil/hwcontext_d3d11va.h>
26 explicit lock_guard(
const AVD3D11VADeviceContext &ctx) : m_ctx(ctx)
28 m_ctx.lock(m_ctx.lock_ctx);
34 lock_guard &
operator=(
const lock_guard &) =
delete;
37 const AVD3D11VADeviceContext &m_ctx;
48Q_LOGGING_CATEGORY(qLcMediaFFmpegHWAccel,
"qt.multimedia.hwaccel");
50ComPtr<ID3D11Texture2D> getAvFrameTexture(
const AVFrame *frame)
52 return reinterpret_cast<ID3D11Texture2D *>(frame->data[0]);
55int getAvFramePoolIndex(
const AVFrame *frame)
57 return static_cast<
int>(
reinterpret_cast<intptr_t>(frame->data[1]));
60const AVD3D11VADeviceContext *getHwDeviceContext(
const AVHWDeviceContext *ctx)
62 return static_cast<AVD3D11VADeviceContext *>(ctx->hwctx);
65AVBufferRef *wrapTextureAsBuffer(
const ComPtr<ID3D11Texture2D> &tex)
69 AVD3D11FrameDescriptor *avFrameDesc =
70 static_cast<AVD3D11FrameDescriptor *>(av_mallocz(
sizeof(AVD3D11FrameDescriptor)));
71 avFrameDesc->index = 0;
72 avFrameDesc->texture = tex.Get();
74 return av_buffer_create(
reinterpret_cast<uint8_t *>(avFrameDesc),
75 sizeof(AVD3D11FrameDescriptor *), [](
void *opaque, uint8_t *data) {
76 static_cast<ID3D11Texture2D *>(opaque)->Release();
81ComPtr<ID3D11Texture2D> copyTexture(
const AVD3D11VADeviceContext *hwDevCtx,
const AVFrame *src)
83 const int poolIndex = getAvFramePoolIndex(src);
84 const ComPtr<ID3D11Texture2D> poolTex = getAvFrameTexture(src);
86 D3D11_TEXTURE2D_DESC texDesc{};
87 poolTex->GetDesc(&texDesc);
89 texDesc.ArraySize = 1;
90 texDesc.MiscFlags = 0;
91 texDesc.BindFlags = 0;
93 ComPtr<ID3D11Texture2D> destTex;
94 if (hwDevCtx->device->CreateTexture2D(&texDesc,
nullptr, &destTex) != S_OK) {
95 qCCritical(qLcMediaFFmpegHWAccel) <<
"Unable to copy frame from decoder pool";
99 hwDevCtx->device_context->CopySubresourceRegion(destTex.Get(), 0, 0, 0, 0, poolTex.Get(),
105class ImportedTextureHandles :
public QVideoFrameTexturesHandles
108 ImportedTextureHandles(TextureConverterBackendPtr &&converterBackend,
109 QVideoFrameTexturesHandlesUPtr &&handles)
110 : m_parentConverterBackend(std::move(converterBackend)), m_handles(std::move(handles))
114 quint64 textureHandle(QRhi &rhi,
int plane)
override
116 return m_handles ? m_handles->textureHandle(rhi, plane) : 0;
120 TextureConverterBackendPtr
121 m_parentConverterBackend;
122 QVideoFrameTexturesHandlesUPtr m_handles;
240 <<
"Failed to initialize HW frames context" <<
AVError{
ret };
247 if (!src || !src->hw_frames_ctx || src->format != AV_PIX_FMT_D3D11)
250 const AVHWDeviceContext *avDevCtx = avFrameDeviceContext(src.get());
251 if (!avDevCtx || avDevCtx->type != AV_HWDEVICE_TYPE_D3D11VA)
254 AVFrameUPtr dest = makeAVFrame();
255 if (
int status = av_frame_copy_props(dest.get(), src.get()); status != 0) {
256 qCCritical(qLcMediaFFmpegHWAccel)
257 <<
"Unable to copy frame from decoder pool" << AVError{ status };
261 const AVD3D11VADeviceContext *hwDevCtx = getHwDeviceContext(avDevCtx);
262 ComPtr<ID3D11Texture2D> destTex = [&] {
263 std::lock_guard<AVD3D11VADeviceContext> guard
(*hwDevCtx
);
264 return copyTexture(hwDevCtx, src.get());
270 dest->buf[0] = wrapTextureAsBuffer(destTex);
271 dest->data[0] =
reinterpret_cast<uint8_t *>(destTex.Detach());
272 dest->data[1] =
reinterpret_cast<uint8_t *>(0);
274 dest->width = src->width;
275 dest->height = src->height;
276 dest->format = src->format;
277 dest->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
lock_guard & operator=(const lock_guard &)=delete
lock_guard(const lock_guard &)=delete
lock_guard(const AVD3D11VADeviceContext &ctx)
AVFrameUPtr copyFromHwPoolD3D11(AVFrameUPtr src)