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
qdmabufvideobuffer.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
"qdmabufvideobuffer_p.h"
5
6
#
include
<
QtMultimedia
/
private
/
qvideotexturehelper_p
.
h
>
7
#
include
<
QtMultimedia
/
private
/
qrhivaluemapper_p
.
h
>
8
#
include
<
QtGui
/
rhi
/
qrhi
.
h
>
9
#
include
<
QtCore
/
qloggingcategory
.
h
>
10
11
#
if
QT_CONFIG
(
opengl
)
&&
QT_CONFIG
(
egl
)
12
#
include
<
QtMultimedia
/
private
/
qdmabuftextureimporter_p
.
h
>
13
#
endif
14
15
#
include
<
cerrno
>
16
#
include
<
cstring
>
17
#
include
<
fcntl
.
h
>
18
#
include
<
unistd
.
h
>
19
#
include
<
sys
/
mman
.
h
>
20
21
static_assert
(QT_CONFIG(linux_dmabuf));
22
23
QT_BEGIN_NAMESPACE
24
25
Q_STATIC_LOGGING_CATEGORY
(qLcDmaBufVideoBuffer,
"qt.multimedia.dmabufvideobuffer"
);
26
27
namespace
QtMultimediaPrivate
{
28
29
#
if
QT_CONFIG
(
opengl
)
&&
QT_CONFIG
(
egl
)
30
static
QRhiValueMapper
<
DmaBufEglContext
>
g_eglContexts
;
31
#
endif
32
33
QDmaBufVideoBuffer
::
QDmaBufVideoBuffer
(
QVideoFrameFormat
::
PixelFormat
format
,
QSize
size
,
34
QSpan
<
const
DmaBufPlane
>
planes
,
35
std
::
shared_ptr
<
void
>
keepAlive
)
36
:
m_format
(
format
),
37
m_size
(
size
),
38
m_planeCount
(
std
::
clamp
(0,
int
(
planes
.
size
()), 4)),
39
m_keepAlive
(
std
::
move
(
keepAlive
))
40
{
41
Q_ASSERT
(!
planes
.
empty
() &&
planes
.
size
() <= 4);
42
43
for
(
int
i
= 0;
i
<
m_planeCount
; ++
i
) {
44
m_planes
[
i
] =
planes
[
i
];
45
46
// Take our own, independent reference: the producer may close its
47
// fd at any point while this buffer is still alive.
48
if
(
m_planes
[
i
].
fd
>= 0) {
49
const
int
dupped
= ::
fcntl
(
m_planes
[
i
].
fd
, F_DUPFD_CLOEXEC, 0);
50
if
(
dupped
< 0) {
51
qCWarning
(
qLcDmaBufVideoBuffer
) <<
"Failed to dup DMABUF fd for plane"
<<
i
<<
':'
52
<<
qt_error_string
(errno);
53
m_planes
[
i
].
fd
= -1;
54
}
else
{
55
m_planes
[
i
].
fd
=
dupped
;
56
}
57
}
58
}
59
}
60
61
QDmaBufVideoBuffer
::~
QDmaBufVideoBuffer
()
62
{
63
Q_ASSERT
(
m_mapMode
==
QVideoFrame
::
NotMapped
);
64
65
for
(
int
i
= 0;
i
<
m_planeCount
; ++
i
) {
66
if
(
m_planes
[
i
].
fd
>= 0)
67
::
close
(
m_planes
[
i
].
fd
);
68
}
69
}
70
71
QVideoFrameTexturesUPtr
QDmaBufVideoBuffer
::
mapTextures
(
QRhi
&
rhi
)
72
{
73
Q_ASSERT
(
rhi
.
thread
()->
isCurrentThread
());
74
75
if
(
rhi
.
backend
() !=
QRhi
::
OpenGLES2
)
76
return
{};
77
78
#
if
QT_CONFIG
(
opengl
)
&&
QT_CONFIG
(
egl
)
79
// DmaBufEglContext is bound to the GL context associated with a QRhi;
80
// textures are (re-)imported on the RHI render thread, so this is
81
// created lazily here (rather than in the constructor, which may run on
82
// a different thread) and cached per-rhi.
83
DmaBufEglContext
&
eglContext
=
g_eglContexts
.
getOrCreate
(
rhi
, [&] {
84
return
DmaBufEglContext
(&
rhi
);
85
});
86
87
if
(!
eglContext
.
isValid
()) {
88
qCDebug
(
qLcDmaBufVideoBuffer
) <<
"DmaBufEglContext is not valid, falling back to CPU path"
;
89
return
{};
90
}
91
92
auto
handles
=
importDmaBufTextures
(
rhi
,
eglContext
,
QSpan
(
m_planes
.
data
(),
m_planeCount
),
93
m_format
,
m_size
,
m_keepAlive
);
94
if
(!
handles
) {
95
if
(
handles
.
error
() ==
FailureSeverity
::
unrecoverable
) {
96
qCWarning
(
qLcDmaBufVideoBuffer
)
97
<<
"Unrecoverable EGL import failure, disabling texture import for this buffer"
;
98
eglContext
.
invalidate
();
99
}
100
return
{};
101
}
102
103
return
QVideoTextureHelper
::
createTexturesFromHandles
(
std
::
move
(*
handles
),
rhi
,
m_format
,
104
m_size
);
105
#
else
// QT_CONFIG(opengl) && QT_CONFIG(egl)
106
qCDebug
(
qLcDmaBufVideoBuffer
)
107
<<
"DMABUF texture import is not supported in this build, falling back to CPU path"
;
108
return
{};
109
#
endif
// QT_CONFIG(opengl) && QT_CONFIG(egl)
110
}
111
112
QAbstractVideoBuffer
::
MapData
QDmaBufVideoBuffer
::
map
(
QVideoFrame
::
MapMode
mode
)
113
{
114
MapData
mapData
;
115
116
// The producer (driver/compositor) owns write access to the DMABUF.
117
if
(
mode
!=
QVideoFrame
::
ReadOnly
||
m_mapMode
!=
QVideoFrame
::
NotMapped
)
118
return
mapData
;
119
120
auto
*
desc
=
QVideoTextureHelper
::
textureDescription
(
m_format
);
121
if
(!
desc
)
122
return
mapData
;
123
124
QVarLengthArray
<
std
::
pair
<
int
,
std
::
pair
<
void
*,
size_t
>>, 4>
mappedByFd
;
125
126
for
(
int
i
= 0;
i
<
m_planeCount
; ++
i
) {
127
const
DmaBufPlane
&
plane
=
m_planes
[
i
];
128
129
void
*
base
=
nullptr
;
130
for
(
const
auto
&
entry
:
mappedByFd
) {
131
if
(
entry
.
first
==
plane
.
fd
) {
132
base
=
entry
.
second
.
first
;
133
break
;
134
}
135
}
136
137
if
(!
base
) {
138
// Determine the size of the DMABUF via lseek (dma-buf file
139
// objects implement llseek to report their size), then mmap it
140
// read-only in one go; individual planes just index into this
141
// mapping via their offset.
142
const
off_t
len
= ::
lseek
(
plane
.
fd
, 0, SEEK_END);
143
if
(
len
<= 0) {
144
qCWarning
(
qLcDmaBufVideoBuffer
) <<
"Could not determine DMABUF size for plane"
<<
i
;
145
for
(
const
auto
&
entry
:
mappedByFd
)
146
::
munmap
(
entry
.
second
.
first
,
entry
.
second
.
second
);
147
return
{};
148
}
149
150
void
*
mapped
= ::
mmap
(
nullptr
,
size_t
(
len
), PROT_READ, MAP_SHARED,
plane
.
fd
, 0);
151
if
(
mapped
==
MAP_FAILED
) {
152
qCWarning
(
qLcDmaBufVideoBuffer
)
153
<<
"mmap failed for plane"
<<
i
<<
':'
<<
qt_error_string
(errno);
154
for
(
const
auto
&
entry
:
mappedByFd
)
155
::
munmap
(
entry
.
second
.
first
,
entry
.
second
.
second
);
156
return
{};
157
}
158
159
mappedByFd
.
push_back
({
plane
.
fd
, {
mapped
,
size_t
(
len
) } });
160
base
=
mapped
;
161
}
162
163
mapData
.
data
[
i
] =
static_cast
<
uchar
*>(
base
) +
plane
.
offset
;
164
mapData
.
bytesPerLine
[
i
] =
int
(
plane
.
pitch
);
165
mapData
.
dataSize
[
i
] =
int
(
plane
.
pitch
) *
desc
->
heightForPlane
(
m_size
.
height
(),
i
);
166
}
167
168
mapData
.
planeCount
=
m_planeCount
;
169
170
m_mappedRegions
.
clear
();
171
for
(
const
auto
&
entry
:
mappedByFd
)
172
m_mappedRegions
.
push_back
(
entry
.
second
);
173
174
m_mapMode
=
mode
;
175
return
mapData
;
176
}
177
178
void
QDmaBufVideoBuffer
::
unmap
()
179
{
180
for
(
const
auto
&
region
:
m_mappedRegions
)
181
::
munmap
(
region
.
first
,
region
.
second
);
182
m_mappedRegions
.
clear
();
183
184
m_mapMode
=
QVideoFrame
::
NotMapped
;
185
}
186
187
}
// namespace QtMultimediaPrivate
188
189
QT_END_NAMESPACE
QtMultimediaPrivate::impl
Definition
qaudiosystem_p.h:257
Q_STATIC_LOGGING_CATEGORY
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
MAP_FAILED
#define MAP_FAILED
Definition
qresource.cpp:1189
qtmultimedia
src
multimedia
video
qdmabufvideobuffer.cpp
Generated on
for Qt by
1.16.1