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
This commit is contained in:
redPanther 2017-08-12 07:55:32 +02:00 committed by GitHub
parent 317a903b14
commit 9eff6384cc
61 changed files with 830 additions and 748 deletions

View File

@ -30,6 +30,11 @@ cd build
[ "${TRAVIS_EVENT_TYPE:-}" != 'cron' -a -z "${TRAVIS_TAG:-}" ] && PLATFORM=${PLATFORM}-dev [ "${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 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}" echo "compile jobs: ${JOBS:=4}"
make -j ${JOBS} || exit 3 make -j ${JOBS} || exit 3

View File

@ -95,6 +95,9 @@ if ( "${PLATFORM}" MATCHES "-dev" )
SET ( DEFAULT_TESTS ON ) SET ( DEFAULT_TESTS ON )
endif() endif()
STRING( TOUPPER "-DPLATFORM_${PLATFORM}" PLATFORM_DEFINE)
STRING( REPLACE "-DEV" "" PLATFORM_DEFINE "${PLATFORM_DEFINE}" )
ADD_DEFINITIONS( ${PLATFORM_DEFINE} )
# set the build options # set the build options
option(ENABLE_AMLOGIC "Enable the AMLOGIC video grabber" ${DEFAULT_AMLOGIC} ) 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) # link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
#endif() #endif()
if(ENABLE_OSX) if(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "-framework CoreGraphics") set(CMAKE_EXE_LINKER_FLAGS "-framework CoreGraphics")
endif() endif()

View File

@ -133,8 +133,8 @@
"device" : "auto", "device" : "auto",
"input" : 0, "input" : 0,
"standard" : "PAL", "standard" : "PAL",
"width" : -1, "width" : 0,
"height" : -1, "height" : 0,
"frameDecimation" : 2, "frameDecimation" : 2,
"sizeDecimation" : 8, "sizeDecimation" : 8,
"priority" : 240, "priority" : 240,

View File

@ -64,8 +64,8 @@
"device" : "auto", "device" : "auto",
"input" : 0, "input" : 0,
"standard" : "PAL", "standard" : "PAL",
"width" : -1, "width" : 0,
"height" : -1, "height" : 0,
"frameDecimation" : 2, "frameDecimation" : 2,
"sizeDecimation" : 8, "sizeDecimation" : 8,
"priority" : 240, "priority" : 240,

View File

@ -11,33 +11,37 @@ class SwitchOption: public Option
{ {
public: public:
SwitchOption(const QString &name, SwitchOption(const QString &name,
const QString &description = QString(), const QString &description = QString(),
const QString &valueName = QString(), const QString &valueName = QString(),
const QString &defaultValue = QString(), const QString &defaultValue = QString(),
const QMap<QString, T> &switches=QMap<QString, T>()) const QMap<QString, T> &switches=QMap<QString, T>())
: Option(name, description, valueName, defaultValue), _switches(switches) : 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<QString, T> &switches=QMap<QString, T>())
: Option(names, description, valueName, defaultValue), _switches(switches)
{}
SwitchOption(const QCommandLineOption &other, const QMap<QString, T> &switches)
: Option(other), _switches(switches)
{}
const QMap<QString, T> &getSwitches() const{return _switches;}; SwitchOption(const QStringList &names,
virtual bool validate(Parser &parser, QString &switch_) override{return hasSwitch(switch_);} const QString &description = QString(),
bool hasSwitch(const QString &switch_){return _switches.contains(switch_.toLower());} const QString &valueName = QString(),
void setSwitches(const QMap<QString, T> &_switches){this->_switches = _switches;} const QString &defaultValue = QString(),
void addSwitch(const QString &switch_, T value=T()){_switches[switch_.toLower()] = value;} const QMap<QString, T> &switches=QMap<QString, T>())
void removeSwitch(const QString &switch_){_switches.remove(switch_.toLower());} : Option(names, description, valueName, defaultValue), _switches(switches)
T & switchValue(Parser & parser){return _switches[value(parser).toLower()];} {}
SwitchOption(const QCommandLineOption &other, const QMap<QString, T> &switches)
: Option(other), _switches(switches)
{}
virtual ~SwitchOption() {}
const QMap<QString, T> &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<QString, T> &_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: protected:
QMap<QString, T> _switches; QMap<QString, T> _switches;
}; };
} }

View File

@ -29,14 +29,17 @@ public:
/// height) /// height)
/// @return Zero on success else negative /// @return Zero on success else negative
/// ///
int grabFrame(Image<ColorBgr> & image); int grabFrame(Image<ColorRgb> & image);
private:
/** /**
* Returns true if video is playing over the amlogic chip * Returns true if video is playing over the amlogic chip
* @return True if video is playing else false * @return True if video is playing else false
*/ */
bool isVideoPlaying(); bool isVideoPlaying();
private:
/** The snapshot/capture device of the amlogic video chip */ /** The snapshot/capture device of the amlogic video chip */
int _amlogicCaptureDev; int _amlogicCaptureDev;
Image<ColorBgr> _image;
}; };

View File

@ -1,16 +1,7 @@
#pragma once #pragma once
// Utils includes
#include <utils/Image.h>
#include <utils/ColorBgr.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.h>
#include <hyperion/GrabberWrapper.h> #include <hyperion/GrabberWrapper.h>
#include <grabber/AmlogicGrabber.h>
// Forward class declaration
class AmlogicGrabber;
class Hyperion;
class ImageProcessor;
/// ///
/// The DispmanxWrapper uses an instance of the DispmanxFrameGrabber to obtain ImageRgb's from the /// 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. /// Destructor of this dispmanx frame grabber. Releases any claimed resources.
/// ///
virtual ~AmlogicWrapper(); virtual ~AmlogicWrapper() {};
public slots: public slots:
/// ///
@ -42,19 +33,7 @@ public slots:
/// ///
virtual void action(); virtual void action();
virtual void setVideoMode(const VideoMode mode);
private: 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<ColorBgr> _image;
/// The actual grabber /// The actual grabber
AmlogicGrabber * _grabber; AmlogicGrabber _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
}; };

View File

@ -1,10 +1,15 @@
#pragma once #pragma once
// BCM includes // BCM includes
#pragma GCC system_header #ifdef PLATFORM_RPI
#include <bcm_host.h> #pragma GCC system_header
#include <bcm_host.h>
#else
#include <grabber/DispmanxFrameGrabberMock.h>
#endif
// Utils includes // Utils includes
#include <utils/Image.h>
#include <utils/ColorRgba.h> #include <utils/ColorRgba.h>
#include <hyperion/Grabber.h> #include <hyperion/Grabber.h>
@ -24,15 +29,6 @@ public:
DispmanxFrameGrabber(const unsigned width, const unsigned height); DispmanxFrameGrabber(const unsigned width, const unsigned height);
~DispmanxFrameGrabber(); ~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 /// 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 /// @param[out] image The snapped screenshot (should be initialized with correct width and
/// height) /// height)
/// ///
void grabFrame(Image<ColorRgba> & image); int grabFrame(Image<ColorRgb> & image);
private: 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 /// Handle to the display that is being captured
DISPMANX_DISPLAY_HANDLE_T _vc_display; DISPMANX_DISPLAY_HANDLE_T _vc_display;
@ -63,4 +66,8 @@ private:
// size of the capture buffer in Pixels // size of the capture buffer in Pixels
unsigned _captureBufferSize; unsigned _captureBufferSize;
// rgba output buffer
Image<ColorRgba> _image_rgba;
}; };

View File

@ -0,0 +1,40 @@
#pragma once
#ifndef PLATFORM_RPI
#include <QRect>
#include <utils/Image.h>
#include <utils/ColorRgba.h>
typedef int DISPMANX_DISPLAY_HANDLE_T;
typedef Image<ColorRgba> 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

View File

@ -1,16 +1,9 @@
#pragma once #pragma once
// Utils includes // Utils includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/ColorRgba.h> #include <utils/ColorRgba.h>
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
#include <hyperion/GrabberWrapper.h> #include <hyperion/GrabberWrapper.h>
#include <grabber/DispmanxFrameGrabber.h>
// Forward class declaration
class DispmanxFrameGrabber;
class ImageProcessor;
/// ///
/// The DispmanxWrapper uses an instance of the DispmanxFrameGrabber to obtain ImageRgb's from the /// 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. /// Destructor of this dispmanx frame grabber. Releases any claimed resources.
/// ///
virtual ~DispmanxWrapper(); virtual ~DispmanxWrapper() {};
public slots: public slots:
/// ///
@ -42,25 +35,7 @@ public slots:
/// ///
virtual void action(); 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: 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<ColorRgba> _image;
/// The actual grabber /// The actual grabber
DispmanxFrameGrabber * _grabber; DispmanxFrameGrabber _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
}; };

View File

@ -28,7 +28,7 @@ public:
/// @param[out] image The snapped screenshot (should be initialized with correct width and /// @param[out] image The snapped screenshot (should be initialized with correct width and
/// height) /// height)
/// ///
void grabFrame(Image<ColorRgb> & image); int grabFrame(Image<ColorRgb> & image);
private: private:
/// Framebuffer file descriptor /// Framebuffer file descriptor

View File

@ -1,15 +1,7 @@
#pragma once #pragma once
// Utils includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
#include <hyperion/GrabberWrapper.h> #include <hyperion/GrabberWrapper.h>
#include <grabber/FramebufferFrameGrabber.h>
// Forward class declaration
class FramebufferFrameGrabber;
class ImageProcessor;
/// ///
/// The FramebufferWrapper uses an instance of the FramebufferFrameGrabber to obtain ImageRgb's from the /// 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. /// Destructor of this framebuffer frame grabber. Releases any claimed resources.
/// ///
virtual ~FramebufferWrapper(); virtual ~FramebufferWrapper() {};
public slots: public slots:
/// ///
@ -41,23 +33,7 @@ public slots:
/// ///
virtual void action(); virtual void action();
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(const VideoMode videoMode);
private: 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<ColorRgb> _image;
/// The actual grabber /// The actual grabber
FramebufferFrameGrabber * _grabber; FramebufferFrameGrabber _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
}; };

View File

@ -1,7 +1,11 @@
#pragma once #pragma once
// OSX includes // OSX includes
#ifdef __APPLE__
#include <CoreGraphics/CoreGraphics.h> #include <CoreGraphics/CoreGraphics.h>
#else
#include <grabber/OsxFrameGrabberMock.h>
#endif
// Utils includes // Utils includes
#include <utils/ColorRgb.h> #include <utils/ColorRgb.h>
@ -31,7 +35,7 @@ public:
/// @param[out] image The snapped screenshot (should be initialized with correct width and /// @param[out] image The snapped screenshot (should be initialized with correct width and
/// height) /// height)
/// ///
void grabFrame(Image<ColorRgb> & image); int grabFrame(Image<ColorRgb> & image);
private: private:
/// display /// display

View File

@ -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 <utils/Image.h>
#include <utils/ColorRgb.h>
typedef int CGDirectDisplayID;
typedef Image<ColorRgb> 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

View File

@ -1,16 +1,7 @@
#pragma once #pragma once
// Utils includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/ColorRgba.h>
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
#include <hyperion/GrabberWrapper.h> #include <hyperion/GrabberWrapper.h>
#include <grabber/OsxFrameGrabber.h>
// Forward class declaration
class OsxFrameGrabber;
class ImageProcessor;
/// ///
/// The OsxWrapper uses an instance of the OsxFrameGrabber to obtain ImageRgb's from the /// 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. /// Destructor of this osx frame grabber. Releases any claimed resources.
/// ///
virtual ~OsxWrapper(); virtual ~OsxWrapper() {};
public slots: public slots:
/// ///
@ -43,23 +34,7 @@ public slots:
/// ///
virtual void action(); virtual void action();
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(const VideoMode videoMode);
private: 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<ColorRgb> _image;
/// The actual grabber /// The actual grabber
OsxFrameGrabber * _grabber; OsxFrameGrabber _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
}; };

View File

@ -10,11 +10,8 @@
#include <QRectF> #include <QRectF>
// util includes // util includes
#include <utils/ColorRgb.h>
#include <utils/PixelFormat.h> #include <utils/PixelFormat.h>
#include <hyperion/Grabber.h> #include <hyperion/Grabber.h>
// grabber includes
#include <grabber/VideoStandard.h> #include <grabber/VideoStandard.h>
/// Capture class for V4L2 devices /// Capture class for V4L2 devices
@ -28,8 +25,8 @@ public:
V4L2Grabber(const QString & device, V4L2Grabber(const QString & device,
int input, int input,
VideoStandard videoStandard, PixelFormat pixelFormat, VideoStandard videoStandard, PixelFormat pixelFormat,
int width, unsigned width,
int height, unsigned height,
int frameDecimation, int frameDecimation,
int horizontalPixelDecimation, int horizontalPixelDecimation,
int verticalPixelDecimation int verticalPixelDecimation
@ -39,12 +36,9 @@ public:
QRectF getSignalDetectionOffset(); QRectF getSignalDetectionOffset();
bool getSignalDetectionEnabled(); bool getSignalDetectionEnabled();
int grabFrame(Image<ColorRgb> &);
public slots: public slots:
void setCropping(int cropLeft,
int cropRight,
int cropTop,
int cropBottom);
void setSignalThreshold( void setSignalThreshold(
double redSignalThreshold, double redSignalThreshold,
double greenSignalThreshold, double greenSignalThreshold,

View File

@ -1,11 +1,6 @@
#pragma once #pragma once
// Hyperion includes
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessor.h>
#include <hyperion/GrabberWrapper.h> #include <hyperion/GrabberWrapper.h>
// Grabber includes
#include <grabber/V4L2Grabber.h> #include <grabber/V4L2Grabber.h>
class V4L2Wrapper : public GrabberWrapper class V4L2Wrapper : public GrabberWrapper
@ -17,8 +12,8 @@ public:
int input, int input,
VideoStandard videoStandard, VideoStandard videoStandard,
PixelFormat pixelFormat, PixelFormat pixelFormat,
int width, unsigned width,
int height, unsigned height,
int frameDecimation, int frameDecimation,
int pixelDecimation, int pixelDecimation,
double redSignalThreshold, double redSignalThreshold,
@ -26,7 +21,7 @@ public:
double blueSignalThreshold, double blueSignalThreshold,
const int priority, const int priority,
bool useGrabbingMode); bool useGrabbingMode);
virtual ~V4L2Wrapper(); virtual ~V4L2Wrapper() {};
bool getSignalDetectionEnable(); bool getSignalDetectionEnable();
@ -36,7 +31,6 @@ public slots:
void setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom); void setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom);
void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax); void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax);
void setVideoMode(VideoMode mode);
void setSignalDetectionEnable(bool enable); void setSignalDetectionEnable(bool enable);
// signals: // signals:
@ -50,12 +44,6 @@ private slots:
void checkSources(); void checkSources();
private: private:
/// The timeout of the led colors [ms]
const int _timeout_ms;
/// The V4L2 grabber /// The V4L2 grabber
V4L2Grabber _grabber; V4L2Grabber _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
}; };

View File

@ -22,8 +22,6 @@ public:
virtual ~X11Grabber(); virtual ~X11Grabber();
bool Setup(); bool Setup();
Image<ColorRgb> & grab();
/// ///
/// Captures a single snapshot of the display and writes the data to the given image. The /// 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 /// @param[out] image The snapped screenshot (should be initialized with correct width and
/// height) /// height)
/// ///
int grabFrame(Image<ColorRgb> & image); virtual int grabFrame(Image<ColorRgb> & image, bool forceUpdate=false);
/// ///
/// update dimension according current screen /// update dimension according current screen
int updateScreenDimensions(); int updateScreenDimensions(bool force=false);
virtual void setVideoMode(VideoMode mode);
private: private:
bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable; bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable;
@ -63,6 +63,8 @@ private:
unsigned _screenWidth; unsigned _screenWidth;
unsigned _screenHeight; unsigned _screenHeight;
unsigned _src_x;
unsigned _src_y;
Image<ColorRgb> _image; Image<ColorRgb> _image;

View File

@ -1,14 +1,12 @@
#pragma once #pragma once
// Utils includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.h>
#include <hyperion/GrabberWrapper.h> #include <hyperion/GrabberWrapper.h>
#include <grabber/X11Grabber.h>
// 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 /// 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. /// Destructor of this framebuffer frame grabber. Releases any claimed resources.
/// ///
virtual ~X11Wrapper(); virtual ~X11Wrapper() {};
public slots: 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 /// Performs a single frame grab and computes the led-colors
/// ///
virtual void action(); virtual void action();
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(const VideoMode videoMode);
private: 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<ColorRgb> _image;
/// The actual grabber /// The actual grabber
X11Grabber * _grabber; X11Grabber _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
bool _init; bool _init;
bool _x11SetupSuccess;
}; };

View File

@ -3,6 +3,7 @@
#include <QObject> #include <QObject>
#include <cstdint> #include <cstdint>
#include <utils/ColorRgb.h>
#include <utils/Image.h> #include <utils/Image.h>
#include <utils/VideoMode.h> #include <utils/VideoMode.h>
#include <utils/GrabbingMode.h> #include <utils/GrabbingMode.h>
@ -16,24 +17,28 @@ class Grabber : public QObject
public: public:
Grabber(QString grabberName, int width=0, int height=0, int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0); 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) /// Set the video mode (2D/3D)
/// @param[in] mode The new video mode /// @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 /// gets resulting height of image
const int getImageWidth() { return _width; }; virtual const int getImageWidth() { return _width; };
/// gets resulting width of image /// gets resulting width of image
const int getImageHeight() { return _height; }; virtual const int getImageHeight() { return _height; };
protected: protected:
ImageResampler _imageResampler; ImageResampler _imageResampler;
bool _useImageResampler;
/// the selected VideoMode /// the selected VideoMode
VideoMode _videoMode; VideoMode _videoMode;

View File

@ -9,14 +9,20 @@
#include <utils/Components.h> #include <utils/Components.h>
#include <utils/GrabbingMode.h> #include <utils/GrabbingMode.h>
#include <hyperion/Hyperion.h> #include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessor.h>
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.h>
class ImageProcessor; class ImageProcessor;
class Grabber;
class DispmanxFrameGrabber;
class GrabberWrapper : public QObject class GrabberWrapper : public QObject
{ {
Q_OBJECT Q_OBJECT
public: 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(); virtual ~GrabberWrapper();
@ -30,8 +36,32 @@ public:
/// ///
virtual void stop(); virtual void stop();
void setImageProcessorEnabled(bool enable);
static QStringList availableGrabbers(); static QStringList availableGrabbers();
public:
template <typename Grabber_T>
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: public slots:
void componentStateChanged(const hyperion::Components component, bool enable); void componentStateChanged(const hyperion::Components component, bool enable);
@ -50,8 +80,9 @@ public slots:
/// Set the video mode (2D/3D) /// Set the video mode (2D/3D)
/// @param[in] mode The new video mode /// @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: signals:
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms); void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
@ -59,6 +90,7 @@ signals:
protected: protected:
void setColors(const std::vector<ColorRgb> &ledColors, const int timeout_ms); void setColors(const std::vector<ColorRgb> &ledColors, const int timeout_ms);
QString _grabberName; QString _grabberName;
/// Pointer to Hyperion for writing led values /// Pointer to Hyperion for writing led values
@ -70,6 +102,12 @@ protected:
/// The timer for generating events with the specified update rate /// The timer for generating events with the specified update rate
QTimer _timer; QTimer _timer;
/// The update rate [Hz]
const int _updateInterval_ms;
/// The timeout of the led colors [ms]
const int _timeout_ms;
/// The Logger instance /// The Logger instance
Logger * _log; Logger * _log;
@ -80,4 +118,15 @@ protected:
ImageProcessor * _processor; ImageProcessor * _processor;
hyperion::Components _grabberComponentId; hyperion::Components _grabberComponentId;
Grabber *_ggrabber;
/// The image used for grabbing frames
Image<ColorRgb> _image;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
bool _imageProcessorEnabled;
}; };

View File

@ -260,7 +260,7 @@ public slots:
/// ///
/// Clears all priority channels. This will switch the leds off until a new priority is written. /// 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 /// Run the specified effect on the given priority channel and optionally specify a timeout
/// @param effectName Name of the effec to run /// @param effectName Name of the effec to run

View File

@ -42,7 +42,6 @@ public:
/// ///
void setSize(const unsigned width, const unsigned height); void setSize(const unsigned width, const unsigned height);
/// Returns starte of black border detector /// Returns starte of black border detector
bool blackBorderDetectorEnabled(); bool blackBorderDetectorEnabled();
@ -59,7 +58,20 @@ public slots:
/// Enable or disable the black border detector /// Enable or disable the black border detector
void setLedMappingType(int mapType); 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 <typename Pixel_T>
void setSize(const Image<Pixel_T> &image)
{
setSize(image.width(), image.height());
}
/// ///
/// Processes the image to a list of led colors. This will update the size of the buffer-image /// 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. /// if required and call the image-to-leds mapping to determine the mean color per led.
@ -71,18 +83,25 @@ public:
template <typename Pixel_T> template <typename Pixel_T>
std::vector<ColorRgb> process(const Image<Pixel_T>& image) std::vector<ColorRgb> process(const Image<Pixel_T>& 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<ColorRgb> colors; std::vector<ColorRgb> colors;
switch (_mappingType) if (image.width()>0 && image.height()>0)
{ {
case 1: colors = _imageToLeds->getUniLedColor(image); break; // Ensure that the buffer-image is the proper size
default: colors = _imageToLeds->getMeanLedColor(image); 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 // return the computed colors
@ -98,19 +117,25 @@ public:
template <typename Pixel_T> template <typename Pixel_T>
void process(const Image<Pixel_T>& image, std::vector<ColorRgb>& ledColors) void process(const Image<Pixel_T>& image, std::vector<ColorRgb>& ledColors)
{ {
// Ensure that the buffer-image is the proper size if ( image.width()>0 && image.height()>0)
setSize(image.width(), image.height());
// 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; // Ensure that the buffer-image is the proper size
default: _imageToLeds->getMeanLedColor(image, ledColors); 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");
}
} }
/// ///

View File

@ -118,7 +118,7 @@ public:
/// ///
/// Clears all priority channels /// 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 /// Updates the current time. Channels with a configured time out will be checked and cleared if
@ -152,5 +152,4 @@ private:
QTimer _timer; QTimer _timer;
QTimer _blockTimer; QTimer _blockTimer;
}; };

View File

@ -20,7 +20,7 @@ public:
int cropTop, int cropTop,
int cropBottom); 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<ColorRgb> & outputImage) const; void processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image<ColorRgb> & outputImage) const;

View File

@ -52,10 +52,6 @@ AmlogicGrabber::~AmlogicGrabber()
bool AmlogicGrabber::isVideoPlaying() bool AmlogicGrabber::isVideoPlaying()
{ {
// TODO crop resulting image accroding member _videoMode
// TODO add croping
const QString videoDevice = "/dev/amvideo"; const QString videoDevice = "/dev/amvideo";
// Open the video device // Open the video device
@ -81,13 +77,10 @@ bool AmlogicGrabber::isVideoPlaying()
return videoDisabled == 0; return videoDisabled == 0;
} }
int AmlogicGrabber::grabFrame(Image<ColorBgr> & image) int AmlogicGrabber::grabFrame(Image<ColorRgb> & image)
{ {
// resize the given image if needed // TODO crop resulting image accroding member _videoMode
if (image.width() != (unsigned)_width || image.height() != (unsigned)_height) // TODO add croping
{
image.resize(_width, _height);
}
// Make sure video is playing, else there is nothing to grab // Make sure video is playing, else there is nothing to grab
if (!isVideoPlaying()) if (!isVideoPlaying())
@ -95,7 +88,6 @@ int AmlogicGrabber::grabFrame(Image<ColorBgr> & image)
return -1; return -1;
} }
// If the device is not open, attempt to open it // If the device is not open, attempt to open it
if (_amlogicCaptureDev == -1) if (_amlogicCaptureDev == -1)
{ {
@ -121,7 +113,7 @@ int AmlogicGrabber::grabFrame(Image<ColorBgr> & image)
} }
// Read the snapshot into the memory // 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 bytesToRead = _width * _height * sizeof(ColorBgr);
const ssize_t bytesRead = pread(_amlogicCaptureDev, image_ptr, bytesToRead, 0); const ssize_t bytesRead = pread(_amlogicCaptureDev, image_ptr, bytesToRead, 0);
@ -150,5 +142,10 @@ int AmlogicGrabber::grabFrame(Image<ColorBgr> & image)
_amlogicCaptureDev = -1; _amlogicCaptureDev = -1;
readCnt = 0; readCnt = 0;
} }
_imageResampler.setHorizontalPixelDecimation(_width);
_imageResampler.setVerticalPixelDecimation(_height);
_imageResampler.processImage((const uint8_t*)image_ptr, _width, _height, 3, PIXELFORMAT_BGR24, image);
return 0; return 0;
} }

View File

@ -1,53 +1,11 @@
// QT includes
#include <QDateTime>
// Hyperion includes
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
// Amlogic grabber includes
#include <grabber/AmlogicWrapper.h> #include <grabber/AmlogicWrapper.h>
#include <grabber/AmlogicGrabber.h>
AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority) AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority)
: GrabberWrapper("AmLogic", priority) : GrabberWrapper("AmLogic", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER)
, _updateInterval_ms(1000/updateRate_Hz) , _grabber(grabWidth, grabHeight)
, _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;
}
void AmlogicWrapper::action() void AmlogicWrapper::action()
{ {
// Grab frame into the allocated image transferFrame(_grabber);
if (_grabber->grabFrame(_image) < 0)
{
// Frame grab failed, maybe nothing playing or ....
return;
}
Image<ColorRgb> 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);
} }

View File

@ -1,6 +1,11 @@
# Find the BCM-package (VC control) # Find the BCM-package (VC control)
find_package(BCM REQUIRED) IF ( "${PLATFORM}" MATCHES rpi)
include_directories(${BCM_INCLUDE_DIRS}) find_package(BCM REQUIRED)
include_directories(${BCM_INCLUDE_DIRS})
ELSE()
SET(BCM_INCLUDE_DIRS "")
SET(BCM_LIBRARIES "")
ENDIF()
# Define the current source locations # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)

View File

@ -13,7 +13,10 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned
, _vc_flags(0) , _vc_flags(0)
, _captureBuffer(new ColorRgba[0]) , _captureBuffer(new ColorRgba[0])
, _captureBufferSize(0) , _captureBufferSize(0)
, _image_rgba(width, height)
{ {
_useImageResampler = false;
// Initiase BCM // Initiase BCM
bcm_host_init(); bcm_host_init();
@ -64,33 +67,15 @@ void DispmanxFrameGrabber::setFlags(const int vc_flags)
_vc_flags = vc_flags; _vc_flags = vc_flags;
} }
void DispmanxFrameGrabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) int DispmanxFrameGrabber::grabFrame(Image<ColorRgb> & image)
{
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<ColorRgba> & image)
{ {
int ret; int ret;
// vc_dispmanx_resource_read_data doesn't seem to work well // vc_dispmanx_resource_read_data doesn't seem to work well
// with arbitrary positions so we have to handle cropping by ourselves // with arbitrary positions so we have to handle cropping by ourselves
unsigned cropLeft = _cropLeft; unsigned cropLeft = _cropLeft;
unsigned cropRight = _cropRight; unsigned cropRight = _cropRight;
unsigned cropTop = _cropTop; unsigned cropTop = _cropTop;
unsigned cropBottom = _cropBottom; unsigned cropBottom = _cropBottom;
if (_vc_flags & DISPMANX_SNAPSHOT_FILL) if (_vc_flags & DISPMANX_SNAPSHOT_FILL)
@ -99,19 +84,19 @@ void DispmanxFrameGrabber::grabFrame(Image<ColorRgba> & image)
cropLeft = cropRight = cropTop = cropBottom = 0; cropLeft = cropRight = cropTop = cropBottom = 0;
} }
unsigned imageWidth = _width - cropLeft - cropRight; unsigned imageWidth = _width - cropLeft - cropRight;
unsigned imageHeight = _height - cropTop - cropBottom; unsigned imageHeight = _height - cropTop - cropBottom;
// calculate final image dimensions and adjust top/left cropping in 3D modes // calculate final image dimensions and adjust top/left cropping in 3D modes
switch (_videoMode) switch (_videoMode)
{ {
case VIDEO_3DSBS: case VIDEO_3DSBS:
imageWidth = imageWidth / 2; imageWidth /= 2;
cropLeft = cropLeft / 2; cropLeft /= 2;
break; break;
case VIDEO_3DTAB: case VIDEO_3DTAB:
imageHeight = imageHeight / 2; imageHeight /= 2;
cropTop = cropTop / 2; cropTop /= 2;
break; break;
case VIDEO_2D: case VIDEO_2D:
default: default:
@ -124,12 +109,17 @@ void DispmanxFrameGrabber::grabFrame(Image<ColorRgba> & image)
image.resize(imageWidth, imageHeight); image.resize(imageWidth, imageHeight);
} }
if (_image_rgba.width() != imageWidth || _image_rgba.height() != imageHeight)
{
_image_rgba.resize(imageWidth, imageHeight);
}
// Open the connection to the display // Open the connection to the display
_vc_display = vc_dispmanx_display_open(0); _vc_display = vc_dispmanx_display_open(0);
if (_vc_display < 0) if (_vc_display < 0)
{ {
Error(_log, "Cannot open display: %d", _vc_display); Error(_log, "Cannot open display: %d", _vc_display);
return; return -1;
} }
// Create the snapshot (incl down-scaling) // Create the snapshot (incl down-scaling)
@ -138,11 +128,11 @@ void DispmanxFrameGrabber::grabFrame(Image<ColorRgba> & image)
{ {
Error(_log, "Snapshot failed: %d", ret); Error(_log, "Snapshot failed: %d", ret);
vc_dispmanx_display_close(_vc_display); vc_dispmanx_display_close(_vc_display);
return; return ret;
} }
// Read the snapshot into the memory // Read the snapshot into the memory
void* imagePtr = image.memptr(); void* imagePtr = _image_rgba.memptr();
void* capturePtr = imagePtr; void* capturePtr = imagePtr;
unsigned imagePitch = imageWidth * sizeof(ColorRgba); unsigned imagePitch = imageWidth * sizeof(ColorRgba);
@ -172,7 +162,7 @@ void DispmanxFrameGrabber::grabFrame(Image<ColorRgba> & image)
{ {
Error(_log, "vc_dispmanx_resource_read_data failed: %d", ret); Error(_log, "vc_dispmanx_resource_read_data failed: %d", ret);
vc_dispmanx_display_close(_vc_display); vc_dispmanx_display_close(_vc_display);
return; return ret;
} }
// copy capture data to image if we captured to temp buffer // copy capture data to image if we captured to temp buffer
@ -193,4 +183,9 @@ void DispmanxFrameGrabber::grabFrame(Image<ColorRgba> & image)
// Close the displaye // Close the displaye
vc_dispmanx_display_close(_vc_display); vc_dispmanx_display_close(_vc_display);
// image to output image
_image_rgba.toRgb(image);
return 0;
} }

View File

@ -0,0 +1,107 @@
#ifndef PLATFORM_RPI
#include <grabber/DispmanxFrameGrabberMock.h>
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; y++)
{
for (unsigned x=0; x<w; x++)
{
unsigned id = 0;
if (x < w/2 && y < h/2) id = 1;
if (x < w/2 && y >= h/2) id = 2;
if (x >= w/2 && y < h/2) id = 3;
resource->memptr()[y*w + x] = color[id];
}
}
return 0;
}
#endif

View File

@ -1,56 +1,13 @@
// QT includes
#include <QDateTime>
// Hyperion includes
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
// Dispmanx grabber includes
#include <grabber/DispmanxWrapper.h> #include <grabber/DispmanxWrapper.h>
#include <grabber/DispmanxFrameGrabber.h>
DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority) DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority)
: GrabberWrapper("Dispmanx", priority) : GrabberWrapper("Dispmanx", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER)
, _updateInterval_ms(1000/updateRate_Hz) , _grabber(grabWidth, grabHeight)
, _timeout_ms(2 * _updateInterval_ms)
, _image(grabWidth, grabHeight)
, _grabber(new DispmanxFrameGrabber(grabWidth, grabHeight))
, _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0})
{ {
// Configure the timer to generate events every n milliseconds setImageProcessorEnabled(false);
_timer.setInterval(_updateInterval_ms);
_processor->setSize(grabWidth, grabHeight);
}
DispmanxWrapper::~DispmanxWrapper()
{
delete _grabber;
} }
void DispmanxWrapper::action() void DispmanxWrapper::action()
{ {
// Grab frame into the allocated image transferFrame(_grabber);
_grabber->grabFrame(_image);
Image<ColorRgb> 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);
} }

View File

@ -47,7 +47,7 @@ FramebufferFrameGrabber::~FramebufferFrameGrabber()
{ {
} }
void FramebufferFrameGrabber::grabFrame(Image<ColorRgb> & image) int FramebufferFrameGrabber::grabFrame(Image<ColorRgb> & image)
{ {
struct fb_var_screeninfo vinfo; struct fb_var_screeninfo vinfo;
unsigned capSize, bytesPerPixel; unsigned capSize, bytesPerPixel;
@ -62,25 +62,17 @@ void FramebufferFrameGrabber::grabFrame(Image<ColorRgb> & image)
bytesPerPixel = vinfo.bits_per_pixel / 8; bytesPerPixel = vinfo.bits_per_pixel / 8;
capSize = vinfo.xres * vinfo.yres * bytesPerPixel; 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 */ /* map the device to memory */
_fbp = (unsigned char*)mmap(0, capSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, _fbfd, 0); _fbp = (unsigned char*)mmap(0, capSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, _fbfd, 0);
@ -95,4 +87,6 @@ void FramebufferFrameGrabber::grabFrame(Image<ColorRgb> & image)
munmap(_fbp, capSize); munmap(_fbp, capSize);
close(_fbfd); close(_fbfd);
return 0;
} }

View File

@ -1,43 +1,11 @@
// Hyperion includes
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
// Framebuffer grabber includes
#include <grabber/FramebufferWrapper.h> #include <grabber/FramebufferWrapper.h>
#include <grabber/FramebufferFrameGrabber.h>
FramebufferWrapper::FramebufferWrapper(const QString & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority) FramebufferWrapper::FramebufferWrapper(const QString & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority)
: GrabberWrapper("FrameBuffer", priority) : GrabberWrapper("FrameBuffer", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER)
, _updateInterval_ms(1000/updateRate_Hz) , _grabber(device, grabWidth, grabHeight)
, _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;
}
void FramebufferWrapper::action() void FramebufferWrapper::action()
{ {
// Grab frame into the allocated image transferFrame(_grabber);
_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);
} }

View File

@ -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); Error(_log, "Display with index %d is not available. Using main display", _screenIndex);
_display = kCGDirectMainDisplay; _display = kCGDirectMainDisplay;
} else { }
else
{
_display = displays[_screenIndex]; _display = displays[_screenIndex];
} }
@ -35,7 +37,7 @@ OsxFrameGrabber::~OsxFrameGrabber()
{ {
} }
void OsxFrameGrabber::grabFrame(Image<ColorRgb> & image) int OsxFrameGrabber::grabFrame(Image<ColorRgb> & image)
{ {
CGImageRef dispImage; CGImageRef dispImage;
CFDataRef imgData; CFDataRef imgData;
@ -52,12 +54,12 @@ void OsxFrameGrabber::grabFrame(Image<ColorRgb> & image)
if (dispImage == NULL) if (dispImage == NULL)
{ {
Error(_log, "No display connected..."); Error(_log, "No display connected...");
return; return -1;
} }
} }
imgData = CGDataProviderCopyData(CGImageGetDataProvider(dispImage)); imgData = CGDataProviderCopyData(CGImageGetDataProvider(dispImage));
pImgData = (unsigned char*) CFDataGetBytePtr(imgData); pImgData = (unsigned char*) CFDataGetBytePtr(imgData);
dspWidth = CGImageGetWidth(dispImage); dspWidth = CGImageGetWidth(dispImage);
dspHeight = CGImageGetHeight(dispImage); dspHeight = CGImageGetHeight(dispImage);
_imageResampler.setHorizontalPixelDecimation(dspWidth/_width); _imageResampler.setHorizontalPixelDecimation(dspWidth/_width);
@ -71,4 +73,6 @@ void OsxFrameGrabber::grabFrame(Image<ColorRgb> & image)
CFRelease(imgData); CFRelease(imgData);
CGImageRelease(dispImage); CGImageRelease(dispImage);
return 0;
} }

View File

@ -0,0 +1,126 @@
#ifndef __APPLE__
#include <grabber/OsxFrameGrabberMock.h>
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; y++)
{
for (unsigned x=0; x<w; x++)
{
unsigned id = 0;
if (x < w/2 && y < h/2) id = 1;
if (x < w/2 && 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; y<image->height(); y++)
{
for (unsigned x=0; x<image->width(); 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

View File

@ -1,44 +1,11 @@
// Hyperion includes
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
// Osx grabber includes
#include <grabber/OsxWrapper.h> #include <grabber/OsxWrapper.h>
#include <grabber/OsxFrameGrabber.h>
OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority) OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority)
: GrabberWrapper("OSX FrameGrabber", priority) : GrabberWrapper("OSX FrameGrabber", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER)
, _updateInterval_ms(1000/updateRate_Hz) , _grabber(display, grabWidth, grabHeight)
, _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;
}
void OsxWrapper::action() void OsxWrapper::action()
{ {
// Grab frame into the allocated image transferFrame(_grabber);
_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);
} }

View File

@ -27,8 +27,8 @@ V4L2Grabber::V4L2Grabber(const QString & device
, int input , int input
, VideoStandard videoStandard , VideoStandard videoStandard
, PixelFormat pixelFormat , PixelFormat pixelFormat
, int width , unsigned width
, int height , unsigned height
, int frameDecimation , int frameDecimation
, int horizontalPixelDecimation , int horizontalPixelDecimation
, int verticalPixelDecimation , 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) void V4L2Grabber::setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold)
{ {
_noSignalThresholdColor.red = uint8_t(255*redSignalThreshold); _noSignalThresholdColor.red = uint8_t(255*redSignalThreshold);

View File

@ -8,8 +8,8 @@ V4L2Wrapper::V4L2Wrapper(const QString &device,
int input, int input,
VideoStandard videoStandard, VideoStandard videoStandard,
PixelFormat pixelFormat, PixelFormat pixelFormat,
int width, unsigned width,
int height, unsigned height,
int frameDecimation, int frameDecimation,
int pixelDecimation, int pixelDecimation,
double redSignalThreshold, double redSignalThreshold,
@ -17,8 +17,7 @@ V4L2Wrapper::V4L2Wrapper(const QString &device,
double blueSignalThreshold, double blueSignalThreshold,
const int priority, const int priority,
bool useGrabbingMode) bool useGrabbingMode)
: GrabberWrapper("V4L2:"+device, priority, hyperion::COMP_V4L) : GrabberWrapper("V4L2:"+device, &_grabber, width, height, 8, priority, hyperion::COMP_V4L)
, _timeout_ms(1000)
, _grabber(device, , _grabber(device,
input, input,
videoStandard, videoStandard,
@ -28,10 +27,10 @@ V4L2Wrapper::V4L2Wrapper(const QString &device,
frameDecimation, frameDecimation,
pixelDecimation, pixelDecimation,
pixelDecimation) pixelDecimation)
, _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0})
{ {
// set the signal detection threshold of the grabber // set the signal detection threshold of the grabber
_grabber.setSignalThreshold( redSignalThreshold, greenSignalThreshold, blueSignalThreshold, 50); _grabber.setSignalThreshold( redSignalThreshold, greenSignalThreshold, blueSignalThreshold, 50);
_ggrabber = &_grabber;
// register the image type // register the image type
qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>"); qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
@ -40,29 +39,15 @@ V4L2Wrapper::V4L2Wrapper(const QString &device,
// Handle the image in the captured thread using a direct connection // Handle the image in the captured thread using a direct connection
QObject::connect(&_grabber, SIGNAL(newFrame(Image<ColorRgb>)), this, SLOT(newFrame(Image<ColorRgb>)), Qt::DirectConnection); QObject::connect(&_grabber, SIGNAL(newFrame(Image<ColorRgb>)), this, SLOT(newFrame(Image<ColorRgb>)), Qt::DirectConnection);
QObject::connect(&_grabber, SIGNAL(readError(const char*)), this, SLOT(readError(const char*)), Qt::DirectConnection); QObject::connect(&_grabber, SIGNAL(readError(const char*)), this, SLOT(readError(const char*)), Qt::DirectConnection);
if (!useGrabbingMode) if (!useGrabbingMode)
{ {
disconnect(_hyperion, SIGNAL(grabbingMode(GrabbingMode)), this, 0); 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<ColorRgb>,int)),
// _hyperion, SLOT(setColors(int,std::vector<ColorRgb>,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); _timer.setInterval(500);
} }
V4L2Wrapper::~V4L2Wrapper()
{
}
bool V4L2Wrapper::start() bool V4L2Wrapper::start()
{ {
return ( _grabber.start() && GrabberWrapper::start()); return ( _grabber.start() && GrabberWrapper::start());
@ -84,12 +69,6 @@ void V4L2Wrapper::setSignalDetectionOffset(double verticalMin, double horizontal
_grabber.setSignalDetectionOffset(verticalMin, horizontalMin, verticalMax, horizontalMax); _grabber.setSignalDetectionOffset(verticalMin, horizontalMin, verticalMax, horizontalMax);
} }
void V4L2Wrapper::setVideoMode(VideoMode mode)
{
_grabber.setVideoMode(mode);
}
void V4L2Wrapper::newFrame(const Image<ColorRgb> &image) void V4L2Wrapper::newFrame(const Image<ColorRgb> &image)
{ {
emit emitImage(_priority, image, _timeout_ms); emit emitImage(_priority, image, _timeout_ms);

View File

@ -14,8 +14,11 @@ X11Grabber::X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropT
, _verticalDecimation(verticalPixelDecimation) , _verticalDecimation(verticalPixelDecimation)
, _screenWidth(0) , _screenWidth(0)
, _screenHeight(0) , _screenHeight(0)
, _src_x(cropLeft)
, _src_y(cropTop)
, _image(0,0) , _image(0,0)
{ {
_useImageResampler = false;
_imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XRender, XShmGetImage or XGetImage _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XRender, XShmGetImage or XGetImage
memset(&_pictAttr, 0, sizeof(_pictAttr)); memset(&_pictAttr, 0, sizeof(_pictAttr));
_pictAttr.repeat = RepeatNone; _pictAttr.repeat = RepeatNone;
@ -52,9 +55,7 @@ void X11Grabber::setupResources()
{ {
if(_XShmAvailable && !_useXGetImage) if(_XShmAvailable && !_useXGetImage)
{ {
_xImage = XShmCreateImage(_x11Display, _windowAttr.visual, _xImage = XShmCreateImage(_x11Display, _windowAttr.visual, _windowAttr.depth, ZPixmap, NULL, &_shminfo, _width, _height);
_windowAttr.depth, ZPixmap, NULL, &_shminfo,
_width, _height);
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777); _shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
_xImage->data = (char*)shmat(_shminfo.shmid,0,0); _xImage->data = (char*)shmat(_shminfo.shmid,0,0);
_shminfo.shmaddr = _xImage->data; _shminfo.shmaddr = _xImage->data;
@ -109,13 +110,16 @@ bool X11Grabber::Setup()
_imageResampler.setHorizontalPixelDecimation(_XRenderAvailable ? 1 : _horizontalDecimation); _imageResampler.setHorizontalPixelDecimation(_XRenderAvailable ? 1 : _horizontalDecimation);
_imageResampler.setVerticalPixelDecimation(_XRenderAvailable ? 1 : _verticalDecimation); _imageResampler.setVerticalPixelDecimation(_XRenderAvailable ? 1 : _verticalDecimation);
return true; bool result = (updateScreenDimensions(true) >=0);
ErrorIf(!result, _log, "X11 Grabber start failed");
return result;
} }
Image<ColorRgb> & X11Grabber::grab() int X11Grabber::grabFrame(Image<ColorRgb> & image, bool forceUpdate)
{ {
updateScreenDimensions(); if (forceUpdate)
updateScreenDimensions(forceUpdate);
if (_XRenderAvailable && !_useXGetImage) if (_XRenderAvailable && !_useXGetImage)
{ {
double scale_x = static_cast<double>(_windowAttr.width / _horizontalDecimation) / static_cast<double>(_windowAttr.width); double scale_x = static_cast<double>(_windowAttr.width / _horizontalDecimation) / static_cast<double>(_windowAttr.width);
@ -145,19 +149,11 @@ Image<ColorRgb> & X11Grabber::grab()
XRenderSetPictureTransform (_x11Display, _srcPicture, &_transform); XRenderSetPictureTransform (_x11Display, _srcPicture, &_transform);
XRenderComposite( _x11Display, // dpy // display, op, src, mask, dest, src_x = cropLeft,
PictOpSrc, // op // src_y = cropTop, mask_x, mask_y, dest_x, dest_y, width, height
_srcPicture, // src XRenderComposite(
None, // mask _x11Display, PictOpSrc, _srcPicture, None, _dstPicture, ( _src_x/_horizontalDecimation),
_dstPicture, // dst (_src_y/_verticalDecimation), 0, 0, 0, 0, _width, _height);
_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); XSync(_x11Display, False);
@ -170,93 +166,15 @@ Image<ColorRgb> & X11Grabber::grab()
_xImage = XGetImage(_x11Display, _pixmap, 0, 0, _width, _height, AllPlanes, ZPixmap); _xImage = XGetImage(_x11Display, _pixmap, 0, 0, _width, _height, AllPlanes, ZPixmap);
} }
} }
else else if (_XShmAvailable && !_useXGetImage)
{ {
if (_XShmAvailable && !_useXGetImage) { // use xshm
XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); XShmGetImage(_x11Display, _window, _xImage, _src_x, _src_y, 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<const uint8_t *>(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image);
return _image;
}
int X11Grabber::grabFrame(Image<ColorRgb> & image)
{
if (_XRenderAvailable && !_useXGetImage)
{
double scale_x = static_cast<double>(_windowAttr.width / _horizontalDecimation) / static_cast<double>(_windowAttr.width);
double scale_y = static_cast<double>(_windowAttr.height / _verticalDecimation) / static_cast<double>(_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);
}
} }
else else
{ {
if (_XShmAvailable && !_useXGetImage) { // all things done by xgetimage
XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); _xImage = XGetImage(_x11Display, _window, _src_x, _src_y, _width, _height, AllPlanes, ZPixmap);
}
else
{
_xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _width, _height, AllPlanes, ZPixmap);
}
} }
if (_xImage == nullptr) if (_xImage == nullptr)
@ -270,7 +188,7 @@ int X11Grabber::grabFrame(Image<ColorRgb> & image)
return 0; return 0;
} }
int X11Grabber::updateScreenDimensions() int X11Grabber::updateScreenDimensions(bool force)
{ {
const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr); const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr);
if (status == 0) if (status == 0)
@ -279,7 +197,7 @@ int X11Grabber::updateScreenDimensions()
return -1; return -1;
} }
if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height)) if (!force && _screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height))
{ {
// No update required // No update required
return 0; return 0;
@ -294,14 +212,16 @@ int X11Grabber::updateScreenDimensions()
_screenWidth = _windowAttr.width; _screenWidth = _windowAttr.width;
_screenHeight = _windowAttr.height; _screenHeight = _windowAttr.height;
int width=0, height=0;
// Image scaling is performed by XRender when available, otherwise by ImageResampler // Image scaling is performed by XRender when available, otherwise by ImageResampler
if (_XRenderAvailable && !_useXGetImage) if (_XRenderAvailable && !_useXGetImage)
{ {
_width = (_screenWidth > unsigned(_cropLeft + _cropRight)) width = (_screenWidth > unsigned(_cropLeft + _cropRight))
? ((_screenWidth - _cropLeft - _cropRight) / _horizontalDecimation) ? ((_screenWidth - _cropLeft - _cropRight) / _horizontalDecimation)
: _screenWidth / _horizontalDecimation; : _screenWidth / _horizontalDecimation;
_height = (_screenHeight > unsigned(_cropTop + _cropBottom)) height = (_screenHeight > unsigned(_cropTop + _cropBottom))
? ((_screenHeight - _cropTop - _cropBottom) / _verticalDecimation) ? ((_screenHeight - _cropTop - _cropBottom) / _verticalDecimation)
: _screenHeight / _verticalDecimation; : _screenHeight / _verticalDecimation;
@ -309,19 +229,52 @@ int X11Grabber::updateScreenDimensions()
} }
else else
{ {
_width = (_screenWidth > unsigned(_cropLeft + _cropRight)) width = (_screenWidth > unsigned(_cropLeft + _cropRight))
? (_screenWidth - _cropLeft - _cropRight) ? (_screenWidth - _cropLeft - _cropRight)
: _screenWidth; : _screenWidth;
_height = (_screenHeight > unsigned(_cropTop + _cropBottom)) height = (_screenHeight > unsigned(_cropTop + _cropBottom))
? (_screenHeight - _cropTop - _cropBottom) ? (_screenHeight - _cropTop - _cropBottom)
: _screenHeight; : _screenHeight;
Info(_log, "Using XGetImage for grabbing"); 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); _image.resize(_width, _height);
setupResources(); setupResources();
return 1; return 1;
} }
void X11Grabber::setVideoMode(VideoMode mode)
{
Info(_log, "a %d", mode);
Grabber::setVideoMode(mode);
updateScreenDimensions(true);
}

View File

@ -1,78 +1,24 @@
// Hyperion includes
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
// X11 grabber includes
#include <grabber/X11Wrapper.h> #include <grabber/X11Wrapper.h>
#include <grabber/X11Grabber.h>
X11Wrapper::X11Wrapper(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation, const unsigned updateRate_Hz, const int priority) 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) : GrabberWrapper("X11", &_grabber, 0, 0, updateRate_Hz, priority, hyperion::COMP_GRABBER)
, _updateInterval_ms(1000/updateRate_Hz) , _grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation)
, _timeout_ms(2 * _updateInterval_ms)
, _grabber(new X11Grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation))
, _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0})
, _init(false) , _init(false)
, _x11SetupSuccess(false) {}
{
// Configure the timer to generate events every n milliseconds
_timer.setInterval(_updateInterval_ms);
}
X11Wrapper::~X11Wrapper() void X11Wrapper::action()
{
delete _grabber;
}
bool X11Wrapper::start()
{ {
if (! _init ) if (! _init )
{ {
_init = true; _init = true;
_x11SetupSuccess = _grabber->Setup(); if ( ! _grabber.Setup() )
if ( _x11SetupSuccess )
{ {
_x11SetupSuccess = (_grabber->updateScreenDimensions() >= 0); stop();
_processor->setSize(_grabber->getImageWidth(), _grabber->getImageHeight());
_image.resize(_grabber->getImageWidth(), _grabber->getImageHeight());
} }
} }
// 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);
} }

View File

@ -3,16 +3,19 @@
Grabber::Grabber(QString grabberName, int width, int height, int cropLeft, int cropRight, int cropTop, int cropBottom) Grabber::Grabber(QString grabberName, int width, int height, int cropLeft, int cropRight, int cropTop, int cropBottom)
: _imageResampler() : _imageResampler()
, _useImageResampler(true)
, _videoMode(VIDEO_2D) , _videoMode(VIDEO_2D)
, _width(width) , _width(width)
, _height(height) , _height(height)
, _cropLeft(cropLeft) , _cropLeft(0)
, _cropRight(cropRight) , _cropRight(0)
, _cropTop(cropTop) , _cropTop(0)
, _cropBottom(cropBottom) , _cropBottom(0)
, _log(Logger::getInstance(grabberName)) , _log(Logger::getInstance(grabberName))
{ {
setVideoMode(VIDEO_2D);
setCropping(cropLeft, cropRight, cropTop, cropBottom);
} }
Grabber::~Grabber() Grabber::~Grabber()
@ -22,6 +25,41 @@ Grabber::~Grabber()
void Grabber::setVideoMode(VideoMode mode) void Grabber::setVideoMode(VideoMode mode)
{ {
Debug(_log,"setvideomode %d", mode);
_videoMode = 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);
}
} }

View File

@ -2,20 +2,32 @@
#include <hyperion/ImageProcessorFactory.h> #include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h> #include <hyperion/ImageProcessor.h>
#include <hyperion/GrabberWrapper.h> #include <hyperion/GrabberWrapper.h>
#include <hyperion/Grabber.h>
#include <HyperionConfig.h> #include <HyperionConfig.h>
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) : _grabberName(grabberName)
, _hyperion(Hyperion::getInstance()) , _hyperion(Hyperion::getInstance())
, _priority(priority) , _priority(priority)
, _timer() , _timer()
, _updateInterval_ms(1000/updateRate_Hz)
, _timeout_ms(2 * _updateInterval_ms)
, _log(Logger::getInstance(grabberName)) , _log(Logger::getInstance(grabberName))
, _forward(true) , _forward(true)
, _processor(ImageProcessorFactory::getInstance().newImageProcessor()) , _processor(ImageProcessorFactory::getInstance().newImageProcessor())
, _grabberComponentId(grabberComponentId) , _grabberComponentId(grabberComponentId)
, _ggrabber(ggrabber)
, _image(0,0)
, _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0})
, _imageProcessorEnabled(true)
{ {
_timer.setSingleShot(false); _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(); _forward = _hyperion->getForwarder()->protoForwardingEnabled();
_hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_BLACKBORDER, _processor->blackBorderDetectorEnabled()); _hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_BLACKBORDER, _processor->blackBorderDetectorEnabled());
qRegisterMetaType<hyperion::Components>("hyperion::Components"); qRegisterMetaType<hyperion::Components>("hyperion::Components");
@ -26,6 +38,7 @@ GrabberWrapper::GrabberWrapper(QString grabberName, const int priority, hyperion
connect(_hyperion, SIGNAL(videoMode(VideoMode)), this, SLOT(setVideoMode(VideoMode))); connect(_hyperion, SIGNAL(videoMode(VideoMode)), this, SLOT(setVideoMode(VideoMode)));
connect(this, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _hyperion, SLOT(setImage(int, const Image<ColorRgb>&, const int)) ); connect(this, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _hyperion, SLOT(setImage(int, const Image<ColorRgb>&, const int)) );
connect(&_timer, SIGNAL(timeout()), this, SLOT(action())); connect(&_timer, SIGNAL(timeout()), this, SLOT(action()));
} }
GrabberWrapper::~GrabberWrapper() GrabberWrapper::~GrabberWrapper()
@ -139,3 +152,24 @@ QStringList GrabberWrapper::availableGrabbers()
return grabbers; 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;
}

View File

@ -487,14 +487,15 @@ unsigned Hyperion::addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequ
void Hyperion::freeObjects(bool emitCloseSignal) void Hyperion::freeObjects(bool emitCloseSignal)
{ {
// switch off all leds
clearall(true);
_device->switchOff();
if (emitCloseSignal) if (emitCloseSignal)
{ {
emit closing(); emit closing();
} }
// switch off all leds
clearall();
_device->switchOff();
// delete components on exit of hyperion core // delete components on exit of hyperion core
delete _effectEngine; delete _effectEngine;
@ -740,9 +741,9 @@ void Hyperion::clear(int priority)
_effectEngine->channelCleared(priority); _effectEngine->channelCleared(priority);
} }
void Hyperion::clearall() void Hyperion::clearall(bool forceClearAll)
{ {
_muxer.clearAll(); _muxer.clearAll(forceClearAll);
setSourceAutoSelectEnabled(true); setSourceAutoSelectEnabled(true);
// update leds // update leds

View File

@ -44,7 +44,7 @@ void ImageProcessor::setSize(const unsigned width, const unsigned height)
delete _imageToLeds; delete _imageToLeds;
// Construct a new buffer and mapping // 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) void ImageProcessor::enableBlackBorderDetector(bool enable)

View File

@ -17,6 +17,8 @@ ImageToLedsMap::ImageToLedsMap(
// Sanity check of the size of the borders (and width and height) // Sanity check of the size of the borders (and width and height)
Q_ASSERT(_width > 2*_verticalBorder); Q_ASSERT(_width > 2*_verticalBorder);
Q_ASSERT(_height > 2*_horizontalBorder); Q_ASSERT(_height > 2*_horizontalBorder);
Q_ASSERT(_width < 10000);
Q_ASSERT(_height < 10000);
// Reserve enough space in the map for the leds // Reserve enough space in the map for the leds
_colorsMap.reserve(leds.size()); _colorsMap.reserve(leds.size());

View File

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

View File

@ -46,8 +46,8 @@
{ {
"type" : "integer", "type" : "integer",
"title" : "edt_conf_v4l2_width_title", "title" : "edt_conf_v4l2_width_title",
"minimum" : -1, "minimum" : 0,
"default" : -1, "default" : 0,
"append" : "edt_append_pixel", "append" : "edt_append_pixel",
"propertyOrder" : 5 "propertyOrder" : 5
}, },
@ -55,8 +55,8 @@
{ {
"type" : "integer", "type" : "integer",
"title" : "edt_conf_v4l2_height_title", "title" : "edt_conf_v4l2_height_title",
"minimum" : -1, "minimum" : 0,
"default" : -1, "default" : 0,
"append" : "edt_append_pixel", "append" : "edt_append_pixel",
"propertyOrder" : 6 "propertyOrder" : 6
}, },

View File

@ -19,6 +19,8 @@ add_library(protoserver
${ProtoServer_PROTO_SRCS} ${ProtoServer_PROTO_SRCS}
${ProtoServer_PROTO_HDRS} ${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 target_link_libraries(protoserver
hyperion hyperion

View File

@ -30,22 +30,22 @@ void ImageResampler::setVerticalPixelDecimation(int decimator)
void ImageResampler::setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom) void ImageResampler::setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom)
{ {
_cropLeft = cropLeft; _cropLeft = cropLeft;
_cropRight = cropRight; _cropRight = cropRight;
_cropTop = cropTop; _cropTop = cropTop;
_cropBottom = cropBottom; _cropBottom = cropBottom;
} }
void ImageResampler::set3D(VideoMode mode) void ImageResampler::setVideoMode(VideoMode mode)
{ {
_videoMode = mode; _videoMode = mode;
} }
void ImageResampler::processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image<ColorRgb> &outputImage) const void ImageResampler::processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image<ColorRgb> &outputImage) const
{ {
int cropLeft = _cropLeft; int cropLeft = _cropLeft;
int cropRight = _cropRight; int cropRight = _cropRight;
int cropTop = _cropTop; int cropTop = _cropTop;
int cropBottom = _cropBottom; int cropBottom = _cropBottom;
// handle 3D mode // handle 3D mode

View File

@ -10,7 +10,7 @@
"tan" : { "tan" : {
"type" : "integer" "type" : "integer"
}, },
"mappingType": { "videoMode": {
"type" : "string", "type" : "string",
"enum" : ["2D", "3DSBS", "3DTAB"] "enum" : ["2D", "3DSBS", "3DTAB"]
} }

View File

@ -16,7 +16,7 @@ AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeig
const Image<ColorRgb> & AmlogicWrapper::getScreenshot() const Image<ColorRgb> & AmlogicWrapper::getScreenshot()
{ {
capture(); capture();
return _screenshot_rgb; return _screenshot;
} }
void AmlogicWrapper::start() void AmlogicWrapper::start()
@ -32,7 +32,5 @@ void AmlogicWrapper::stop()
void AmlogicWrapper::capture() void AmlogicWrapper::capture()
{ {
_grabber.grabFrame(_screenshot); _grabber.grabFrame(_screenshot);
_screenshot.toRgb(_screenshot_rgb); emit sig_screenshot(_screenshot);
emit sig_screenshot(_screenshot_rgb);
} }

View File

@ -37,7 +37,6 @@ private:
AmlogicGrabber _grabber; AmlogicGrabber _grabber;
// image buffers // image buffers
Image<ColorRgb> _screenshot_rgb; Image<ColorRgb> _screenshot;
Image<ColorBgr> _screenshot;
}; };

View File

@ -2,7 +2,12 @@ cmake_minimum_required(VERSION 2.8.12)
project(hyperion-dispmanx) project(hyperion-dispmanx)
find_package(Qt5Widgets REQUIRED) 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( include_directories(
${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver

View File

@ -22,7 +22,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe
const Image<ColorRgb> & DispmanxWrapper::getScreenshot() const Image<ColorRgb> & DispmanxWrapper::getScreenshot()
{ {
capture(); capture();
return _screenshot_rgb; return _screenshot;
} }
void DispmanxWrapper::start() void DispmanxWrapper::start()
@ -38,7 +38,5 @@ void DispmanxWrapper::stop()
void DispmanxWrapper::capture() void DispmanxWrapper::capture()
{ {
_grabber.grabFrame(_screenshot); _grabber.grabFrame(_screenshot);
_screenshot.toRgb(_screenshot_rgb); emit sig_screenshot(_screenshot);
emit sig_screenshot(_screenshot_rgb);
} }

View File

@ -40,7 +40,5 @@ private:
/// The grabber for creating screenshots /// The grabber for creating screenshots
DispmanxFrameGrabber _grabber; DispmanxFrameGrabber _grabber;
Image<ColorRgb> _screenshot_rgb; Image<ColorRgb> _screenshot;
Image<ColorRgba> _screenshot;
}; };

View File

@ -15,8 +15,8 @@ X11Wrapper::X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cr
const Image<ColorRgb> & X11Wrapper::getScreenshot() const Image<ColorRgb> & X11Wrapper::getScreenshot()
{ {
const Image<ColorRgb> & screenshot = _grabber.grab(); _grabber.grabFrame(_screenshot, true);
return screenshot; return _screenshot;
} }
void X11Wrapper::start() void X11Wrapper::start()
@ -36,8 +36,8 @@ bool X11Wrapper::displayInit()
void X11Wrapper::capture() void X11Wrapper::capture()
{ {
const Image<ColorRgb> & screenshot = _grabber.grab(); _grabber.grabFrame(_screenshot, true);
emit sig_screenshot(screenshot); emit sig_screenshot(_screenshot);
} }
void X11Wrapper::setGrabbingMode(const GrabbingMode mode) void X11Wrapper::setGrabbingMode(const GrabbingMode mode)

View File

@ -55,4 +55,6 @@ private:
/// The grabber for creating screenshots /// The grabber for creating screenshots
X11Grabber _grabber; X11Grabber _grabber;
Image<ColorRgb> _screenshot;
}; };

View File

@ -98,7 +98,7 @@ int main(int argc, char ** argv)
catch (const std::runtime_error & e) catch (const std::runtime_error & e)
{ {
// An error occured. Display error and quit // An error occured. Display error and quit
Error(Logger::getInstance("X11GRABBER"), "%s", e.what()); Error(Logger::getInstance("X11GRABBER"), "%s", e.what());
return -1; return -1;
} }

View File

@ -86,6 +86,7 @@ HyperionDaemon::~HyperionDaemon()
void HyperionDaemon::freeObjects() void HyperionDaemon::freeObjects()
{ {
_hyperion->clearall(true);
Debug(_log, "destroy grabbers and network stuff"); Debug(_log, "destroy grabbers and network stuff");
delete _amlGrabber; delete _amlGrabber;
delete _dispmanx; delete _dispmanx;
@ -117,7 +118,6 @@ void HyperionDaemon::freeObjects()
void HyperionDaemon::run() void HyperionDaemon::run()
{ {
startInitialEffect();
createKODIVideoChecker(); createKODIVideoChecker();
// ---- network services ----- // ---- network services -----
@ -133,6 +133,8 @@ void HyperionDaemon::run()
Info(_log, "Hyperion started"); Info(_log, "Hyperion started");
connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects())); connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects()));
startInitialEffect();
} }
void HyperionDaemon::loadConfig(const QString & configFile) void HyperionDaemon::loadConfig(const QString & configFile)
@ -499,6 +501,7 @@ void HyperionDaemon::createGrabberX11(const QJsonObject & grabberConfig)
grabberConfig["horizontalPixelDecimation"].toInt(8), grabberConfig["horizontalPixelDecimation"].toInt(8),
grabberConfig["verticalPixelDecimation"].toInt(8), grabberConfig["verticalPixelDecimation"].toInt(8),
_grabber_frequency, _grabber_priority ); _grabber_frequency, _grabber_priority );
_x11Grabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom);
QObject::connect(_x11Grabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) ); QObject::connect(_x11Grabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
@ -517,7 +520,7 @@ void HyperionDaemon::createGrabberFramebuffer(const QJsonObject & grabberConfig)
_fbGrabber = new FramebufferWrapper( _fbGrabber = new FramebufferWrapper(
grabberConfig["device"].toString("/dev/fb0"), grabberConfig["device"].toString("/dev/fb0"),
_grabber_width, _grabber_height, _grabber_frequency, _grabber_priority); _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<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) ); QObject::connect(_fbGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
_fbGrabber->start(); _fbGrabber->start();
@ -570,8 +573,8 @@ void HyperionDaemon::createGrabberV4L2()
grabberConfig["input"].toInt(0), grabberConfig["input"].toInt(0),
parseVideoStandard(grabberConfig["standard"].toString("no-change")), parseVideoStandard(grabberConfig["standard"].toString("no-change")),
parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change")), parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change")),
grabberConfig["width"].toInt(-1), grabberConfig["width"].toInt(0),
grabberConfig["height"].toInt(-1), grabberConfig["height"].toInt(0),
grabberConfig["frameDecimation"].toInt(2), grabberConfig["frameDecimation"].toInt(2),
grabberConfig["sizeDecimation"].toInt(8), grabberConfig["sizeDecimation"].toInt(8),
grabberConfig["redSignalThreshold"].toDouble(0.0)/100.0, grabberConfig["redSignalThreshold"].toDouble(0.0)/100.0,

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <QObject> #include <QObject>
#include <QJsonObject>
#ifdef ENABLE_DISPMANX #ifdef ENABLE_DISPMANX
#include <grabber/DispmanxWrapper.h> #include <grabber/DispmanxWrapper.h>
@ -46,7 +47,7 @@
#include <boblightserver/BoblightServer.h> #include <boblightserver/BoblightServer.h>
#include <udplistener/UDPListener.h> #include <udplistener/UDPListener.h>
#include <utils/Stats.h> #include <utils/Stats.h>
#include <QJsonObject>
class SysTray; class SysTray;

View File

@ -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) add_definitions(${QT_DEFINITIONS})
find_package(BCM REQUIRED) link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
include_directories(${BCM_INCLUDE_DIRS})
add_definitions(${QT_DEFINITIONS}) add_executable(dispmanx2png
link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
add_executable(dispmanx2png
dispmanx2png.cpp) dispmanx2png.cpp)
target_link_libraries(dispmanx2png target_link_libraries(dispmanx2png
dispmanx-grabber dispmanx-grabber
Qt5::Gui) Qt5::Gui)
ENDIF()