Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
4
#
include
"qwindowsd3d11videoprocessor_p.h"
5
6
#
include
<
QtCore
/
qloggingcategory
.
h
>
7
#
include
<
QtCore
/
private
/
qsystemerror_p
.
h
>
8
9
#
include
<
dxgi1_2
.
h
>
10
11
QT_BEGIN_NAMESPACE
12
13
Q_STATIC_LOGGING_CATEGORY(lcD3D11VideoProcessor,
"qt.multimedia.windows.d3d11videoprocessor"
);
14
15
namespace
QtMultimediaPrivate
{
16
17
namespace
{
18
19
DXGI_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
61
QWindowsD3D11VideoProcessor
::
QWindowsD3D11VideoProcessor
() =
default
;
62
QWindowsD3D11VideoProcessor
::~
QWindowsD3D11VideoProcessor
() =
default
;
63
64
bool
QWindowsD3D11VideoProcessor
::
isPixelFormatSupported
(
QVideoFrameFormat
::
PixelFormat
pixelFormat
)
65
{
66
// Matches the D3D11VA surface formats in FFmpeg's hwcontext_d3d11va supported_formats[].
67
switch
(
pixelFormat
) {
68
case
QVideoFrameFormat
::
Format_NV12
:
69
case
QVideoFrameFormat
::
Format_P010
:
70
return
true
;
71
default
:
72
return
false
;
73
}
74
}
75
76
bool
QWindowsD3D11VideoProcessor
::
ensureVideoProcessor
(
ID3D11Device
*
device
,
const
QSize
&
frameSize
)
77
{
78
if
(
m_videoProcessor
&&
m_processorSize
==
frameSize
)
79
return
true
;
80
81
m_videoProcessor
.
Reset
();
82
m_enumerator
.
Reset
();
83
m_processorSize
= {};
84
85
if
(!
m_videoDevice
) {
86
if
(
FAILED
(
device
->
QueryInterface
(
IID_PPV_ARGS
(&
m_videoDevice
))))
87
return
false
;
88
}
89
90
if
(!
m_videoContext
) {
91
ComPtr
<
ID3D11DeviceContext
>
ctx
;
92
device
->
GetImmediateContext
(&
ctx
);
93
if
(
FAILED
(
ctx
.
As
(&
m_videoContext
)))
94
return
false
;
95
}
96
97
D3D11_VIDEO_PROCESSOR_CONTENT_DESC
contentDesc
{};
98
contentDesc
.
InputFrameFormat
=
D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE
;
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
());
103
contentDesc
.
Usage
=
D3D11_VIDEO_USAGE_PLAYBACK_NORMAL
;
104
105
HRESULT
hr
=
m_videoDevice
->
CreateVideoProcessorEnumerator
(&
contentDesc
, &
m_enumerator
);
106
if
(
FAILED
(
hr
)) {
107
qCWarning
(
lcD3D11VideoProcessor
)
108
<<
"CreateVideoProcessorEnumerator:"
<<
QSystemError
::
windowsComString
(
hr
);
109
return
false
;
110
}
111
112
hr
=
m_videoDevice
->
CreateVideoProcessor
(
m_enumerator
.
Get
(), 0, &
m_videoProcessor
);
113
if
(
FAILED
(
hr
)) {
114
qCWarning
(
lcD3D11VideoProcessor
)
115
<<
"CreateVideoProcessor:"
<<
QSystemError
::
windowsComString
(
hr
);
116
m_enumerator
.
Reset
();
117
return
false
;
118
}
119
120
m_processorSize
=
frameSize
;
121
return
true
;
122
}
123
124
bool
QWindowsD3D11VideoProcessor
::
ensureOutputTexture
(
ID3D11Device
*
device
,
const
QSize
&
frameSize
)
125
{
126
if
(
m_outputTex
) {
127
D3D11_TEXTURE2D_DESC
desc
{};
128
m_outputTex
->
GetDesc
(&
desc
);
129
if
(
desc
.
Width
==
static_cast
<
UINT
>(
frameSize
.
width
())
130
&&
desc
.
Height
==
static_cast
<
UINT
>(
frameSize
.
height
()))
131
return
true
;
132
}
133
134
m_outputView
.
Reset
();
135
m_outputTex
.
Reset
();
136
137
D3D11_TEXTURE2D_DESC
desc
{};
138
desc
.
Width
=
static_cast
<
UINT
>(
frameSize
.
width
());
139
desc
.
Height
=
static_cast
<
UINT
>(
frameSize
.
height
());
140
desc
.
MipLevels
= 1;
141
desc
.
ArraySize
= 1;
142
desc
.
Format
=
DXGI_FORMAT_B8G8R8A8_UNORM
;
143
desc
.
SampleDesc
= { 1, 0 };
144
desc
.
Usage
=
D3D11_USAGE_DEFAULT
;
145
desc
.
BindFlags
=
D3D11_BIND_RENDER_TARGET
|
D3D11_BIND_SHADER_RESOURCE
;
146
147
if
(
FAILED
(
device
->
CreateTexture2D
(&
desc
,
nullptr
, &
m_outputTex
)))
148
return
false
;
149
150
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC
outputViewDesc
{};
151
outputViewDesc
.
ViewDimension
=
D3D11_VPOV_DIMENSION_TEXTURE2D
;
152
outputViewDesc
.
Texture2D
.
MipSlice
= 0;
153
154
HRESULT
hr
=
m_videoDevice
->
CreateVideoProcessorOutputView
(
155
m_outputTex
.
Get
(),
m_enumerator
.
Get
(), &
outputViewDesc
, &
m_outputView
);
156
if
(
FAILED
(
hr
)) {
157
qCWarning
(
lcD3D11VideoProcessor
)
158
<<
"CreateVideoProcessorOutputView:"
<<
QSystemError
::
windowsComString
(
hr
);
159
m_outputTex
.
Reset
();
160
return
false
;
161
}
162
163
return
true
;
164
}
165
166
ComPtr
<
ID3D11Texture2D
>
QWindowsD3D11VideoProcessor
::
convertToBGRA
(
167
ID3D11Device
*
device
,
ID3D11DeviceContext
*
context
,
const
ComPtr
<
ID3D11Texture2D
> &
texture
,
168
const
QSize
&
frameSize
,
QVideoFrameFormat
::
ColorSpace
colorSpace
,
169
QVideoFrameFormat
::
ColorRange
colorRange
,
QVideoFrameFormat
::
ColorTransfer
colorTransfer
,
170
UINT
subresourceIndex
)
171
{
172
Q_ASSERT
(
device
);
173
Q_ASSERT
(
context
);
174
Q_ASSERT
(
texture
);
175
176
if
(
frameSize
.
isEmpty
())
177
return
nullptr
;
178
179
if
(!
ensureVideoProcessor
(
device
,
frameSize
))
180
return
nullptr
;
181
182
if
(!
ensureOutputTexture
(
device
,
frameSize
))
183
return
nullptr
;
184
185
D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC
inputViewDesc
{};
186
inputViewDesc
.
FourCC
= 0;
187
inputViewDesc
.
ViewDimension
=
D3D11_VPIV_DIMENSION_TEXTURE2D
;
188
inputViewDesc
.
Texture2D
.
MipSlice
= 0;
189
inputViewDesc
.
Texture2D
.
ArraySlice
=
subresourceIndex
;
190
191
ComPtr
<
ID3D11VideoProcessorInputView
>
inputView
;
192
HRESULT
hr
=
m_videoDevice
->
CreateVideoProcessorInputView
(
texture
.
Get
(),
m_enumerator
.
Get
(),
193
&
inputViewDesc
, &
inputView
);
194
if
(
FAILED
(
hr
)) {
195
qCWarning
(
lcD3D11VideoProcessor
)
196
<<
"CreateVideoProcessorInputView:"
<<
QSystemError
::
windowsComString
(
hr
);
197
return
nullptr
;
198
}
199
200
m_videoContext
->
VideoProcessorSetStreamColorSpace1
(
201
m_videoProcessor
.
Get
(), 0,
toDxgiColorSpace
(
colorSpace
,
colorRange
,
colorTransfer
));
202
m_videoContext
->
VideoProcessorSetOutputColorSpace1
(
m_videoProcessor
.
Get
(),
203
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
);
204
205
D3D11_VIDEO_PROCESSOR_STREAM
stream
{};
206
stream
.
Enable
=
TRUE
;
207
stream
.
pInputSurface
=
inputView
.
Get
();
208
209
// ID3D11VideoContext is not thread-safe; the caller must hold the D3D11 device lock.
210
hr
=
m_videoContext
->
VideoProcessorBlt
(
m_videoProcessor
.
Get
(),
m_outputView
.
Get
(), 0, 1,
211
&
stream
);
212
if
(
FAILED
(
hr
)) {
213
qCWarning
(
lcD3D11VideoProcessor
)
214
<<
"VideoProcessorBlt:"
<<
QSystemError
::
windowsComString
(
hr
);
215
return
nullptr
;
216
}
217
218
context
->
Flush
();
219
220
return
m_outputTex
;
221
}
222
223
}
// namespace QtMultimediaPrivate
224
225
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QtMultimediaPrivate::impl
Definition
qaudiosystem_p.h:257
qtmultimedia
src
multimedia
windows
qwindowsd3d11videoprocessor.cpp
Generated on
for Qt by
1.18.0