14#include "private/qabstractvideobuffer_p.h"
15#include "private/qcapturablewindow_p.h"
19#include <X11/extensions/XShm.h>
21#include <X11/extensions/Xrandr.h>
31void destroyXImage(XImage*
image) {
35template <
typename T,
typename D>
36std::unique_ptr<T, D> makeXUptr(T*
ptr, D deleter) {
37 return std::unique_ptr<T, D>(
ptr, deleter);
47 auto found = std::find_if(
monitors.get(),
end, [&](
const XRRMonitorInfo &
info) {
48 auto atomName = makeXUptr(XGetAtomName(display, info.name), &XFree);
49 return atomName && name == QString::fromUtf8(atomName.get());
52 return found ==
end ? -1 : std::distance(
monitors.get(), found);
59 if (
image.red_mask == 0xff0000 &&
60 image.green_mask == 0xff00 &&
61 image.blue_mask == 0xff)
64 if (
image.red_mask == 0xff00 &&
65 image.green_mask == 0xff0000 &&
66 image.blue_mask == 0xff000000)
69 if (
image.blue_mask == 0xff0000 &&
70 image.green_mask == 0xff00 &&
71 image.red_mask == 0xff)
74 if (
image.red_mask == 0xff00 &&
75 image.green_mask == 0xff0000 &&
76 image.blue_mask == 0xff000000)
85 DataVideoBuffer(
const char *
data,
int bytesPerLine,
int size)
89 m_bytesPerLine(bytesPerLine)
155 m_display.reset(XOpenDisplay(
nullptr));
161 return m_display !=
nullptr;
169 return createDisplay() && initWithXID(
static_cast<XID>(wid));
179 if (!createDisplay())
182 auto screenNumber = screenNumberByName(m_display.get(),
screen->
name());
184 if (screenNumber < 0)
189 return initWithXID(RootWindow(m_display.get(), screenNumber));
192 bool initWithXID(
XID xid)
206 if (std::exchange(m_attached,
false)) {
207 XShmDetach(m_display.get(), &m_shmInfo);
208 shmdt(m_shmInfo.shmaddr);
209 shmctl(m_shmInfo.shmid, IPC_RMID, 0);
218 shmget(IPC_PRIVATE, m_xImage->bytes_per_line * m_xImage->height, IPC_CREAT | 0777);
220 if (m_shmInfo.shmid == -1)
223 m_shmInfo.readOnly =
false;
224 m_shmInfo.shmaddr = m_xImage->data = (
char *)shmat(m_shmInfo.shmid, 0, 0);
226 m_attached = XShmAttach(m_display.get(), &m_shmInfo);
231 XWindowAttributes wndattr = {};
232 if (XGetWindowAttributes(m_display.get(), m_xid, &wndattr) == 0) {
245 if (!m_xImage || wndattr.width != m_xImage->width || wndattr.height != m_xImage->height
246 || wndattr.depth != m_xImage->depth || wndattr.visual->visualid != m_visualID) {
248 qCDebug(qLcX11SurfaceCapture) <<
"recreate ximage: " << wndattr.width << wndattr.height
249 << wndattr.depth << wndattr.visual->visualid;
254 m_visualID = wndattr.visual->visualid;
255 m_xImage.reset(XShmCreateImage(m_display.get(), wndattr.visual, wndattr.depth, ZPixmap,
256 nullptr, &m_shmInfo, wndattr.width, wndattr.height));
264 const auto pixelFormat = xImagePixelFormat(*m_xImage);
295 if (!XShmGetImage(m_display.get(), m_xid, m_xImage.get(), m_xOffset, m_yOffset,
299 "Cannot get ximage; the window may be out of the screen borders"));
303 auto buffer =
new DataVideoBuffer(m_xImage->data, m_xImage->bytes_per_line,
304 m_xImage->bytes_per_line * m_xImage->height);
311 std::optional<QPlatformSurfaceCapture::Error> m_prevGrabberError;
315 std::unique_ptr<
Display,
decltype(&XCloseDisplay)> m_display{
nullptr, &XCloseDisplay };
316 std::unique_ptr<XImage,
decltype(&destroyXImage)> m_xImage{
nullptr, &destroyXImage };
317 XShmSegmentInfo m_shmInfo;
318 bool m_attached =
false;
319 VisualID m_visualID =
None;
342 qCDebug(qLcX11SurfaceCapture) <<
"set active" << active;
349 return static_cast<bool>(m_grabber) == active;
352void QX11SurfaceCapture::activate(ScreenSource
screen)
358void QX11SurfaceCapture::activate(WindowSource
window)
The QAbstractVideoBuffer class is an abstraction for video data. \inmodule QtMultimedia.
virtual void unmap()=0
Releases the memory mapped by the map() function.
virtual QVideoFrame::MapMode mapMode() const =0
int compare(QByteArrayView a, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
static const QCapturableWindowPrivate * handle(const QCapturableWindow &window)
void addFrameCallback(Object &object, Method method)
void errorUpdated(QPlatformSurfaceCapture::Error error, const QString &description)
void setFrameRate(qreal rate)
QScreen * primaryScreen
the primary (or default) screen of the application.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
The QScreen class is used to query screen properties. \inmodule QtGui.
qreal refreshRate
the approximate vertical refresh rate of the screen in Hz
QString name
a user presentable string representing the screen
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void start(Priority=InheritPriority)
The QVideoFrame class represents a frame of video data.
MapMode
Enumerates how a video buffer's data is mapped to system memory.
static std::unique_ptr< Grabber > create(QX11SurfaceCapture &capture, QScreen *screen)
const QVideoFrameFormat & format() const
QVideoFrame grabFrame() override
static std::unique_ptr< Grabber > create(QX11SurfaceCapture &capture, WId wid)
QVideoFrameFormat frameFormat() const override
~QX11SurfaceCapture() override
bool setActiveInternal(bool active) override
QX11SurfaceCapture(Source initialSource)
static bool isSupported()
QMap< QString, QString > map
[6]
struct wl_display * display
Combined button and popup list for selecting options.
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
static ControlElement< T > * ptr(QWidget *widget)
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLsizei GLchar * source
static QAbstractVideoBuffer::MapData mapData(const camera_frame_nv12_t &frame, unsigned char *baseAddress)
QLatin1StringView QLatin1String
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
QFileInfo info(fileName)
[8]