Skip to content

Commit

Permalink
Pipewire DMA & EGL hardware support 2 (Wayland/x11 grabber) (#556)
Browse files Browse the repository at this point in the history
  • Loading branch information
awawa-dev committed Oct 26, 2023
1 parent 8143d8b commit bcf1471
Show file tree
Hide file tree
Showing 14 changed files with 113 additions and 149 deletions.
2 changes: 0 additions & 2 deletions include/base/Grabber.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@ class Grabber : public DetectionAutomatic, public DetectionManual
};

public slots:
virtual bool isRunning();

virtual bool start() = 0;

virtual void stop() = 0;
Expand Down
1 change: 0 additions & 1 deletion include/base/SystemWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public slots:
void setHdrToneMappingEnabled(int mode);
void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
virtual void stateChanged(bool state);
bool isRunning();

protected:
virtual QString getGrabberInfo();
Expand Down
12 changes: 5 additions & 7 deletions include/grabber/PipewireGrabber.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <utils/PixelFormat.h>
#include <base/Grabber.h>
#include <utils/Components.h>
#include <grabber/smartPipewire.h>

// general JPEG decoder includes
#include <QImage>
Expand All @@ -43,11 +42,11 @@ class PipewireGrabber : public Grabber

void stateChanged(bool state);

static void callbackFunction(const PipewireImage& frame);
private slots:

public slots:
void grabFrame();

void grabFrame(const PipewireImage& data);
public slots:

bool start() override;

Expand All @@ -57,8 +56,6 @@ public slots:

void newWorkerFrameError(unsigned int workerIndex, QString error, quint64 sourceCount) override {};

bool isRunning() override;

private:
QString GetSharedLut();

Expand All @@ -78,11 +75,12 @@ public slots:

private:
QString _configurationPath;
QTimer _timer;
QSemaphore _semaphore;

void* _library;
int _actualDisplay;
bool _isActive;
bool _storedToken;
bool _versionCheck;
bool _hasFrame;
};
1 change: 0 additions & 1 deletion include/grabber/PipewireWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class PipewireWrapper : public SystemWrapper

public slots:
void stateChanged(bool state) override;
void processFrame(const PipewireImage& frame);

protected:
QString getGrabberInfo() override;
Expand Down
11 changes: 5 additions & 6 deletions include/grabber/smartPipewire.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ struct PipewireImage
bool isError;
int width, height, stride;
bool isOrderRgb;
uint8_t* data;
uint8_t* data = nullptr;
};

typedef int (*pipewire_callback_func)(const PipewireImage& frame);

extern "C" const char* getPipewireToken();
extern "C" const char* getPipewireError();
extern "C" bool hasPipewire();
extern "C" void initPipewireDisplay(const char* restorationToken, uint32_t requestedFPS, pipewire_callback_func callback);
extern "C" void uniniPipewireDisplay();
extern "C" void initPipewireDisplay(const char* restorationToken, uint32_t requestedFPS);
extern "C" void uninitPipewireDisplay();
extern "C" PipewireImage getFramePipewire();
extern "C" void releaseFramePipewire();

5 changes: 0 additions & 5 deletions sources/base/Grabber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -927,8 +927,3 @@ QString Grabber::getConfigurationPath()
{
return _configurationPath;
}

bool Grabber::isRunning()
{
return false;
}
2 changes: 1 addition & 1 deletion sources/base/HyperHdrInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ void HyperHdrInstance::updateResult(std::vector<ColorRgb> _ledBuffer)
else if (prevToken != (_computeStats.token = PerformanceCounters::currentToken()))
{

if (diff >= 59000)
if (diff >= 59000 && diff <= 65000)
emit PerformanceCounters::getInstance()->newCounter(
PerformanceReport(static_cast<int>(PerformanceReportType::INSTANCE), _computeStats.token, _name, _computeStats.total / qMax(diff/1000.0, 1.0), _computeStats.total, 0, 0, getInstanceIndex()));

Expand Down
3 changes: 0 additions & 3 deletions sources/base/SystemControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,6 @@ void SystemControl::handleCompStateChangeRequest(hyperhdr::Components component,

void SystemControl::setSysInactive()
{
if (SystemWrapper::getInstance() != nullptr && SystemWrapper::getInstance()->isRunning())
return;

if (!_alive)
_hyperhdr->setInputInactive(_sysCaptPrio);

Expand Down
10 changes: 0 additions & 10 deletions sources/base/SystemWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,3 @@ QJsonObject SystemWrapper::getJsonInfo()

return systemDevice;
}

bool SystemWrapper::isRunning()
{
if (_grabber != NULL)
{
return _grabber->isRunning();
}

return false;
}
129 changes: 63 additions & 66 deletions sources/grabber/pipewire/PipewireGrabber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,27 +47,31 @@
#include <QCoreApplication>

#include <grabber/PipewireGrabber.h>
#include <base/SystemWrapper.h>
#include <grabber/PipewireWrapper.h>
#include <grabber/smartPipewire.h>
#include <utils/ColorSys.h>
#include <dlfcn.h>

bool (*_hasPipewire)() = nullptr;
const char* (*_getPipewireError)() = nullptr;
void (*_initPipewireDisplay)(const char* restorationToken, uint32_t requestedFPS, pipewire_callback_func callback) = nullptr;
void (*_initPipewireDisplay)(const char* restorationToken, uint32_t requestedFPS) = nullptr;
void (*_uninitPipewireDisplay)() = nullptr;
PipewireImage (*_getFramePipewire)() = nullptr;
void (*_releaseFramePipewire)() = nullptr;
const char* (*_getPipewireToken)() = nullptr;

PipewireGrabber::PipewireGrabber(const QString& device, const QString& configurationPath)
: Grabber("PIPEWIRE_SYSTEM:" + device.left(14))
, _configurationPath(configurationPath)
, _semaphore(1)
, _library(nullptr)
, _actualDisplay(0)
, _isActive(false)
, _storedToken(false)
, _versionCheck(false)
, _hasFrame(false)
{
_timer.setTimerType(Qt::PreciseTimer);
connect(&_timer, &QTimer::timeout, this, &PipewireGrabber::grabFrame);

// Load library
_library = dlopen("libsmartPipewire.so", RTLD_NOW);

Expand All @@ -76,13 +80,15 @@ PipewireGrabber::PipewireGrabber(const QString& device, const QString& configura
_getPipewireToken = (const char* (*)()) dlsym(_library, "getPipewireToken");
_getPipewireError = (const char* (*)()) dlsym(_library, "getPipewireError");
_hasPipewire = (bool (*)()) dlsym(_library, "hasPipewire");
_initPipewireDisplay = (void (*)(const char*, uint32_t, pipewire_callback_func)) dlsym(_library, "initPipewireDisplay");
_uninitPipewireDisplay = (void (*)()) dlsym(_library, "uniniPipewireDisplay");
_initPipewireDisplay = (void (*)(const char*, uint32_t)) dlsym(_library, "initPipewireDisplay");
_uninitPipewireDisplay = (void (*)()) dlsym(_library, "uninitPipewireDisplay");
_getFramePipewire = (PipewireImage (*)()) dlsym(_library, "getFramePipewire");
_releaseFramePipewire = (void (*)()) dlsym(_library, "releaseFramePipewire");
}
else
Warning(_log, "Could not load Pipewire proxy library. Error: %s", dlerror());

if (_library && (_getPipewireToken == nullptr || _hasPipewire == nullptr || _initPipewireDisplay == nullptr || _uninitPipewireDisplay == nullptr ))
if (_library && (_getPipewireToken == nullptr || _hasPipewire == nullptr || _releaseFramePipewire == nullptr || _initPipewireDisplay == nullptr || _uninitPipewireDisplay == nullptr || _getFramePipewire == nullptr))
{
Error(_log, "Could not load Pipewire proxy library definition. Error: %s", dlerror());

Expand Down Expand Up @@ -147,14 +153,14 @@ void PipewireGrabber::uninit()
Debug(_log, "Uninit grabber: %s", QSTRING_CSTR(_deviceName));
}


_initialized = false;
}

bool PipewireGrabber::init()
{
Debug(_log, "init");

_hasFrame = false;

if (!_initialized)
{
Expand Down Expand Up @@ -230,6 +236,8 @@ bool PipewireGrabber::start()
{
if (init())
{
_timer.setInterval(1000/_fps);
_timer.start();
Info(_log, "Started");
return true;
}
Expand All @@ -246,11 +254,14 @@ void PipewireGrabber::stop()
{
if (_initialized)
{
_semaphore.acquire();
_timer.stop();

_uninitPipewireDisplay();
_isActive = false;
_initialized = false;
_hasFrame = false;

_semaphore.release();
Info(_log, "Stopped");
}
}
Expand All @@ -268,7 +279,7 @@ bool PipewireGrabber::init_device(int _display)
token = "";
else
Info(_log, "Loading restoration token: %s", QSTRING_CSTR(maskToken(token)));
_initPipewireDisplay(token.toLatin1().constData(), _fps, (pipewire_callback_func) &PipewireGrabber::callbackFunction);
_initPipewireDisplay(token.toLatin1().constData(), _fps);

_isActive = true;

Expand Down Expand Up @@ -302,60 +313,67 @@ void PipewireGrabber::stateChanged(bool state)
}
}

void PipewireGrabber::grabFrame(const PipewireImage& data)
void PipewireGrabber::grabFrame()
{
bool stopNow = false;

if (_initialized && _isActive)
if (_semaphore.tryAcquire())
{
if (!_versionCheck)
if (_initialized && _isActive)
{
if (data.version >= 4)
Info(_log, "Portal protocol version: %i", data.version);
else
Warning(_log, "Legacy portal protocol version: %i. To enjoy persistant autorization since version 4, you should update xdg-desktop-portal at least to version 1.12.1 *AND* provide backend that can implement it (for example newest xdg-desktop-portal-gnome).", data.version);
PipewireImage data = _getFramePipewire();

_versionCheck = true;
}
if (!_versionCheck)
{
if (data.version >= 4)
Info(_log, "Portal protocol version: %i", data.version);
else
Warning(_log, "Legacy portal protocol version: %i. To enjoy persistant autorization since version 4, you should update xdg-desktop-portal at least to version 1.12.1 *AND* provide backend that can implement it (for example newest xdg-desktop-portal-gnome).", data.version);

_versionCheck = true;
}

if (!_storedToken && !data.isError)
{
QString token = QString("%1").arg(_getPipewireToken());

if (!token.isEmpty())
if (!_storedToken && !data.isError)
{
AuthManager* instance = AuthManager::getInstance();
QString token = QString("%1").arg(_getPipewireToken());

Info(_log, "Saving restoration token: %s", QSTRING_CSTR(maskToken(token)));
if (!token.isEmpty())
{
AuthManager* instance = AuthManager::getInstance();

instance->savePipewire(token);
Info(_log, "Saving restoration token: %s", QSTRING_CSTR(maskToken(token)));

_storedToken = true;
}
}
instance->savePipewire(token);

_storedToken = true;
}
}

if (data.data == nullptr)
{
if (data.isError)

if (data.data == nullptr)
{
QString err = QString("%1").arg(_getPipewireError());
Error(_log, "Could not capture pipewire frame: %s", QSTRING_CSTR(err));
stopNow = true;
if (data.isError)
{
QString err = QString("%1").arg(_getPipewireError());
Error(_log, "Could not capture pipewire frame: %s", QSTRING_CSTR(err));
stopNow = true;
}
}
}
else
{
_hasFrame = true;
_actualWidth = data.width;
_actualHeight = data.height;

if (data.isOrderRgb)
processSystemFrameRGBA(data.data, data.stride);
else
processSystemFrameBGRA(data.data, data.stride);
{
_actualWidth = data.width;
_actualHeight = data.height;

if (data.isOrderRgb)
processSystemFrameRGBA(data.data);
else
processSystemFrameBGRA(data.data);

_releaseFramePipewire();
}
}
_semaphore.release();
}

if (stopNow)
Expand All @@ -372,24 +390,3 @@ void PipewireGrabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigne
_cropTop = cropTop;
_cropBottom = cropBottom;
}

void PipewireGrabber::callbackFunction(const PipewireImage& frame)
{
if (SystemWrapper::getInstance() == nullptr)
return;

PipewireWrapper* wrapper = dynamic_cast<PipewireWrapper*>(SystemWrapper::getInstance());

if (wrapper != NULL)
{
if (QThread::currentThread() == wrapper->thread())
wrapper->processFrame(frame);
else
QMetaObject::invokeMethod(wrapper, "processFrame", Qt::ConnectionType::BlockingQueuedConnection, Q_ARG(const PipewireImage&, frame));
}
}

bool PipewireGrabber::isRunning()
{
return _initialized && _hasFrame;
}
Loading

0 comments on commit bcf1471

Please sign in to comment.