Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwindowsd3d11videoprocessor.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtCore/qloggingcategory.h>
7#include <QtCore/private/qsystemerror_p.h>
8
9#include <dxgi1_2.h>
10
12
13Q_STATIC_LOGGING_CATEGORY(lcD3D11VideoProcessor, "qt.multimedia.windows.d3d11videoprocessor");
14
15namespace QtMultimediaPrivate {
16
17namespace {
18
19DXGI_COLOR_SPACE_TYPE toDxgiColorSpace(QVideoFrameFormat::ColorSpace colorSpace,
20 QVideoFrameFormat::ColorRange colorRange,
21 QVideoFrameFormat::ColorTransfer colorTransfer)
22{
23 const bool fullRange = colorRange == QVideoFrameFormat::ColorRange_Full;
24
25 switch (colorSpace) {
26 case QVideoFrameFormat::ColorSpace_BT2020:
27 switch (colorTransfer) {
28 case QVideoFrameFormat::ColorTransfer_ST2084:
29 // DXGI defines no full-range YCbCr/PQ/2020 space; HDR10 input is always
30 // studio-range, tone-mapped to the SDR output space by the processor.
31 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020;
32 case QVideoFrameFormat::ColorTransfer_STD_B67:
33 return fullRange ? DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020
34 : DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020;
35 case QVideoFrameFormat::ColorTransfer_Unknown:
36 case QVideoFrameFormat::ColorTransfer_BT709:
37 case QVideoFrameFormat::ColorTransfer_BT601:
38 case QVideoFrameFormat::ColorTransfer_Linear:
39 case QVideoFrameFormat::ColorTransfer_Gamma22:
40 case QVideoFrameFormat::ColorTransfer_Gamma28:
41 // BT.2020 primaries with a gamma transfer are wide-gamut SDR, not HDR.
42 return fullRange ? DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020
43 : DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020;
44 }
45 Q_UNREACHABLE_RETURN(DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020);
46 case QVideoFrameFormat::ColorSpace_BT601:
47 return fullRange ? DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601
48 : DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601;
49 case QVideoFrameFormat::ColorSpace_BT709:
50 case QVideoFrameFormat::ColorSpace_AdobeRgb:
51 case QVideoFrameFormat::ColorSpace_Undefined:
52 // Fallback for color spaces with no DXGI equivalent (e.g. AdobeRgb).
53 return fullRange ? DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709
54 : DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
55 }
56 Q_UNREACHABLE_RETURN(DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709);
57}
58
59} // namespace
60
63
65{
66 // Matches the D3D11VA surface formats in FFmpeg's hwcontext_d3d11va supported_formats[].
67 switch (pixelFormat) {
70 return true;
71 default:
72 return false;
73 }
74}
75
77{
79 return true;
80
83 m_processorSize = {};
84
85 if (!m_videoDevice) {
87 return false;
88 }
89
90 if (!m_videoContext) {
94 return false;
95 }
96
99 contentDesc.InputWidth = static_cast<UINT>(frameSize.width());
100 contentDesc.InputHeight = static_cast<UINT>(frameSize.height());
101 contentDesc.OutputWidth = static_cast<UINT>(frameSize.width());
102 contentDesc.OutputHeight = static_cast<UINT>(frameSize.height());
104
106 if (FAILED(hr)) {
108 << "CreateVideoProcessorEnumerator:" << QSystemError::windowsComString(hr);
109 return false;
110 }
111
113 if (FAILED(hr)) {
115 << "CreateVideoProcessor:" << QSystemError::windowsComString(hr);
117 return false;
118 }
119
121 return true;
122}
123
125{
126 if (m_outputTex) {
129 if (desc.Width == static_cast<UINT>(frameSize.width())
130 && desc.Height == static_cast<UINT>(frameSize.height()))
131 return true;
132 }
133
136
138 desc.Width = static_cast<UINT>(frameSize.width());
139 desc.Height = static_cast<UINT>(frameSize.height());
140 desc.MipLevels = 1;
141 desc.ArraySize = 1;
143 desc.SampleDesc = { 1, 0 };
146
147 if (FAILED(device->CreateTexture2D(&desc, nullptr, &m_outputTex)))
148 return false;
149
153
156 if (FAILED(hr)) {
158 << "CreateVideoProcessorOutputView:" << QSystemError::windowsComString(hr);
160 return false;
161 }
162
163 return true;
164}
165
171{
175
176 if (frameSize.isEmpty())
177 return nullptr;
178
180 return nullptr;
181
183 return nullptr;
184
190
194 if (FAILED(hr)) {
196 << "CreateVideoProcessorInputView:" << QSystemError::windowsComString(hr);
197 return nullptr;
198 }
199
204
208
209 // ID3D11VideoContext is not thread-safe; the caller must hold the D3D11 device lock.
211 &stream);
212 if (FAILED(hr)) {
214 << "VideoProcessorBlt:" << QSystemError::windowsComString(hr);
215 return nullptr;
216 }
217
218 context->Flush();
219
220 return m_outputTex;
221}
222
223} // namespace QtMultimediaPrivate
224
225QT_END_NAMESPACE
Combined button and popup list for selecting options.