mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	implement use of multiple v4l devices.
Not all v4l devices are compat with that or must be attaches to different usb controllers
This commit is contained in:
		@@ -168,25 +168,27 @@
 | 
			
		||||
	///  * greenSignalThreshold : Signal threshold for the green channel between 0.0 and 1.0 [default=0.0]
 | 
			
		||||
	///  * blueSignalThreshold  : Signal threshold for the blue channel between 0.0 and 1.0 [default=0.0]
 | 
			
		||||
	"grabber-v4l2" :
 | 
			
		||||
	{
 | 
			
		||||
		"enable"               : false,
 | 
			
		||||
		"device"               : "/dev/video0",
 | 
			
		||||
		"input"                : 0,
 | 
			
		||||
		"standard"             : "no-change",
 | 
			
		||||
		"width"                : -1,
 | 
			
		||||
		"height"               : -1,
 | 
			
		||||
		"frameDecimation"      : 2,
 | 
			
		||||
		"sizeDecimation"       : 8,
 | 
			
		||||
		"priority"             : 890,
 | 
			
		||||
		"mode"                 : "2D",
 | 
			
		||||
		"cropLeft"             : 0,
 | 
			
		||||
		"cropRight"            : 0,
 | 
			
		||||
		"cropTop"              : 0,
 | 
			
		||||
		"cropBottom"           : 0,
 | 
			
		||||
		"redSignalThreshold"   : 0.0,
 | 
			
		||||
		"greenSignalThreshold" : 0.0,
 | 
			
		||||
		"blueSignalThreshold"  : 0.0
 | 
			
		||||
	},
 | 
			
		||||
	[
 | 
			
		||||
		{
 | 
			
		||||
			"enable"   : false,
 | 
			
		||||
			"device"   : "auto",
 | 
			
		||||
			"input"    : 0,
 | 
			
		||||
			"standard" : "PAL",
 | 
			
		||||
			"width"    : -1,
 | 
			
		||||
			"height"   : -1,
 | 
			
		||||
			"frameDecimation" : 2,
 | 
			
		||||
			"sizeDecimation"  : 8,
 | 
			
		||||
			"priority"    : 890,
 | 
			
		||||
			"mode"        : "2D",
 | 
			
		||||
			"cropLeft"    : 0,
 | 
			
		||||
			"cropRight"   : 0,
 | 
			
		||||
			"cropTop"     : 0,
 | 
			
		||||
			"cropBottom"  : 0,
 | 
			
		||||
			"redSignalThreshold"   : 0.0,
 | 
			
		||||
			"greenSignalThreshold" : 0.0,
 | 
			
		||||
			"blueSignalThreshold"  : 0.0
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
 | 
			
		||||
	///  The configuration for the frame-grabber, contains the following items: 
 | 
			
		||||
	///   * enable       : true if the framegrabber (platform grabber) should be activated
 | 
			
		||||
 
 | 
			
		||||
@@ -97,25 +97,27 @@
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"grabber-v4l2" :
 | 
			
		||||
	{
 | 
			
		||||
		"enable"   : false,
 | 
			
		||||
		"device"   : "auto",
 | 
			
		||||
		"input"    : 0,
 | 
			
		||||
		"standard" : "PAL",
 | 
			
		||||
		"width"    : -1,
 | 
			
		||||
		"height"   : -1,
 | 
			
		||||
		"frameDecimation" : 2,
 | 
			
		||||
		"sizeDecimation"  : 8,
 | 
			
		||||
		"priority"    : 890,
 | 
			
		||||
		"mode"        : "2D",
 | 
			
		||||
		"cropLeft"    : 0,
 | 
			
		||||
		"cropRight"   : 0,
 | 
			
		||||
		"cropTop"     : 0,
 | 
			
		||||
		"cropBottom"  : 0,
 | 
			
		||||
		"redSignalThreshold"   : 0.0,
 | 
			
		||||
		"greenSignalThreshold" : 0.0,
 | 
			
		||||
		"blueSignalThreshold"  : 0.0
 | 
			
		||||
	},
 | 
			
		||||
	[
 | 
			
		||||
		{
 | 
			
		||||
			"enable"   : false,
 | 
			
		||||
			"device"   : "auto",
 | 
			
		||||
			"input"    : 0,
 | 
			
		||||
			"standard" : "PAL",
 | 
			
		||||
			"width"    : -1,
 | 
			
		||||
			"height"   : -1,
 | 
			
		||||
			"frameDecimation" : 2,
 | 
			
		||||
			"sizeDecimation"  : 8,
 | 
			
		||||
			"priority"    : 890,
 | 
			
		||||
			"mode"        : "2D",
 | 
			
		||||
			"cropLeft"    : 0,
 | 
			
		||||
			"cropRight"   : 0,
 | 
			
		||||
			"cropTop"     : 0,
 | 
			
		||||
			"cropBottom"  : 0,
 | 
			
		||||
			"redSignalThreshold"   : 0.0,
 | 
			
		||||
			"greenSignalThreshold" : 0.0,
 | 
			
		||||
			"blueSignalThreshold"  : 0.0
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
 | 
			
		||||
	"framegrabber" :
 | 
			
		||||
	{
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ V4L2Grabber::V4L2Grabber(const std::string & device,
 | 
			
		||||
	, _noSignalCounter(0)
 | 
			
		||||
	, _streamNotifier(nullptr)
 | 
			
		||||
	, _imageResampler()
 | 
			
		||||
	, _log(Logger::getInstance("V4L2"))
 | 
			
		||||
	, _log(Logger::getInstance("V4L2:"+device))
 | 
			
		||||
	, _initialized(false)
 | 
			
		||||
	, _deviceAutoDiscoverEnabled(false)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ V4L2Wrapper::V4L2Wrapper(const std::string &device,
 | 
			
		||||
		double greenSignalThreshold,
 | 
			
		||||
		double blueSignalThreshold,
 | 
			
		||||
		const int priority)
 | 
			
		||||
	: GrabberWrapper("V4L2", priority)
 | 
			
		||||
	: GrabberWrapper("V4L2:"+device, priority)
 | 
			
		||||
	, _timeout_ms(1000)
 | 
			
		||||
	, _grabber(device,
 | 
			
		||||
			input,
 | 
			
		||||
 
 | 
			
		||||
@@ -399,83 +399,87 @@
 | 
			
		||||
		},
 | 
			
		||||
		"grabber-v4l2" :
 | 
			
		||||
		{
 | 
			
		||||
			"type" : "object",
 | 
			
		||||
			"properties" :
 | 
			
		||||
			"type":"array",
 | 
			
		||||
			"items":
 | 
			
		||||
			{
 | 
			
		||||
				"enable" :
 | 
			
		||||
				"type" : "object",
 | 
			
		||||
				"properties" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "boolean"
 | 
			
		||||
					"enable" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "boolean"
 | 
			
		||||
					},
 | 
			
		||||
					"device" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "string"
 | 
			
		||||
					},
 | 
			
		||||
					"input" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"standard" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "string"
 | 
			
		||||
					},
 | 
			
		||||
					"width" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"height" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"frameDecimation" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"sizeDecimation" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"priority" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"mode" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "string"
 | 
			
		||||
					},
 | 
			
		||||
					"useKodiChecker" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "boolean"
 | 
			
		||||
					},
 | 
			
		||||
					"cropLeft" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"cropRight" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"cropTop" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"cropBottom" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "integer"
 | 
			
		||||
					},
 | 
			
		||||
					"redSignalThreshold" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "number"
 | 
			
		||||
					},
 | 
			
		||||
					"greenSignalThreshold" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "number"
 | 
			
		||||
					},
 | 
			
		||||
					"blueSignalThreshold" :
 | 
			
		||||
					{
 | 
			
		||||
						"type" : "number"
 | 
			
		||||
					}
 | 
			
		||||
				},
 | 
			
		||||
				"device" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "string"
 | 
			
		||||
				},
 | 
			
		||||
				"input" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"standard" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "string"
 | 
			
		||||
				},
 | 
			
		||||
				"width" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"height" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"frameDecimation" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"sizeDecimation" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"priority" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"mode" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "string"
 | 
			
		||||
				},
 | 
			
		||||
				"useKodiChecker" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "boolean"
 | 
			
		||||
				},
 | 
			
		||||
				"cropLeft" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"cropRight" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"cropTop" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"cropBottom" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "integer"
 | 
			
		||||
				},
 | 
			
		||||
				"redSignalThreshold" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "number"
 | 
			
		||||
				},
 | 
			
		||||
				"greenSignalThreshold" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "number"
 | 
			
		||||
				},
 | 
			
		||||
				"blueSignalThreshold" :
 | 
			
		||||
				{
 | 
			
		||||
					"type" : "number"
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			"additionalProperties" : false
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"framegrabber" :
 | 
			
		||||
		{
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ HyperionDaemon::HyperionDaemon(QString configFile, QObject *parent)
 | 
			
		||||
	, _protoServer(nullptr)
 | 
			
		||||
	, _boblightServer(nullptr)
 | 
			
		||||
	, _udpListener(nullptr)
 | 
			
		||||
	, _v4l2Grabber(nullptr)
 | 
			
		||||
	, _v4l2Grabbers()
 | 
			
		||||
	, _dispmanx(nullptr)
 | 
			
		||||
#ifdef ENABLE_X11
 | 
			
		||||
	, _x11Grabber(nullptr)
 | 
			
		||||
@@ -83,7 +83,10 @@ HyperionDaemon::~HyperionDaemon()
 | 
			
		||||
	delete _dispmanx;
 | 
			
		||||
	delete _fbGrabber;
 | 
			
		||||
	delete _osxGrabber;
 | 
			
		||||
	delete _v4l2Grabber;
 | 
			
		||||
	for(V4L2Wrapper* grabber : _v4l2Grabbers)
 | 
			
		||||
	{
 | 
			
		||||
		delete grabber;
 | 
			
		||||
	}
 | 
			
		||||
	delete _kodiVideoChecker;
 | 
			
		||||
	delete _jsonServer;
 | 
			
		||||
	delete _protoServer;
 | 
			
		||||
@@ -538,39 +541,52 @@ void HyperionDaemon::createGrabberV4L2()
 | 
			
		||||
{
 | 
			
		||||
	// construct and start the v4l2 grabber if the configuration is present
 | 
			
		||||
	bool v4lConfigured = _qconfig.contains("grabber-v4l2");
 | 
			
		||||
	const QJsonObject & grabberConfig = _qconfig["grabber-v4l2"].toObject();
 | 
			
		||||
	bool enableV4l = v4lConfigured && grabberConfig["enable"].toBool(true);
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_V4L2
 | 
			
		||||
	_v4l2Grabber = new V4L2Wrapper(
 | 
			
		||||
		grabberConfig["device"].toString("auto").toStdString(),
 | 
			
		||||
		grabberConfig["input"].toInt(0),
 | 
			
		||||
		parseVideoStandard(grabberConfig["standard"].toString("no-change").toStdString()),
 | 
			
		||||
		parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change").toStdString()),
 | 
			
		||||
		grabberConfig["width"].toInt(-1),
 | 
			
		||||
		grabberConfig["height"].toInt(-1),
 | 
			
		||||
		grabberConfig["frameDecimation"].toInt(2),
 | 
			
		||||
		grabberConfig["sizeDecimation"].toInt(8),
 | 
			
		||||
		grabberConfig["redSignalThreshold"].toDouble(0.0),
 | 
			
		||||
		grabberConfig["greenSignalThreshold"].toDouble(0.0),
 | 
			
		||||
		grabberConfig["blueSignalThreshold"].toDouble(0.0),
 | 
			
		||||
		grabberConfig["priority"].toInt(890));
 | 
			
		||||
	_v4l2Grabber->set3D(parse3DMode(grabberConfig["mode"].toString("2D").toStdString()));
 | 
			
		||||
	_v4l2Grabber->setCropping(
 | 
			
		||||
		grabberConfig["cropLeft"].toInt(0),
 | 
			
		||||
		grabberConfig["cropRight"].toInt(0),
 | 
			
		||||
		grabberConfig["cropTop"].toInt(0),
 | 
			
		||||
		grabberConfig["cropBottom"].toInt(0));
 | 
			
		||||
	Debug(_log, "V4L2 grabber created");
 | 
			
		||||
 | 
			
		||||
	QObject::connect(_v4l2Grabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)));
 | 
			
		||||
	if (grabberConfig["useKodiChecker"].toBool(false))
 | 
			
		||||
	unsigned v4lEnableCount = 0;
 | 
			
		||||
	
 | 
			
		||||
	if (_qconfig["grabber-v4l2"].isArray())
 | 
			
		||||
	{
 | 
			
		||||
		QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _v4l2Grabber, SLOT(setGrabbingMode(GrabbingMode)));
 | 
			
		||||
	}
 | 
			
		||||
	InfoIf( enableV4l && _v4l2Grabber->start(), _log, "V4L2 grabber started");
 | 
			
		||||
#endif
 | 
			
		||||
		const QJsonArray & v4lArray = _qconfig["grabber-v4l2"].toArray();
 | 
			
		||||
		for ( signed idx=0; idx<v4lArray.size(); idx++)
 | 
			
		||||
		{
 | 
			
		||||
			const QJsonObject & grabberConfig = v4lArray.at(idx).toObject();
 | 
			
		||||
			bool enableV4l = v4lConfigured && grabberConfig["enable"].toBool(true);
 | 
			
		||||
			if (enableV4l)
 | 
			
		||||
			{
 | 
			
		||||
				v4lEnableCount++;
 | 
			
		||||
			}
 | 
			
		||||
			#ifdef ENABLE_V4L2
 | 
			
		||||
			V4L2Wrapper* grabber = new V4L2Wrapper(
 | 
			
		||||
				grabberConfig["device"].toString("auto").toStdString(),
 | 
			
		||||
				grabberConfig["input"].toInt(0),
 | 
			
		||||
				parseVideoStandard(grabberConfig["standard"].toString("no-change").toStdString()),
 | 
			
		||||
				parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change").toStdString()),
 | 
			
		||||
				grabberConfig["width"].toInt(-1),
 | 
			
		||||
				grabberConfig["height"].toInt(-1),
 | 
			
		||||
				grabberConfig["frameDecimation"].toInt(2),
 | 
			
		||||
				grabberConfig["sizeDecimation"].toInt(8),
 | 
			
		||||
				grabberConfig["redSignalThreshold"].toDouble(0.0),
 | 
			
		||||
				grabberConfig["greenSignalThreshold"].toDouble(0.0),
 | 
			
		||||
				grabberConfig["blueSignalThreshold"].toDouble(0.0),
 | 
			
		||||
				grabberConfig["priority"].toInt(890));
 | 
			
		||||
			grabber->set3D(parse3DMode(grabberConfig["mode"].toString("2D").toStdString()));
 | 
			
		||||
			grabber->setCropping(
 | 
			
		||||
				grabberConfig["cropLeft"].toInt(0),
 | 
			
		||||
				grabberConfig["cropRight"].toInt(0),
 | 
			
		||||
				grabberConfig["cropTop"].toInt(0),
 | 
			
		||||
				grabberConfig["cropBottom"].toInt(0));
 | 
			
		||||
			Debug(_log, "V4L2 grabber created");
 | 
			
		||||
 | 
			
		||||
	ErrorIf(enableV4l && _v4l2Grabber==nullptr, _log, "The v4l2 grabber can not be instantiated, because it has been left out from the build");
 | 
			
		||||
			QObject::connect(grabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)));
 | 
			
		||||
			if (grabberConfig["useKodiChecker"].toBool(false))
 | 
			
		||||
			{
 | 
			
		||||
				QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), grabber, SLOT(setGrabbingMode(GrabbingMode)));
 | 
			
		||||
			}
 | 
			
		||||
			InfoIf( enableV4l && grabber->start(), _log, "V4L2 grabber started");
 | 
			
		||||
			_v4l2Grabbers.push_back(grabber);
 | 
			
		||||
			#endif
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ErrorIf( (v4lEnableCount>0 && _v4l2Grabbers.size()==0), _log, "The v4l2 grabber can not be instantiated, because it has been left out from the build");
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,7 @@ private:
 | 
			
		||||
	ProtoServer*        _protoServer;
 | 
			
		||||
	BoblightServer*     _boblightServer;
 | 
			
		||||
	UDPListener*        _udpListener;
 | 
			
		||||
	V4L2Wrapper*        _v4l2Grabber;
 | 
			
		||||
	std::vector<V4L2Wrapper*>  _v4l2Grabbers;
 | 
			
		||||
	DispmanxWrapper*    _dispmanx;
 | 
			
		||||
#ifdef ENABLE_X11
 | 
			
		||||
	X11Wrapper*         _x11Grabber;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user