Commit 530ed29a authored by Jan Grulich's avatar Jan Grulich

Merge screencastcommon into waylandintegration

Push buffers to stream based on framerate
parent 3f8cf28d
......@@ -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
......
......@@ -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";
......
......@@ -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
......
......@@ -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";
......
......@@ -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
......
/*
* 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 <jgrulich@redhat.com>
*/
#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;
}
}
}
/*
* 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 <jgrulich@redhat.com>
*/
#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
......@@ -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) {
......
......@@ -66,6 +66,7 @@ public:
// Public
void init();
uint framerate();
uint nodeId();
// Public because we need access from static functions
......
This diff is collapsed.
......@@ -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();
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment