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