2016-08-11 07:13:55 +02:00
|
|
|
// Hyperion includes
|
|
|
|
#include <hyperion/GrabberWrapper.h>
|
2017-08-12 07:55:32 +02:00
|
|
|
#include <hyperion/Grabber.h>
|
2017-02-17 08:33:34 +01:00
|
|
|
#include <HyperionConfig.h>
|
2016-08-11 07:13:55 +02:00
|
|
|
|
2019-01-01 19:47:07 +01:00
|
|
|
// utils includes
|
|
|
|
#include <utils/GlobalSignals.h>
|
|
|
|
|
2018-12-27 23:11:32 +01:00
|
|
|
// qt
|
|
|
|
#include <QTimer>
|
|
|
|
|
2020-04-17 16:59:20 +02:00
|
|
|
GrabberWrapper* GrabberWrapper::instance = nullptr;
|
|
|
|
|
2018-12-27 23:11:32 +01:00
|
|
|
GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned width, unsigned height, const unsigned updateRate_Hz)
|
2016-08-11 07:13:55 +02:00
|
|
|
: _grabberName(grabberName)
|
2018-12-27 23:11:32 +01:00
|
|
|
, _timer(new QTimer(this))
|
2017-08-12 07:55:32 +02:00
|
|
|
, _updateInterval_ms(1000/updateRate_Hz)
|
2017-02-17 08:33:34 +01:00
|
|
|
, _log(Logger::getInstance(grabberName))
|
2017-08-12 07:55:32 +02:00
|
|
|
, _ggrabber(ggrabber)
|
|
|
|
, _image(0,0)
|
2016-08-11 07:13:55 +02:00
|
|
|
{
|
2020-04-17 16:59:20 +02:00
|
|
|
GrabberWrapper::instance = this;
|
|
|
|
|
2017-08-12 07:55:32 +02:00
|
|
|
// Configure the timer to generate events every n milliseconds
|
2018-12-27 23:11:32 +01:00
|
|
|
_timer->setInterval(_updateInterval_ms);
|
2016-08-11 07:13:55 +02:00
|
|
|
|
2017-08-12 07:55:32 +02:00
|
|
|
_image.resize(width, height);
|
2017-11-22 00:52:55 +01:00
|
|
|
|
2018-12-27 23:11:32 +01:00
|
|
|
connect(_timer, &QTimer::timeout, this, &GrabberWrapper::action);
|
2019-01-01 19:47:07 +01:00
|
|
|
|
|
|
|
// connect the image forwarding
|
2019-07-14 22:43:22 +02:00
|
|
|
(_grabberName.startsWith("V4L"))
|
2019-01-01 19:47:07 +01:00
|
|
|
? connect(this, &GrabberWrapper::systemImage, GlobalSignals::getInstance(), &GlobalSignals::setV4lImage)
|
|
|
|
: connect(this, &GrabberWrapper::systemImage, GlobalSignals::getInstance(), &GlobalSignals::setSystemImage);
|
2020-03-26 17:49:36 +01:00
|
|
|
|
|
|
|
// listen for source requests
|
|
|
|
connect(GlobalSignals::getInstance(), &GlobalSignals::requestSource, this, &GrabberWrapper::handleSourceRequest);
|
2016-08-11 07:13:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
GrabberWrapper::~GrabberWrapper()
|
|
|
|
{
|
2020-07-12 18:27:24 +02:00
|
|
|
stop();
|
2017-02-17 08:33:34 +01:00
|
|
|
Debug(_log,"Close grabber: %s", QSTRING_CSTR(_grabberName));
|
2016-08-11 07:13:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GrabberWrapper::start()
|
|
|
|
{
|
|
|
|
// Start the timer with the pre configured interval
|
2020-03-26 17:49:36 +01:00
|
|
|
Debug(_log,"Grabber start()");
|
2018-12-27 23:11:32 +01:00
|
|
|
_timer->start();
|
|
|
|
return _timer->isActive();
|
2016-08-11 07:13:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void GrabberWrapper::stop()
|
|
|
|
{
|
2020-07-12 18:27:24 +02:00
|
|
|
if (_timer->isActive())
|
|
|
|
{
|
|
|
|
// Stop the timer, effectivly stopping the process
|
|
|
|
Debug(_log,"Grabber stop()");
|
|
|
|
_timer->stop();
|
|
|
|
}
|
2016-10-10 18:29:54 +02:00
|
|
|
}
|
2017-02-17 08:33:34 +01:00
|
|
|
|
2020-07-23 16:50:37 +02:00
|
|
|
bool GrabberWrapper::isActive() const
|
|
|
|
{
|
|
|
|
return _timer->isActive();
|
|
|
|
}
|
|
|
|
|
2017-02-17 08:33:34 +01:00
|
|
|
QStringList GrabberWrapper::availableGrabbers()
|
|
|
|
{
|
|
|
|
QStringList grabbers;
|
|
|
|
|
|
|
|
#ifdef ENABLE_DISPMANX
|
|
|
|
grabbers << "dispmanx";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_V4L2
|
|
|
|
grabbers << "v4l2";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_FB
|
|
|
|
grabbers << "framebuffer";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_AMLOGIC
|
|
|
|
grabbers << "amlogic";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_OSX
|
|
|
|
grabbers << "osx";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_X11
|
|
|
|
grabbers << "x11";
|
|
|
|
#endif
|
|
|
|
|
2020-08-03 12:31:39 +02:00
|
|
|
#ifdef ENABLE_XCB
|
|
|
|
grabbers << "xcb";
|
|
|
|
#endif
|
|
|
|
|
2019-01-06 19:49:56 +01:00
|
|
|
#ifdef ENABLE_QT
|
|
|
|
grabbers << "qt";
|
|
|
|
#endif
|
|
|
|
|
2017-02-17 08:33:34 +01:00
|
|
|
return grabbers;
|
|
|
|
}
|
2017-08-12 07:55:32 +02:00
|
|
|
|
2018-12-27 23:11:32 +01:00
|
|
|
void GrabberWrapper::setVideoMode(const VideoMode& mode)
|
2017-08-12 07:55:32 +02:00
|
|
|
{
|
|
|
|
if (_ggrabber != nullptr)
|
|
|
|
{
|
|
|
|
Info(_log,"setvideomode");
|
|
|
|
_ggrabber->setVideoMode(mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GrabberWrapper::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom)
|
|
|
|
{
|
|
|
|
_ggrabber->setCropping(cropLeft, cropRight, cropTop, cropBottom);
|
|
|
|
}
|
|
|
|
|
2020-07-23 16:50:37 +02:00
|
|
|
void GrabberWrapper::updateTimer(int interval)
|
|
|
|
{
|
|
|
|
if(_updateInterval_ms != interval)
|
|
|
|
{
|
|
|
|
_updateInterval_ms = interval;
|
|
|
|
|
|
|
|
const bool& timerWasActive = _timer->isActive();
|
|
|
|
_timer->stop();
|
|
|
|
_timer->setInterval(_updateInterval_ms);
|
|
|
|
|
|
|
|
if(timerWasActive)
|
|
|
|
_timer->start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-27 23:11:32 +01:00
|
|
|
void GrabberWrapper::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
|
2017-08-12 07:55:32 +02:00
|
|
|
{
|
2020-07-23 16:50:37 +02:00
|
|
|
if(type == settings::SYSTEMCAPTURE && !_grabberName.startsWith("V4L"))
|
2018-12-27 23:11:32 +01:00
|
|
|
{
|
|
|
|
// extract settings
|
2019-05-03 17:54:43 +02:00
|
|
|
const QJsonObject& obj = config.object();
|
2018-12-27 23:11:32 +01:00
|
|
|
|
2020-07-23 16:50:37 +02:00
|
|
|
// width/height
|
|
|
|
_ggrabber->setWidthHeight(obj["width"].toInt(96), obj["height"].toInt(96));
|
|
|
|
|
|
|
|
// display index for MAC
|
|
|
|
_ggrabber->setDisplayIndex(obj["display"].toInt(0));
|
|
|
|
|
|
|
|
// device path for Framebuffer
|
|
|
|
_ggrabber->setDevicePath(obj["device"].toString("/dev/fb0"));
|
|
|
|
|
|
|
|
// pixel decimation for x11
|
|
|
|
_ggrabber->setPixelDecimation(obj["pixelDecimation"].toInt(8));
|
|
|
|
|
|
|
|
// crop for system capture
|
|
|
|
_ggrabber->setCropping(
|
|
|
|
obj["cropLeft"].toInt(0),
|
|
|
|
obj["cropRight"].toInt(0),
|
|
|
|
obj["cropTop"].toInt(0),
|
|
|
|
obj["cropBottom"].toInt(0));
|
|
|
|
|
|
|
|
// eval new update time
|
|
|
|
updateTimer(1000/obj["frequency_Hz"].toInt(10));
|
2018-12-27 23:11:32 +01:00
|
|
|
}
|
2017-08-12 07:55:32 +02:00
|
|
|
}
|
2020-03-26 17:49:36 +01:00
|
|
|
|
|
|
|
void GrabberWrapper::handleSourceRequest(const hyperion::Components& component, const int hyperionInd, const bool listen)
|
|
|
|
{
|
|
|
|
if(component == hyperion::Components::COMP_GRABBER && !_grabberName.startsWith("V4L"))
|
|
|
|
{
|
|
|
|
if(listen && !GRABBER_SYS_CLIENTS.contains(hyperionInd))
|
|
|
|
GRABBER_SYS_CLIENTS.append(hyperionInd);
|
|
|
|
else if (!listen)
|
|
|
|
GRABBER_SYS_CLIENTS.removeOne(hyperionInd);
|
|
|
|
|
|
|
|
if(GRABBER_SYS_CLIENTS.empty())
|
|
|
|
stop();
|
|
|
|
else
|
|
|
|
start();
|
|
|
|
}
|
|
|
|
else if(component == hyperion::Components::COMP_V4L && _grabberName.startsWith("V4L"))
|
|
|
|
{
|
|
|
|
if(listen && !GRABBER_V4L_CLIENTS.contains(hyperionInd))
|
|
|
|
GRABBER_V4L_CLIENTS.append(hyperionInd);
|
|
|
|
else if (!listen)
|
|
|
|
GRABBER_V4L_CLIENTS.removeOne(hyperionInd);
|
|
|
|
|
|
|
|
if(GRABBER_V4L_CLIENTS.empty())
|
|
|
|
stop();
|
|
|
|
else
|
|
|
|
start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GrabberWrapper::tryStart()
|
|
|
|
{
|
2020-07-12 18:27:24 +02:00
|
|
|
// verify start condition
|
2020-03-26 17:49:36 +01:00
|
|
|
if((_grabberName.startsWith("V4L") && !GRABBER_V4L_CLIENTS.empty()) || (!_grabberName.startsWith("V4L") && !GRABBER_SYS_CLIENTS.empty()))
|
|
|
|
{
|
|
|
|
start();
|
|
|
|
}
|
|
|
|
}
|
2020-04-17 16:59:20 +02:00
|
|
|
|
|
|
|
QStringList GrabberWrapper::getV4L2devices()
|
|
|
|
{
|
|
|
|
if(_grabberName.startsWith("V4L"))
|
|
|
|
return _ggrabber->getV4L2devices();
|
|
|
|
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString GrabberWrapper::getV4L2deviceName(QString devicePath)
|
|
|
|
{
|
|
|
|
if(_grabberName.startsWith("V4L"))
|
|
|
|
return _ggrabber->getV4L2deviceName(devicePath);
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2020-06-17 20:55:57 +02:00
|
|
|
QMultiMap<QString, int> GrabberWrapper::getV4L2deviceInputs(QString devicePath)
|
|
|
|
{
|
|
|
|
if(_grabberName.startsWith("V4L"))
|
|
|
|
return _ggrabber->getV4L2deviceInputs(devicePath);
|
|
|
|
|
|
|
|
return QMultiMap<QString, int>();
|
|
|
|
}
|
|
|
|
|
2020-04-17 16:59:20 +02:00
|
|
|
QStringList GrabberWrapper::getResolutions(QString devicePath)
|
|
|
|
{
|
|
|
|
if(_grabberName.startsWith("V4L"))
|
|
|
|
return _ggrabber->getResolutions(devicePath);
|
|
|
|
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList GrabberWrapper::getFramerates(QString devicePath)
|
|
|
|
{
|
|
|
|
if(_grabberName.startsWith("V4L"))
|
|
|
|
return _ggrabber->getFramerates(devicePath);
|
|
|
|
|
|
|
|
return QStringList();
|
|
|
|
}
|