diff --git a/assets/webconfig/i18n/de.json b/assets/webconfig/i18n/de.json index 533d080f..d8dc4a53 100644 --- a/assets/webconfig/i18n/de.json +++ b/assets/webconfig/i18n/de.json @@ -467,6 +467,7 @@ "edt_conf_v4l2_cropTop_expl" : "Anzahl der Pixel auf der oberen Seite die vom Bild entfernt werden.", "edt_conf_v4l2_cropBottom_title" : "Entferne unten", "edt_conf_v4l2_cropBottom_expl" : "Anzahl der Pixel auf der unteren Seite die vom Bild entfernt werden.", + "edt_conf_v4l2_signalDetection_title" : "Signal Erkennung", "edt_conf_v4l2_redSignalThreshold_title" : "Rote Signalschwelle", "edt_conf_v4l2_redSignalThreshold_expl" : "Verdunkelt rote Werte. (Wird als schwarz interpretiert)", "edt_conf_v4l2_greenSignalThreshold_title" : "Grüne Signalschwelle", diff --git a/assets/webconfig/i18n/en.json b/assets/webconfig/i18n/en.json index d1062bc4..f42cbe70 100644 --- a/assets/webconfig/i18n/en.json +++ b/assets/webconfig/i18n/en.json @@ -468,6 +468,7 @@ "edt_conf_v4l2_cropTop_expl" : "Count of pixels on the top side that are removed from the picture.", "edt_conf_v4l2_cropBottom_title" : "Crop bottom", "edt_conf_v4l2_cropBottom_expl" : "Count of pixels on the bottom side that are removed from the picture.", + "edt_conf_v4l2_signalDetection_title" : "Enable signal detection", "edt_conf_v4l2_redSignalThreshold_title" : "Red signal threshold", "edt_conf_v4l2_redSignalThreshold_expl" : "Darkens low red values (recognized as black)", "edt_conf_v4l2_greenSignalThreshold_title" : "Green signal threshold", diff --git a/assets/webconfig/i18n/es.json b/assets/webconfig/i18n/es.json index 1947a352..8cb14e73 100644 --- a/assets/webconfig/i18n/es.json +++ b/assets/webconfig/i18n/es.json @@ -461,6 +461,7 @@ "edt_conf_v4l2_cropTop_expl": "Cuenta de píxeles en la parte superior que se quitan de la imagen.", "edt_conf_v4l2_cropBottom_title": "Cortar abajo", "edt_conf_v4l2_cropBottom_expl": "Cuenta de píxeles en la parte inferior que se quitan de la imagen.", + "edt_conf_v4l2_signalDetection_title" : "Detección de señal", "edt_conf_v4l2_redSignalThreshold_title": "Umbral de señal rojo", "edt_conf_v4l2_redSignalThreshold_expl": "Oscurece los valores bajos de color rojo (reconocidos como negros)", "edt_conf_v4l2_greenSignalThreshold_title": "Umbral de señal verde", diff --git a/config/hyperion.config.json.commented b/config/hyperion.config.json.commented index dd2d64b9..02d49f23 100644 --- a/config/hyperion.config.json.commented +++ b/config/hyperion.config.json.commented @@ -114,6 +114,7 @@ /// * cropRight : Cropping from the right [default=0] /// * cropTop : Cropping from the top [default=0] /// * cropBottom : Cropping from the bottom [default=0] + /// * signalDetection : enable/disable signal detection [default=true] /// * redSignalThreshold : Signal threshold for the red channel between 0.0 and 1.0 [default=0.0] /// * 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] @@ -142,6 +143,7 @@ "redSignalThreshold" : 0.0, "greenSignalThreshold" : 0.0, "blueSignalThreshold" : 0.0, + "signalDetection" : true, "signalDetectionVerticalOffsetMin" : 0.25, "signalDetectionHorizontalOffsetMin" : 0.25, "signalDetectionVerticalOffsetMax" : 0.75, diff --git a/config/hyperion.config.json.default b/config/hyperion.config.json.default index f4b8dd6e..91b15ce6 100644 --- a/config/hyperion.config.json.default +++ b/config/hyperion.config.json.default @@ -76,6 +76,7 @@ "redSignalThreshold" : 0.0, "greenSignalThreshold" : 0.0, "blueSignalThreshold" : 0.0, + "signalDetection" : true, "signalDetectionVerticalOffsetMin" : 0.25, "signalDetectionHorizontalOffsetMin" : 0.25, "signalDetectionVerticalOffsetMax" : 0.75, diff --git a/include/grabber/V4L2Grabber.h b/include/grabber/V4L2Grabber.h index 4d157af9..36c2f8a9 100644 --- a/include/grabber/V4L2Grabber.h +++ b/include/grabber/V4L2Grabber.h @@ -40,6 +40,7 @@ public: virtual ~V4L2Grabber(); QRectF getSignalDetectionOffset(); + bool getSignalDetectionEnabled(); public slots: void setCropping(int cropLeft, @@ -61,6 +62,8 @@ public slots: double verticalMax, double horizontalMax); + void setSignalDetectionEnable(bool enable); + bool start(); void stop(); @@ -133,13 +136,19 @@ private: int _lineLength; int _frameByteSize; int _frameDecimation; - int _noSignalCounterThreshold; + // signal detection + int _noSignalCounterThreshold; ColorRgb _noSignalThresholdColor; + bool _signalDetectionEnabled; + bool _noSignalDetected; + int _noSignalCounter; + double _x_frac_min; + double _y_frac_min; + double _x_frac_max; + double _y_frac_max; int _currentFrame; - int _noSignalCounter; - QSocketNotifier * _streamNotifier; ImageResampler _imageResampler; @@ -148,10 +157,5 @@ private: bool _initialized; bool _deviceAutoDiscoverEnabled; - bool _noSignalDetected; - double _x_frac_min; - double _y_frac_min; - double _x_frac_max; - double _y_frac_max; }; diff --git a/include/grabber/V4L2Wrapper.h b/include/grabber/V4L2Wrapper.h index bf347a12..39e52192 100644 --- a/include/grabber/V4L2Wrapper.h +++ b/include/grabber/V4L2Wrapper.h @@ -27,6 +27,8 @@ public: const int priority); virtual ~V4L2Wrapper(); + bool getSignalDetectionEnable(); + public slots: bool start(); void stop(); @@ -34,6 +36,7 @@ public slots: void setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom); void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax); void set3D(VideoMode mode); + void setSignalDetectionEnable(bool enable); // signals: // void emitColors(int priority, const std::vector &ledColors, const int timeout_ms); diff --git a/libsrc/grabber/v4l2/V4L2Grabber.cpp b/libsrc/grabber/v4l2/V4L2Grabber.cpp index dc71fe5c..d5234530 100644 --- a/libsrc/grabber/v4l2/V4L2Grabber.cpp +++ b/libsrc/grabber/v4l2/V4L2Grabber.cpp @@ -47,6 +47,12 @@ V4L2Grabber::V4L2Grabber(const QString & device , _frameDecimation(std::max(1, frameDecimation)) , _noSignalCounterThreshold(50) , _noSignalThresholdColor(ColorRgb{0,0,0}) + , _signalDetectionEnabled(true) + , _noSignalDetected(false) + , _x_frac_min(0.25) + , _y_frac_min(0.25) + , _x_frac_max(0.75) + , _y_frac_max(0.75) , _currentFrame(0) , _noSignalCounter(0) , _streamNotifier(nullptr) @@ -54,11 +60,6 @@ V4L2Grabber::V4L2Grabber(const QString & device , _log(Logger::getInstance("V4L2:"+device)) , _initialized(false) , _deviceAutoDiscoverEnabled(false) - , _noSignalDetected(false) - , _x_frac_min(0.25) - , _y_frac_min(0.25) - , _x_frac_max(0.75) - , _y_frac_max(0.75) { _imageResampler.setHorizontalPixelDecimation(std::max(1, horizontalPixelDecimation)); @@ -809,50 +810,57 @@ void V4L2Grabber::process_image(const uint8_t * data) Image image(0, 0); _imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image); - // check signal (only in center of the resulting image, because some grabbers have noise values along the borders) - bool noSignal = true; - - // top left - unsigned xOffset = image.width() * _x_frac_min; - unsigned yOffset = image.height() * _y_frac_min; - - // bottom right - unsigned xMax = image.width() * _x_frac_max; - unsigned yMax = image.height() * _y_frac_max; - - - for (unsigned x = xOffset; noSignal && x < xMax; ++x) + if (_signalDetectionEnabled) { - for (unsigned y = yOffset; noSignal && y < yMax; ++y) + // check signal (only in center of the resulting image, because some grabbers have noise values along the borders) + bool noSignal = true; + + // top left + unsigned xOffset = image.width() * _x_frac_min; + unsigned yOffset = image.height() * _y_frac_min; + + // bottom right + unsigned xMax = image.width() * _x_frac_max; + unsigned yMax = image.height() * _y_frac_max; + + + for (unsigned x = xOffset; noSignal && x < xMax; ++x) { - noSignal &= (ColorRgb&)image(x, y) <= _noSignalThresholdColor; + for (unsigned y = yOffset; noSignal && y < yMax; ++y) + { + noSignal &= (ColorRgb&)image(x, y) <= _noSignalThresholdColor; + } } - } - if (noSignal) - { - ++_noSignalCounter; + if (noSignal) + { + ++_noSignalCounter; + } + else + { + if (_noSignalCounter >= _noSignalCounterThreshold) + { + _noSignalDetected = true; + Info(_log, "Signal detected"); + } + + _noSignalCounter = 0; + } + + if ( _noSignalCounter < _noSignalCounterThreshold) + { + emit newFrame(image); + } + else if (_noSignalCounter == _noSignalCounterThreshold) + { + _noSignalDetected = false; + Info(_log, "Signal lost"); + } } else - { - if (_noSignalCounter >= _noSignalCounterThreshold) - { - _noSignalDetected = true; - Info(_log, "Signal detected"); - } - - _noSignalCounter = 0; - } - - if (_noSignalCounter < _noSignalCounterThreshold) { emit newFrame(image); } - else if (_noSignalCounter == _noSignalCounterThreshold) - { - _noSignalDetected = false; - Info(_log, "Signal lost"); - } } int V4L2Grabber::xioctl(int request, void *arg) @@ -877,3 +885,13 @@ void V4L2Grabber::throw_errno_exception(const QString & error) { throw std::runtime_error(QString(error + " error code " + QString::number(errno) + ", " + strerror(errno)).toStdString()); } + +void V4L2Grabber::setSignalDetectionEnable(bool enable) +{ + _signalDetectionEnabled = enable; +} + +bool V4L2Grabber::getSignalDetectionEnabled() +{ + return _signalDetectionEnabled; +} diff --git a/libsrc/grabber/v4l2/V4L2Wrapper.cpp b/libsrc/grabber/v4l2/V4L2Wrapper.cpp index 3ff2664f..b56e8243 100644 --- a/libsrc/grabber/v4l2/V4L2Wrapper.cpp +++ b/libsrc/grabber/v4l2/V4L2Wrapper.cpp @@ -122,3 +122,13 @@ void V4L2Wrapper::action() { checkSources(); } + +void V4L2Wrapper::setSignalDetectionEnable(bool enable) +{ + _grabber.setSignalDetectionEnable(enable); +} + +bool V4L2Wrapper::getSignalDetectionEnable() +{ + return _grabber.getSignalDetectionEnabled(); +} diff --git a/libsrc/hyperion/schemas/hyperion.schema-2.json b/libsrc/hyperion/schemas/hyperion.schema-2.json index ba852278..8ea9f066 100644 --- a/libsrc/hyperion/schemas/hyperion.schema-2.json +++ b/libsrc/hyperion/schemas/hyperion.schema-2.json @@ -544,6 +544,13 @@ "append" : "edt_append_pixel", "propertyOrder" : 15 }, + "signalDetection" : + { + "type" : "boolean", + "title" : "edt_conf_v4l2_signalDetection_title", + "default" : true, + "propertyOrder" : 16 + }, "redSignalThreshold" : { "type" : "number", @@ -553,7 +560,7 @@ "default" : 0.1, "step" : 0.005, "append" : "edt_append_percent", - "propertyOrder" : 16 + "propertyOrder" : 17 }, "greenSignalThreshold" : { @@ -564,7 +571,7 @@ "default" : 0.1, "step" : 0.025, "append" : "edt_append_percent", - "propertyOrder" : 17 + "propertyOrder" : 18 }, "blueSignalThreshold" : { @@ -575,7 +582,7 @@ "default" : 0.1, "step" : 0.005, "append" : "edt_append_percent", - "propertyOrder" : 18 + "propertyOrder" : 19 }, "signalDetectionVerticalOffsetMin" : { @@ -586,7 +593,7 @@ "default" : 0.1, "step" : 0.005, "append" : "edt_append_percent", - "propertyOrder" : 19 + "propertyOrder" : 20 }, "signalDetectionVerticalOffsetMax" : { @@ -597,7 +604,7 @@ "default" : 0.1, "step" : 0.005, "append" : "edt_append_percent", - "propertyOrder" : 20 + "propertyOrder" : 21 }, "signalDetectionHorizontalOffsetMin" : { @@ -608,7 +615,7 @@ "default" : 0.1, "step" : 0.005, "append" : "edt_append_percent", - "propertyOrder" : 21 + "propertyOrder" : 22 }, "signalDetectionHorizontalOffsetMax" : { @@ -619,7 +626,7 @@ "default" : 0.1, "step" : 0.005, "append" : "edt_append_percent", - "propertyOrder" : 22 + "propertyOrder" : 23 } }, "additionalProperties" : false diff --git a/src/hyperion-v4l2/hyperion-v4l2.cpp b/src/hyperion-v4l2/hyperion-v4l2.cpp index a159f95c..aaca69a9 100644 --- a/src/hyperion-v4l2/hyperion-v4l2.cpp +++ b/src/hyperion-v4l2/hyperion-v4l2.cpp @@ -72,6 +72,7 @@ int main(int argc, char** argv) IntOption & argFrameDecimation = parser.add ('f', "frame-decimator", "Decimation factor for the video frames [default=%1]", "1"); BooleanOption & argScreenshot = parser.add(0x0, "screenshot", "Take a single screenshot, save it to file and quit"); + BooleanOption & argSignalDetection = parser.add('s', "signal-detection-disabled", "disable signal detection"); DoubleOption & argSignalThreshold = parser.add ('t', "signal-threshold", "The signal threshold for detecting the presence of a signal. Value should be between 0.0 and 1.0.", QString(), 0.0, 1.0); DoubleOption & argRedSignalThreshold = parser.add (0x0, "red-threshold", "The red signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)"); DoubleOption & argGreenSignalThreshold= parser.add (0x0, "green-threshold", "The green signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)"); @@ -120,6 +121,7 @@ int main(int argc, char** argv) std::max(1, argSizeDecimation.getInt(parser))); // set signal detection + grabber.setSignalDetectionEnable(! parser.isSet(argSignalDetection)); grabber.setSignalThreshold( std::min(1.0, std::max(0.0, parser.isSet(argRedSignalThreshold) ? argRedSignalThreshold.getDouble(parser) : argSignalThreshold.getDouble(parser))), std::min(1.0, std::max(0.0, parser.isSet(argGreenSignalThreshold) ? argGreenSignalThreshold.getDouble(parser) : argSignalThreshold.getDouble(parser))), diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index f9051e81..453b738d 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -612,6 +612,7 @@ void HyperionDaemon::createGrabberV4L2() grabberConfig["cropRight"].toInt(0), grabberConfig["cropTop"].toInt(0), grabberConfig["cropBottom"].toInt(0)); + grabber->setSignalDetectionEnable(grabberConfig["signalDetection"].toBool(true)); grabber->setSignalDetectionOffset( grabberConfig["signalDetectionHorizontalOffsetMin"].toDouble(0.25), grabberConfig["signalDetectionVerticalOffsetMin"].toDouble(0.25),