From 9eff6384cc71d91ff85994b1d85d2d8c403aeac7 Mon Sep 17 00:00:00 2001 From: redPanther Date: Sat, 12 Aug 2017 07:55:32 +0200 Subject: [PATCH] grabber api and feature unification (#462) * move setvideomode to common place * implement more croping and 3d support * more api unification * more refactoring * osx fix * next step * add a mock for osx grabber. Now it is possible to test compile on none osx platforms. * more unifications ... * remove obsolete includes and grabbers are not dyn allocated. dispmanx needs rework an probaly not work atm * first version of dispmanx mock. it compiles, but outputs a black image * now dispmanx mock works! * activate mocks in travis linux build prepare dispmanx to rgb image out * dispmanx now with image rgb output fix deadlock with w/h -1 in grabber v4l cleanups * fix json * fix some runtime stuff * Update FramebufferWrapper.cpp fix missing code * unify grabframe * 3d and croping for amlogic * fix setimage not working * make use of templates save some codelines * save more code lines --- .travis/travis_build.sh | 5 + CMakeLists.txt | 5 +- config/hyperion.config.json.commented | 4 +- config/hyperion.config.json.default | 4 +- include/commandline/SwitchOption.h | 52 +++--- include/grabber/AmlogicGrabber.h | 7 +- include/grabber/AmlogicWrapper.h | 27 +-- include/grabber/DispmanxFrameGrabber.h | 31 ++-- include/grabber/DispmanxFrameGrabberMock.h | 40 ++++ include/grabber/DispmanxWrapper.h | 31 +--- include/grabber/FramebufferFrameGrabber.h | 2 +- include/grabber/FramebufferWrapper.h | 30 +-- include/grabber/OsxFrameGrabber.h | 6 +- include/grabber/OsxFrameGrabberMock.h | 34 ++++ include/grabber/OsxWrapper.h | 31 +--- include/grabber/V4L2Grabber.h | 14 +- include/grabber/V4L2Wrapper.h | 18 +- include/grabber/X11Grabber.h | 10 +- include/grabber/X11Wrapper.h | 40 +--- include/hyperion/Grabber.h | 15 +- include/hyperion/GrabberWrapper.h | 53 +++++- include/hyperion/Hyperion.h | 2 +- include/hyperion/ImageProcessor.h | 71 +++++--- include/hyperion/PriorityMuxer.h | 3 +- include/utils/ImageResampler.h | 2 +- libsrc/grabber/amlogic/AmlogicGrabber.cpp | 21 +-- libsrc/grabber/amlogic/AmlogicWrapper.cpp | 50 +---- libsrc/grabber/dispmanx/CMakeLists.txt | 9 +- .../grabber/dispmanx/DispmanxFrameGrabber.cpp | 57 +++--- .../dispmanx/DispmanxFrameGrabberMock.cpp | 107 +++++++++++ libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 51 +----- .../framebuffer/FramebufferFrameGrabber.cpp | 30 ++- .../framebuffer/FramebufferWrapper.cpp | 40 +--- libsrc/grabber/osx/OsxFrameGrabber.cpp | 16 +- libsrc/grabber/osx/OsxFrameGrabberMock.cpp | 126 +++++++++++++ libsrc/grabber/osx/OsxWrapper.cpp | 41 +---- libsrc/grabber/v4l2/V4L2Grabber.cpp | 9 +- libsrc/grabber/v4l2/V4L2Wrapper.cpp | 29 +-- libsrc/grabber/x11/X11Grabber.cpp | 171 +++++++----------- libsrc/grabber/x11/X11Wrapper.cpp | 72 +------- libsrc/hyperion/Grabber.cpp | 48 ++++- libsrc/hyperion/GrabberWrapper.cpp | 36 +++- libsrc/hyperion/Hyperion.cpp | 11 +- libsrc/hyperion/ImageProcessor.cpp | 2 +- libsrc/hyperion/ImageToLedsMap.cpp | 2 + libsrc/hyperion/PriorityMuxer.cpp | 17 +- .../hyperion/schema/schema-grabberV4L2.json | 8 +- libsrc/protoserver/CMakeLists.txt | 2 + libsrc/utils/ImageResampler.cpp | 14 +- .../JSONRPC_schema/schema-videomode.json | 2 +- src/hyperion-aml/AmlogicWrapper.cpp | 6 +- src/hyperion-aml/AmlogicWrapper.h | 3 +- src/hyperion-dispmanx/CMakeLists.txt | 7 +- src/hyperion-dispmanx/DispmanxWrapper.cpp | 6 +- src/hyperion-dispmanx/DispmanxWrapper.h | 4 +- src/hyperion-x11/X11Wrapper.cpp | 8 +- src/hyperion-x11/X11Wrapper.h | 2 + src/hyperion-x11/hyperion-x11.cpp | 2 +- src/hyperiond/hyperiond.cpp | 11 +- src/hyperiond/hyperiond.h | 3 +- test/dispmanx2png/CMakeLists.txt | 18 +- 61 files changed, 830 insertions(+), 748 deletions(-) create mode 100644 include/grabber/DispmanxFrameGrabberMock.h create mode 100644 include/grabber/OsxFrameGrabberMock.h create mode 100644 libsrc/grabber/dispmanx/DispmanxFrameGrabberMock.cpp create mode 100644 libsrc/grabber/osx/OsxFrameGrabberMock.cpp diff --git a/.travis/travis_build.sh b/.travis/travis_build.sh index 186f1b93..e1f864d0 100755 --- a/.travis/travis_build.sh +++ b/.travis/travis_build.sh @@ -30,6 +30,11 @@ cd build [ "${TRAVIS_EVENT_TYPE:-}" != 'cron' -a -z "${TRAVIS_TAG:-}" ] && PLATFORM=${PLATFORM}-dev cmake -DPLATFORM=$PLATFORM -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_INSTALL_PREFIX=/usr .. || exit 2 +if [[ "$TRAVIS_OS_NAME" == 'linux' ]] +then + # activate dispmanx and osx mocks + cmake -DENABLE_OSX=ON -DENABLE_DISPMANX=ON .. || exit 5 +fi echo "compile jobs: ${JOBS:=4}" make -j ${JOBS} || exit 3 diff --git a/CMakeLists.txt b/CMakeLists.txt index bc257f96..2af512c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,9 @@ if ( "${PLATFORM}" MATCHES "-dev" ) SET ( DEFAULT_TESTS ON ) endif() +STRING( TOUPPER "-DPLATFORM_${PLATFORM}" PLATFORM_DEFINE) +STRING( REPLACE "-DEV" "" PLATFORM_DEFINE "${PLATFORM_DEFINE}" ) +ADD_DEFINITIONS( ${PLATFORM_DEFINE} ) # set the build options option(ENABLE_AMLOGIC "Enable the AMLOGIC video grabber" ${DEFAULT_AMLOGIC} ) @@ -240,7 +243,7 @@ add_definitions(${QT_DEFINITIONS}) # link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) #endif() -if(ENABLE_OSX) +if(APPLE) set(CMAKE_EXE_LINKER_FLAGS "-framework CoreGraphics") endif() diff --git a/config/hyperion.config.json.commented b/config/hyperion.config.json.commented index d3577238..7634b336 100644 --- a/config/hyperion.config.json.commented +++ b/config/hyperion.config.json.commented @@ -133,8 +133,8 @@ "device" : "auto", "input" : 0, "standard" : "PAL", - "width" : -1, - "height" : -1, + "width" : 0, + "height" : 0, "frameDecimation" : 2, "sizeDecimation" : 8, "priority" : 240, diff --git a/config/hyperion.config.json.default b/config/hyperion.config.json.default index a79e2357..7b3f6076 100644 --- a/config/hyperion.config.json.default +++ b/config/hyperion.config.json.default @@ -64,8 +64,8 @@ "device" : "auto", "input" : 0, "standard" : "PAL", - "width" : -1, - "height" : -1, + "width" : 0, + "height" : 0, "frameDecimation" : 2, "sizeDecimation" : 8, "priority" : 240, diff --git a/include/commandline/SwitchOption.h b/include/commandline/SwitchOption.h index 6133e3bd..54060c51 100644 --- a/include/commandline/SwitchOption.h +++ b/include/commandline/SwitchOption.h @@ -11,33 +11,37 @@ class SwitchOption: public Option { public: SwitchOption(const QString &name, - const QString &description = QString(), - const QString &valueName = QString(), - const QString &defaultValue = QString(), - const QMap &switches=QMap()) - : Option(name, description, valueName, defaultValue), _switches(switches) - {} - SwitchOption(const QStringList &names, - const QString &description = QString(), - const QString &valueName = QString(), - const QString &defaultValue = QString(), - const QMap &switches=QMap()) - : Option(names, description, valueName, defaultValue), _switches(switches) - {} - SwitchOption(const QCommandLineOption &other, const QMap &switches) - : Option(other), _switches(switches) - {} + const QString &description = QString(), + const QString &valueName = QString(), + const QString &defaultValue = QString(), + const QMap &switches=QMap()) + : Option(name, description, valueName, defaultValue), _switches(switches) + {} - const QMap &getSwitches() const{return _switches;}; - virtual bool validate(Parser &parser, QString &switch_) override{return hasSwitch(switch_);} - bool hasSwitch(const QString &switch_){return _switches.contains(switch_.toLower());} - void setSwitches(const QMap &_switches){this->_switches = _switches;} - void addSwitch(const QString &switch_, T value=T()){_switches[switch_.toLower()] = value;} - void removeSwitch(const QString &switch_){_switches.remove(switch_.toLower());} - T & switchValue(Parser & parser){return _switches[value(parser).toLower()];} + SwitchOption(const QStringList &names, + const QString &description = QString(), + const QString &valueName = QString(), + const QString &defaultValue = QString(), + const QMap &switches=QMap()) + : Option(names, description, valueName, defaultValue), _switches(switches) + {} + + SwitchOption(const QCommandLineOption &other, const QMap &switches) + : Option(other), _switches(switches) + {} + + virtual ~SwitchOption() {} + + const QMap &getSwitches() const { return _switches; } + virtual bool validate(Parser &parser, QString &switch_) override { return hasSwitch(switch_); } + bool hasSwitch(const QString &switch_) { return _switches.contains(switch_.toLower()); } + void setSwitches(const QMap &_switches) { this->_switches = _switches; } + void addSwitch(const QString &switch_, T value=T()) { _switches[switch_.toLower()] = value; } + void removeSwitch(const QString &switch_) { _switches.remove(switch_.toLower()); } + T & switchValue(Parser & parser) { return _switches[value(parser).toLower()]; } protected: - QMap _switches; + QMap _switches; }; } diff --git a/include/grabber/AmlogicGrabber.h b/include/grabber/AmlogicGrabber.h index 1b9dd8cc..acc731e7 100755 --- a/include/grabber/AmlogicGrabber.h +++ b/include/grabber/AmlogicGrabber.h @@ -29,14 +29,17 @@ public: /// height) /// @return Zero on success else negative /// - int grabFrame(Image & image); + int grabFrame(Image & image); +private: /** * Returns true if video is playing over the amlogic chip * @return True if video is playing else false */ bool isVideoPlaying(); -private: + /** The snapshot/capture device of the amlogic video chip */ int _amlogicCaptureDev; + + Image _image; }; diff --git a/include/grabber/AmlogicWrapper.h b/include/grabber/AmlogicWrapper.h index 82b8243e..bfcc9552 100644 --- a/include/grabber/AmlogicWrapper.h +++ b/include/grabber/AmlogicWrapper.h @@ -1,16 +1,7 @@ #pragma once -// Utils includes -#include -#include -#include -#include #include - -// Forward class declaration -class AmlogicGrabber; -class Hyperion; -class ImageProcessor; +#include /// /// The DispmanxWrapper uses an instance of the DispmanxFrameGrabber to obtain ImageRgb's from the @@ -34,7 +25,7 @@ public: /// /// Destructor of this dispmanx frame grabber. Releases any claimed resources. /// - virtual ~AmlogicWrapper(); + virtual ~AmlogicWrapper() {}; public slots: /// @@ -42,19 +33,7 @@ public slots: /// virtual void action(); - virtual void setVideoMode(const VideoMode mode); - private: - /// The update rate [Hz] - const int _updateInterval_ms; - /// The timeout of the led colors [ms] - const int _timeout_ms; - - /// The image used for grabbing frames - Image _image; /// The actual grabber - AmlogicGrabber * _grabber; - - /// The list with computed led colors - std::vector _ledColors; + AmlogicGrabber _grabber; }; diff --git a/include/grabber/DispmanxFrameGrabber.h b/include/grabber/DispmanxFrameGrabber.h index 0f28e33e..3d22d3dc 100644 --- a/include/grabber/DispmanxFrameGrabber.h +++ b/include/grabber/DispmanxFrameGrabber.h @@ -1,10 +1,15 @@ #pragma once // BCM includes -#pragma GCC system_header -#include +#ifdef PLATFORM_RPI + #pragma GCC system_header + #include +#else + #include +#endif // Utils includes +#include #include #include @@ -24,15 +29,6 @@ public: DispmanxFrameGrabber(const unsigned width, const unsigned height); ~DispmanxFrameGrabber(); - /// - /// Updates the frame-grab flags as used by the VC library for frame grabbing - /// - /// @param vc_flags The snapshot grabbing mask - /// - void setFlags(const int vc_flags); - - void setCropping(const unsigned cropLeft, const unsigned cropRight, - const unsigned cropTop, const unsigned cropBottom); /// /// Captures a single snapshot of the display and writes the data to the given image. The @@ -42,9 +38,16 @@ public: /// @param[out] image The snapped screenshot (should be initialized with correct width and /// height) /// - void grabFrame(Image & image); + int grabFrame(Image & image); private: + /// + /// Updates the frame-grab flags as used by the VC library for frame grabbing + /// + /// @param vc_flags The snapshot grabbing mask + /// + void setFlags(const int vc_flags); + /// Handle to the display that is being captured DISPMANX_DISPLAY_HANDLE_T _vc_display; @@ -63,4 +66,8 @@ private: // size of the capture buffer in Pixels unsigned _captureBufferSize; + + // rgba output buffer + Image _image_rgba; + }; diff --git a/include/grabber/DispmanxFrameGrabberMock.h b/include/grabber/DispmanxFrameGrabberMock.h new file mode 100644 index 00000000..477909e8 --- /dev/null +++ b/include/grabber/DispmanxFrameGrabberMock.h @@ -0,0 +1,40 @@ +#pragma once +#ifndef PLATFORM_RPI + +#include +#include +#include + +typedef int DISPMANX_DISPLAY_HANDLE_T; +typedef Image DISPMANX_RESOURCE; +typedef DISPMANX_RESOURCE* DISPMANX_RESOURCE_HANDLE_T; +const int VC_IMAGE_RGBA32 = 1; +const int DISPMANX_SNAPSHOT_FILL = 1; +typedef int DISPMANX_TRANSFORM_T; + + +struct DISPMANX_MODEINFO_T { + int width; + int height; +}; + +struct VC_RECT_T { + int left; + int top; + int width; + int height; +}; + +void bcm_host_init(); +void bcm_host_deinit(); +int vc_dispmanx_display_open(int); +void vc_dispmanx_display_close(int); +int vc_dispmanx_display_get_info(int, DISPMANX_MODEINFO_T *vc_info); +DISPMANX_RESOURCE_HANDLE_T vc_dispmanx_resource_create(int,int width,int height, uint32_t *); +void vc_dispmanx_resource_delete(DISPMANX_RESOURCE_HANDLE_T resource); +int vc_dispmanx_resource_read_data(DISPMANX_RESOURCE_HANDLE_T vc_resource, VC_RECT_T *rectangle, void* capturePtr, unsigned capturePitch); +void vc_dispmanx_rect_set(VC_RECT_T *rectangle, int left, int top, int width, int height); +int vc_dispmanx_snapshot(int, DISPMANX_RESOURCE_HANDLE_T resource, int vc_flags); + + +#endif diff --git a/include/grabber/DispmanxWrapper.h b/include/grabber/DispmanxWrapper.h index afe0bd1d..618a8b27 100644 --- a/include/grabber/DispmanxWrapper.h +++ b/include/grabber/DispmanxWrapper.h @@ -1,16 +1,9 @@ #pragma once // Utils includes -#include -#include #include -#include -#include #include - -// Forward class declaration -class DispmanxFrameGrabber; -class ImageProcessor; +#include /// /// The DispmanxWrapper uses an instance of the DispmanxFrameGrabber to obtain ImageRgb's from the @@ -34,7 +27,7 @@ public: /// /// Destructor of this dispmanx frame grabber. Releases any claimed resources. /// - virtual ~DispmanxWrapper(); + virtual ~DispmanxWrapper() {}; public slots: /// @@ -42,25 +35,7 @@ public slots: /// virtual void action(); - void setCropping(const unsigned cropLeft, const unsigned cropRight, const unsigned cropTop, const unsigned cropBottom); - - /// - /// Set the video mode (2D/3D) - /// @param[in] mode The new video mode - /// - void setVideoMode(const VideoMode videoMode); - private: - /// The update rate [Hz] - const int _updateInterval_ms; - /// The timeout of the led colors [ms] - const int _timeout_ms; - - /// The image used for grabbing frames - Image _image; /// The actual grabber - DispmanxFrameGrabber * _grabber; - - /// The list with computed led colors - std::vector _ledColors; + DispmanxFrameGrabber _grabber; }; diff --git a/include/grabber/FramebufferFrameGrabber.h b/include/grabber/FramebufferFrameGrabber.h index d478c074..6077bb1b 100644 --- a/include/grabber/FramebufferFrameGrabber.h +++ b/include/grabber/FramebufferFrameGrabber.h @@ -28,7 +28,7 @@ public: /// @param[out] image The snapped screenshot (should be initialized with correct width and /// height) /// - void grabFrame(Image & image); + int grabFrame(Image & image); private: /// Framebuffer file descriptor diff --git a/include/grabber/FramebufferWrapper.h b/include/grabber/FramebufferWrapper.h index 4b5a80ef..164c56b3 100644 --- a/include/grabber/FramebufferWrapper.h +++ b/include/grabber/FramebufferWrapper.h @@ -1,15 +1,7 @@ #pragma once -// Utils includes -#include -#include -#include -#include #include - -// Forward class declaration -class FramebufferFrameGrabber; -class ImageProcessor; +#include /// /// The FramebufferWrapper uses an instance of the FramebufferFrameGrabber to obtain ImageRgb's from the @@ -33,7 +25,7 @@ public: /// /// Destructor of this framebuffer frame grabber. Releases any claimed resources. /// - virtual ~FramebufferWrapper(); + virtual ~FramebufferWrapper() {}; public slots: /// @@ -41,23 +33,7 @@ public slots: /// virtual void action(); - /// - /// Set the video mode (2D/3D) - /// @param[in] mode The new video mode - /// - void setVideoMode(const VideoMode videoMode); - private: - /// The update rate [Hz] - const int _updateInterval_ms; - /// The timeout of the led colors [ms] - const int _timeout_ms; - - /// The image used for grabbing frames - Image _image; /// The actual grabber - FramebufferFrameGrabber * _grabber; - - /// The list with computed led colors - std::vector _ledColors; + FramebufferFrameGrabber _grabber; }; diff --git a/include/grabber/OsxFrameGrabber.h b/include/grabber/OsxFrameGrabber.h index 1126478f..8cba6394 100644 --- a/include/grabber/OsxFrameGrabber.h +++ b/include/grabber/OsxFrameGrabber.h @@ -1,7 +1,11 @@ #pragma once // OSX includes +#ifdef __APPLE__ #include +#else +#include +#endif // Utils includes #include @@ -31,7 +35,7 @@ public: /// @param[out] image The snapped screenshot (should be initialized with correct width and /// height) /// - void grabFrame(Image & image); + int grabFrame(Image & image); private: /// display diff --git a/include/grabber/OsxFrameGrabberMock.h b/include/grabber/OsxFrameGrabberMock.h new file mode 100644 index 00000000..65bc62f3 --- /dev/null +++ b/include/grabber/OsxFrameGrabberMock.h @@ -0,0 +1,34 @@ +#pragma once +#ifndef __APPLE__ + +/* + * this is a mock up for compiling and testing osx wrapper on no osx platform. + * this will show a test image and rotate the colors. + * + */ + +#include +#include + +typedef int CGDirectDisplayID; +typedef Image CGImage; +typedef CGImage* CGImageRef; +typedef unsigned char CFData; +typedef CFData* CFDataRef; +typedef unsigned CGDisplayCount; + +const int kCGDirectMainDisplay = 0; + +void CGGetActiveDisplayList(int max, CGDirectDisplayID *displays, CGDisplayCount *displayCount); +CGImageRef CGDisplayCreateImage(CGDirectDisplayID display); +void CGImageRelease(CGImageRef image); +CGImageRef CGImageGetDataProvider(CGImageRef image); +CFDataRef CGDataProviderCopyData(CGImageRef image); +unsigned char* CFDataGetBytePtr(CFDataRef imgData); +unsigned CGImageGetWidth(CGImageRef image); +unsigned CGImageGetHeight(CGImageRef image); +unsigned CGImageGetBitsPerPixel(CGImageRef image); +unsigned CGImageGetBytesPerRow(CGImageRef image); +void CFRelease(CFDataRef imgData); + +#endif diff --git a/include/grabber/OsxWrapper.h b/include/grabber/OsxWrapper.h index e14daf4d..65b765d7 100644 --- a/include/grabber/OsxWrapper.h +++ b/include/grabber/OsxWrapper.h @@ -1,16 +1,7 @@ #pragma once -// Utils includes -#include -#include -#include -#include -#include #include - -// Forward class declaration -class OsxFrameGrabber; -class ImageProcessor; +#include /// /// The OsxWrapper uses an instance of the OsxFrameGrabber to obtain ImageRgb's from the @@ -35,7 +26,7 @@ public: /// /// Destructor of this osx frame grabber. Releases any claimed resources. /// - virtual ~OsxWrapper(); + virtual ~OsxWrapper() {}; public slots: /// @@ -43,23 +34,7 @@ public slots: /// virtual void action(); - /// - /// Set the video mode (2D/3D) - /// @param[in] mode The new video mode - /// - void setVideoMode(const VideoMode videoMode); - private: - /// The update rate [Hz] - const int _updateInterval_ms; - /// The timeout of the led colors [ms] - const int _timeout_ms; - - /// The image used for grabbing frames - Image _image; /// The actual grabber - OsxFrameGrabber * _grabber; - - /// The list with computed led colors - std::vector _ledColors; + OsxFrameGrabber _grabber; }; diff --git a/include/grabber/V4L2Grabber.h b/include/grabber/V4L2Grabber.h index 8a631a5c..b21aa005 100644 --- a/include/grabber/V4L2Grabber.h +++ b/include/grabber/V4L2Grabber.h @@ -10,11 +10,8 @@ #include // util includes -#include #include #include - -// grabber includes #include /// Capture class for V4L2 devices @@ -28,8 +25,8 @@ public: V4L2Grabber(const QString & device, int input, VideoStandard videoStandard, PixelFormat pixelFormat, - int width, - int height, + unsigned width, + unsigned height, int frameDecimation, int horizontalPixelDecimation, int verticalPixelDecimation @@ -39,12 +36,9 @@ public: QRectF getSignalDetectionOffset(); bool getSignalDetectionEnabled(); + int grabFrame(Image &); + public slots: - void setCropping(int cropLeft, - int cropRight, - int cropTop, - int cropBottom); - void setSignalThreshold( double redSignalThreshold, double greenSignalThreshold, diff --git a/include/grabber/V4L2Wrapper.h b/include/grabber/V4L2Wrapper.h index fbeb23f0..36b566f2 100644 --- a/include/grabber/V4L2Wrapper.h +++ b/include/grabber/V4L2Wrapper.h @@ -1,11 +1,6 @@ #pragma once -// Hyperion includes -#include -#include #include - -// Grabber includes #include class V4L2Wrapper : public GrabberWrapper @@ -17,8 +12,8 @@ public: int input, VideoStandard videoStandard, PixelFormat pixelFormat, - int width, - int height, + unsigned width, + unsigned height, int frameDecimation, int pixelDecimation, double redSignalThreshold, @@ -26,7 +21,7 @@ public: double blueSignalThreshold, const int priority, bool useGrabbingMode); - virtual ~V4L2Wrapper(); + virtual ~V4L2Wrapper() {}; bool getSignalDetectionEnable(); @@ -36,7 +31,6 @@ public slots: void setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom); void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax); - void setVideoMode(VideoMode mode); void setSignalDetectionEnable(bool enable); // signals: @@ -50,12 +44,6 @@ private slots: void checkSources(); private: - /// The timeout of the led colors [ms] - const int _timeout_ms; - /// The V4L2 grabber V4L2Grabber _grabber; - - /// The list with computed led colors - std::vector _ledColors; }; diff --git a/include/grabber/X11Grabber.h b/include/grabber/X11Grabber.h index 26c30991..7ef286fb 100755 --- a/include/grabber/X11Grabber.h +++ b/include/grabber/X11Grabber.h @@ -22,8 +22,6 @@ public: virtual ~X11Grabber(); bool Setup(); - - Image & grab(); /// /// Captures a single snapshot of the display and writes the data to the given image. The @@ -33,11 +31,13 @@ public: /// @param[out] image The snapped screenshot (should be initialized with correct width and /// height) /// - int grabFrame(Image & image); + virtual int grabFrame(Image & image, bool forceUpdate=false); /// /// update dimension according current screen - int updateScreenDimensions(); + int updateScreenDimensions(bool force=false); + + virtual void setVideoMode(VideoMode mode); private: bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable; @@ -63,6 +63,8 @@ private: unsigned _screenWidth; unsigned _screenHeight; + unsigned _src_x; + unsigned _src_y; Image _image; diff --git a/include/grabber/X11Wrapper.h b/include/grabber/X11Wrapper.h index 24ecdc62..e29b3ca4 100644 --- a/include/grabber/X11Wrapper.h +++ b/include/grabber/X11Wrapper.h @@ -1,14 +1,12 @@ #pragma once -// Utils includes -#include -#include -#include #include +#include +// some include of xorg defines "None" this is also used by QT and has to be undefined to avoid collisions +#ifdef None + #undef None +#endif -// Forward class declaration -class X11Grabber; -class ImageProcessor; /// /// The X11Wrapper uses an instance of the X11Grabber to obtain ImageRgb's from the @@ -31,42 +29,18 @@ public: /// /// Destructor of this framebuffer frame grabber. Releases any claimed resources. /// - virtual ~X11Wrapper(); + virtual ~X11Wrapper() {}; public slots: - /// - /// Starts the grabber wich produces led values with the specified update rate - /// - bool start(); - /// /// Performs a single frame grab and computes the led-colors /// virtual void action(); - /// - /// Set the video mode (2D/3D) - /// @param[in] mode The new video mode - /// - void setVideoMode(const VideoMode videoMode); - private: - /// The update rate [Hz] - const int _updateInterval_ms; - /// The timeout of the led colors [ms] - const int _timeout_ms; - - /// The image used for grabbing frames - Image _image; - /// The actual grabber - X11Grabber * _grabber; - - /// The list with computed led colors - std::vector _ledColors; - + X11Grabber _grabber; bool _init; - bool _x11SetupSuccess; }; diff --git a/include/hyperion/Grabber.h b/include/hyperion/Grabber.h index 83a9c783..aa6ac941 100644 --- a/include/hyperion/Grabber.h +++ b/include/hyperion/Grabber.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -16,24 +17,28 @@ class Grabber : public QObject public: Grabber(QString grabberName, int width=0, int height=0, int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0); - ~Grabber(); - + virtual ~Grabber(); + /// /// Set the video mode (2D/3D) /// @param[in] mode The new video mode /// - void setVideoMode(VideoMode mode); + virtual void setVideoMode(VideoMode mode); + virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom); + /// gets resulting height of image - const int getImageWidth() { return _width; }; + virtual const int getImageWidth() { return _width; }; /// gets resulting width of image - const int getImageHeight() { return _height; }; + virtual const int getImageHeight() { return _height; }; protected: ImageResampler _imageResampler; + bool _useImageResampler; + /// the selected VideoMode VideoMode _videoMode; diff --git a/include/hyperion/GrabberWrapper.h b/include/hyperion/GrabberWrapper.h index 43c52aa5..9650b4ed 100644 --- a/include/hyperion/GrabberWrapper.h +++ b/include/hyperion/GrabberWrapper.h @@ -9,14 +9,20 @@ #include #include #include +#include +#include +#include +#include class ImageProcessor; +class Grabber; +class DispmanxFrameGrabber; class GrabberWrapper : public QObject { Q_OBJECT public: - GrabberWrapper(QString grabberName, const int priority, hyperion::Components grabberComponentId=hyperion::COMP_GRABBER); + GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned width, unsigned height, const unsigned updateRate_Hz, const int priority, hyperion::Components grabberComponentId=hyperion::COMP_GRABBER); virtual ~GrabberWrapper(); @@ -30,8 +36,32 @@ public: /// virtual void stop(); + void setImageProcessorEnabled(bool enable); + static QStringList availableGrabbers(); + +public: + template + void transferFrame(Grabber_T &grabber) + { + unsigned w = grabber.getImageWidth(); + unsigned h = grabber.getImageHeight(); + if (_imageProcessorEnabled && ( _image.width() != w || _image.height() != h)) + { + _processor->setSize(w, h); + _image.resize(w, h); + } + + if (grabber.grabFrame(_image) >= 0) + { + emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); + setColors(_ledColors, _timeout_ms); + } + } + + public slots: void componentStateChanged(const hyperion::Components component, bool enable); @@ -50,8 +80,9 @@ public slots: /// Set the video mode (2D/3D) /// @param[in] mode The new video mode /// - virtual void setVideoMode(const VideoMode videoMode) = 0; + virtual void setVideoMode(const VideoMode videoMode); + virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom); signals: void emitImage(int priority, const Image & image, const int timeout_ms); @@ -59,6 +90,7 @@ signals: protected: void setColors(const std::vector &ledColors, const int timeout_ms); + QString _grabberName; /// Pointer to Hyperion for writing led values @@ -70,6 +102,12 @@ protected: /// The timer for generating events with the specified update rate QTimer _timer; + /// The update rate [Hz] + const int _updateInterval_ms; + + /// The timeout of the led colors [ms] + const int _timeout_ms; + /// The Logger instance Logger * _log; @@ -80,4 +118,15 @@ protected: ImageProcessor * _processor; hyperion::Components _grabberComponentId; + + Grabber *_ggrabber; + + /// The image used for grabbing frames + Image _image; + + /// The list with computed led colors + std::vector _ledColors; + + bool _imageProcessorEnabled; }; + diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 63ea3b32..29ac5f90 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -260,7 +260,7 @@ public slots: /// /// Clears all priority channels. This will switch the leds off until a new priority is written. /// - void clearall(); + void clearall(bool forceClearAll=false); /// Run the specified effect on the given priority channel and optionally specify a timeout /// @param effectName Name of the effec to run diff --git a/include/hyperion/ImageProcessor.h b/include/hyperion/ImageProcessor.h index ee53c7ff..6e8aa9c2 100644 --- a/include/hyperion/ImageProcessor.h +++ b/include/hyperion/ImageProcessor.h @@ -42,7 +42,6 @@ public: /// void setSize(const unsigned width, const unsigned height); - /// Returns starte of black border detector bool blackBorderDetectorEnabled(); @@ -59,7 +58,20 @@ public slots: /// Enable or disable the black border detector void setLedMappingType(int mapType); -public: +public: + /// + /// Specifies the width and height of 'incomming' images. This will resize the buffer-image to + /// match the given size. + /// NB All earlier obtained references will be invalid. + /// + /// @param[in] image The dimensions taken from image + /// + template + void setSize(const Image &image) + { + setSize(image.width(), image.height()); + } + /// /// Processes the image to a list of led colors. This will update the size of the buffer-image /// if required and call the image-to-leds mapping to determine the mean color per led. @@ -71,18 +83,25 @@ public: template std::vector process(const Image& image) { - // Ensure that the buffer-image is the proper size - setSize(image.width(), image.height()); - - // Check black border detection - verifyBorder(image); - - // Create a result vector and call the 'in place' functionl std::vector colors; - switch (_mappingType) + if (image.width()>0 && image.height()>0) { - case 1: colors = _imageToLeds->getUniLedColor(image); break; - default: colors = _imageToLeds->getMeanLedColor(image); + // Ensure that the buffer-image is the proper size + setSize(image); + + // Check black border detection + verifyBorder(image); + + // Create a result vector and call the 'in place' functionl + switch (_mappingType) + { + case 1: colors = _imageToLeds->getUniLedColor(image); break; + default: colors = _imageToLeds->getMeanLedColor(image); + } + } + else + { + Warning(_log, "ImageProcessor::process called without image size 0"); } // return the computed colors @@ -98,19 +117,25 @@ public: template void process(const Image& image, std::vector& ledColors) { - // Ensure that the buffer-image is the proper size - setSize(image.width(), image.height()); - - // Check black border detection - verifyBorder(image); - - // Determine the mean-colors of each led (using the existing mapping) - switch (_mappingType) + if ( image.width()>0 && image.height()>0) { - case 1: _imageToLeds->getUniLedColor(image, ledColors); break; - default: _imageToLeds->getMeanLedColor(image, ledColors); - } + // Ensure that the buffer-image is the proper size + setSize(image); + // Check black border detection + verifyBorder(image); + + // Determine the mean-colors of each led (using the existing mapping) + switch (_mappingType) + { + case 1: _imageToLeds->getUniLedColor(image, ledColors); break; + default: _imageToLeds->getMeanLedColor(image, ledColors); + } + } + else + { + Warning(_log, "ImageProcessor::process called without image size 0"); + } } /// diff --git a/include/hyperion/PriorityMuxer.h b/include/hyperion/PriorityMuxer.h index 680b1a97..a0cc23b9 100644 --- a/include/hyperion/PriorityMuxer.h +++ b/include/hyperion/PriorityMuxer.h @@ -118,7 +118,7 @@ public: /// /// Clears all priority channels /// - void clearAll(); + void clearAll(bool forceClearAll=false); /// /// Updates the current time. Channels with a configured time out will be checked and cleared if @@ -152,5 +152,4 @@ private: QTimer _timer; QTimer _blockTimer; - }; diff --git a/include/utils/ImageResampler.h b/include/utils/ImageResampler.h index 7f8029f4..847db2bb 100644 --- a/include/utils/ImageResampler.h +++ b/include/utils/ImageResampler.h @@ -20,7 +20,7 @@ public: int cropTop, int cropBottom); - void set3D(VideoMode mode); + void setVideoMode(VideoMode mode); void processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image & outputImage) const; diff --git a/libsrc/grabber/amlogic/AmlogicGrabber.cpp b/libsrc/grabber/amlogic/AmlogicGrabber.cpp index 1422e59c..4d642cca 100755 --- a/libsrc/grabber/amlogic/AmlogicGrabber.cpp +++ b/libsrc/grabber/amlogic/AmlogicGrabber.cpp @@ -52,10 +52,6 @@ AmlogicGrabber::~AmlogicGrabber() bool AmlogicGrabber::isVideoPlaying() { - - // TODO crop resulting image accroding member _videoMode - // TODO add croping - const QString videoDevice = "/dev/amvideo"; // Open the video device @@ -81,13 +77,10 @@ bool AmlogicGrabber::isVideoPlaying() return videoDisabled == 0; } -int AmlogicGrabber::grabFrame(Image & image) +int AmlogicGrabber::grabFrame(Image & image) { - // resize the given image if needed - if (image.width() != (unsigned)_width || image.height() != (unsigned)_height) - { - image.resize(_width, _height); - } + // TODO crop resulting image accroding member _videoMode + // TODO add croping // Make sure video is playing, else there is nothing to grab if (!isVideoPlaying()) @@ -95,7 +88,6 @@ int AmlogicGrabber::grabFrame(Image & image) return -1; } - // If the device is not open, attempt to open it if (_amlogicCaptureDev == -1) { @@ -121,7 +113,7 @@ int AmlogicGrabber::grabFrame(Image & image) } // Read the snapshot into the memory - void * image_ptr = image.memptr(); + void * image_ptr = _image.memptr(); const ssize_t bytesToRead = _width * _height * sizeof(ColorBgr); const ssize_t bytesRead = pread(_amlogicCaptureDev, image_ptr, bytesToRead, 0); @@ -150,5 +142,10 @@ int AmlogicGrabber::grabFrame(Image & image) _amlogicCaptureDev = -1; readCnt = 0; } + + _imageResampler.setHorizontalPixelDecimation(_width); + _imageResampler.setVerticalPixelDecimation(_height); + _imageResampler.processImage((const uint8_t*)image_ptr, _width, _height, 3, PIXELFORMAT_BGR24, image); + return 0; } diff --git a/libsrc/grabber/amlogic/AmlogicWrapper.cpp b/libsrc/grabber/amlogic/AmlogicWrapper.cpp index ef21bced..8db02591 100644 --- a/libsrc/grabber/amlogic/AmlogicWrapper.cpp +++ b/libsrc/grabber/amlogic/AmlogicWrapper.cpp @@ -1,53 +1,11 @@ -// QT includes -#include - -// Hyperion includes -#include -#include -#include - -// Amlogic grabber includes #include -#include - AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority) - : GrabberWrapper("AmLogic", priority) - , _updateInterval_ms(1000/updateRate_Hz) - , _timeout_ms(2 * _updateInterval_ms) - , _image(grabWidth, grabHeight) - , _grabber(new AmlogicGrabber(grabWidth, grabHeight)) - , _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0}) -{ - // Configure the timer to generate events every n milliseconds - _timer.setInterval(_updateInterval_ms); - - _processor->setSize(grabWidth, grabHeight); -} - -AmlogicWrapper::~AmlogicWrapper() -{ - delete _grabber; -} + : GrabberWrapper("AmLogic", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER) + , _grabber(grabWidth, grabHeight) +{} void AmlogicWrapper::action() { - // Grab frame into the allocated image - if (_grabber->grabFrame(_image) < 0) - { - // Frame grab failed, maybe nothing playing or .... - return; - } - - Image image_rgb; - _image.toRgb(image_rgb); - emit emitImage(_priority, image_rgb, _timeout_ms); - - _processor->process(_image, _ledColors); - setColors(_ledColors, _timeout_ms); -} - -void AmlogicWrapper::setVideoMode(const VideoMode mode) -{ - _grabber->setVideoMode(mode); + transferFrame(_grabber); } diff --git a/libsrc/grabber/dispmanx/CMakeLists.txt b/libsrc/grabber/dispmanx/CMakeLists.txt index 2da57aa5..187de707 100644 --- a/libsrc/grabber/dispmanx/CMakeLists.txt +++ b/libsrc/grabber/dispmanx/CMakeLists.txt @@ -1,6 +1,11 @@ # Find the BCM-package (VC control) -find_package(BCM REQUIRED) -include_directories(${BCM_INCLUDE_DIRS}) +IF ( "${PLATFORM}" MATCHES rpi) + find_package(BCM REQUIRED) + include_directories(${BCM_INCLUDE_DIRS}) +ELSE() + SET(BCM_INCLUDE_DIRS "") + SET(BCM_LIBRARIES "") +ENDIF() # Define the current source locations SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp index d5003a1b..833fd1bb 100644 --- a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp +++ b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp @@ -13,7 +13,10 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned , _vc_flags(0) , _captureBuffer(new ColorRgba[0]) , _captureBufferSize(0) + , _image_rgba(width, height) { + _useImageResampler = false; + // Initiase BCM bcm_host_init(); @@ -64,33 +67,15 @@ void DispmanxFrameGrabber::setFlags(const int vc_flags) _vc_flags = vc_flags; } -void DispmanxFrameGrabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) -{ - if (cropLeft + cropRight >= (unsigned)_width || cropTop + cropBottom >= (unsigned)_height) - { - Error(_log, "Rejecting invalid crop values: left: %d, right: %d, top: %d, bottom: %d", cropLeft, cropRight, cropTop, cropBottom); - return; - } - _cropLeft = cropLeft; - _cropRight = cropRight; - _cropTop = cropTop; - _cropBottom = cropBottom; - - if (cropLeft > 0 || cropRight > 0 || cropTop > 0 || cropBottom > 0) - { - Info(_log, "Cropping image: width=%d height=%d; crop: left=%d right=%d top=%d bottom=%d ", _width, _height, cropLeft, cropRight, cropTop, cropBottom); - } -} - -void DispmanxFrameGrabber::grabFrame(Image & image) +int DispmanxFrameGrabber::grabFrame(Image & image) { int ret; // vc_dispmanx_resource_read_data doesn't seem to work well // with arbitrary positions so we have to handle cropping by ourselves - unsigned cropLeft = _cropLeft; - unsigned cropRight = _cropRight; - unsigned cropTop = _cropTop; + unsigned cropLeft = _cropLeft; + unsigned cropRight = _cropRight; + unsigned cropTop = _cropTop; unsigned cropBottom = _cropBottom; if (_vc_flags & DISPMANX_SNAPSHOT_FILL) @@ -99,19 +84,19 @@ void DispmanxFrameGrabber::grabFrame(Image & image) cropLeft = cropRight = cropTop = cropBottom = 0; } - unsigned imageWidth = _width - cropLeft - cropRight; + unsigned imageWidth = _width - cropLeft - cropRight; unsigned imageHeight = _height - cropTop - cropBottom; // calculate final image dimensions and adjust top/left cropping in 3D modes switch (_videoMode) { case VIDEO_3DSBS: - imageWidth = imageWidth / 2; - cropLeft = cropLeft / 2; + imageWidth /= 2; + cropLeft /= 2; break; case VIDEO_3DTAB: - imageHeight = imageHeight / 2; - cropTop = cropTop / 2; + imageHeight /= 2; + cropTop /= 2; break; case VIDEO_2D: default: @@ -124,12 +109,17 @@ void DispmanxFrameGrabber::grabFrame(Image & image) image.resize(imageWidth, imageHeight); } + if (_image_rgba.width() != imageWidth || _image_rgba.height() != imageHeight) + { + _image_rgba.resize(imageWidth, imageHeight); + } + // Open the connection to the display _vc_display = vc_dispmanx_display_open(0); if (_vc_display < 0) { Error(_log, "Cannot open display: %d", _vc_display); - return; + return -1; } // Create the snapshot (incl down-scaling) @@ -138,11 +128,11 @@ void DispmanxFrameGrabber::grabFrame(Image & image) { Error(_log, "Snapshot failed: %d", ret); vc_dispmanx_display_close(_vc_display); - return; + return ret; } // Read the snapshot into the memory - void* imagePtr = image.memptr(); + void* imagePtr = _image_rgba.memptr(); void* capturePtr = imagePtr; unsigned imagePitch = imageWidth * sizeof(ColorRgba); @@ -172,7 +162,7 @@ void DispmanxFrameGrabber::grabFrame(Image & image) { Error(_log, "vc_dispmanx_resource_read_data failed: %d", ret); vc_dispmanx_display_close(_vc_display); - return; + return ret; } // copy capture data to image if we captured to temp buffer @@ -193,4 +183,9 @@ void DispmanxFrameGrabber::grabFrame(Image & image) // Close the displaye vc_dispmanx_display_close(_vc_display); + + // image to output image + _image_rgba.toRgb(image); + + return 0; } diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabberMock.cpp b/libsrc/grabber/dispmanx/DispmanxFrameGrabberMock.cpp new file mode 100644 index 00000000..f30d161a --- /dev/null +++ b/libsrc/grabber/dispmanx/DispmanxFrameGrabberMock.cpp @@ -0,0 +1,107 @@ +#ifndef PLATFORM_RPI + +#include + +unsigned __bcm_frame_counter = 0; +const int __screenWidth = 800; +const int __screenHeight = 600; + +void bcm_host_init() +{ +} + +void bcm_host_deinit() +{ +} + +int vc_dispmanx_display_open(int) +{ + return 1; +} + +void vc_dispmanx_display_close(int) +{ +} + +int vc_dispmanx_display_get_info(int, DISPMANX_MODEINFO_T *vc_info) +{ + vc_info->width = __screenWidth; + vc_info->height = __screenHeight; + return 0; +} + +DISPMANX_RESOURCE_HANDLE_T vc_dispmanx_resource_create(int,int width,int height, uint32_t *) +{ + return new DISPMANX_RESOURCE(width,height); +} + +void vc_dispmanx_resource_delete(DISPMANX_RESOURCE_HANDLE_T resource) +{ + delete resource; +} + +int vc_dispmanx_resource_read_data(DISPMANX_RESOURCE_HANDLE_T resource, VC_RECT_T *rectangle, void* capturePtr, unsigned capturePitch) +{ + memcpy(capturePtr, resource->memptr(), resource->height()*resource->width() * sizeof(ColorRgba)); + return 0; +} + +void vc_dispmanx_rect_set(VC_RECT_T *rectangle, int left, int top, int width, int height) +{ + rectangle->width = width; + rectangle->height = height; + rectangle->left = left; + rectangle->top = top; +} + +int vc_dispmanx_snapshot(int, DISPMANX_RESOURCE_HANDLE_T resource, int vc_flags) +{ + __bcm_frame_counter++; + if (__bcm_frame_counter > 100) + { + __bcm_frame_counter = 0; + } + + ColorRgba color[4] = {ColorRgba::RED, ColorRgba::BLUE, ColorRgba::GREEN, ColorRgba::WHITE}; + if (__bcm_frame_counter < 25) + { + color[0] = ColorRgba::WHITE; + color[1] = ColorRgba::RED; + color[2] = ColorRgba::BLUE; + color[3] = ColorRgba::GREEN; + } + else if(__bcm_frame_counter < 50) + { + color[1] = ColorRgba::WHITE; + color[2] = ColorRgba::RED; + color[3] = ColorRgba::BLUE; + color[0] = ColorRgba::GREEN; + } + else if(__bcm_frame_counter < 75) + { + color[2] = ColorRgba::WHITE; + color[3] = ColorRgba::RED; + color[0] = ColorRgba::BLUE; + color[1] = ColorRgba::GREEN; + } + + unsigned w = resource->width(); + unsigned h = resource->height(); + for (unsigned y=0; y= h/2) id = 2; + if (x >= w/2 && y < h/2) id = 3; + + resource->memptr()[y*w + x] = color[id]; + } + } + + return 0; +} + +#endif + diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index 791195c3..633fa60d 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -1,56 +1,13 @@ -// QT includes -#include - -// Hyperion includes -#include -#include -#include - -// Dispmanx grabber includes #include -#include - DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority) - : GrabberWrapper("Dispmanx", priority) - , _updateInterval_ms(1000/updateRate_Hz) - , _timeout_ms(2 * _updateInterval_ms) - , _image(grabWidth, grabHeight) - , _grabber(new DispmanxFrameGrabber(grabWidth, grabHeight)) - , _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0}) + : GrabberWrapper("Dispmanx", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER) + , _grabber(grabWidth, grabHeight) { - // Configure the timer to generate events every n milliseconds - _timer.setInterval(_updateInterval_ms); - - _processor->setSize(grabWidth, grabHeight); -} - -DispmanxWrapper::~DispmanxWrapper() -{ - delete _grabber; + setImageProcessorEnabled(false); } void DispmanxWrapper::action() { - // Grab frame into the allocated image - _grabber->grabFrame(_image); - - Image image_rgb; - _image.toRgb(image_rgb); - emit emitImage(_priority, image_rgb, _timeout_ms); - - _processor->process(_image, _ledColors); - setColors(_ledColors, _timeout_ms); -} - - -void DispmanxWrapper::setVideoMode(const VideoMode mode) -{ - _grabber->setVideoMode(mode); -} - -void DispmanxWrapper::setCropping(const unsigned cropLeft, const unsigned cropRight, - const unsigned cropTop, const unsigned cropBottom) -{ - _grabber->setCropping(cropLeft, cropRight, cropTop, cropBottom); + transferFrame(_grabber); } diff --git a/libsrc/grabber/framebuffer/FramebufferFrameGrabber.cpp b/libsrc/grabber/framebuffer/FramebufferFrameGrabber.cpp index 9e072830..4b1a15f8 100755 --- a/libsrc/grabber/framebuffer/FramebufferFrameGrabber.cpp +++ b/libsrc/grabber/framebuffer/FramebufferFrameGrabber.cpp @@ -47,7 +47,7 @@ FramebufferFrameGrabber::~FramebufferFrameGrabber() { } -void FramebufferFrameGrabber::grabFrame(Image & image) +int FramebufferFrameGrabber::grabFrame(Image & image) { struct fb_var_screeninfo vinfo; unsigned capSize, bytesPerPixel; @@ -62,25 +62,17 @@ void FramebufferFrameGrabber::grabFrame(Image & image) bytesPerPixel = vinfo.bits_per_pixel / 8; capSize = vinfo.xres * vinfo.yres * bytesPerPixel; - if (vinfo.bits_per_pixel == 16) + switch (vinfo.bits_per_pixel) { - pixelFormat = PIXELFORMAT_BGR16; + case 16: pixelFormat = PIXELFORMAT_BGR16; break; + case 24: pixelFormat = PIXELFORMAT_BGR24; break; + case 32: pixelFormat = PIXELFORMAT_BGR32; break; + default: + Error(_log, "Unknown pixel format: %d bits per pixel", vinfo.bits_per_pixel); + close(_fbfd); + return -1; } - else if (vinfo.bits_per_pixel == 24) - { - pixelFormat = PIXELFORMAT_BGR24; - } - else if (vinfo.bits_per_pixel == 32) - { - pixelFormat = PIXELFORMAT_BGR32; - } - else - { - Error(_log, "Unknown pixel format: %d bits per pixel", vinfo.bits_per_pixel); - close(_fbfd); - return; - } - + /* map the device to memory */ _fbp = (unsigned char*)mmap(0, capSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, _fbfd, 0); @@ -95,4 +87,6 @@ void FramebufferFrameGrabber::grabFrame(Image & image) munmap(_fbp, capSize); close(_fbfd); + + return 0; } diff --git a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp index 6deb0d9b..9a7cc367 100644 --- a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp +++ b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp @@ -1,43 +1,11 @@ -// Hyperion includes -#include -#include -#include - -// Framebuffer grabber includes #include -#include FramebufferWrapper::FramebufferWrapper(const QString & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority) - : GrabberWrapper("FrameBuffer", priority) - , _updateInterval_ms(1000/updateRate_Hz) - , _timeout_ms(2 * _updateInterval_ms) - , _image(grabWidth, grabHeight) - , _grabber(new FramebufferFrameGrabber(device, grabWidth, grabHeight)) - , _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0}) -{ - // Configure the timer to generate events every n milliseconds - _timer.setInterval(_updateInterval_ms); - - _processor->setSize(grabWidth, grabHeight); -} - -FramebufferWrapper::~FramebufferWrapper() -{ - delete _grabber; -} + : GrabberWrapper("FrameBuffer", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER) + , _grabber(device, grabWidth, grabHeight) +{} void FramebufferWrapper::action() { - // Grab frame into the allocated image - _grabber->grabFrame(_image); - - emit emitImage(_priority, _image, _timeout_ms); - - _processor->process(_image, _ledColors); - setColors(_ledColors, _timeout_ms); -} - -void FramebufferWrapper::setVideoMode(const VideoMode mode) -{ - _grabber->setVideoMode(mode); + transferFrame(_grabber); } diff --git a/libsrc/grabber/osx/OsxFrameGrabber.cpp b/libsrc/grabber/osx/OsxFrameGrabber.cpp index eb523836..707292d2 100755 --- a/libsrc/grabber/osx/OsxFrameGrabber.cpp +++ b/libsrc/grabber/osx/OsxFrameGrabber.cpp @@ -19,7 +19,9 @@ OsxFrameGrabber::OsxFrameGrabber(const unsigned display, const unsigned width, c { Error(_log, "Display with index %d is not available. Using main display", _screenIndex); _display = kCGDirectMainDisplay; - } else { + } + else + { _display = displays[_screenIndex]; } @@ -35,7 +37,7 @@ OsxFrameGrabber::~OsxFrameGrabber() { } -void OsxFrameGrabber::grabFrame(Image & image) +int OsxFrameGrabber::grabFrame(Image & image) { CGImageRef dispImage; CFDataRef imgData; @@ -52,12 +54,12 @@ void OsxFrameGrabber::grabFrame(Image & image) if (dispImage == NULL) { Error(_log, "No display connected..."); - return; + return -1; } } - imgData = CGDataProviderCopyData(CGImageGetDataProvider(dispImage)); - pImgData = (unsigned char*) CFDataGetBytePtr(imgData); - dspWidth = CGImageGetWidth(dispImage); + imgData = CGDataProviderCopyData(CGImageGetDataProvider(dispImage)); + pImgData = (unsigned char*) CFDataGetBytePtr(imgData); + dspWidth = CGImageGetWidth(dispImage); dspHeight = CGImageGetHeight(dispImage); _imageResampler.setHorizontalPixelDecimation(dspWidth/_width); @@ -71,4 +73,6 @@ void OsxFrameGrabber::grabFrame(Image & image) CFRelease(imgData); CGImageRelease(dispImage); + + return 0; } diff --git a/libsrc/grabber/osx/OsxFrameGrabberMock.cpp b/libsrc/grabber/osx/OsxFrameGrabberMock.cpp new file mode 100644 index 00000000..501bcefc --- /dev/null +++ b/libsrc/grabber/osx/OsxFrameGrabberMock.cpp @@ -0,0 +1,126 @@ +#ifndef __APPLE__ +#include + +unsigned __osx_frame_counter = 0; +const int __screenWidth = 800; +const int __screenHeight = 600; + +void CGGetActiveDisplayList(int max, CGDirectDisplayID *displays, CGDisplayCount *displayCount) +{ + *displayCount = 1; + displays[0] = 1; +} + +CGImageRef CGDisplayCreateImage(CGDirectDisplayID display) +{ + CGImageRef image = new CGImage(__screenWidth, __screenHeight); + + return image; +} + +void CGImageRelease(CGImageRef image) +{ + delete image; +} + +CGImageRef CGImageGetDataProvider(CGImageRef image) +{ + __osx_frame_counter++; + if (__osx_frame_counter > 100) + { + __osx_frame_counter = 0; + } + + ColorRgb color[4] = {ColorRgb::RED, ColorRgb::BLUE, ColorRgb::GREEN, ColorRgb::WHITE}; + if (__osx_frame_counter < 25) + { + color[0] = ColorRgb::WHITE; + color[1] = ColorRgb::RED; + color[2] = ColorRgb::BLUE; + color[3] = ColorRgb::GREEN; + } + else if(__osx_frame_counter < 50) + { + color[1] = ColorRgb::WHITE; + color[2] = ColorRgb::RED; + color[3] = ColorRgb::BLUE; + color[0] = ColorRgb::GREEN; + } + else if(__osx_frame_counter < 75) + { + color[2] = ColorRgb::WHITE; + color[3] = ColorRgb::RED; + color[0] = ColorRgb::BLUE; + color[1] = ColorRgb::GREEN; + } + unsigned w = image->width(); + unsigned h = image->height(); + + for (unsigned y=0; y= h/2) id = 2; + if (x >= w/2 && y < h/2) id = 3; + + image->memptr()[y*w + x] = color[id]; + } + } + + return image; +} + +CFDataRef CGDataProviderCopyData(CGImageRef image) +{ + const unsigned indexMax = image->width() * image->height() * CGImageGetBitsPerPixel(image); + CFDataRef data = new CFData[indexMax]; + int lineLength = CGImageGetBytesPerRow(image); + + for (unsigned y=0; yheight(); y++) + { + for (unsigned x=0; xwidth(); x++) + { + int index = lineLength * y + x * CGImageGetBitsPerPixel(image); + + data[index ] = (*image)(x,y).blue; + data[index+1] = (*image)(x,y).green; + data[index+2] = (*image)(x,y).red; + data[index+3] = 0; + } + } + return data; +} + +unsigned char* CFDataGetBytePtr(CFDataRef imgData) +{ + return imgData; +} + +unsigned CGImageGetWidth(CGImageRef image) +{ + return image->width(); +} + +unsigned CGImageGetHeight(CGImageRef image) +{ + return image->height(); +} + +unsigned CGImageGetBytesPerRow(CGImageRef image) +{ + return image->width()*CGImageGetBitsPerPixel(image); +} + +unsigned CGImageGetBitsPerPixel(CGImageRef) +{ + return 4; +} + +void CFRelease(CFDataRef imgData) +{ + delete imgData; +} + +#endif diff --git a/libsrc/grabber/osx/OsxWrapper.cpp b/libsrc/grabber/osx/OsxWrapper.cpp index da190b15..f543eada 100644 --- a/libsrc/grabber/osx/OsxWrapper.cpp +++ b/libsrc/grabber/osx/OsxWrapper.cpp @@ -1,44 +1,11 @@ -// Hyperion includes -#include -#include -#include - -// Osx grabber includes #include -#include OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority) - : GrabberWrapper("OSX FrameGrabber", priority) - , _updateInterval_ms(1000/updateRate_Hz) - , _timeout_ms(2 * _updateInterval_ms) - , _image(grabWidth, grabHeight) - , _grabber(new OsxFrameGrabber(display, grabWidth, grabHeight)) - , _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0}) -{ - // Configure the timer to generate events every n milliseconds - _timer.setInterval(_updateInterval_ms); - - _processor->setSize(grabWidth, grabHeight); -} - -OsxWrapper::~OsxWrapper() -{ - delete _grabber; -} + : GrabberWrapper("OSX FrameGrabber", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER) + , _grabber(display, grabWidth, grabHeight) +{} void OsxWrapper::action() { - // Grab frame into the allocated image - _grabber->grabFrame(_image); - - emit emitImage(_priority, _image, _timeout_ms); - - _processor->process(_image, _ledColors); - setColors(_ledColors, _timeout_ms); -} - - -void OsxWrapper::setVideoMode(const VideoMode mode) -{ - _grabber->setVideoMode(mode); + transferFrame(_grabber); } diff --git a/libsrc/grabber/v4l2/V4L2Grabber.cpp b/libsrc/grabber/v4l2/V4L2Grabber.cpp index 65714850..5c150ec5 100644 --- a/libsrc/grabber/v4l2/V4L2Grabber.cpp +++ b/libsrc/grabber/v4l2/V4L2Grabber.cpp @@ -27,8 +27,8 @@ V4L2Grabber::V4L2Grabber(const QString & device , int input , VideoStandard videoStandard , PixelFormat pixelFormat - , int width - , int height + , unsigned width + , unsigned height , int frameDecimation , int horizontalPixelDecimation , int verticalPixelDecimation @@ -180,11 +180,6 @@ void V4L2Grabber::getV4Ldevices() } } -void V4L2Grabber::setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom) -{ - _imageResampler.setCropping(cropLeft, cropRight, cropTop, cropBottom); -} - void V4L2Grabber::setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold) { _noSignalThresholdColor.red = uint8_t(255*redSignalThreshold); diff --git a/libsrc/grabber/v4l2/V4L2Wrapper.cpp b/libsrc/grabber/v4l2/V4L2Wrapper.cpp index eb0b48cd..480899b6 100644 --- a/libsrc/grabber/v4l2/V4L2Wrapper.cpp +++ b/libsrc/grabber/v4l2/V4L2Wrapper.cpp @@ -8,8 +8,8 @@ V4L2Wrapper::V4L2Wrapper(const QString &device, int input, VideoStandard videoStandard, PixelFormat pixelFormat, - int width, - int height, + unsigned width, + unsigned height, int frameDecimation, int pixelDecimation, double redSignalThreshold, @@ -17,8 +17,7 @@ V4L2Wrapper::V4L2Wrapper(const QString &device, double blueSignalThreshold, const int priority, bool useGrabbingMode) - : GrabberWrapper("V4L2:"+device, priority, hyperion::COMP_V4L) - , _timeout_ms(1000) + : GrabberWrapper("V4L2:"+device, &_grabber, width, height, 8, priority, hyperion::COMP_V4L) , _grabber(device, input, videoStandard, @@ -28,10 +27,10 @@ V4L2Wrapper::V4L2Wrapper(const QString &device, frameDecimation, pixelDecimation, pixelDecimation) - , _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0}) { // set the signal detection threshold of the grabber _grabber.setSignalThreshold( redSignalThreshold, greenSignalThreshold, blueSignalThreshold, 50); + _ggrabber = &_grabber; // register the image type qRegisterMetaType>("Image"); @@ -40,29 +39,15 @@ V4L2Wrapper::V4L2Wrapper(const QString &device, // Handle the image in the captured thread using a direct connection QObject::connect(&_grabber, SIGNAL(newFrame(Image)), this, SLOT(newFrame(Image)), Qt::DirectConnection); - QObject::connect(&_grabber, SIGNAL(readError(const char*)), this, SLOT(readError(const char*)), Qt::DirectConnection); if (!useGrabbingMode) { disconnect(_hyperion, SIGNAL(grabbingMode(GrabbingMode)), this, 0); } - // send color data to Hyperion using a queued connection to handle the data over to the main event loop -// QObject::connect( -// this, SIGNAL(emitColors(int,std::vector,int)), -// _hyperion, SLOT(setColors(int,std::vector,int)), -// Qt::QueuedConnection); - - - // setup the higher prio source checker - // this will disable the v4l2 grabber when a source with higher priority is active _timer.setInterval(500); } -V4L2Wrapper::~V4L2Wrapper() -{ -} - bool V4L2Wrapper::start() { return ( _grabber.start() && GrabberWrapper::start()); @@ -84,12 +69,6 @@ void V4L2Wrapper::setSignalDetectionOffset(double verticalMin, double horizontal _grabber.setSignalDetectionOffset(verticalMin, horizontalMin, verticalMax, horizontalMax); } - -void V4L2Wrapper::setVideoMode(VideoMode mode) -{ - _grabber.setVideoMode(mode); -} - void V4L2Wrapper::newFrame(const Image &image) { emit emitImage(_priority, image, _timeout_ms); diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index 7b19be73..ce02a125 100755 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -14,8 +14,11 @@ X11Grabber::X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropT , _verticalDecimation(verticalPixelDecimation) , _screenWidth(0) , _screenHeight(0) + , _src_x(cropLeft) + , _src_y(cropTop) , _image(0,0) { + _useImageResampler = false; _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XRender, XShmGetImage or XGetImage memset(&_pictAttr, 0, sizeof(_pictAttr)); _pictAttr.repeat = RepeatNone; @@ -52,9 +55,7 @@ void X11Grabber::setupResources() { if(_XShmAvailable && !_useXGetImage) { - _xImage = XShmCreateImage(_x11Display, _windowAttr.visual, - _windowAttr.depth, ZPixmap, NULL, &_shminfo, - _width, _height); + _xImage = XShmCreateImage(_x11Display, _windowAttr.visual, _windowAttr.depth, ZPixmap, NULL, &_shminfo, _width, _height); _shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777); _xImage->data = (char*)shmat(_shminfo.shmid,0,0); _shminfo.shmaddr = _xImage->data; @@ -109,13 +110,16 @@ bool X11Grabber::Setup() _imageResampler.setHorizontalPixelDecimation(_XRenderAvailable ? 1 : _horizontalDecimation); _imageResampler.setVerticalPixelDecimation(_XRenderAvailable ? 1 : _verticalDecimation); - return true; + bool result = (updateScreenDimensions(true) >=0); + ErrorIf(!result, _log, "X11 Grabber start failed"); + return result; } -Image & X11Grabber::grab() +int X11Grabber::grabFrame(Image & image, bool forceUpdate) { - updateScreenDimensions(); - + if (forceUpdate) + updateScreenDimensions(forceUpdate); + if (_XRenderAvailable && !_useXGetImage) { double scale_x = static_cast(_windowAttr.width / _horizontalDecimation) / static_cast(_windowAttr.width); @@ -145,19 +149,11 @@ Image & X11Grabber::grab() XRenderSetPictureTransform (_x11Display, _srcPicture, &_transform); - XRenderComposite( _x11Display, // dpy - PictOpSrc, // op - _srcPicture, // src - None, // mask - _dstPicture, // dst - _cropLeft / _horizontalDecimation, // src_x _cropLeft - _cropTop / _verticalDecimation, // src_y _cropTop - 0, // mask_x - 0, // mask_y - 0, // dst_x - 0, // dst_y - _width, // width - _height); // height + // display, op, src, mask, dest, src_x = cropLeft, + // src_y = cropTop, mask_x, mask_y, dest_x, dest_y, width, height + XRenderComposite( + _x11Display, PictOpSrc, _srcPicture, None, _dstPicture, ( _src_x/_horizontalDecimation), + (_src_y/_verticalDecimation), 0, 0, 0, 0, _width, _height); XSync(_x11Display, False); @@ -170,93 +166,15 @@ Image & X11Grabber::grab() _xImage = XGetImage(_x11Display, _pixmap, 0, 0, _width, _height, AllPlanes, ZPixmap); } } - else + else if (_XShmAvailable && !_useXGetImage) { - if (_XShmAvailable && !_useXGetImage) { - XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); - } - else - { - _xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _width, _height, AllPlanes, ZPixmap); - } - } - - if (_xImage == nullptr) - { - Error(_log, "Grab Failed!"); - return _image; - } - - _imageResampler.processImage(reinterpret_cast(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image); - - return _image; -} - -int X11Grabber::grabFrame(Image & image) -{ - if (_XRenderAvailable && !_useXGetImage) - { - double scale_x = static_cast(_windowAttr.width / _horizontalDecimation) / static_cast(_windowAttr.width); - double scale_y = static_cast(_windowAttr.height / _verticalDecimation) / static_cast(_windowAttr.height); - double scale = qMin(scale_y, scale_x); - - _transform = - { - { - { - XDoubleToFixed(1), - XDoubleToFixed(0), - XDoubleToFixed(0) - }, - { - XDoubleToFixed(0), - XDoubleToFixed(1), - XDoubleToFixed(0) - }, - { - XDoubleToFixed(0), - XDoubleToFixed(0), - XDoubleToFixed(scale) - } - } - }; - - XRenderSetPictureTransform (_x11Display, _srcPicture, &_transform); - - XRenderComposite( _x11Display, // dpy - PictOpSrc, // op - _srcPicture, // src - None, // mask - _dstPicture, // dst - _cropLeft / _horizontalDecimation, // src_x _cropLeft - _cropTop / _verticalDecimation, // src_y _cropTop - 0, // mask_x - 0, // mask_y - 0, // dst_x - 0, // dst_y - _width, // width - _height); // height - - XSync(_x11Display, False); - - if (_XShmAvailable) - { - XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes); - } - else - { - _xImage = XGetImage(_x11Display, _pixmap, 0, 0, _width, _height, AllPlanes, ZPixmap); - } + // use xshm + XShmGetImage(_x11Display, _window, _xImage, _src_x, _src_y, AllPlanes); } else { - if (_XShmAvailable && !_useXGetImage) { - XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); - } - else - { - _xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _width, _height, AllPlanes, ZPixmap); - } + // all things done by xgetimage + _xImage = XGetImage(_x11Display, _window, _src_x, _src_y, _width, _height, AllPlanes, ZPixmap); } if (_xImage == nullptr) @@ -270,7 +188,7 @@ int X11Grabber::grabFrame(Image & image) return 0; } -int X11Grabber::updateScreenDimensions() +int X11Grabber::updateScreenDimensions(bool force) { const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr); if (status == 0) @@ -279,7 +197,7 @@ int X11Grabber::updateScreenDimensions() return -1; } - if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height)) + if (!force && _screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height)) { // No update required return 0; @@ -294,14 +212,16 @@ int X11Grabber::updateScreenDimensions() _screenWidth = _windowAttr.width; _screenHeight = _windowAttr.height; + int width=0, height=0; + // Image scaling is performed by XRender when available, otherwise by ImageResampler if (_XRenderAvailable && !_useXGetImage) { - _width = (_screenWidth > unsigned(_cropLeft + _cropRight)) + width = (_screenWidth > unsigned(_cropLeft + _cropRight)) ? ((_screenWidth - _cropLeft - _cropRight) / _horizontalDecimation) : _screenWidth / _horizontalDecimation; - _height = (_screenHeight > unsigned(_cropTop + _cropBottom)) + height = (_screenHeight > unsigned(_cropTop + _cropBottom)) ? ((_screenHeight - _cropTop - _cropBottom) / _verticalDecimation) : _screenHeight / _verticalDecimation; @@ -309,19 +229,52 @@ int X11Grabber::updateScreenDimensions() } else { - _width = (_screenWidth > unsigned(_cropLeft + _cropRight)) + width = (_screenWidth > unsigned(_cropLeft + _cropRight)) ? (_screenWidth - _cropLeft - _cropRight) : _screenWidth; - _height = (_screenHeight > unsigned(_cropTop + _cropBottom)) + height = (_screenHeight > unsigned(_cropTop + _cropBottom)) ? (_screenHeight - _cropTop - _cropBottom) : _screenHeight; Info(_log, "Using XGetImage for grabbing"); } + // calculate final image dimensions and adjust top/left cropping in 3D modes + switch (_videoMode) + { + case VIDEO_3DSBS: + _width = width /2; + _height = height; + _src_x = _cropLeft / 2; + _src_y = _cropTop; + break; + case VIDEO_3DTAB: + _width = width; + _height = height / 2; + _src_x = _cropLeft; + _src_y = _cropTop / 2; + break; + case VIDEO_2D: + default: + _width = width; + _height = height; + _src_x = _cropLeft; + _src_y = _cropTop; + break; + } + + Info(_log, "Update output image resolution: [%dx%d] to [%dx%d]", _image.width(), _image.height(), _width, _height); + _image.resize(_width, _height); setupResources(); return 1; } + +void X11Grabber::setVideoMode(VideoMode mode) +{ + Info(_log, "a %d", mode); + Grabber::setVideoMode(mode); + updateScreenDimensions(true); +} diff --git a/libsrc/grabber/x11/X11Wrapper.cpp b/libsrc/grabber/x11/X11Wrapper.cpp index ff610910..75f5f117 100644 --- a/libsrc/grabber/x11/X11Wrapper.cpp +++ b/libsrc/grabber/x11/X11Wrapper.cpp @@ -1,78 +1,24 @@ - -// Hyperion includes -#include -#include -#include - -// X11 grabber includes #include -#include X11Wrapper::X11Wrapper(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation, const unsigned updateRate_Hz, const int priority) - : GrabberWrapper("X11", priority) - , _updateInterval_ms(1000/updateRate_Hz) - , _timeout_ms(2 * _updateInterval_ms) - , _grabber(new X11Grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation)) - , _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0}) + : GrabberWrapper("X11", &_grabber, 0, 0, updateRate_Hz, priority, hyperion::COMP_GRABBER) + , _grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation) , _init(false) - , _x11SetupSuccess(false) -{ - // Configure the timer to generate events every n milliseconds - _timer.setInterval(_updateInterval_ms); -} +{} -X11Wrapper::~X11Wrapper() -{ - delete _grabber; -} - -bool X11Wrapper::start() +void X11Wrapper::action() { if (! _init ) { _init = true; - _x11SetupSuccess = _grabber->Setup(); - if ( _x11SetupSuccess ) + if ( ! _grabber.Setup() ) { - _x11SetupSuccess = (_grabber->updateScreenDimensions() >= 0); - _processor->setSize(_grabber->getImageWidth(), _grabber->getImageHeight()); - _image.resize(_grabber->getImageWidth(), _grabber->getImageHeight()); + stop(); } } - // Start the timer with the pre configured interval - if ( _x11SetupSuccess ) + + if (_grabber.updateScreenDimensions() >= 0 ) { - GrabberWrapper::start(); + transferFrame(_grabber); } - - ErrorIf( ! _x11SetupSuccess, _log, "X11 Grabber start failed"); - return _x11SetupSuccess; -} - - -void X11Wrapper::action() -{ - int result = _grabber->updateScreenDimensions(); - if (result < 0 ) - { - return; - } - if ( result > 0 ) - { - _processor->setSize(_grabber->getImageWidth(), _grabber->getImageHeight()); - _image.resize(_grabber->getImageWidth(), _grabber->getImageHeight()); - } - // Grab frame into the allocated image - _grabber->grabFrame(_image); - - emit emitImage(_priority, _image, _timeout_ms); - - _processor->process(_image, _ledColors); - setColors(_ledColors, _timeout_ms); -} - - -void X11Wrapper::setVideoMode(const VideoMode mode) -{ - _grabber->setVideoMode(mode); } diff --git a/libsrc/hyperion/Grabber.cpp b/libsrc/hyperion/Grabber.cpp index db0d9598..ce146898 100644 --- a/libsrc/hyperion/Grabber.cpp +++ b/libsrc/hyperion/Grabber.cpp @@ -3,16 +3,19 @@ Grabber::Grabber(QString grabberName, int width, int height, int cropLeft, int cropRight, int cropTop, int cropBottom) : _imageResampler() + , _useImageResampler(true) , _videoMode(VIDEO_2D) , _width(width) , _height(height) - , _cropLeft(cropLeft) - , _cropRight(cropRight) - , _cropTop(cropTop) - , _cropBottom(cropBottom) + , _cropLeft(0) + , _cropRight(0) + , _cropTop(0) + , _cropBottom(0) , _log(Logger::getInstance(grabberName)) { + setVideoMode(VIDEO_2D); + setCropping(cropLeft, cropRight, cropTop, cropBottom); } Grabber::~Grabber() @@ -22,6 +25,41 @@ Grabber::~Grabber() void Grabber::setVideoMode(VideoMode mode) { + Debug(_log,"setvideomode %d", mode); _videoMode = mode; - _imageResampler.set3D(_videoMode); + if ( _useImageResampler ) + { + _imageResampler.setVideoMode(_videoMode); + } +} + +void Grabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) +{ + if (_width>0 && _height>0) + { + if (cropLeft + cropRight >= (unsigned)_width || cropTop + cropBottom >= (unsigned)_height) + { + Error(_log, "Rejecting invalid crop values: left: %d, right: %d, top: %d, bottom: %d", cropLeft, cropRight, cropTop, cropBottom); + return; + } + } + + _cropLeft = cropLeft; + _cropRight = cropRight; + _cropTop = cropTop; + _cropBottom = cropBottom; + + if ( _useImageResampler ) + { + _imageResampler.setCropping(cropLeft, cropRight, cropTop, cropBottom); + } + else + { + _imageResampler.setCropping(0, 0, 0, 0); + } + + if (cropLeft > 0 || cropRight > 0 || cropTop > 0 || cropBottom > 0) + { + Info(_log, "Cropping image: width=%d height=%d; crop: left=%d right=%d top=%d bottom=%d ", _width, _height, cropLeft, cropRight, cropTop, cropBottom); + } } diff --git a/libsrc/hyperion/GrabberWrapper.cpp b/libsrc/hyperion/GrabberWrapper.cpp index cd743606..e9b7e5c0 100644 --- a/libsrc/hyperion/GrabberWrapper.cpp +++ b/libsrc/hyperion/GrabberWrapper.cpp @@ -2,20 +2,32 @@ #include #include #include +#include #include -GrabberWrapper::GrabberWrapper(QString grabberName, const int priority, hyperion::Components grabberComponentId) +GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned width, unsigned height, const unsigned updateRate_Hz, const int priority, hyperion::Components grabberComponentId) : _grabberName(grabberName) , _hyperion(Hyperion::getInstance()) , _priority(priority) , _timer() + , _updateInterval_ms(1000/updateRate_Hz) + , _timeout_ms(2 * _updateInterval_ms) , _log(Logger::getInstance(grabberName)) , _forward(true) , _processor(ImageProcessorFactory::getInstance().newImageProcessor()) , _grabberComponentId(grabberComponentId) + , _ggrabber(ggrabber) + , _image(0,0) + , _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0}) + , _imageProcessorEnabled(true) { _timer.setSingleShot(false); + // Configure the timer to generate events every n milliseconds + _timer.setInterval(_updateInterval_ms); + _image.resize(width, height); + _processor->setSize(width, height); + _forward = _hyperion->getForwarder()->protoForwardingEnabled(); _hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_BLACKBORDER, _processor->blackBorderDetectorEnabled()); qRegisterMetaType("hyperion::Components"); @@ -26,6 +38,7 @@ GrabberWrapper::GrabberWrapper(QString grabberName, const int priority, hyperion connect(_hyperion, SIGNAL(videoMode(VideoMode)), this, SLOT(setVideoMode(VideoMode))); connect(this, SIGNAL(emitImage(int, const Image&, const int)), _hyperion, SLOT(setImage(int, const Image&, const int)) ); connect(&_timer, SIGNAL(timeout()), this, SLOT(action())); + } GrabberWrapper::~GrabberWrapper() @@ -139,3 +152,24 @@ QStringList GrabberWrapper::availableGrabbers() return grabbers; } + + +void GrabberWrapper::setVideoMode(const VideoMode mode) +{ + if (_ggrabber != nullptr) + { + Info(_log,"setvideomode"); + _ggrabber->setVideoMode(mode); + } +} + +void GrabberWrapper::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) +{ + _ggrabber->setCropping(cropLeft, cropRight, cropTop, cropBottom); +} + +void GrabberWrapper::setImageProcessorEnabled(bool enable) +{ + _imageProcessorEnabled = enable; +} + diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index b9e5e2b7..18a566d2 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -487,14 +487,15 @@ unsigned Hyperion::addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequ void Hyperion::freeObjects(bool emitCloseSignal) { + // switch off all leds + clearall(true); + _device->switchOff(); + if (emitCloseSignal) { emit closing(); } - // switch off all leds - clearall(); - _device->switchOff(); // delete components on exit of hyperion core delete _effectEngine; @@ -740,9 +741,9 @@ void Hyperion::clear(int priority) _effectEngine->channelCleared(priority); } -void Hyperion::clearall() +void Hyperion::clearall(bool forceClearAll) { - _muxer.clearAll(); + _muxer.clearAll(forceClearAll); setSourceAutoSelectEnabled(true); // update leds diff --git a/libsrc/hyperion/ImageProcessor.cpp b/libsrc/hyperion/ImageProcessor.cpp index 0b5038da..1bebddc5 100644 --- a/libsrc/hyperion/ImageProcessor.cpp +++ b/libsrc/hyperion/ImageProcessor.cpp @@ -44,7 +44,7 @@ void ImageProcessor::setSize(const unsigned width, const unsigned height) delete _imageToLeds; // Construct a new buffer and mapping - _imageToLeds = new ImageToLedsMap(width, height, 0, 0, _ledString.leds()); + _imageToLeds = (width>0 && height>0) ? (new ImageToLedsMap(width, height, 0, 0, _ledString.leds())) : nullptr; } void ImageProcessor::enableBlackBorderDetector(bool enable) diff --git a/libsrc/hyperion/ImageToLedsMap.cpp b/libsrc/hyperion/ImageToLedsMap.cpp index 679b46b8..d02e9c81 100644 --- a/libsrc/hyperion/ImageToLedsMap.cpp +++ b/libsrc/hyperion/ImageToLedsMap.cpp @@ -17,6 +17,8 @@ ImageToLedsMap::ImageToLedsMap( // Sanity check of the size of the borders (and width and height) Q_ASSERT(_width > 2*_verticalBorder); Q_ASSERT(_height > 2*_horizontalBorder); + Q_ASSERT(_width < 10000); + Q_ASSERT(_height < 10000); // Reserve enough space in the map for the leds _colorsMap.reserve(leds.size()); diff --git a/libsrc/hyperion/PriorityMuxer.cpp b/libsrc/hyperion/PriorityMuxer.cpp index 67de4dfa..33908917 100644 --- a/libsrc/hyperion/PriorityMuxer.cpp +++ b/libsrc/hyperion/PriorityMuxer.cpp @@ -78,13 +78,22 @@ void PriorityMuxer::clearInput(const int priority) } } -void PriorityMuxer::clearAll() +void PriorityMuxer::clearAll(bool forceClearAll) { - for(auto key : _activeInputs.keys()) + if (forceClearAll) { - if (key < LOWEST_PRIORITY-1) + _activeInputs.clear(); + _currentPriority = LOWEST_PRIORITY; + _activeInputs[_currentPriority] = _lowestPriorityInfo; + } + else + { + for(auto key : _activeInputs.keys()) { - _activeInputs.remove(key); + if (key < LOWEST_PRIORITY-1) + { + _activeInputs.remove(key); + } } } } diff --git a/libsrc/hyperion/schema/schema-grabberV4L2.json b/libsrc/hyperion/schema/schema-grabberV4L2.json index c67330c3..6cc01aad 100644 --- a/libsrc/hyperion/schema/schema-grabberV4L2.json +++ b/libsrc/hyperion/schema/schema-grabberV4L2.json @@ -46,8 +46,8 @@ { "type" : "integer", "title" : "edt_conf_v4l2_width_title", - "minimum" : -1, - "default" : -1, + "minimum" : 0, + "default" : 0, "append" : "edt_append_pixel", "propertyOrder" : 5 }, @@ -55,8 +55,8 @@ { "type" : "integer", "title" : "edt_conf_v4l2_height_title", - "minimum" : -1, - "default" : -1, + "minimum" : 0, + "default" : 0, "append" : "edt_append_pixel", "propertyOrder" : 6 }, diff --git a/libsrc/protoserver/CMakeLists.txt b/libsrc/protoserver/CMakeLists.txt index 5c5bd1e6..737292f2 100644 --- a/libsrc/protoserver/CMakeLists.txt +++ b/libsrc/protoserver/CMakeLists.txt @@ -19,6 +19,8 @@ add_library(protoserver ${ProtoServer_PROTO_SRCS} ${ProtoServer_PROTO_HDRS} ) +# disable warnings for auto generatet proto files, we can't change the files .... +SET_SOURCE_FILES_PROPERTIES ( ${ProtoServer_PROTO_SRCS} ${ProtoServer_PROTO_HDRS} ${ProtoServer_PROTOS} PROPERTIES COMPILE_FLAGS -w ) target_link_libraries(protoserver hyperion diff --git a/libsrc/utils/ImageResampler.cpp b/libsrc/utils/ImageResampler.cpp index d8df181c..2c42941f 100755 --- a/libsrc/utils/ImageResampler.cpp +++ b/libsrc/utils/ImageResampler.cpp @@ -30,22 +30,22 @@ void ImageResampler::setVerticalPixelDecimation(int decimator) void ImageResampler::setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom) { - _cropLeft = cropLeft; - _cropRight = cropRight; - _cropTop = cropTop; + _cropLeft = cropLeft; + _cropRight = cropRight; + _cropTop = cropTop; _cropBottom = cropBottom; } -void ImageResampler::set3D(VideoMode mode) +void ImageResampler::setVideoMode(VideoMode mode) { _videoMode = mode; } void ImageResampler::processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image &outputImage) const { - int cropLeft = _cropLeft; - int cropRight = _cropRight; - int cropTop = _cropTop; + int cropLeft = _cropLeft; + int cropRight = _cropRight; + int cropTop = _cropTop; int cropBottom = _cropBottom; // handle 3D mode diff --git a/libsrc/utils/JSONRPC_schema/schema-videomode.json b/libsrc/utils/JSONRPC_schema/schema-videomode.json index 8ffc7c28..fb06f738 100644 --- a/libsrc/utils/JSONRPC_schema/schema-videomode.json +++ b/libsrc/utils/JSONRPC_schema/schema-videomode.json @@ -10,7 +10,7 @@ "tan" : { "type" : "integer" }, - "mappingType": { + "videoMode": { "type" : "string", "enum" : ["2D", "3DSBS", "3DTAB"] } diff --git a/src/hyperion-aml/AmlogicWrapper.cpp b/src/hyperion-aml/AmlogicWrapper.cpp index cf9c2ea2..54228208 100644 --- a/src/hyperion-aml/AmlogicWrapper.cpp +++ b/src/hyperion-aml/AmlogicWrapper.cpp @@ -16,7 +16,7 @@ AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeig const Image & AmlogicWrapper::getScreenshot() { capture(); - return _screenshot_rgb; + return _screenshot; } void AmlogicWrapper::start() @@ -32,7 +32,5 @@ void AmlogicWrapper::stop() void AmlogicWrapper::capture() { _grabber.grabFrame(_screenshot); - _screenshot.toRgb(_screenshot_rgb); - - emit sig_screenshot(_screenshot_rgb); + emit sig_screenshot(_screenshot); } diff --git a/src/hyperion-aml/AmlogicWrapper.h b/src/hyperion-aml/AmlogicWrapper.h index 3f5b0bc8..7ddbcda1 100644 --- a/src/hyperion-aml/AmlogicWrapper.h +++ b/src/hyperion-aml/AmlogicWrapper.h @@ -37,7 +37,6 @@ private: AmlogicGrabber _grabber; // image buffers - Image _screenshot_rgb; - Image _screenshot; + Image _screenshot; }; diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt index 91d46066..8f441afa 100644 --- a/src/hyperion-dispmanx/CMakeLists.txt +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -2,7 +2,12 @@ cmake_minimum_required(VERSION 2.8.12) project(hyperion-dispmanx) find_package(Qt5Widgets REQUIRED) -find_package(BCM REQUIRED) +IF ( "${PLATFORM}" MATCHES rpi) + find_package(BCM REQUIRED) +ELSE() + SET(BCM_INCLUDE_DIRS "") + SET(BCM_LIBRARIES "") +ENDIF() include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp index 78f10f02..48ace5b8 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.cpp +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -22,7 +22,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe const Image & DispmanxWrapper::getScreenshot() { capture(); - return _screenshot_rgb; + return _screenshot; } void DispmanxWrapper::start() @@ -38,7 +38,5 @@ void DispmanxWrapper::stop() void DispmanxWrapper::capture() { _grabber.grabFrame(_screenshot); - _screenshot.toRgb(_screenshot_rgb); - - emit sig_screenshot(_screenshot_rgb); + emit sig_screenshot(_screenshot); } diff --git a/src/hyperion-dispmanx/DispmanxWrapper.h b/src/hyperion-dispmanx/DispmanxWrapper.h index fa89fa4f..712e4093 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.h +++ b/src/hyperion-dispmanx/DispmanxWrapper.h @@ -40,7 +40,5 @@ private: /// The grabber for creating screenshots DispmanxFrameGrabber _grabber; - Image _screenshot_rgb; - Image _screenshot; - + Image _screenshot; }; diff --git a/src/hyperion-x11/X11Wrapper.cpp b/src/hyperion-x11/X11Wrapper.cpp index 53b4cb44..01731ecf 100644 --- a/src/hyperion-x11/X11Wrapper.cpp +++ b/src/hyperion-x11/X11Wrapper.cpp @@ -15,8 +15,8 @@ X11Wrapper::X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cr const Image & X11Wrapper::getScreenshot() { - const Image & screenshot = _grabber.grab(); - return screenshot; + _grabber.grabFrame(_screenshot, true); + return _screenshot; } void X11Wrapper::start() @@ -36,8 +36,8 @@ bool X11Wrapper::displayInit() void X11Wrapper::capture() { - const Image & screenshot = _grabber.grab(); - emit sig_screenshot(screenshot); + _grabber.grabFrame(_screenshot, true); + emit sig_screenshot(_screenshot); } void X11Wrapper::setGrabbingMode(const GrabbingMode mode) diff --git a/src/hyperion-x11/X11Wrapper.h b/src/hyperion-x11/X11Wrapper.h index c16487eb..f258df90 100644 --- a/src/hyperion-x11/X11Wrapper.h +++ b/src/hyperion-x11/X11Wrapper.h @@ -55,4 +55,6 @@ private: /// The grabber for creating screenshots X11Grabber _grabber; + + Image _screenshot; }; diff --git a/src/hyperion-x11/hyperion-x11.cpp b/src/hyperion-x11/hyperion-x11.cpp index 97e031a1..aada15ff 100644 --- a/src/hyperion-x11/hyperion-x11.cpp +++ b/src/hyperion-x11/hyperion-x11.cpp @@ -98,7 +98,7 @@ 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()); + Error(Logger::getInstance("X11GRABBER"), "%s", e.what()); return -1; } diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index d8d75718..5cbd2e1d 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -86,6 +86,7 @@ HyperionDaemon::~HyperionDaemon() void HyperionDaemon::freeObjects() { + _hyperion->clearall(true); Debug(_log, "destroy grabbers and network stuff"); delete _amlGrabber; delete _dispmanx; @@ -117,7 +118,6 @@ void HyperionDaemon::freeObjects() void HyperionDaemon::run() { - startInitialEffect(); createKODIVideoChecker(); // ---- network services ----- @@ -133,6 +133,8 @@ void HyperionDaemon::run() Info(_log, "Hyperion started"); connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects())); + + startInitialEffect(); } void HyperionDaemon::loadConfig(const QString & configFile) @@ -499,6 +501,7 @@ void HyperionDaemon::createGrabberX11(const QJsonObject & grabberConfig) grabberConfig["horizontalPixelDecimation"].toInt(8), grabberConfig["verticalPixelDecimation"].toInt(8), _grabber_frequency, _grabber_priority ); + _x11Grabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom); QObject::connect(_x11Grabber, SIGNAL(emitImage(int, const Image&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); @@ -517,7 +520,7 @@ void HyperionDaemon::createGrabberFramebuffer(const QJsonObject & grabberConfig) _fbGrabber = new FramebufferWrapper( grabberConfig["device"].toString("/dev/fb0"), _grabber_width, _grabber_height, _grabber_frequency, _grabber_priority); - + _fbGrabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom); QObject::connect(_fbGrabber, SIGNAL(emitImage(int, const Image&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); _fbGrabber->start(); @@ -570,8 +573,8 @@ void HyperionDaemon::createGrabberV4L2() grabberConfig["input"].toInt(0), parseVideoStandard(grabberConfig["standard"].toString("no-change")), parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change")), - grabberConfig["width"].toInt(-1), - grabberConfig["height"].toInt(-1), + grabberConfig["width"].toInt(0), + grabberConfig["height"].toInt(0), grabberConfig["frameDecimation"].toInt(2), grabberConfig["sizeDecimation"].toInt(8), grabberConfig["redSignalThreshold"].toDouble(0.0)/100.0, diff --git a/src/hyperiond/hyperiond.h b/src/hyperiond/hyperiond.h index f774ea9f..173fdd37 100644 --- a/src/hyperiond/hyperiond.h +++ b/src/hyperiond/hyperiond.h @@ -1,6 +1,7 @@ #pragma once #include +#include #ifdef ENABLE_DISPMANX #include @@ -46,7 +47,7 @@ #include #include #include -#include + class SysTray; diff --git a/test/dispmanx2png/CMakeLists.txt b/test/dispmanx2png/CMakeLists.txt index 8037f8b0..4ee6f38f 100644 --- a/test/dispmanx2png/CMakeLists.txt +++ b/test/dispmanx2png/CMakeLists.txt @@ -1,15 +1,15 @@ +# this is only available on real pi +IF ( "${PLATFORM}" MATCHES rpi) + # Find the BCM-package (VC control) + find_package(Qt5Widgets REQUIRED) -# Find the BCM-package (VC control) -find_package(BCM REQUIRED) -include_directories(${BCM_INCLUDE_DIRS}) + add_definitions(${QT_DEFINITIONS}) + link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) -add_definitions(${QT_DEFINITIONS}) -link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) - - -add_executable(dispmanx2png + add_executable(dispmanx2png dispmanx2png.cpp) -target_link_libraries(dispmanx2png + target_link_libraries(dispmanx2png dispmanx-grabber Qt5::Gui) +ENDIF()