From 305a2e856a152afa7729319f32ed353304a485cb Mon Sep 17 00:00:00 2001 From: johan Date: Sun, 26 Jan 2014 15:51:02 +0100 Subject: [PATCH] Added signal detection option Former-commit-id: 1bd70d02814d6238c488db765d9d25af655c1872 --- dependencies/build/getoptPlusPlus/getoptpp.cc | 2 +- src/hyperion-v4l2/CMakeLists.txt | 4 + src/hyperion-v4l2/ImageHandler.cpp | 41 ++++++++++ src/hyperion-v4l2/ImageHandler.h | 34 ++++++++ src/hyperion-v4l2/VideoStandardParameter.h | 36 +++++++++ src/hyperion-v4l2/hyperion-v4l2.cpp | 81 ++++++------------- 6 files changed, 140 insertions(+), 58 deletions(-) create mode 100644 src/hyperion-v4l2/ImageHandler.cpp create mode 100644 src/hyperion-v4l2/ImageHandler.h create mode 100644 src/hyperion-v4l2/VideoStandardParameter.h diff --git a/dependencies/build/getoptPlusPlus/getoptpp.cc b/dependencies/build/getoptPlusPlus/getoptpp.cc index 9c385585..e7b8b420 100644 --- a/dependencies/build/getoptPlusPlus/getoptpp.cc +++ b/dependencies/build/getoptPlusPlus/getoptpp.cc @@ -120,7 +120,7 @@ void OptionsParser::usage() const { for(i = parameters.parameters.begin(); i != parameters.parameters.end(); i++) { - cerr.width(31); + cerr.width(33); cerr << std::left << " " + (*i)->usageLine(); cerr.width(40); diff --git a/src/hyperion-v4l2/CMakeLists.txt b/src/hyperion-v4l2/CMakeLists.txt index 58b62ac1..5e5de616 100644 --- a/src/hyperion-v4l2/CMakeLists.txt +++ b/src/hyperion-v4l2/CMakeLists.txt @@ -17,12 +17,15 @@ include_directories( set(Hyperion_V4L2_HEADERS V4L2Grabber.h ProtoConnection.h + ImageHandler.h + VideoStandardParameter.h ) set(Hyperion_V4L2_SOURCES hyperion-v4l2.cpp V4L2Grabber.cpp ProtoConnection.cpp + ImageHandler.cpp ) set(Hyperion_V4L2_PROTOS @@ -42,6 +45,7 @@ add_executable(hyperion-v4l2 target_link_libraries(hyperion-v4l2 getoptPlusPlus + blackborder hyperion-utils ${PROTOBUF_LIBRARIES} pthread diff --git a/src/hyperion-v4l2/ImageHandler.cpp b/src/hyperion-v4l2/ImageHandler.cpp new file mode 100644 index 00000000..a100fd5d --- /dev/null +++ b/src/hyperion-v4l2/ImageHandler.cpp @@ -0,0 +1,41 @@ +// hyperion-v4l2 includes +#include "ImageHandler.h" + +ImageHandler::ImageHandler(const std::string &address, int priority, double signalThreshold, bool skipProtoReply) : + _priority(priority), + _connection(address), + _signalThreshold(signalThreshold), + _signalProcessor(100, 50, 0, uint8_t(std::min(255, std::max(0, int(255*signalThreshold))))) +{ + _connection.setSkipReply(skipProtoReply); +} + +void ImageHandler::receiveImage(const Image &image) +{ + // check if we should do signal detection + if (_signalThreshold < 0) + { + _connection.setImage(image, _priority, 200); + } + else + { + if (_signalProcessor.process(image)) + { + std::cout << "Signal state = " << (_signalProcessor.getCurrentBorder().unknown ? "off" : "on") << std::endl; + } + + // consider an unknown border as no signal + // send the image to Hyperion if we have a signal + if (!_signalProcessor.getCurrentBorder().unknown) + { + _connection.setImage(image, _priority, 200); + } + } +} + +void ImageHandler::imageCallback(void *arg, const Image &image) +{ + ImageHandler * handler = static_cast(arg); + handler->receiveImage(image); +} + diff --git a/src/hyperion-v4l2/ImageHandler.h b/src/hyperion-v4l2/ImageHandler.h new file mode 100644 index 00000000..e0e0adbf --- /dev/null +++ b/src/hyperion-v4l2/ImageHandler.h @@ -0,0 +1,34 @@ +// blackborder includes +#include + +// hyperion-v4l includes +#include "ProtoConnection.h" + +/// This class handles callbacks from the V4L2 grabber +class ImageHandler +{ +public: + ImageHandler(const std::string & address, int priority, double signalThreshold, bool skipProtoReply); + + /// Handle a single image + /// @param image The image to process + void receiveImage(const Image & image); + + /// static function used to direct callbacks to a ImageHandler object + /// @param arg This should be an ImageHandler instance + /// @param image The image to process + static void imageCallback(void * arg, const Image & image); + +private: + /// Priority for calls to Hyperion + const int _priority; + + /// Hyperion proto connection object + ProtoConnection _connection; + + /// Threshold used for signal detection + double _signalThreshold; + + /// Blackborder detector which is used as a signal detector (unknown border = no signal) + hyperion::BlackBorderProcessor _signalProcessor; +}; diff --git a/src/hyperion-v4l2/VideoStandardParameter.h b/src/hyperion-v4l2/VideoStandardParameter.h new file mode 100644 index 00000000..7d711ccf --- /dev/null +++ b/src/hyperion-v4l2/VideoStandardParameter.h @@ -0,0 +1,36 @@ +// getoptPlusPLus includes +#include + +using namespace vlofgren; + +/// Data parameter for the video standard +typedef vlofgren::PODParameter VideoStandardParameter; + +namespace vlofgren { + /// Translates a string (as passed on the commandline) to a color standard + /// + /// @param[in] s The string (as passed on the commandline) + /// @return The color standard + /// @throws Parameter::ParameterRejected If the string did not result in a video standard + template<> + V4L2Grabber::VideoStandard VideoStandardParameter::validate(const std::string& s) throw (Parameter::ParameterRejected) + { + QString input = QString::fromStdString(s).toLower(); + + if (input == "pal") + { + return V4L2Grabber::PAL; + } + else if (input == "ntsc") + { + return V4L2Grabber::NTSC; + } + else if (input == "no-change") + { + return V4L2Grabber::NO_CHANGE; + } + + throw Parameter::ParameterRejected("Invalid value for video standard. Valid values are: PAL, NTSC, and NO-CHANGE"); + return V4L2Grabber::NO_CHANGE; + } +} diff --git a/src/hyperion-v4l2/hyperion-v4l2.cpp b/src/hyperion-v4l2/hyperion-v4l2.cpp index 0df6ca95..cf82ba35 100644 --- a/src/hyperion-v4l2/hyperion-v4l2.cpp +++ b/src/hyperion-v4l2/hyperion-v4l2.cpp @@ -9,43 +9,17 @@ // getoptPlusPLus includes #include +// blackborder includes +#include + +// hyperion-v4l2 includes #include "V4L2Grabber.h" #include "ProtoConnection.h" +#include "VideoStandardParameter.h" +#include "ImageHandler.h" using namespace vlofgren; -/// Data parameter for the video standard -typedef vlofgren::PODParameter VideoStandardParameter; - -namespace vlofgren { - /// Translates a string (as passed on the commandline) to a color standard - /// - /// @param[in] s The string (as passed on the commandline) - /// @return The color standard - /// @throws Parameter::ParameterRejected If the string did not result in a video standard - template<> - V4L2Grabber::VideoStandard VideoStandardParameter::validate(const std::string& s) throw (Parameter::ParameterRejected) - { - QString input = QString::fromStdString(s).toLower(); - - if (input == "pal") - { - return V4L2Grabber::PAL; - } - else if (input == "ntsc") - { - return V4L2Grabber::NTSC; - } - else if (input == "no-change") - { - return V4L2Grabber::NO_CHANGE; - } - - throw Parameter::ParameterRejected("Invalid value for video standard. Valid values are: PAL, NTSC, and NO-CHANGE"); - return V4L2Grabber::NO_CHANGE; - } -} - // save the image as screenshot void saveScreenshot(void *, const Image & image) { @@ -54,13 +28,6 @@ void saveScreenshot(void *, const Image & image) pngImage.save("screenshot.png"); } -// send the image to Hyperion -void sendImage(void * arg, const Image & image) -{ - ProtoConnection * connection = static_cast(arg); - connection->setImage(image, 50, 200); -} - int main(int argc, char** argv) { try @@ -69,20 +36,21 @@ int main(int argc, char** argv) OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface"); ParameterSet & parameters = optionParser.getParameters(); - StringParameter & argDevice = parameters.add ('d', "device", "The device to use [default=/dev/video0]"); - VideoStandardParameter & argVideoStandard = parameters.add('v', "video-standard", "The used video standard. Valid values are PAL. NYSC, or NO-CHANGE [default=PAL]"); - IntParameter & argInput = parameters.add (0x0, "input", "Input channel (optional)"); - IntParameter & argWidth = parameters.add (0x0, "width", "Try to set the width of the video input (optional)"); - IntParameter & argHeight = parameters.add (0x0, "height", "Try to set the height of the video input (optional)"); - IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides in the picture before decimation [default=0]"); - IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom in the picture before decimation [default=0]"); - IntParameter & argSizeDecimation = parameters.add ('s', "size-decimator", "Decimation factor for the output size [default=1]"); - IntParameter & argFrameDecimation = parameters.add ('f', "frame-decimator","Decimation factor for the video frames [default=1]"); - SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); - StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); - IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); - SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); - SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); + StringParameter & argDevice = parameters.add ('d', "device", "The device to use [default=/dev/video0]"); + VideoStandardParameter & argVideoStandard = parameters.add('v', "video-standard", "The used video standard. Valid values are PAL. NYSC, or NO-CHANGE [default=PAL]"); + IntParameter & argInput = parameters.add (0x0, "input", "Input channel (optional)"); + IntParameter & argWidth = parameters.add (0x0, "width", "Try to set the width of the video input (optional)"); + IntParameter & argHeight = parameters.add (0x0, "height", "Try to set the height of the video input (optional)"); + IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides in the picture before decimation [default=0]"); + IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom in the picture before decimation [default=0]"); + IntParameter & argSizeDecimation = parameters.add ('s', "size-decimator", "Decimation factor for the output size [default=1]"); + IntParameter & argFrameDecimation = parameters.add ('f', "frame-decimator", "Decimation factor for the video frames [default=1]"); + SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); + DoubleParameter & argSignalThreshold = parameters.add ('t', "signal-threshold", "The signal threshold for detecting the presence of a signal. Value should be between 0.0 and 1.0."); + StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); + IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); // set defaults argDevice.setDefault("/dev/video0"); @@ -96,6 +64,7 @@ int main(int argc, char** argv) argFrameDecimation.setDefault(1); argAddress.setDefault("127.0.0.1:19445"); argPriority.setDefault(800); + argSignalThreshold.setDefault(-1); // parse all options optionParser.parse(argc, const_cast(argv)); @@ -126,10 +95,8 @@ int main(int argc, char** argv) } else { - ProtoConnection connection(argAddress.getValue()); - connection.setSkipReply(argSkipReply.isSet()); - - grabber.setCallback(&sendImage, &connection); + ImageHandler handler(argAddress.getValue(), argPriority.getValue(), argSignalThreshold.getValue(), argSkipReply.isSet()); + grabber.setCallback(&ImageHandler::imageCallback, &handler); grabber.capture(); } grabber.stop();