aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Grulich <[email protected]>2018-10-18 14:15:13 +0200
committerJan Grulich <[email protected]>2018-10-18 14:15:13 +0200
commit530ed29aaaf690d0020f948ff5a344303decc989 (patch)
tree23aeafbb438f79067a9fef828c5ff53e8353520b
parent3f8cf28dda5fff93949428bbd50d15345fb5cdcb (diff)
Merge screencastcommon into waylandintegration
Push buffers to stream based on framerate
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/remotedesktop.cpp12
-rw-r--r--src/remotedesktop.h4
-rw-r--r--src/screencast.cpp14
-rw-r--r--src/screencast.h3
-rw-r--r--src/screencastcommon.cpp126
-rw-r--r--src/screencastcommon.h56
-rw-r--r--src/screencaststream.cpp9
-rw-r--r--src/screencaststream.h1
-rw-r--r--src/waylandintegration.cpp163
-rw-r--r--src/waylandintegration.h6
-rw-r--r--src/waylandintegration_p.h16
12 files changed, 172 insertions, 239 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7f7e2d7..8c3499b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -25,7 +25,6 @@ if (SCREENCAST_ENABLED)
set (xdg_desktop_portal_kde_SRCS
${xdg_desktop_portal_kde_SRCS}
screencast.cpp
- screencastcommon.cpp
screencaststream.cpp
screencastwidget.cpp
screenchooserdialog.cpp
diff --git a/src/remotedesktop.cpp b/src/remotedesktop.cpp
index d0a55f9..ec137fc 100644
--- a/src/remotedesktop.cpp
+++ b/src/remotedesktop.cpp
@@ -30,15 +30,11 @@ Q_LOGGING_CATEGORY(XdgDesktopPortalKdeRemoteDesktop, "xdp-kde-remotedesktop")
RemoteDesktopPortal::RemoteDesktopPortal(QObject *parent)
: QDBusAbstractAdaptor(parent)
- , m_screenCastCommon(new ScreenCastCommon())
{
}
RemoteDesktopPortal::~RemoteDesktopPortal()
{
- if (m_screenCastCommon) {
- delete m_screenCastCommon;
- }
}
uint RemoteDesktopPortal::CreateSession(const QDBusObjectPath &handle,
@@ -60,7 +56,7 @@ uint RemoteDesktopPortal::CreateSession(const QDBusObjectPath &handle,
}
connect(session, &Session::closed, [this] () {
- m_screenCastCommon->stopStreaming();
+ WaylandIntegration::stopStreaming();
});
return 0;
@@ -128,7 +124,11 @@ uint RemoteDesktopPortal::Start(const QDBusObjectPath &handle,
if (session->screenSharingEnabled()) {
WaylandIntegration::WaylandOutput selectedOutput = WaylandIntegration::screens().value(remoteDesktopDialog->selectedScreens().first());
- QVariant streams = m_screenCastCommon->startStreaming(selectedOutput);
+ if (!WaylandIntegration::startStreaming(selectedOutput)) {
+ return 2;
+ }
+
+ QVariant streams = WaylandIntegration::streams();
if (!streams.isValid()) {
qCWarning(XdgDesktopPortalKdeRemoteDesktop()) << "Pipewire stream is not ready to be streamed";
diff --git a/src/remotedesktop.h b/src/remotedesktop.h
index 6668dad..8c4f404 100644
--- a/src/remotedesktop.h
+++ b/src/remotedesktop.h
@@ -119,10 +119,6 @@ public Q_SLOTS:
void NotifyTouchUp(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint slot);
-
-private:
- ScreenCastCommon *m_screenCastCommon;
-
};
#endif // XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_H
diff --git a/src/screencast.cpp b/src/screencast.cpp
index a5eaab9..7832198 100644
--- a/src/screencast.cpp
+++ b/src/screencast.cpp
@@ -30,15 +30,11 @@ Q_LOGGING_CATEGORY(XdgDesktopPortalKdeScreenCast, "xdp-kde-screencast")
ScreenCastPortal::ScreenCastPortal(QObject *parent)
: QDBusAbstractAdaptor(parent)
- , m_screenCastCommon(new ScreenCastCommon())
{
}
ScreenCastPortal::~ScreenCastPortal()
{
- if (m_screenCastCommon) {
- delete m_screenCastCommon;
- }
}
uint ScreenCastPortal::CreateSession(const QDBusObjectPath &handle,
@@ -62,9 +58,7 @@ uint ScreenCastPortal::CreateSession(const QDBusObjectPath &handle,
}
connect(session, &Session::closed, [this] () {
- if (m_screenCastCommon) {
- m_screenCastCommon->stopStreaming();
- }
+ WaylandIntegration::stopStreaming();
});
return 0;
@@ -155,7 +149,11 @@ uint ScreenCastPortal::Start(const QDBusObjectPath &handle,
if (screenDialog->exec()) {
WaylandIntegration::WaylandOutput selectedOutput = WaylandIntegration::screens().value(screenDialog->selectedScreens().first());
- QVariant streams = m_screenCastCommon->startStreaming(selectedOutput);
+ if (!WaylandIntegration::startStreaming(selectedOutput)) {
+ return 2;
+ }
+
+ QVariant streams = WaylandIntegration::streams();
if (!streams.isValid()) {
qCWarning(XdgDesktopPortalKdeScreenCast) << "Pipewire stream is not ready to be streamed";
diff --git a/src/screencast.h b/src/screencast.h
index 1a245ec..6d3df2d 100644
--- a/src/screencast.h
+++ b/src/screencast.h
@@ -64,9 +64,6 @@ public Q_SLOTS:
const QString &parent_window,
const QVariantMap &options,
QVariantMap &results);
-
-private:
- ScreenCastCommon *m_screenCastCommon;
};
#endif // XDG_DESKTOP_PORTAL_KDE_SCREENCAST_H
diff --git a/src/screencastcommon.cpp b/src/screencastcommon.cpp
deleted file mode 100644
index f691d8c..0000000
--- a/src/screencastcommon.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright © 2018 Red Hat, Inc
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Jan Grulich <[email protected]>
- */
-
-#include "screencastcommon.h"
-#include "screencaststream.h"
-
-#include <QDBusArgument>
-#include <QDBusMetaType>
-
-#include <QEventLoop>
-#include <QTimer>
-
-const QDBusArgument &operator >> (const QDBusArgument &arg, ScreenCastCommon::Stream &stream)
-{
- arg.beginStructure();
- arg >> stream.nodeId;
-
- arg.beginMap();
- while (!arg.atEnd()) {
- QString key;
- QVariant map;
- arg.beginMapEntry();
- arg >> key >> map;
- arg.endMapEntry();
- stream.map.insert(key, map);
- }
- arg.endMap();
- arg.endStructure();
-
- return arg;
-}
-
-const QDBusArgument &operator << (QDBusArgument &arg, const ScreenCastCommon::Stream &stream)
-{
- arg.beginStructure();
- arg << stream.nodeId;
- arg << stream.map;
- arg.endStructure();
-
- return arg;
-}
-
-Q_DECLARE_METATYPE(ScreenCastCommon::Stream);
-Q_DECLARE_METATYPE(ScreenCastCommon::Streams);
-
-ScreenCastCommon::ScreenCastCommon(QObject *parent)
- : QObject(parent)
- , m_streamingEnabled(false)
-{
- qDBusRegisterMetaType<ScreenCastCommon::Stream>();
- qDBusRegisterMetaType<ScreenCastCommon::Streams>();
-}
-
-ScreenCastCommon::~ScreenCastCommon()
-{
-}
-
-QVariant ScreenCastCommon::startStreaming(const WaylandIntegration::WaylandOutput &output)
-{
- m_stream = new ScreenCastStream(output.resolution());
- m_stream->init();
-
- connect(WaylandIntegration::waylandIntegration(), &WaylandIntegration::WaylandIntegration::newBuffer, m_stream, &ScreenCastStream::recordFrame);
-
- connect(m_stream, &ScreenCastStream::startStreaming, this, [this] {
- m_streamingEnabled = true;
- WaylandIntegration::startStreaming();
- });
-
- connect(m_stream, &ScreenCastStream::stopStreaming, this, &ScreenCastCommon::stopStreaming);
-
- bool streamReady = false;
- QEventLoop loop;
- connect(m_stream, &ScreenCastStream::streamReady, this, [&loop, &streamReady] {
- loop.quit();
- streamReady = true;
- });
-
- // HACK wait for stream to be ready
- QTimer::singleShot(3000, &loop, &QEventLoop::quit);
- loop.exec();
-
- disconnect(m_stream, &ScreenCastStream::streamReady, this, nullptr);
-
- if (!streamReady) {
- return QVariant();
- }
-
- // TODO support multiple outputs
-
- WaylandIntegration::bindOutput(output.waylandOutputName(), output.waylandOutputVersion());
-
- Stream stream;
- stream.nodeId = m_stream->nodeId();
- stream.map = QVariantMap({{QLatin1String("size"), output.resolution()}});
- return QVariant::fromValue<ScreenCastCommon::Streams>({stream});
-}
-
-void ScreenCastCommon::stopStreaming()
-{
- if (m_streamingEnabled) {
- WaylandIntegration::stopStreaming();
- m_streamingEnabled = false;
- if (m_stream) {
- delete m_stream;
- m_stream = nullptr;
- }
- }
-}
diff --git a/src/screencastcommon.h b/src/screencastcommon.h
deleted file mode 100644
index 6d0f96b..0000000
--- a/src/screencastcommon.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright © 2018 Red Hat, Inc
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Jan Grulich <[email protected]>
- */
-
-#ifndef XDG_DESKTOP_PORTAL_KDE_SCREENCAST_COMMON_H
-#define XDG_DESKTOP_PORTAL_KDE_SCREENCAST_COMMON_H
-
-#include <QObject>
-#include <QMap>
-#include <QSize>
-
-#include "waylandintegration.h"
-
-class ScreenCastStream;
-
-class ScreenCastCommon : public QObject
-{
-public:
- typedef struct {
- uint nodeId;
- QVariantMap map;
- } Stream;
- typedef QList<Stream> Streams;
-
- explicit ScreenCastCommon(QObject *parent = nullptr);
- ~ScreenCastCommon();
-
- QVariant startStreaming(const WaylandIntegration::WaylandOutput &output);
-
-public Q_SLOTS:
- void stopStreaming();
-
-private:
- bool m_streamingEnabled;
- ScreenCastStream *m_stream;
-};
-
-#endif // XDG_DESKTOP_PORTAL_KDE_SCREENCAST_COMMON_H
-
-
diff --git a/src/screencaststream.cpp b/src/screencaststream.cpp
index 3a91f70..a8ea4d5 100644
--- a/src/screencaststream.cpp
+++ b/src/screencaststream.cpp
@@ -311,6 +311,15 @@ void ScreenCastStream::init()
pw_remote_connect(pwRemote);
}
+uint ScreenCastStream::framerate()
+{
+ if (pwStream) {
+ return videoFormat.max_framerate.num / videoFormat.max_framerate.denom;
+ }
+
+ return 0;
+}
+
uint ScreenCastStream::nodeId()
{
if (pwStream) {
diff --git a/src/screencaststream.h b/src/screencaststream.h
index 88fd767..d3a7dad 100644
--- a/src/screencaststream.h
+++ b/src/screencaststream.h
@@ -66,6 +66,7 @@ public:
// Public
void init();
+ uint framerate();
uint nodeId();
// Public because we need access from static functions
diff --git a/src/waylandintegration.cpp b/src/waylandintegration.cpp
index 5a702b9..687ce3d 100644
--- a/src/waylandintegration.cpp
+++ b/src/waylandintegration.cpp
@@ -20,6 +20,10 @@
#include "waylandintegration.h"
#include "waylandintegration_p.h"
+#include "screencaststream.h"
+
+#include <QDBusArgument>
+#include <QDBusMetaType>
#include <QEventLoop>
#include <QLoggingCategory>
@@ -54,14 +58,9 @@ bool WaylandIntegration::isEGLInitialized()
return globalWaylandIntegration->isEGLInitialized();
}
-void WaylandIntegration::bindOutput(int outputName, int outputVersion)
-{
- globalWaylandIntegration->bindOutput(outputName, outputVersion);
-}
-
-void WaylandIntegration::startStreaming()
+bool WaylandIntegration::startStreaming(const WaylandOutput &output)
{
- globalWaylandIntegration->startStreaming();
+ return globalWaylandIntegration->startStreaming(output);
}
void WaylandIntegration::stopStreaming()
@@ -74,6 +73,11 @@ QMap<quint32, WaylandIntegration::WaylandOutput> WaylandIntegration::screens()
return globalWaylandIntegration->screens();
}
+QVariant WaylandIntegration::streams()
+{
+ return globalWaylandIntegration->streams();
+}
+
WaylandIntegration::WaylandIntegration * WaylandIntegration::waylandIntegration()
{
return globalWaylandIntegration;
@@ -126,6 +130,39 @@ void WaylandIntegration::WaylandOutput::setOutputType(const QString &type)
}
}
+const QDBusArgument &operator >> (const QDBusArgument &arg, WaylandIntegration::WaylandIntegrationPrivate::Stream &stream)
+{
+ arg.beginStructure();
+ arg >> stream.nodeId;
+
+ arg.beginMap();
+ while (!arg.atEnd()) {
+ QString key;
+ QVariant map;
+ arg.beginMapEntry();
+ arg >> key >> map;
+ arg.endMapEntry();
+ stream.map.insert(key, map);
+ }
+ arg.endMap();
+ arg.endStructure();
+
+ return arg;
+}
+
+const QDBusArgument &operator << (QDBusArgument &arg, const WaylandIntegration::WaylandIntegrationPrivate::Stream &stream)
+{
+ arg.beginStructure();
+ arg << stream.nodeId;
+ arg << stream.map;
+ arg.endStructure();
+
+ return arg;
+}
+
+Q_DECLARE_METATYPE(WaylandIntegration::WaylandIntegrationPrivate::Stream)
+Q_DECLARE_METATYPE(WaylandIntegration::WaylandIntegrationPrivate::Streams)
+
WaylandIntegration::WaylandIntegrationPrivate::WaylandIntegrationPrivate()
: WaylandIntegration()
, m_eglInitialized(false)
@@ -135,6 +172,8 @@ WaylandIntegration::WaylandIntegrationPrivate::WaylandIntegrationPrivate()
, m_registry(nullptr)
, m_remoteAccessManager(nullptr)
{
+ qDBusRegisterMetaType<WaylandIntegrationPrivate::Stream>();
+ qDBusRegisterMetaType<WaylandIntegrationPrivate::Streams>();
}
WaylandIntegration::WaylandIntegrationPrivate::~WaylandIntegrationPrivate()
@@ -160,19 +199,44 @@ void WaylandIntegration::WaylandIntegrationPrivate::bindOutput(int outputName, i
m_bindOutputs << output;
}
-void WaylandIntegration::WaylandIntegrationPrivate::startStreaming()
+bool WaylandIntegration::WaylandIntegrationPrivate::startStreaming(const WaylandOutput &output)
{
- m_streamingEnabled = true;
+ m_stream = new ScreenCastStream(output.resolution());
+ m_stream->init();
- if (!m_registryInitialized) {
- qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Cannot start stream because registry is not initialized yet";
- return;
+ connect(m_stream, &ScreenCastStream::startStreaming, this, [this, output] {
+ m_streamingEnabled = true;
+ bindOutput(output.waylandOutputName(), output.waylandOutputVersion());
+ });
+
+ connect(m_stream, &ScreenCastStream::stopStreaming, this, &WaylandIntegrationPrivate::stopStreaming);
+
+ bool streamReady = false;
+ QEventLoop loop;
+ connect(m_stream, &ScreenCastStream::streamReady, this, [&loop, &streamReady] {
+ loop.quit();
+ streamReady = true;
+ });
+
+ // HACK wait for stream to be ready
+ QTimer::singleShot(3000, &loop, &QEventLoop::quit);
+ loop.exec();
+
+ disconnect(m_stream, &ScreenCastStream::streamReady, this, nullptr);
+
+ if (!streamReady) {
+ delete m_stream;
+ m_stream = nullptr;
+ return false;
}
+
+ // TODO support multiple outputs
+
if (m_registry->hasInterface(KWayland::Client::Registry::Interface::RemoteAccessManager)) {
KWayland::Client::Registry::AnnouncedInterface interface = m_registry->interface(KWayland::Client::Registry::Interface::RemoteAccessManager);
if (!interface.name && !interface.version) {
- qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Cannot start stream because remote access interface is not initialized yet";
- return;
+ qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to start streaming: remote access manager interface is not initialized yet";
+ return false;
}
m_remoteAccessManager = m_registry->createRemoteAccessManager(interface.name, interface.version);
connect(m_remoteAccessManager, &KWayland::Client::RemoteAccessManager::bufferReady, this, [this] (const void *output, const KWayland::Client::RemoteBuffer * rbuf) {
@@ -181,20 +245,34 @@ void WaylandIntegration::WaylandIntegrationPrivate::startStreaming()
processBuffer(rbuf);
});
});
+ m_output = output.waylandOutputName();
+ return true;
}
+
+ delete m_stream;
+ m_stream = nullptr;
+
+ qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to start streaming: no remote access manager interface";
+ return false;
}
void WaylandIntegration::WaylandIntegrationPrivate::stopStreaming()
{
- if (m_remoteAccessManager) {
- m_remoteAccessManager->release();
- m_remoteAccessManager->destroy();
- }
-
- m_streamingEnabled = false;
+ if (m_streamingEnabled) {
+ // First unbound outputs and destroy remote access manager so we no longer recieve buffers
+ if (m_remoteAccessManager) {
+ m_remoteAccessManager->release();
+ m_remoteAccessManager->destroy();
+ }
+ qDeleteAll(m_bindOutputs);
+ m_bindOutputs.clear();
- qDeleteAll(m_bindOutputs);
- m_bindOutputs.clear();
+ if (m_stream) {
+ delete m_stream;
+ m_stream = nullptr;
+ }
+ m_streamingEnabled = false;
+ }
}
QMap<quint32, WaylandIntegration::WaylandOutput> WaylandIntegration::WaylandIntegrationPrivate::screens()
@@ -202,6 +280,14 @@ QMap<quint32, WaylandIntegration::WaylandOutput> WaylandIntegration::WaylandInte
return m_outputMap;
}
+QVariant WaylandIntegration::WaylandIntegrationPrivate::streams()
+{
+ Stream stream;
+ stream.nodeId = m_stream->nodeId();
+ stream.map = QVariantMap({{QLatin1String("size"), m_outputMap.value(m_output).resolution()}});
+ return QVariant::fromValue<WaylandIntegrationPrivate::Streams>({stream});
+}
+
void WaylandIntegration::WaylandIntegrationPrivate::initDrm()
{
m_drmFd = open("/dev/dri/renderD128", O_RDWR);
@@ -275,8 +361,6 @@ void WaylandIntegration::WaylandIntegrationPrivate::initEGL()
void WaylandIntegration::WaylandIntegrationPrivate::initWayland()
{
- qCDebug(XdgDesktopPortalKdeWaylandIntegration) << "InitWayland()";
-
m_thread = new QThread(this);
m_connection = new KWayland::Client::ConnectionThread;
@@ -361,15 +445,25 @@ void WaylandIntegration::WaylandIntegrationPrivate::processBuffer(const KWayland
return;
}
+ if (m_lastFrameTime.isValid() &&
+ m_lastFrameTime.msecsTo(QDateTime::currentDateTime()) < (1000 / m_stream->framerate())) {
+ close(gbmHandle);
+ return;
+ }
+
if (!gbm_device_is_format_supported(m_gbmDevice, format, GBM_BO_USE_SCANOUT)) {
- qCritical() << "GBM format is not supported by device!";
+ qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to process buffer: GBM format is not supported by device!";
+ close(gbmHandle);
+ return;
}
// import GBM buffer that was passed from KWin
gbm_import_fd_data importInfo = {gbmHandle, width, height, stride, format};
gbm_bo *imported = gbm_bo_import(m_gbmDevice, GBM_BO_IMPORT_FD, &importInfo, GBM_BO_USE_SCANOUT);
if (!imported) {
- qCritical() << "Cannot import passed GBM fd:" << strerror(errno);
+ qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to process buffer: Cannot import passed GBM fd - " << strerror(errno);
+ close(gbmHandle);
+ return;
}
// bind context to render thread
@@ -377,10 +471,16 @@ void WaylandIntegration::WaylandIntegrationPrivate::processBuffer(const KWayland
// create EGL image from imported BO
EGLImageKHR image = eglCreateImageKHR(m_egl.display, nullptr, EGL_NATIVE_PIXMAP_KHR, imported, nullptr);
+
+ // We can already close gbm handle
+ gbm_bo_destroy(imported);
+ close(gbmHandle);
+
if (image == EGL_NO_IMAGE_KHR) {
- qCritical() << "Error creating EGLImageKHR" << formatGLError(glGetError());
+ qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to process buffer: Error creating EGLImageKHR - " << formatGLError(glGetError());
return;
}
+
// create GL 2D texture for framebuffer
GLuint texture;
glGenTextures(1, &texture);
@@ -398,7 +498,7 @@ void WaylandIntegration::WaylandIntegrationPrivate::processBuffer(const KWayland
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
const GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
- qCritical() << "glCheckFramebufferStatus failed:" << formatGLError(glGetError());
+ qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to process buffer: glCheckFramebufferStatus failed - " << formatGLError(glGetError());
glDeleteTextures(1, &texture);
glDeleteFramebuffers(1, &framebuffer);
eglDestroyImageKHR(m_egl.display, image);
@@ -409,16 +509,15 @@ void WaylandIntegration::WaylandIntegrationPrivate::processBuffer(const KWayland
glViewport(0, 0, width, height);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, capture->bits());
- Q_EMIT newBuffer(capture->bits());
+ if (m_stream->recordFrame(capture->bits())) {
+ m_lastFrameTime = QDateTime::currentDateTime();
+ }
- gbm_bo_destroy(imported);
glDeleteTextures(1, &texture);
glDeleteFramebuffers(1, &framebuffer);
eglDestroyImageKHR(m_egl.display, image);
delete capture;
-
- close(gbmHandle);
}
void WaylandIntegration::WaylandIntegrationPrivate::setupRegistry()
diff --git a/src/waylandintegration.h b/src/waylandintegration.h
index 1395f5e..df019e1 100644
--- a/src/waylandintegration.h
+++ b/src/waylandintegration.h
@@ -23,6 +23,7 @@
#include <QObject>
#include <QSize>
+#include <QVariant>
#include <QtCore/QtGlobal>
@@ -77,10 +78,11 @@ Q_SIGNALS:
bool isEGLInitialized();
- void bindOutput(int outputName, int outputVersion);
- void startStreaming();
+ bool startStreaming(const WaylandOutput &output);
void stopStreaming();
+
QMap<quint32, WaylandOutput> screens();
+ QVariant streams();
WaylandIntegration *waylandIntegration();
diff --git a/src/waylandintegration_p.h b/src/waylandintegration_p.h
index afc14fc..65479b9 100644
--- a/src/waylandintegration_p.h
+++ b/src/waylandintegration_p.h
@@ -23,6 +23,7 @@
#include "waylandintegration.h"
+#include <QDateTime>
#include <QObject>
#include <QMap>
@@ -31,6 +32,8 @@
#include <epoxy/egl.h>
#include <epoxy/gl.h>
+class ScreenCastStream;
+
namespace KWayland {
namespace Client {
class ConnectionThread;
@@ -50,6 +53,12 @@ class WaylandIntegrationPrivate : public WaylandIntegration::WaylandIntegration
{
Q_OBJECT
public:
+ typedef struct {
+ uint nodeId;
+ QVariantMap map;
+ } Stream;
+ typedef QList<Stream> Streams;
+
WaylandIntegrationPrivate();
~WaylandIntegrationPrivate();
@@ -60,9 +69,10 @@ public:
bool isEGLInitialized() const;
void bindOutput(int outputName, int outputVersion);
- void startStreaming();
+ bool startStreaming(const WaylandOutput &output);
void stopStreaming();
QMap<quint32, WaylandOutput> screens();
+ QVariant streams();
protected Q_SLOTS:
void addOutput(quint32 name, quint32 version);
@@ -75,6 +85,10 @@ private:
bool m_streamingEnabled;
bool m_registryInitialized;
+ quint32 m_output;
+ QDateTime m_lastFrameTime;
+ ScreenCastStream *m_stream;
+
QThread *m_thread;
QMap<quint32, WaylandOutput> m_outputMap;