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

@@ -1,18 +1,27 @@
// Hyperion-AmLogic includes
#include "AmlogicWrapper.h"
// Linux includes
#include <unistd.h>
AmlogicWrapper::AmlogicWrapper(unsigned grabWidth, unsigned grabHeight) :
_thread(this),
_grabber(grabWidth, grabHeight)
AmlogicWrapper::AmlogicWrapper( int updateRate_Hz,
int pixelDecimation,
int cropLeft, int cropRight,
int cropTop, int cropBottom
) :
_timer(this),
_grabber()
{
_thread.setObjectName("AmlogicWrapperThread");
_grabber.setFramerate(updateRate_Hz);
_grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom);
_grabber.setPixelDecimation(pixelDecimation);
_timer.setTimerType(Qt::PreciseTimer);
_timer.setSingleShot(false);
_timer.setInterval(_grabber.getUpdateInterval());
// Connect capturing to the timeout signal of the timer
connect(&_thread, SIGNAL (started()), this, SLOT(capture()));
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
}
const Image<ColorRgb> & AmlogicWrapper::getScreenshot()
@@ -23,20 +32,27 @@ const Image<ColorRgb> & AmlogicWrapper::getScreenshot()
void AmlogicWrapper::start()
{
_thread.start();
_timer.start();
}
void AmlogicWrapper::stop()
{
_thread.quit();
_timer.stop();
}
bool AmlogicWrapper::screenInit()
{
return _grabber.setupScreen();
}
void AmlogicWrapper::capture()
{
while (_thread.isRunning())
{
_grabber.grabFrame(_screenshot);
emit sig_screenshot(_screenshot);
usleep(1 * 1000);
}
_grabber.grabFrame(_screenshot);
emit sig_screenshot(_screenshot);
}
void AmlogicWrapper::setVideoMode(VideoMode mode)
{
_grabber.setVideoMode(mode);
}

View File

@@ -1,15 +1,19 @@

// QT includes
#include <QThread>
#include <QTimer>
// Hyperion-Dispmanx includes
#include <grabber/AmlogicGrabber.h>
#include <hyperion/GrabberWrapper.h>
class AmlogicWrapper : public QObject
{
Q_OBJECT
public:
AmlogicWrapper(unsigned grabWidth, unsigned grabHeight);
AmlogicWrapper( int updateRate_Hz=GrabberWrapper::DEFAULT_RATE_HZ,
int pixelDecimation=GrabberWrapper::DEFAULT_PIXELDECIMATION,
int cropLeft=0, int cropRight=0,
int cropTop=0, int cropBottom=0
);
const Image<ColorRgb> & getScreenshot();
@@ -20,9 +24,18 @@ public:
void stop();
bool screenInit();
signals:
void sig_screenshot(const Image<ColorRgb> & screenshot);
public slots:
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(VideoMode videoMode);
private slots:
///
/// Performs screenshot captures and publishes the capture screenshot on the screenshot signal.
@@ -30,8 +43,9 @@ private slots:
void capture();
private:
/// The QT thread to generate capture-publish events
QThread _thread;
/// The QT timer to generate capture-publish events
QTimer _timer;
/// The grabber for creating screenshots
AmlogicGrabber _grabber;

View File

@@ -26,6 +26,9 @@ void saveScreenshot(QString filename, const Image<ColorRgb> & image)
int main(int argc, char ** argv)
{
Logger *log = Logger::getInstance("AMLOGIC");
Logger::setLogLevel(Logger::INFO);
std::cout
<< "hyperion-aml:" << std::endl
<< "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl
@@ -40,24 +43,64 @@ int main(int argc, char ** argv)
// create the option parser and initialize all parser
Parser parser("AmLogic capture application for Hyperion. Will automatically search a Hyperion server if -a option isn't used. Please note that if you have more than one server running it's more or less random which one will be used.");
IntOption & argWidth = parser.add<IntOption> (0x0, "width", "Width of the captured image [default: %1]", "160", 160, 4096);
IntOption & argHeight = parser.add<IntOption> (0x0, "height", "Height of the captured image [default: %1]", "160", 160, 4096);
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", QString::number(GrabberWrapper::DEFAULT_RATE_HZ), GrabberWrapper::DEFAULT_MIN_GRAB_RATE_HZ, GrabberWrapper::DEFAULT_MAX_GRAB_RATE_HZ);
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output image size [default=%1]", QString::number(GrabberWrapper::DEFAULT_PIXELDECIMATION), 1);
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
BooleanOption & argDebug = parser.add<BooleanOption>(0x0, "debug", "Enable debug logging");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
// parse all options
parser.process(app);
// check if debug logging is required
if (parser.isSet(argDebug))
{
Logger::setLogLevel(Logger::DEBUG);
}
// check if we need to display the usage. exit if we do.
if (parser.isSet(argHelp))
{
parser.showHelp(0);
}
AmlogicWrapper amlWrapper(argWidth.getInt(parser), argHeight.getInt(parser));
AmlogicWrapper amlWrapper(
argFps.getInt(parser),
argSizeDecimation.getInt(parser),
argCropLeft.getInt(parser),
argCropRight.getInt(parser),
argCropTop.getInt(parser),
argCropBottom.getInt(parser)
);
if (!amlWrapper.screenInit())
{
Error(log, "Failed to initialise the screen/display for this grabber");
return -1;
}
// set 3D mode if applicable
if (parser.isSet(arg3DSBS))
{
amlWrapper.setVideoMode(VideoMode::VIDEO_3DSBS);
}
else if (parser.isSet(arg3DTAB))
{
amlWrapper.setVideoMode(VideoMode::VIDEO_3DTAB);
}
if (parser.isSet(argScreenshot))
{
@@ -94,8 +137,8 @@ int main(int argc, char ** argv)
}
catch (const std::runtime_error & e)
{
// An error occured. Display error and quit
Error(Logger::getInstance("AMLOGIC"), "%s", e.what());
// An error occurred. Display error and quit
Error(log, "%s", e.what());
return -1;
}
return 0;

View File

@@ -1,19 +1,21 @@
// Hyperion-Dispmanx includes
#include "DispmanxWrapper.h"
DispmanxWrapper::DispmanxWrapper(unsigned grabWidth, unsigned grabHeight,
VideoMode videoMode,
unsigned cropLeft, unsigned cropRight,
unsigned cropTop, unsigned cropBottom,
unsigned updateRate_Hz) :
DispmanxWrapper::DispmanxWrapper( int updateRate_Hz,
int pixelDecimation,
int cropLeft, int cropRight,
int cropTop, int cropBottom
) :
_timer(this),
_grabber(grabWidth, grabHeight)
_grabber()
{
_grabber.setVideoMode(videoMode);
_grabber.setFramerate(updateRate_Hz);
_grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom);
_grabber.setPixelDecimation(pixelDecimation);
_timer.setTimerType(Qt::PreciseTimer);
_timer.setSingleShot(false);
_timer.setInterval(updateRate_Hz);
_timer.setInterval(_grabber.getUpdateInterval());
// Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
@@ -35,8 +37,19 @@ void DispmanxWrapper::stop()
_timer.stop();
}
bool DispmanxWrapper::screenInit()
{
return _grabber.setupScreen();
}
void DispmanxWrapper::capture()
{
_grabber.grabFrame(_screenshot);
emit sig_screenshot(_screenshot);
}
void DispmanxWrapper::setVideoMode(VideoMode mode)
{
_grabber.setVideoMode(mode);
}

View File

@@ -2,18 +2,18 @@
// QT includes
#include <QTimer>
// Hyperion-Dispmanx includes
#include <grabber/DispmanxFrameGrabber.h>
#include <hyperion/GrabberWrapper.h>
class DispmanxWrapper : public QObject
{
Q_OBJECT
public:
DispmanxWrapper(unsigned grabWidth, unsigned grabHeight,
VideoMode videoMode,
unsigned cropLeft, unsigned cropRight,
unsigned cropTop, unsigned cropBottom,
unsigned updateRate_Hz);
DispmanxWrapper( int updateRate_Hz=GrabberWrapper::DEFAULT_RATE_HZ,
int pixelDecimation=GrabberWrapper::DEFAULT_PIXELDECIMATION,
int cropLeft=0, int cropRight=0,
int cropTop=0, int cropBottom=0
);
const Image<ColorRgb> & getScreenshot();
@@ -24,9 +24,18 @@ public:
void stop();
bool screenInit();
signals:
void sig_screenshot(const Image<ColorRgb> & screenshot);
public slots:
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(VideoMode videoMode);
private slots:
///
/// Performs a single screenshot capture and publishes the capture screenshot on the screenshot

View File

@@ -5,6 +5,7 @@
#include <flatbufserver/FlatBufferConnection.h>
#include "DispmanxWrapper.h"
#include <hyperion/GrabberWrapper.h>
#include "HyperionConfig.h"
#include <commandline/Parser.h>
@@ -26,6 +27,9 @@ void saveScreenshot(QString filename, const Image<ColorRgb> & image)
int main(int argc, char ** argv)
{
Logger *log = Logger::getInstance("DISPMANX");
Logger::setLogLevel(Logger::INFO);
std::cout
<< "hyperion-dispmanx:" << std::endl
<< "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl
@@ -40,37 +44,34 @@ int main(int argc, char ** argv)
// create the option parser and initialize all parameters
Parser parser("Dispmanx capture application for Hyperion. Will automatically search a Hyperion server if -a option isn't used. Please note that if you have more than one server running it's more or less random which one will be used.");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", "10", 1, 25);
IntOption & argWidth = parser.add<IntOption> (0x0, "width", "Width of the captured image [default: %1]", "64", 64);
IntOption & argHeight = parser.add<IntOption> (0x0, "height", "Height of the captured image [default: %1]", "64", 64);
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", QString::number(GrabberWrapper::DEFAULT_RATE_HZ), GrabberWrapper::DEFAULT_MIN_GRAB_RATE_HZ, GrabberWrapper::DEFAULT_MAX_GRAB_RATE_HZ);
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output image size [default=%1]", QString::number(GrabberWrapper::DEFAULT_PIXELDECIMATION), 1);
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "pixels to remove on left after grabbing");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "pixels to remove on right after grabbing");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "pixels to remove on top after grabbing");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "pixels to remove on bottom after grabbing");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
BooleanOption & argDebug = parser.add<BooleanOption>(0x0, "debug", "Enable debug logging");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
// parse all options
parser.process(app);
VideoMode videoMode = VideoMode::VIDEO_2D;
// check if debug logging is required
if (parser.isSet(argDebug))
{
Logger::setLogLevel(Logger::DEBUG);
}
if (parser.isSet(arg3DSBS))
{
videoMode = VideoMode::VIDEO_3DSBS;
}
else if (parser.isSet(arg3DTAB))
{
videoMode = VideoMode::VIDEO_3DTAB;
}
// check if we need to display the usage. exit if we do.
if (parser.isSet(argHelp))
@@ -80,14 +81,29 @@ int main(int argc, char ** argv)
// Create the dispmanx grabbing stuff
DispmanxWrapper dispmanxWrapper(
argWidth.getInt(parser),
argHeight.getInt(parser),
videoMode,
argFps.getInt(parser),
argSizeDecimation.getInt(parser),
argCropLeft.getInt(parser),
argCropRight.getInt(parser),
argCropTop.getInt(parser),
argCropBottom.getInt(parser),
1000 / argFps.getInt(parser));
argCropBottom.getInt(parser)
);
if (!dispmanxWrapper.screenInit())
{
Error(log, "Failed to initialise the screen/display for this grabber");
return -1;
}
// set 3D mode if applicable
if (parser.isSet(arg3DSBS))
{
dispmanxWrapper.setVideoMode(VideoMode::VIDEO_3DSBS);
}
else if (parser.isSet(arg3DTAB))
{
dispmanxWrapper.setVideoMode(VideoMode::VIDEO_3DTAB);
}
if (parser.isSet(argScreenshot))
{
@@ -123,8 +139,8 @@ int main(int argc, char ** argv)
}
catch (const std::runtime_error & e)
{
// An error occured. Display error and quit
Error(Logger::getInstance("DISPMANXGRABBER"), "%s", e.what());
// An error occurred. Display error and quit
Error(log, "%s", e.what());
return -1;
}

View File

@@ -1,14 +1,22 @@
// Hyperion-AmLogic includes
#include "FramebufferWrapper.h"
FramebufferWrapper::FramebufferWrapper(const QString & device, unsigned grabWidth, unsigned grabHeight, unsigned updateRate_Hz) :
_timer(this),
_grabber(device,grabWidth, grabHeight)
FramebufferWrapper::FramebufferWrapper( int updateRate_Hz,
const QString & device,
int pixelDecimation,
int cropLeft, int cropRight,
int cropTop, int cropBottom
) :
_timer(this),
_grabber(device)
{
_grabber.setFramerate(updateRate_Hz);
_grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom);
_grabber.setPixelDecimation(pixelDecimation);
_timer.setTimerType(Qt::PreciseTimer);
_timer.setSingleShot(false);
_timer.setInterval(updateRate_Hz);
_timer.setInterval(_grabber.getUpdateInterval());
// Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
@@ -30,9 +38,19 @@ void FramebufferWrapper::stop()
_timer.stop();
}
bool FramebufferWrapper::screenInit()
{
return _grabber.setupScreen();
}
void FramebufferWrapper::capture()
{
_grabber.grabFrame(_screenshot);
emit sig_screenshot(_screenshot);
}
void FramebufferWrapper::setVideoMode(VideoMode mode)
{
_grabber.setVideoMode(mode);
}

View File

@@ -3,14 +3,20 @@
// QT includes
#include <QTimer>
// Hyperion-Dispmanx includes
#include <grabber/FramebufferFrameGrabber.h>
#include <hyperion/GrabberWrapper.h>
class FramebufferWrapper : public QObject
{
Q_OBJECT
public:
FramebufferWrapper(const QString & device, unsigned grabWidth, unsigned grabHeight, unsigned updateRate_Hz);
FramebufferWrapper( int updateRate_Hz=GrabberWrapper::DEFAULT_RATE_HZ,
const QString & device = "/dev/fb0",
int pixelDecimation=GrabberWrapper::DEFAULT_PIXELDECIMATION,
int cropLeft=0, int cropRight=0,
int cropTop=0, int cropBottom=0
);
const Image<ColorRgb> & getScreenshot();
@@ -21,9 +27,18 @@ public:
void stop();
bool screenInit();
signals:
void sig_screenshot(const Image<ColorRgb> & screenshot);
public slots:
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(VideoMode videoMode);
private slots:
///
/// Performs a single screenshot capture and publishes the capture screenshot on the screenshot signal.

View File

@@ -4,6 +4,9 @@
#include <flatbufserver/FlatBufferConnection.h>
#include "FramebufferWrapper.h"
#include <hyperion/GrabberWrapper.h>
#include "HyperionConfig.h"
#include <commandline/Parser.h>
// ssdp discover
@@ -14,7 +17,7 @@
using namespace commandline;
// save the image as screenshot
void saveScreenshot(QString filename, const Image<ColorRgb> & image)
void saveScreenshot(const QString & filename, const Image<ColorRgb> & image)
{
// store as PNG
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
@@ -23,6 +26,14 @@ void saveScreenshot(QString filename, const Image<ColorRgb> & image)
int main(int argc, char ** argv)
{
Logger *log = Logger::getInstance("FRAMEBUFFER");
Logger::setLogLevel(Logger::INFO);
std::cout
<< "hyperion-framebuffer:" << std::endl
<< "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
DefaultSignalHandler::install();
QCoreApplication app(argc, argv);
@@ -32,26 +43,67 @@ int main(int argc, char ** argv)
// create the option parser and initialize all parameters
Parser parser("FrameBuffer capture application for Hyperion. Will automatically search a Hyperion server if -a option isn't used. Please note that if you have more than one server running it's more or less random which one will be used.");
Option & argDevice = parser.add<Option> ('d', "device", "Set the video device [default: %1]", "/dev/video0");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", "10", 1, 25);
IntOption & argWidth = parser.add<IntOption> (0x0, "width", "Width of the captured image [default: %1]", "160", 160);
IntOption & argHeight = parser.add<IntOption> (0x0, "height", "Height of the captured image [default: %1]", "160", 160);
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
Option & argDevice = parser.add<Option> ('d', "device", "Set the framebuffer device [default: %1]", "/dev/fb0");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", QString::number(GrabberWrapper::DEFAULT_RATE_HZ), GrabberWrapper::DEFAULT_MIN_GRAB_RATE_HZ, GrabberWrapper::DEFAULT_MAX_GRAB_RATE_HZ);
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output image size [default=%1]", QString::number(GrabberWrapper::DEFAULT_PIXELDECIMATION), 1);
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
BooleanOption & argDebug = parser.add<BooleanOption>(0x0, "debug", "Enable debug logging");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
// parse all options
parser.process(app);
// check if debug logging is required
if (parser.isSet(argDebug))
{
Logger::setLogLevel(Logger::DEBUG);
}
// check if we need to display the usage. exit if we do.
if (parser.isSet(argHelp))
{
parser.showHelp(0);
}
FramebufferWrapper fbWrapper(argDevice.value(parser), argWidth.getInt(parser), argHeight.getInt(parser), 1000 / argFps.getInt(parser));
FramebufferWrapper fbWrapper(
argFps.getInt(parser),
argDevice.value(parser),
argSizeDecimation.getInt(parser),
argCropLeft.getInt(parser),
argCropRight.getInt(parser),
argCropTop.getInt(parser),
argCropBottom.getInt(parser)
);
if (!fbWrapper.screenInit())
{
Error(log, "Failed to initialise the screen/display for this grabber");
return -1;
}
// set 3D mode if applicable
if (parser.isSet(arg3DSBS))
{
fbWrapper.setVideoMode(VideoMode::VIDEO_3DSBS);
}
else if (parser.isSet(arg3DTAB))
{
fbWrapper.setVideoMode(VideoMode::VIDEO_3DTAB);
}
if (parser.isSet(argScreenshot))
{
@@ -88,8 +140,8 @@ int main(int argc, char ** argv)
}
catch (const std::runtime_error & e)
{
// An error occured. Display error and quit
Error(Logger::getInstance("FRAMEBUFFER"), "%s", e.what());
// An error occurred. Display error and quit
Error(log, "%s", e.what());
return -1;
}
return 0;

View File

@@ -1,13 +1,22 @@
// Hyperion-AmLogic includes
#include "OsxWrapper.h"
OsxWrapper::OsxWrapper(unsigned display, unsigned grabWidth, unsigned grabHeight, unsigned updateRate_Hz) :
_timer(this),
_grabber(display,grabWidth, grabHeight)
OsxWrapper::OsxWrapper( int updateRate_Hz,
int display,
int pixelDecimation,
int cropLeft, int cropRight,
int cropTop, int cropBottom
) :
_timer(this),
_grabber(display)
{
_grabber.setFramerate(updateRate_Hz);
_grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom);
_grabber.setPixelDecimation(pixelDecimation);
_timer.setTimerType(Qt::PreciseTimer);
_timer.setSingleShot(false);
_timer.setInterval(updateRate_Hz);
_timer.setInterval(_grabber.getUpdateInterval());
// Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
@@ -19,6 +28,11 @@ const Image<ColorRgb> & OsxWrapper::getScreenshot()
return _screenshot;
}
bool OsxWrapper::displayInit()
{
return _grabber.setupDisplay();
}
void OsxWrapper::start()
{
_timer.start();
@@ -34,3 +48,9 @@ void OsxWrapper::capture()
_grabber.grabFrame(_screenshot);
emit sig_screenshot(_screenshot);
}
void OsxWrapper::setVideoMode(VideoMode mode)
{
_grabber.setVideoMode(mode);
}

View File

@@ -2,14 +2,20 @@
// QT includes
#include <QTimer>
// Hyperion-Dispmanx includes
#include <grabber/OsxFrameGrabber.h>
#include <hyperion/GrabberWrapper.h>
class OsxWrapper : public QObject
{
Q_OBJECT
public:
OsxWrapper(unsigned display, unsigned grabWidth, unsigned grabHeight, unsigned updateRate_Hz);
OsxWrapper( int updateRate_Hz=GrabberWrapper::DEFAULT_RATE_HZ,
int display=kCGDirectMainDisplay,
int pixelDecimation=GrabberWrapper::DEFAULT_PIXELDECIMATION,
int cropLeft=0, int cropRight=0,
int cropTop=0, int cropBottom=0
);
const Image<ColorRgb> & getScreenshot();
@@ -20,9 +26,18 @@ public:
void stop();
bool displayInit();
signals:
void sig_screenshot(const Image<ColorRgb> & screenshot);
public slots:
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(VideoMode videoMode);
private slots:
///
/// Performs a single screenshot capture and publishes the capture screenshot on the screenshot signal.

View File

@@ -25,6 +25,9 @@ void saveScreenshot(QString filename, const Image<ColorRgb> & image)
int main(int argc, char ** argv)
{
Logger *log = Logger::getInstance("OSXGRABBER");
Logger::setLogLevel(Logger::INFO);
DefaultSignalHandler::install();
QCoreApplication app(argc, argv);
@@ -34,27 +37,67 @@ int main(int argc, char ** argv)
// create the option parser and initialize all parameters
Parser parser("OSX capture application for Hyperion. Will automatically search a Hyperion server if -a option isn't used. Please note that if you have more than one server running it's more or less random which one will be used.");
IntOption & argDisplay = parser.add<IntOption> ('d', "display", "Set the display to capture [default: %1]", "0");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", "10", 1, 25);
IntOption & argWidth = parser.add<IntOption> (0x0, "width", "Width of the captured image [default: %1]", "160", 160);
IntOption & argHeight = parser.add<IntOption> (0x0, "height", "Height of the captured image [default: %1]", "160", 160);
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
IntOption & argDisplay = parser.add<IntOption> ('d', "display", "Set the display to capture [default: %1]", "0");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", QString::number(GrabberWrapper::DEFAULT_RATE_HZ), GrabberWrapper::DEFAULT_MIN_GRAB_RATE_HZ, GrabberWrapper::DEFAULT_MAX_GRAB_RATE_HZ);
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output image size [default=%1]", QString::number(GrabberWrapper::DEFAULT_PIXELDECIMATION), 1);
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
BooleanOption & argDebug = parser.add<BooleanOption>(0x0, "debug", "Enable debug logging");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
// parse all arguments
parser.process(app);
// check if debug logging is required
if (parser.isSet(argDebug))
{
Logger::setLogLevel(Logger::DEBUG);
}
// check if we need to display the usage. exit if we do.
if (parser.isSet(argHelp))
{
parser.showHelp(0);
}
OsxWrapper osxWrapper
(argDisplay.getInt(parser), argWidth.getInt(parser), argHeight.getInt(parser), 1000 / argFps.getInt(parser));
OsxWrapper osxWrapper (
argFps.getInt(parser),
argDisplay.getInt(parser),
argSizeDecimation.getInt(parser),
argCropLeft.getInt(parser),
argCropRight.getInt(parser),
argCropTop.getInt(parser),
argCropBottom.getInt(parser)
);
if (!osxWrapper.displayInit())
{
Error(log, "Failed to initialise the screen/display for this grabber");
return -1;
}
// set 3D mode if applicable
if (parser.isSet(arg3DSBS))
{
osxWrapper.setVideoMode(VideoMode::VIDEO_3DSBS);
}
else if (parser.isSet(arg3DTAB))
{
osxWrapper.setVideoMode(VideoMode::VIDEO_3DTAB);
}
if (parser.isSet(argScreenshot))
{
@@ -87,12 +130,12 @@ int main(int argc, char ** argv)
// Start the application
app.exec();
}
}
}
catch (const std::runtime_error & e)
{
// An error occured. Display error and quit
Error(Logger::getInstance("OSXGRABBER"), "%s", e.what());
// An error occurred. Display error and quit
Error(log, "%s", e.what());
return -1;
}
return 0;

View File

@@ -1,12 +1,22 @@
// Hyperion-qt includes
#include "QtWrapper.h"
QtWrapper::QtWrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation, int display) :
_timer(this),
_grabber(cropLeft, cropRight, cropTop, cropBottom, pixelDecimation, display)
QtWrapper::QtWrapper( int updateRate_Hz,
int display,
int pixelDecimation,
int cropLeft, int cropRight,
int cropTop, int cropBottom
) :
_timer(this),
_grabber(display, cropLeft, cropRight, cropTop, cropBottom)
{
_timer.setInterval(grabInterval);
_grabber.setFramerate(updateRate_Hz);
_grabber.setPixelDecimation(pixelDecimation);
_timer.setTimerType(Qt::PreciseTimer);
_timer.setSingleShot(false);
_timer.setInterval(_grabber.getUpdateInterval());
// Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
}
@@ -27,6 +37,11 @@ void QtWrapper::stop()
_timer.stop();
}
bool QtWrapper::displayInit()
{
return _grabber.setupDisplay();
}
void QtWrapper::capture()
{
if(unsigned(_grabber.getImageWidth()) != unsigned(_screenshot.width()) || unsigned(_grabber.getImageHeight()) != unsigned(_screenshot.height()))

View File

@@ -5,15 +5,20 @@
// Hyperion-Qt includes
#include <grabber/QtGrabber.h>
//Utils includes
#include <utils/VideoMode.h>
#include <hyperion/GrabberWrapper.h>
class QtWrapper : public QObject
{
Q_OBJECT
public:
QtWrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation, int display);
QtWrapper( int updateRate_Hz=GrabberWrapper::DEFAULT_RATE_HZ,
int display=0,
int pixelDecimation=GrabberWrapper::DEFAULT_PIXELDECIMATION,
int cropLeft=0, int cropRight=0,
int cropTop=0, int cropBottom=0
);
const Image<ColorRgb> & getScreenshot();
@@ -24,6 +29,8 @@ public:
void stop();
bool displayInit();
signals:
void sig_screenshot(const Image<ColorRgb> & screenshot);

View File

@@ -6,6 +6,8 @@
#include "QtWrapper.h"
#include <utils/ColorRgb.h>
#include <utils/Image.h>
#include "HyperionConfig.h"
#include <commandline/Parser.h>
//flatbuf sending
@@ -26,49 +28,88 @@ void saveScreenshot(QString filename, const Image<ColorRgb> & image)
int main(int argc, char ** argv)
{
Logger *log = Logger::getInstance("QTGRABBER");
Logger::setLogLevel(Logger::INFO);
std::cout
<< "hyperion-qt:" << std::endl
<< "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
//QCoreApplication app(argc, argv);
QGuiApplication app(argc, argv);
try
{
// create the option parser and initialize all parameters
Parser parser("Qt interface capture application for Hyperion");
Parser parser("Qt interface capture application for Hyperion. Will automatically search a Hyperion server if -a option isn't used. Please note that if you have more than one server running it's more or less random which one will be used.");
IntOption & argDisplay = parser.add<IntOption> ('d', "display", "Set the display to capture [default: %1]", "0");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", "10", 1, 25);
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output image size [default=%1]", "8", 1);
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
IntOption & argDisplay = parser.add<IntOption> ('d', "display", "Set the display to capture [default: %1]", "0");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", QString::number(GrabberWrapper::DEFAULT_RATE_HZ), GrabberWrapper::DEFAULT_MIN_GRAB_RATE_HZ, GrabberWrapper::DEFAULT_MAX_GRAB_RATE_HZ);
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output image size [default=%1]", QString::number(GrabberWrapper::DEFAULT_PIXELDECIMATION), 1);
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
BooleanOption & argDebug = parser.add<BooleanOption>(0x0, "debug", "Enable debug logging");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
// parse all arguments
parser.process(app);
// check if debug logging is required
if (parser.isSet(argDebug))
{
Logger::setLogLevel(Logger::DEBUG);
}
// check if we need to display the usage. exit if we do.
if (parser.isSet(argHelp))
{
parser.showHelp(0);
}
QtWrapper grabber(
1000 / argFps.getInt(parser),
QtWrapper qtWrapper(
argFps.getInt(parser),
argDisplay.getInt(parser),
argSizeDecimation.getInt(parser),
argCropLeft.getInt(parser),
argCropRight.getInt(parser),
argCropTop.getInt(parser),
argCropBottom.getInt(parser),
argSizeDecimation.getInt(parser),
argDisplay.getInt(parser));
argCropBottom.getInt(parser)
);
if (!qtWrapper.displayInit())
{
Error(log, "Failed to initialise the screen/display for this grabber");
return -1;
}
// set 3D mode if applicable
if (parser.isSet(arg3DSBS))
{
qtWrapper.setVideoMode(VideoMode::VIDEO_3DSBS);
}
else if (parser.isSet(arg3DTAB))
{
qtWrapper.setVideoMode(VideoMode::VIDEO_3DTAB);
}
if (parser.isSet(argScreenshot))
{
// Capture a single screenshot and finish
const Image<ColorRgb> &screenshot = grabber.getScreenshot();
const Image<ColorRgb> &screenshot = qtWrapper.getScreenshot();
saveScreenshot("screenshot.png", screenshot);
}
else
@@ -89,10 +130,10 @@ int main(int argc, char ** argv)
FlatBufferConnection flatbuf("Qt Standalone", address, argPriority.getInt(parser), parser.isSet(argSkipReply));
// Connect the screen capturing to flatbuf connection processing
QObject::connect(&grabber, SIGNAL(sig_screenshot(const Image<ColorRgb> &)), &flatbuf, SLOT(setImage(Image<ColorRgb>)));
QObject::connect(&qtWrapper, SIGNAL(sig_screenshot(const Image<ColorRgb> &)), &flatbuf, SLOT(setImage(Image<ColorRgb>)));
// Start the capturing
grabber.start();
qtWrapper.start();
// Start the application
app.exec();
@@ -100,8 +141,8 @@ int main(int argc, char ** argv)
}
catch (const std::runtime_error & e)
{
// An error occured. Display error and quit
Error(Logger::getInstance("QTGRABBER"), "%s", e.what());
// An error occurred. Display error and quit
Error(log, "%s", e.what());
return -1;
}
return 0;

View File

@@ -31,7 +31,7 @@ using namespace commandline;
int main(int argc, char** argv)
{
Logger *log = Logger::getInstance("V4L2GRABBER");
Logger::setLogLevel(Logger::WARNING);
Logger::setLogLevel(Logger::INFO);
std::cout
<< "hyperion-v4l2:" << std::endl
@@ -56,35 +56,39 @@ int main(int argc, char** argv)
IntOption & argInput = parser.add<IntOption> ('i', "input", "The device input [default: %1]", "0");
SwitchOption<VideoStandard> & argVideoStandard= parser.add<SwitchOption<VideoStandard>>('v', "video-standard", "The used video standard. Valid values are PAL, NTSC, SECAM or no-change. [default: %1]", "no-change");
SwitchOption<PixelFormat> & argPixelFormat = parser.add<SwitchOption<PixelFormat>> (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, RGB32, MJPEG or no-change. [default: %1]", "no-change");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", "15", 1, 25);
IntOption & argWidth = parser.add<IntOption> (0x0, "width", "Width of the captured image [default: %1]", "160", 160);
IntOption & argHeight = parser.add<IntOption> (0x0, "height", "Height of the captured image [default: %1]", "160", 160);
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", QString::number(GrabberWrapper::DEFAULT_RATE_HZ), GrabberWrapper::DEFAULT_MIN_GRAB_RATE_HZ, GrabberWrapper::DEFAULT_MAX_GRAB_RATE_HZ);
SwitchOption<FlipMode> & argFlipMode = parser.add<SwitchOption<FlipMode>>(0x0, "flip-mode", "The used image flip mode. Valid values are HORIZONTAL, VERTICAL, BOTH or no-change. [default: %1]", "no-change");
IntOption & argWidth = parser.add<IntOption> ('w', "width", "Width of the captured image [default: %1]", "640", 640);
IntOption & argHeight = parser.add<IntOption> ('h', "height", "Height of the captured image [default: %1]", "480", 480);
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output image size [default=%1]", QString::number(GrabberWrapper::DEFAULT_PIXELDECIMATION), 1);
IntOption & argCropWidth = parser.add<IntOption> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: %1]", "0");
IntOption & argCropHeight = parser.add<IntOption> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: %1]", "0");
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output size [default=%1]", "6", 1);
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
BooleanOption & argSignalDetection = parser.add<BooleanOption>('s', "signal-detection-disabled", "disable signal detection");
DoubleOption & argSignalThreshold = parser.add<DoubleOption> ('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);
BooleanOption & argSignalDetection = parser.add<BooleanOption>(0x0, "signal-detection-disabled", "disable signal detection");
DoubleOption & argSignalThreshold = parser.add<DoubleOption> (0x0, "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<DoubleOption> (0x0, "red-threshold", "The red signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
DoubleOption & argGreenSignalThreshold= parser.add<DoubleOption> (0x0, "green-threshold", "The green signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
DoubleOption & argBlueSignalThreshold = parser.add<DoubleOption> (0x0, "blue-threshold", "The blue signal threshold. Value should be between 0.0 and 1.0. (overrides --signal-threshold)");
DoubleOption & argSignalHorizontalMin = parser.add<DoubleOption> (0x0, "signal-horizontal-min", "area for signal detection - horizontal minimum offset value. Values between 0.0 and 1.0");
DoubleOption & argSignalVerticalMin = parser.add<DoubleOption> (0x0, "signal-vertical-min" , "area for signal detection - vertical minimum offset value. Values between 0.0 and 1.0");
DoubleOption & argSignalHorizontalMax = parser.add<DoubleOption> (0x0, "signal-horizontal-max", "area for signal detection - horizontal maximum offset value. Values between 0.0 and 1.0");
DoubleOption & argSignalVerticalMax = parser.add<DoubleOption> (0x0, "signal-vertical-max" , "area for signal detection - vertical maximum offset value. Values between 0.0 and 1.0");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
BooleanOption & argScreenshot = parser.add<BooleanOption>('S', "screenshot", "Take a single screenshot, save it to file and quit");
BooleanOption & argDebug = parser.add<BooleanOption>(0x0, "debug", "Enable debug logging");
BooleanOption & argHelp = parser.add<BooleanOption>(0x0, "help", "Show this help message and exit");
argVideoStandard.addSwitch("pal", VideoStandard::PAL);
argVideoStandard.addSwitch("ntsc", VideoStandard::NTSC);
@@ -99,9 +103,20 @@ int main(int argc, char** argv)
#endif
argPixelFormat.addSwitch("no-change", PixelFormat::NO_CHANGE);
argFlipMode.addSwitch("horizontal", FlipMode::HORIZONTAL);
argFlipMode.addSwitch("vertical", FlipMode::VERTICAL);
argFlipMode.addSwitch("both", FlipMode::BOTH);
argFlipMode.addSwitch("no-change", FlipMode::NO_CHANGE);
// parse all options
parser.process(app);
// check if debug logging is required
if (parser.isSet(argDebug))
{
Logger::setLogLevel(Logger::DEBUG);
}
// check if we need to display the usage. exit if we do.
if (parser.isSet(argHelp))
{
@@ -109,15 +124,34 @@ int main(int argc, char** argv)
}
// initialize the grabber
V4L2Grabber grabber(
argDevice.value(parser),
argWidth.getInt(parser),
argHeight.getInt(parser),
1000 / argFps.getInt(parser),
argInput.getInt(parser),
argVideoStandard.switchValue(parser),
argPixelFormat.switchValue(parser),
std::max(1, argSizeDecimation.getInt(parser)));
V4L2Grabber grabber;
// set device
grabber.setDevice(argDevice.value(parser), "");
// set input
grabber.setInput(argInput.getInt(parser));
// set resolution
grabber.setWidthHeight(argWidth.getInt(parser), argHeight.getInt(parser));
// set fps
if (parser.isSet(argFps))
grabber.setFramerate(argFps.getInt(parser));
// set encoding format
if (parser.isSet(argPixelFormat))
grabber.setEncoding(pixelFormatToString(argPixelFormat.switchValue(parser)));
// set video standard
if (parser.isSet(argVideoStandard))
grabber.setVideoStandard(argVideoStandard.switchValue(parser));
// set image size decimation
grabber.setPixelDecimation(std::max(1, argSizeDecimation.getInt(parser)));
// set flip mode
grabber.setFlipMode(argFlipMode.switchValue(parser));
// set signal detection
grabber.setSignalDetectionEnable(! parser.isSet(argSignalDetection));
@@ -214,7 +248,8 @@ int main(int argc, char** argv)
QObject::connect(&grabber, SIGNAL(newFrame(const Image<ColorRgb> &)), &flatbuf, SLOT(setImage(Image<ColorRgb>)));
// Start the capturing
grabber.start();
if (grabber.prepare())
grabber.start();
// Start the application
app.exec();

View File

@@ -1,13 +1,20 @@
// Hyperion-X11 includes
#include "X11Wrapper.h"
X11Wrapper::X11Wrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation) :
_timer(this),
_grabber(cropLeft, cropRight, cropTop, cropBottom, pixelDecimation)
X11Wrapper::X11Wrapper( int updateRate_Hz,
int pixelDecimation,
int cropLeft, int cropRight,
int cropTop, int cropBottom
) :
_timer(this),
_grabber(cropLeft, cropRight, cropTop, cropBottom)
{
_grabber.setFramerate(updateRate_Hz);
_grabber.setPixelDecimation(pixelDecimation);
_timer.setTimerType(Qt::PreciseTimer);
_timer.setSingleShot(false);
_timer.setInterval(grabInterval);
_timer.setInterval(_grabber.getUpdateInterval());
// Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
@@ -31,7 +38,7 @@ void X11Wrapper::stop()
bool X11Wrapper::displayInit()
{
return _grabber.Setup();
return _grabber.setupDisplay();
}
void X11Wrapper::capture()

View File

@@ -5,15 +5,18 @@
// Hyperion-X11 includes
#include <grabber/X11Grabber.h>
//Utils includes
#include <utils/VideoMode.h>
#include <hyperion/GrabberWrapper.h>
class X11Wrapper : public QObject
{
Q_OBJECT
public:
X11Wrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation);
X11Wrapper( int updateRate_Hz=GrabberWrapper::DEFAULT_RATE_HZ,
int pixelDecimation=GrabberWrapper::DEFAULT_PIXELDECIMATION,
int cropLeft=0, int cropRight=0,
int cropTop=0, int cropBottom=0
);
const Image<ColorRgb> & getScreenshot();

View File

@@ -24,7 +24,10 @@ void saveScreenshot(QString filename, const Image<ColorRgb> & image)
int main(int argc, char ** argv)
{
std::cout
Logger *log = Logger::getInstance("X11GRABBER");
Logger::setLogLevel(Logger::INFO);
std::cout
<< "hyperion-x11:" << std::endl
<< "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
@@ -37,23 +40,36 @@ int main(int argc, char ** argv)
// create the option parser and initialize all parameters
Parser parser("X11 capture application for Hyperion. Will automatically search a Hyperion server if -a option isn't used. Please note that if you have more than one server running it's more or less random which one will be used.");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", "10");
IntOption & argCropWidth = parser.add<IntOption> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: %1]", "0");
IntOption & argCropHeight = parser.add<IntOption> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: %1]", "0");
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output size [default=%1]", "8", 1);
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", QString::number(GrabberWrapper::DEFAULT_RATE_HZ), GrabberWrapper::DEFAULT_MIN_GRAB_RATE_HZ, GrabberWrapper::DEFAULT_MAX_GRAB_RATE_HZ);
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output image size [default=%1]", QString::number(GrabberWrapper::DEFAULT_PIXELDECIMATION), 1);
IntOption & argCropWidth = parser.add<IntOption> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: %1]", "0");
IntOption & argCropHeight = parser.add<IntOption> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: %1]", "0");
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
BooleanOption & argDebug = parser.add<BooleanOption>(0x0, "debug", "Enable debug logging");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
// parse all options
parser.process(app);
// check if debug logging is required
if (parser.isSet(argDebug))
{
Logger::setLogLevel(Logger::DEBUG);
}
// check if we need to display the usage. exit if we do.
if (parser.isSet(argHelp))
{
@@ -62,15 +78,29 @@ int main(int argc, char ** argv)
// Create the X11 grabbing stuff
X11Wrapper x11Wrapper(
1000 / argFps.getInt(parser),
parser.isSet(argCropLeft) ? argCropLeft.getInt(parser) : argCropWidth.getInt(parser),
parser.isSet(argCropRight) ? argCropRight.getInt(parser) : argCropWidth.getInt(parser),
parser.isSet(argCropTop) ? argCropTop.getInt(parser) : argCropHeight.getInt(parser),
parser.isSet(argCropBottom) ? argCropBottom.getInt(parser) : argCropHeight.getInt(parser),
argSizeDecimation.getInt(parser)); // decimation
argFps.getInt(parser),
argSizeDecimation.getInt(parser),
parser.isSet(argCropLeft) ? argCropLeft.getInt(parser) : argCropWidth.getInt(parser),
parser.isSet(argCropRight) ? argCropRight.getInt(parser) : argCropWidth.getInt(parser),
parser.isSet(argCropTop) ? argCropTop.getInt(parser) : argCropHeight.getInt(parser),
parser.isSet(argCropBottom) ? argCropBottom.getInt(parser) : argCropHeight.getInt(parser)
);
if (!x11Wrapper.displayInit())
{
Error(log, "Failed to initialise the screen/display for this grabber");
return -1;
}
// set 3D mode if applicable
if (parser.isSet(arg3DSBS))
{
x11Wrapper.setVideoMode(VideoMode::VIDEO_3DSBS);
}
else if (parser.isSet(arg3DTAB))
{
x11Wrapper.setVideoMode(VideoMode::VIDEO_3DTAB);
}
if (parser.isSet(argScreenshot))
{
@@ -106,8 +136,8 @@ int main(int argc, char ** argv)
}
catch (const std::runtime_error & e)
{
// An error occured. Display error and quit
Error(Logger::getInstance("X11GRABBER"), "%s", e.what());
// An error occurred. Display error and quit
Error(log, "%s", e.what());
return -1;
}

View File

@@ -1,13 +1,21 @@
// Hyperion-Xcb includes
#include "XcbWrapper.h"
XcbWrapper::XcbWrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation) :
_timer(this),
_grabber(cropLeft, cropRight, cropTop, cropBottom, pixelDecimation)
XcbWrapper::XcbWrapper( int updateRate_Hz,
int pixelDecimation,
int cropLeft, int cropRight,
int cropTop, int cropBottom
) :
_timer(this),
_grabber(cropLeft, cropRight, cropTop, cropBottom)
{
_grabber.setFramerate(updateRate_Hz);
_grabber.setPixelDecimation(pixelDecimation);
_timer.setTimerType(Qt::PreciseTimer);
_timer.setSingleShot(false);
_timer.setInterval(grabInterval);
_timer.setInterval(_grabber.getUpdateInterval());
// Connect capturing to the timeout signal of the timer
connect(&_timer, SIGNAL(timeout()), this, SLOT(capture()));
@@ -31,7 +39,7 @@ void XcbWrapper::stop()
bool XcbWrapper::displayInit()
{
return _grabber.Setup();
return _grabber.setupDisplay();
}
void XcbWrapper::capture()

View File

@@ -5,6 +5,7 @@
// Hyperion-Xcb includes
#include <grabber/XcbGrabber.h>
#include <hyperion/GrabberWrapper.h>
//Utils includes
#include <utils/VideoMode.h>
@@ -13,7 +14,11 @@ class XcbWrapper : public QObject
{
Q_OBJECT
public:
XcbWrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation);
XcbWrapper( int updateRate_Hz=GrabberWrapper::DEFAULT_RATE_HZ,
int pixelDecimation=GrabberWrapper::DEFAULT_PIXELDECIMATION,
int cropLeft=0, int cropRight=0,
int cropTop=0, int cropBottom=0
);
const Image<ColorRgb> & getScreenshot();

View File

@@ -24,7 +24,10 @@ void saveScreenshot(QString filename, const Image<ColorRgb> & image)
int main(int argc, char ** argv)
{
std::cout
Logger *log = Logger::getInstance("XCBGRABBER");
Logger::setLogLevel(Logger::INFO);
std::cout
<< "hyperion-xcb:" << std::endl
<< "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl
<< "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl;
@@ -37,23 +40,36 @@ int main(int argc, char ** argv)
// create the option parser and initialize all parameters
Parser parser("XCB capture application for Hyperion. Will automatically search a Hyperion server if -a option isn't used. Please note that if you have more than one server running it's more or less random which one will be used.");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", "10");
IntOption & argCropWidth = parser.add<IntOption> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: %1]", "0");
IntOption & argCropHeight = parser.add<IntOption> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: %1]", "0");
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output size [default=%1]", "8", 1);
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
IntOption & argFps = parser.add<IntOption> ('f', "framerate", "Capture frame rate [default: %1]", QString::number(GrabberWrapper::DEFAULT_RATE_HZ), GrabberWrapper::DEFAULT_MIN_GRAB_RATE_HZ, GrabberWrapper::DEFAULT_MAX_GRAB_RATE_HZ);
IntOption & argSizeDecimation = parser.add<IntOption> ('s', "size-decimator", "Decimation factor for the output image size [default=%1]", QString::number(GrabberWrapper::DEFAULT_PIXELDECIMATION), 1);
IntOption & argCropWidth = parser.add<IntOption> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: %1]", "0");
IntOption & argCropHeight = parser.add<IntOption> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: %1]", "0");
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
IntOption & argCropRight = parser.add<IntOption> (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
IntOption & argCropTop = parser.add<IntOption> (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");
IntOption & argCropBottom = parser.add<IntOption> (0x0, "crop-bottom", "Number of pixels to crop from the bottom of the picture before decimation (overrides --crop-height)");
BooleanOption & arg3DSBS = parser.add<BooleanOption>(0x0, "3DSBS", "Interpret the incoming video stream as 3D side-by-side");
BooleanOption & arg3DTAB = parser.add<BooleanOption>(0x0, "3DTAB", "Interpret the incoming video stream as 3D top-and-bottom");
Option & argAddress = parser.add<Option> ('a', "address", "Set the address of the hyperion server [default: %1]", "127.0.0.1:19400");
IntOption & argPriority = parser.add<IntOption> ('p', "priority", "Use the provided priority channel (suggested 100-199) [default: %1]", "150");
BooleanOption & argSkipReply = parser.add<BooleanOption>(0x0, "skip-reply", "Do not receive and check reply messages from Hyperion");
BooleanOption & argScreenshot = parser.add<BooleanOption>(0x0, "screenshot", "Take a single screenshot, save it to file and quit");
BooleanOption & argDebug = parser.add<BooleanOption>(0x0, "debug", "Enable debug logging");
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help", "Show this help message and exit");
// parse all options
parser.process(app);
// check if debug logging is required
if (parser.isSet(argDebug))
{
Logger::setLogLevel(Logger::DEBUG);
}
// check if we need to display the usage. exit if we do.
if (parser.isSet(argHelp))
{
@@ -62,15 +78,29 @@ int main(int argc, char ** argv)
// Create the XCB grabbing stuff
XcbWrapper xcbWrapper(
1000 / argFps.getInt(parser),
parser.isSet(argCropLeft) ? argCropLeft.getInt(parser) : argCropWidth.getInt(parser),
parser.isSet(argCropRight) ? argCropRight.getInt(parser) : argCropWidth.getInt(parser),
parser.isSet(argCropTop) ? argCropTop.getInt(parser) : argCropHeight.getInt(parser),
parser.isSet(argCropBottom) ? argCropBottom.getInt(parser) : argCropHeight.getInt(parser),
argSizeDecimation.getInt(parser)); // decimation
argFps.getInt(parser),
argSizeDecimation.getInt(parser),
parser.isSet(argCropLeft) ? argCropLeft.getInt(parser) : argCropWidth.getInt(parser),
parser.isSet(argCropRight) ? argCropRight.getInt(parser) : argCropWidth.getInt(parser),
parser.isSet(argCropTop) ? argCropTop.getInt(parser) : argCropHeight.getInt(parser),
parser.isSet(argCropBottom) ? argCropBottom.getInt(parser) : argCropHeight.getInt(parser)
);
if (!xcbWrapper.displayInit())
{
Error(log, "Failed to initialise the screen/display for this grabber");
return -1;
}
// set 3D mode if applicable
if (parser.isSet(arg3DSBS))
{
xcbWrapper.setVideoMode(VideoMode::VIDEO_3DSBS);
}
else if (parser.isSet(arg3DTAB))
{
xcbWrapper.setVideoMode(VideoMode::VIDEO_3DTAB);
}
if (parser.isSet(argScreenshot))
{
@@ -106,8 +136,8 @@ int main(int argc, char ** argv)
}
catch (const std::runtime_error & e)
{
// An error occured. Display error and quit
Error(Logger::getInstance("XCBGRABBER"), "%s", e.what());
// An error occurred. Display error and quit
Error(log, "%s", e.what());
return -1;
}

View File

@@ -12,7 +12,7 @@ find_package(Qt5Widgets REQUIRED)
if (WIN32)
include(${CMAKE_SOURCE_DIR}/cmake/win/win_rc.cmake)
generate_win_rc_file(hyperiond)
endif()
endif(WIN32)
add_executable(hyperiond
console.h
@@ -27,7 +27,7 @@ add_executable(hyperiond
# promote hyperiond as GUI app
if (WIN32)
target_link_options(hyperiond PUBLIC /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup)
endif()
endif(WIN32)
target_link_libraries(hyperiond
commandline
@@ -52,14 +52,14 @@ endif()
if (ENABLE_AVAHI)
target_link_libraries(hyperiond bonjour)
endif ()
endif (ENABLE_AVAHI)
if (ENABLE_AMLOGIC)
target_link_libraries(hyperiond
Qt5::Core
pcre16 dl z
)
endif()
endif(ENABLE_AMLOGIC)
if (ENABLE_DISPMANX)
IF ( "${PLATFORM}" MATCHES rpi)
@@ -70,47 +70,51 @@ if (ENABLE_DISPMANX)
SET(BCM_LIBRARIES "")
ENDIF()
target_link_libraries(hyperiond dispmanx-grabber)
endif ()
endif (ENABLE_DISPMANX)
if (ENABLE_FB)
target_link_libraries(hyperiond framebuffer-grabber)
endif ()
endif (ENABLE_FB)
if (ENABLE_OSX)
target_link_libraries(hyperiond osx-grabber)
endif ()
endif (ENABLE_OSX)
if (ENABLE_V4L2)
target_link_libraries(hyperiond v4l2-grabber)
endif ()
if (ENABLE_MF)
target_link_libraries(hyperiond mf-grabber)
endif (ENABLE_MF)
if (ENABLE_AMLOGIC)
target_link_libraries(hyperiond amlogic-grabber)
endif ()
endif (ENABLE_AMLOGIC)
if (ENABLE_X11)
if(APPLE)
include_directories("/opt/X11/include")
endif(APPLE)
target_link_libraries(hyperiond x11-grabber)
endif ()
endif (ENABLE_X11)
if (ENABLE_XCB)
target_link_libraries(hyperiond xcb-grabber)
endif ()
endif (ENABLE_XCB)
if (ENABLE_QT)
target_link_libraries(hyperiond qt-grabber)
endif ()
endif (ENABLE_QT)
if (ENABLE_DX)
include_directories(${DIRECTX9_INCLUDE_DIRS})
target_link_libraries(hyperiond directx-grabber)
endif ()
endif (ENABLE_DX)
if (ENABLE_CEC)
target_link_libraries(hyperiond cechandler)
endif ()
endif (ENABLE_CEC)
if(NOT WIN32)
install ( TARGETS hyperiond DESTINATION "share/hyperion/bin" COMPONENT "Hyperion" )

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);
}
});

View File

@@ -10,10 +10,10 @@
typedef QObject DispmanxWrapper;
#endif
#ifdef ENABLE_V4L2
#include <grabber/V4L2Wrapper.h>
#if defined(ENABLE_V4L2) || defined(ENABLE_MF)
#include <grabber/VideoWrapper.h>
#else
typedef QObject V4L2Wrapper;
typedef QObject VideoWrapper;
#endif
#ifdef ENABLE_FB
@@ -151,8 +151,8 @@ private slots:
void setVideoMode(VideoMode mode);
private:
void createGrabberDispmanx();
void createGrabberAmlogic();
void createGrabberDispmanx(const QJsonObject & grabberConfig);
void createGrabberAmlogic(const QJsonObject & grabberConfig);
void createGrabberFramebuffer(const QJsonObject & grabberConfig);
void createGrabberOsx(const QJsonObject & grabberConfig);
void createGrabberX11(const QJsonObject & grabberConfig);
@@ -170,7 +170,7 @@ private:
WebServer* _webserver;
WebServer* _sslWebserver;
JsonServer* _jsonServer;
V4L2Wrapper* _v4l2Grabber;
VideoWrapper* _videoGrabber;
DispmanxWrapper* _dispmanx;
X11Wrapper* _x11Grabber;
XcbWrapper* _xcbGrabber;
@@ -184,15 +184,14 @@ private:
FlatBufferServer* _flatBufferServer;
ProtoServer* _protoServer;
unsigned _grabber_width;
unsigned _grabber_height;
unsigned _grabber_frequency;
unsigned _grabber_cropLeft;
unsigned _grabber_cropRight;
unsigned _grabber_cropTop;
unsigned _grabber_cropBottom;
int _grabber_ge2d_mode;
QString _grabber_device;
int _grabber_width;
int _grabber_height;
int _grabber_pixelDecimation;
int _grabber_frequency;
int _grabber_cropLeft;
int _grabber_cropRight;
int _grabber_cropTop;
int _grabber_cropBottom;
QString _prevType;

View File

@@ -89,11 +89,31 @@ void SysTray::createTrayIcon()
_trayIconEfxMenu = new QMenu(_trayIconMenu);
_trayIconEfxMenu->setTitle(tr("Effects"));
_trayIconEfxMenu->setIcon(QPixmap(":/effects.svg"));
// custom effects
for (auto efx : efxs)
{
QAction *efxAction = new QAction(efx.name, this);
connect(efxAction, SIGNAL(triggered()), this, SLOT(setEffect()));
_trayIconEfxMenu->addAction(efxAction);
if (efx.file.mid(0, 1) != ":")
{
QAction *efxAction = new QAction(efx.name, this);
connect(efxAction, SIGNAL(triggered()), this, SLOT(setEffect()));
_trayIconEfxMenu->addAction(efxAction);
}
}
// add seperator if custom effects exists
if (!_trayIconEfxMenu->isEmpty())
_trayIconEfxMenu->addSeparator();
// build in effects
for (auto efx : efxs)
{
if (efx.file.mid(0, 1) == ":")
{
QAction *efxAction = new QAction(efx.name, this);
connect(efxAction, SIGNAL(triggered()), this, SLOT(setEffect()));
_trayIconEfxMenu->addAction(efxAction);
}
}
#ifdef _WIN32
@@ -121,13 +141,13 @@ void SysTray::createTrayIcon()
bool SysTray::getCurrentAutorunState()
{
QSettings reg("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
if (reg.value("Hyperion", 0).toString() == qApp->applicationFilePath().replace('/', '\\'))
if (reg.value("Hyperion", 0).toString() == qApp->applicationFilePath().replace('/', '\\'))
{
autorunAction->setText(tr("&Disable autostart"));
return true;
return true;
}
autorunAction->setText(tr("&Enable autostart"));
autorunAction->setText(tr("&Enable autostart"));
return false;
}
#endif
@@ -147,7 +167,7 @@ void SysTray::setColor(const QColor & color)
{
std::vector<ColorRgb> rgbColor{ ColorRgb{ (uint8_t)color.red(), (uint8_t)color.green(), (uint8_t)color.blue() } };
_hyperion->setColor(1 ,rgbColor, 0);
_hyperion->setColor(PriorityMuxer::FG_PRIORITY,rgbColor, Effect::ENDLESS);
}
void SysTray::showColorDialog()