Media Foundation/V4L2 grabber ... (#1119)

* - New Media Foundation grabber
- JsonAPI available grabber fix
- commented json config removed

* Added libjpeg-turbo to dependencies

* Fix OSX build
Removed Azure Pipelines from build scripts

* Remove Platform from Dashboard

* Correct Grabber Namings

* Grabber UI improvements, generic JSONEditor Selection Update

* Active grabber fix

* Stop Framebuffer grabber on failure

* - Image format NV12 and I420 added
- Flip mode
- Scaling factor for MJPEG
- VSCode (compile before run)
- CI (push) dependency libjpeg-turbo added

* Refactor MediaFoundation (Part 1)

* Remove QDebug output

* Added image flipping ability to MF Grabber

* fix issue 1160

* -Reload MF Grabber only once per WebUI update
- Cleanup

* Improvements

* - Set 'Software Frame Decimation' begin to 0
- Removed grabber specific device name from Log
- Keep pixel format when switching resolution
- Display 'Flip mode' correct in Log
- BGR24 images always flipped

* Refactor MediaFoundation (Part 2)

* Refactor V4L2 grabber (part 1) (#62)

* Media Foundation grabber adapted to V4L2 change

* Enable Media Foundation grabber on windows

* Have fps as int, fix height typo

* Added video standards to JsonAPI output

* Error handling in source reader improved

* Fix "Frame to small" error

* Discovery VideoSources and Dynamically Update Editor

* Hide all element when no video grabber discovered, upate naming

* Do not show unsupported grabbers

* Copy Log to Clipboard

* Update Grabber schema and Defaults

* Update access levels and validate crop ranges

* Height and width in Qt grabber corrected

* Correct formatting

* Untabify

* Global component states across instances

* Components divided on the dashboard

* refactor

* Fix Merge-issues

* Database migration aligning with updated grabber model

* Align Grabber.js with new utility functions

* Allow editor-validation for enum-lists

* Handle "Show Explainations scenario" correctly

* Grabber - Ensure save is only possible on valid content

* Dashboard update + fix GlobalSignal connection

* Ensure default database is populated with current release

* Correct grabber4L2 access level

* Display Signal detection area in preview

* Write Hyperion version into default config on compiling.

* Create defaultconfig.json dynamically

* WebUI changes

* Correct grabber config look-ups

* Refactor i18n language loading

* Fix en.json

* Split global capture from instance capture config

* Update grabber default values

* Standalone grabber: Add --debug switch

* Enhance showInputOptionsForKey for multiple keys

* Add grabber instance link to system grabber config

* Only show signal detection area, if grabber is enabled

* Always show Active element on grabber page

* Remote control - Only display gabber status, if global grabber is enabled

* WebUI optimization (thx to @mkcologne)
Start Grabber only when global settings are enabled
Fixed an issue in the WebUI preview

* V4L2/MF changes

* Jsoneditor, Correct translation for default values

* Refactor LED-Device handling in UI and make element naming consistent

* MF Discovery extended

* Fix LGTM finding

* Support Grabber Bri, Hue, Sat and Con in UI, plus their defaults

* Concider Access level for item filtering

* Concider Access level for item filtering

* Revert "Concider Access level for item filtering"

This reverts commit 5b0ce3c0f2.

* Disable fpsSoftwareDecimation for framegrabber, as not supported yet

* JSON-Editor- Add updated schema for validation on dynamic elements

* added V4L2 color IDs

* LGTM findings fix

* destroy SR callback only on exit

* Grabber.js - Hide elements not supported by platform

* Fixed freezing start effect

* Grabber UI - Hardware controls - Show current values and allow to reset to defaults

* Grabber - Discovery - Add current values to properties

* Small things

* Clean-up Effects and have ENDLESS consistently defined

* Fix on/off/on priority during startup, by initializing _prevVisComp in line with background priority

* Add missing translation mappings

* DirectX Grabber reactivated/ QT Grabber size decimation fixed

* typo in push-master workflow

* Use PreciseTimer for Grabber to ensure stable FPS timing

* Set default Screencapture rate consistently

* Fix libjpeg-turbo download

* Remove Zero character from file

* docker-compile Add PLATFORM parameter, only copy output file after successful compile

* Framebuffer, Dispmanx, OSX, AML Grabber discovery, various clean-up and consistencies across grabbers

* Fix merge problem - on docker-compile Add PLATFORM parameter, only copy output file after successful compile

* Fix definition

* OSXFRameGrabber - Revert cast

* Clean-ups nach Feedback

* Disable certain libraries when building armlogic via standard stretch image as developer

* Add CEC availability to ServerInfo to have it platform independent

* Grabber UI - Fix problem that crop values are not populated when refining editor rage

* Preserve value when updating json-editor range

* LEDVisualisation - Clear image when source changes

* Fix - Preserve value when updating json-editor range

* LEDVisualisation - Clear image when no component is active

* Allow to have password handled by Password-Manager (#1263)

* Update default signal detection area to green assuming rainbow grabber

* LED Visualisation - Handle empty priority update

* Fix yuv420 in v4l2 grabber

* V4L2-Grabber discovery - Only report grabbers with valid video input information

* Grabber - Update static variables to have them working in release build

* LED Visualisation - ClearImage when no priorities

* LED Visualisation - Fix Logo resizing issue

* LED Visualisation - Have nearly black background and negative logo

Co-authored-by: LordGrey <lordgrey.emmel@gmail.com>
Co-authored-by: LordGrey <48840279+Lord-Grey@users.noreply.github.com>
This commit is contained in:
Markus
2021-07-14 20:48:33 +02:00
committed by GitHub
parent b0e1510a78
commit c135d91986
163 changed files with 10756 additions and 5953 deletions

View File

@@ -73,7 +73,7 @@ HyperionDaemon::HyperionDaemon(const QString& rootPath, QObject* parent, bool lo
, _webserver(nullptr)
, _sslWebserver(nullptr)
, _jsonServer(nullptr)
, _v4l2Grabber(nullptr)
, _videoGrabber(nullptr)
, _dispmanx(nullptr)
, _x11Grabber(nullptr)
, _xcbGrabber(nullptr)
@@ -125,9 +125,8 @@ HyperionDaemon::HyperionDaemon(const QString& rootPath, QObject* parent, bool lo
//Cleaning up Hyperion before quit
connect(parent, SIGNAL(aboutToQuit()), this, SLOT(freeObjects()));
// pipe settings changes and component state changes from HyperionIManager to Daemon
// pipe settings changes from HyperionIManager to Daemon
connect(_instanceManager, &HyperionIManager::settingsChanged, this, &HyperionDaemon::settingsChanged);
connect(_instanceManager, &HyperionIManager::compStateChangeRequest, this, &HyperionDaemon::compStateChangeRequest);
// listen for setting changes of framegrabber and v4l2
connect(this, &HyperionDaemon::settingsChanged, this, &HyperionDaemon::handleSettingsUpdate);
@@ -145,7 +144,7 @@ HyperionDaemon::HyperionDaemon(const QString& rootPath, QObject* parent, bool lo
// init system capture (framegrabber)
handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
// init v4l2 capture
// init v4l2 && media foundation capture
handleSettingsUpdate(settings::V4L2, getSetting(settings::V4L2));
// ---- network services -----
@@ -252,16 +251,15 @@ void HyperionDaemon::freeObjects()
delete _osxGrabber;
delete _qtGrabber;
delete _dxGrabber;
delete _v4l2Grabber;
delete _videoGrabber;
_v4l2Grabber = nullptr;
_amlGrabber = nullptr;
_dispmanx = nullptr;
_fbGrabber = nullptr;
_osxGrabber = nullptr;
_qtGrabber = nullptr;
_dxGrabber = nullptr;
_videoGrabber = nullptr;
_amlGrabber = nullptr;
_dispmanx = nullptr;
_fbGrabber = nullptr;
_osxGrabber = nullptr;
_qtGrabber = nullptr;
_dxGrabber = nullptr;
}
void HyperionDaemon::startNetworkServices()
@@ -358,20 +356,18 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
_grabber_width = grabberConfig["width"].toInt(96);
_grabber_height = grabberConfig["height"].toInt(96);
_grabber_frequency = grabberConfig["frequency_Hz"].toInt(10);
_grabber_pixelDecimation = grabberConfig["pixelDecimation"].toInt(GrabberWrapper::DEFAULT_PIXELDECIMATION);
_grabber_frequency = grabberConfig["fps"].toInt(GrabberWrapper::DEFAULT_RATE_HZ);
_grabber_cropLeft = grabberConfig["cropLeft"].toInt(0);
_grabber_cropRight = grabberConfig["cropRight"].toInt(0);
_grabber_cropTop = grabberConfig["cropTop"].toInt(0);
_grabber_cropBottom = grabberConfig["cropBottom"].toInt(0);
_grabber_ge2d_mode = grabberConfig["ge2d_mode"].toInt(0);
_grabber_device = grabberConfig["amlogic_grabber"].toString("amvideocap0");
#ifdef ENABLE_OSX
QString type = "osx";
QString type = grabberConfig["device"].toString("osx");
#else
QString type = grabberConfig["type"].toString("auto");
QString type = grabberConfig["device"].toString("auto");
#endif
// auto eval of type
@@ -389,9 +385,10 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
{
type = "amlogic";
if (!QFile::exists("/dev/" + _grabber_device))
QString amlDevice ("/dev/amvideocap0");
if (!QFile::exists(amlDevice))
{
Error(_log, "grabber device '%s' for type amlogic not found!", QSTRING_CSTR(_grabber_device));
Error(_log, "grabber device '%s' for type amlogic not found!", QSTRING_CSTR(amlDevice));
}
}
else
@@ -495,27 +492,30 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
createGrabberFramebuffer(grabberConfig);
}
#ifdef ENABLE_FB
_fbGrabber->tryStart();
_fbGrabber->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
_fbGrabber->tryStart();
#endif
}
else if (type == "dispmanx")
{
if (_dispmanx == nullptr)
{
createGrabberDispmanx();
createGrabberDispmanx(grabberConfig);
}
#ifdef ENABLE_DISPMANX
_dispmanx->tryStart();
_dispmanx->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
_dispmanx->tryStart();
#endif
}
else if (type == "amlogic")
{
if (_amlGrabber == nullptr)
{
createGrabberAmlogic();
createGrabberAmlogic(grabberConfig);
}
#ifdef ENABLE_AMLOGIC
_amlGrabber->tryStart();
_amlGrabber->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
_amlGrabber->tryStart();
#endif
}
else if (type == "osx")
@@ -525,7 +525,8 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
createGrabberOsx(grabberConfig);
}
#ifdef ENABLE_OSX
_osxGrabber->tryStart();
_osxGrabber->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
_osxGrabber->tryStart();
#endif
}
else if (type == "x11")
@@ -535,7 +536,8 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
createGrabberX11(grabberConfig);
}
#ifdef ENABLE_X11
_x11Grabber->tryStart();
_x11Grabber->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
_x11Grabber->tryStart();
#endif
}
else if (type == "xcb")
@@ -545,7 +547,8 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
createGrabberXcb(grabberConfig);
}
#ifdef ENABLE_XCB
_xcbGrabber->tryStart();
_xcbGrabber->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
_xcbGrabber->tryStart();
#endif
}
else if (type == "qt")
@@ -555,7 +558,8 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
createGrabberQt(grabberConfig);
}
#ifdef ENABLE_QT
_qtGrabber->tryStart();
_qtGrabber->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
_qtGrabber->tryStart();
#endif
}
else if (type == "dx")
@@ -565,7 +569,8 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
createGrabberDx(grabberConfig);
}
#ifdef ENABLE_DX
_dxGrabber->tryStart();
_dxGrabber->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
_dxGrabber->tryStart();
#endif
}
else
@@ -579,11 +584,8 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
else if (settingsType == settings::V4L2)
{
#if defined(ENABLE_CEC) || defined(ENABLE_V4L2)
const QJsonObject& grabberConfig = config.object();
#endif
#ifdef ENABLE_CEC
const QJsonObject& grabberConfig = config.object();
if (_cecHandler != nullptr && grabberConfig["cecDetection"].toBool(false))
{
QMetaObject::invokeMethod(_cecHandler, "start", Qt::QueuedConnection);
@@ -594,54 +596,35 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
#endif
if (_v4l2Grabber != nullptr)
#if defined(ENABLE_V4L2) || defined(ENABLE_MF)
if (_videoGrabber == nullptr)
{
return;
_videoGrabber = new VideoWrapper();
_videoGrabber->handleSettingsUpdate(settings::V4L2, getSetting(settings::V4L2));
#if defined(ENABLE_MF)
Debug(_log, "Media Foundation grabber created");
#elif defined(ENABLE_V4L2)
Debug(_log, "V4L2 grabber created");
#endif
// connect to HyperionDaemon signal
connect(this, &HyperionDaemon::videoMode, _videoGrabber, &VideoWrapper::setVideoMode);
connect(this, &HyperionDaemon::settingsChanged, _videoGrabber, &VideoWrapper::handleSettingsUpdate);
}
#ifdef ENABLE_V4L2
_v4l2Grabber = new V4L2Wrapper(
grabberConfig["device"].toString("auto"),
grabberConfig["width"].toInt(0),
grabberConfig["height"].toInt(0),
grabberConfig["fps"].toInt(15),
grabberConfig["input"].toInt(-1),
parseVideoStandard(grabberConfig["standard"].toString("no-change")),
parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change")),
grabberConfig["sizeDecimation"].toInt(8));
_v4l2Grabber->setSignalThreshold(
grabberConfig["redSignalThreshold"].toDouble(0.0) / 100.0,
grabberConfig["greenSignalThreshold"].toDouble(0.0) / 100.0,
grabberConfig["blueSignalThreshold"].toDouble(0.0) / 100.0);
_v4l2Grabber->setCropping(
grabberConfig["cropLeft"].toInt(0),
grabberConfig["cropRight"].toInt(0),
grabberConfig["cropTop"].toInt(0),
grabberConfig["cropBottom"].toInt(0));
_v4l2Grabber->setCecDetectionEnable(grabberConfig["cecDetection"].toBool(true));
_v4l2Grabber->setSignalDetectionEnable(grabberConfig["signalDetection"].toBool(true));
_v4l2Grabber->setSignalDetectionOffset(
grabberConfig["sDHOffsetMin"].toDouble(0.25),
grabberConfig["sDVOffsetMin"].toDouble(0.25),
grabberConfig["sDHOffsetMax"].toDouble(0.75),
grabberConfig["sDVOffsetMax"].toDouble(0.75));
Debug(_log, "V4L2 grabber created");
// connect to HyperionDaemon signal
connect(this, &HyperionDaemon::videoMode, _v4l2Grabber, &V4L2Wrapper::setVideoMode);
connect(this, &HyperionDaemon::settingsChanged, _v4l2Grabber, &V4L2Wrapper::handleSettingsUpdate);
#else
Debug(_log, "The v4l2 grabber is not supported on this platform");
#endif
}
}
void HyperionDaemon::createGrabberDispmanx()
void HyperionDaemon::createGrabberDispmanx(const QJsonObject& /*grabberConfig*/)
{
#ifdef ENABLE_DISPMANX
_dispmanx = new DispmanxWrapper(_grabber_width, _grabber_height, _grabber_frequency);
_dispmanx = new DispmanxWrapper(
_grabber_frequency,
_grabber_pixelDecimation
);
_dispmanx->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom);
// connect to HyperionDaemon signal
@@ -654,10 +637,13 @@ void HyperionDaemon::createGrabberDispmanx()
#endif
}
void HyperionDaemon::createGrabberAmlogic()
void HyperionDaemon::createGrabberAmlogic(const QJsonObject& /*grabberConfig*/)
{
#ifdef ENABLE_AMLOGIC
_amlGrabber = new AmlogicWrapper(_grabber_width, _grabber_height);
_amlGrabber = new AmlogicWrapper(
_grabber_frequency,
_grabber_pixelDecimation
);
_amlGrabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom);
// connect to HyperionDaemon signal
@@ -670,13 +656,14 @@ void HyperionDaemon::createGrabberAmlogic()
#endif
}
void HyperionDaemon::createGrabberX11(const QJsonObject& grabberConfig)
void HyperionDaemon::createGrabberX11(const QJsonObject& /*grabberConfig*/)
{
#ifdef ENABLE_X11
_x11Grabber = new X11Wrapper(
_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom,
grabberConfig["pixelDecimation"].toInt(8),
_grabber_frequency);
_grabber_frequency,
_grabber_pixelDecimation,
_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom
);
_x11Grabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom);
// connect to HyperionDaemon signal
@@ -689,13 +676,14 @@ void HyperionDaemon::createGrabberX11(const QJsonObject& grabberConfig)
#endif
}
void HyperionDaemon::createGrabberXcb(const QJsonObject& grabberConfig)
void HyperionDaemon::createGrabberXcb(const QJsonObject& /*grabberConfig*/)
{
#ifdef ENABLE_XCB
_xcbGrabber = new XcbWrapper(
_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom,
grabberConfig["pixelDecimation"].toInt(8),
_grabber_frequency);
_grabber_frequency,
_grabber_pixelDecimation,
_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom
);
_xcbGrabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom);
// connect to HyperionDaemon signal
@@ -712,10 +700,11 @@ void HyperionDaemon::createGrabberQt(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_QT
_qtGrabber = new QtWrapper(
_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom,
grabberConfig["pixelDecimation"].toInt(8),
grabberConfig["display"].toInt(0),
_grabber_frequency);
_grabber_frequency,
grabberConfig["input"].toInt(0),
_grabber_pixelDecimation,
_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom
);
// connect to HyperionDaemon signal
connect(this, &HyperionDaemon::videoMode, _qtGrabber, &QtWrapper::setVideoMode);
@@ -731,10 +720,11 @@ void HyperionDaemon::createGrabberDx(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_DX
_dxGrabber = new DirectXWrapper(
_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom,
grabberConfig["pixelDecimation"].toInt(8),
_grabber_frequency,
grabberConfig["display"].toInt(0),
_grabber_frequency);
_grabber_pixelDecimation,
_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom
);
// connect to HyperionDaemon signal
connect(this, &HyperionDaemon::videoMode, _dxGrabber, &DirectXWrapper::setVideoMode);
@@ -750,9 +740,14 @@ void HyperionDaemon::createGrabberFramebuffer(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_FB
// Construct and start the framebuffer grabber if the configuration is present
int fbIdx = grabberConfig["input"].toInt(0);
QString devicePath = QString("/dev/fb%1").arg(fbIdx);
_fbGrabber = new FramebufferWrapper(
grabberConfig["device"].toString("/dev/fb0"),
_grabber_width, _grabber_height, _grabber_frequency);
_grabber_frequency,
devicePath,
_grabber_pixelDecimation
);
_fbGrabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom);
// connect to HyperionDaemon signal
connect(this, &HyperionDaemon::videoMode, _fbGrabber, &FramebufferWrapper::setVideoMode);
@@ -764,13 +759,16 @@ void HyperionDaemon::createGrabberFramebuffer(const QJsonObject& grabberConfig)
#endif
}
void HyperionDaemon::createGrabberOsx(const QJsonObject& grabberConfig)
void HyperionDaemon::createGrabberOsx(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_OSX
// Construct and start the osx grabber if the configuration is present
_osxGrabber = new OsxWrapper(
grabberConfig["display"].toInt(0),
_grabber_width, _grabber_height, _grabber_frequency);
_grabber_frequency,
grabberConfig["input"].toInt(0),
_grabber_pixelDecimation
);
_osxGrabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom);
// connect to HyperionDaemon signal
connect(this, &HyperionDaemon::videoMode, _osxGrabber, &OsxWrapper::setVideoMode);
@@ -793,9 +791,9 @@ void HyperionDaemon::createCecHandler()
thread->start();
connect(_cecHandler, &CECHandler::cecEvent, [&](CECEvent event) {
if (_v4l2Grabber != nullptr)
if (_videoGrabber != nullptr)
{
_v4l2Grabber->handleCecEvent(event);
_videoGrabber->handleCecEvent(event);
}
});