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
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

View File

@ -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()

View File

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

View File

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

View File

@ -17,6 +17,7 @@ public:
const QMap<QString, T> &switches=QMap<QString, T>())
: Option(name, description, valueName, defaultValue), _switches(switches)
{}
SwitchOption(const QStringList &names,
const QString &description = QString(),
const QString &valueName = QString(),
@ -24,11 +25,14 @@ public:
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;};
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; }

View File

@ -29,14 +29,17 @@ public:
/// height)
/// @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
* @return True if video is playing else false
*/
bool isVideoPlaying();
private:
/** The snapshot/capture device of the amlogic video chip */
int _amlogicCaptureDev;
Image<ColorBgr> _image;
};

View File

@ -1,16 +1,7 @@
#pragma once
// Utils includes
#include <utils/Image.h>
#include <utils/ColorBgr.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.h>
#include <hyperion/GrabberWrapper.h>
// Forward class declaration
class AmlogicGrabber;
class Hyperion;
class ImageProcessor;
#include <grabber/AmlogicGrabber.h>
///
/// 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<ColorBgr> _image;
/// The actual grabber
AmlogicGrabber * _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
AmlogicGrabber _grabber;
};

View File

@ -1,10 +1,15 @@
#pragma once
// BCM includes
#ifdef PLATFORM_RPI
#pragma GCC system_header
#include <bcm_host.h>
#else
#include <grabber/DispmanxFrameGrabberMock.h>
#endif
// Utils includes
#include <utils/Image.h>
#include <utils/ColorRgba.h>
#include <hyperion/Grabber.h>
@ -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<ColorRgba> & image);
int grabFrame(Image<ColorRgb> & 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<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
// 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>
// Forward class declaration
class DispmanxFrameGrabber;
class ImageProcessor;
#include <grabber/DispmanxFrameGrabber.h>
///
/// 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<ColorRgba> _image;
/// The actual grabber
DispmanxFrameGrabber * _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
DispmanxFrameGrabber _grabber;
};

View File

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

View File

@ -1,15 +1,7 @@
#pragma once
// Utils includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
#include <hyperion/GrabberWrapper.h>
// Forward class declaration
class FramebufferFrameGrabber;
class ImageProcessor;
#include <grabber/FramebufferFrameGrabber.h>
///
/// 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<ColorRgb> _image;
/// The actual grabber
FramebufferFrameGrabber * _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
FramebufferFrameGrabber _grabber;
};

View File

@ -1,7 +1,11 @@
#pragma once
// OSX includes
#ifdef __APPLE__
#include <CoreGraphics/CoreGraphics.h>
#else
#include <grabber/OsxFrameGrabberMock.h>
#endif
// Utils includes
#include <utils/ColorRgb.h>
@ -31,7 +35,7 @@ public:
/// @param[out] image The snapped screenshot (should be initialized with correct width and
/// height)
///
void grabFrame(Image<ColorRgb> & image);
int grabFrame(Image<ColorRgb> & image);
private:
/// 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
// 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>
// Forward class declaration
class OsxFrameGrabber;
class ImageProcessor;
#include <grabber/OsxFrameGrabber.h>
///
/// 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<ColorRgb> _image;
/// The actual grabber
OsxFrameGrabber * _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
OsxFrameGrabber _grabber;
};

View File

@ -10,11 +10,8 @@
#include <QRectF>
// util includes
#include <utils/ColorRgb.h>
#include <utils/PixelFormat.h>
#include <hyperion/Grabber.h>
// grabber includes
#include <grabber/VideoStandard.h>
/// 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();
public slots:
void setCropping(int cropLeft,
int cropRight,
int cropTop,
int cropBottom);
int grabFrame(Image<ColorRgb> &);
public slots:
void setSignalThreshold(
double redSignalThreshold,
double greenSignalThreshold,

View File

@ -1,11 +1,6 @@
#pragma once
// Hyperion includes
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessor.h>
#include <hyperion/GrabberWrapper.h>
// Grabber includes
#include <grabber/V4L2Grabber.h>
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<ColorRgb> _ledColors;
};

View File

@ -23,8 +23,6 @@ public:
bool Setup();
Image<ColorRgb> & grab();
///
/// Captures a single snapshot of the display and writes the data to the given image. The
/// provided image should have the same dimensions as the configured values (_width and
@ -33,11 +31,13 @@ public:
/// @param[out] image The snapped screenshot (should be initialized with correct width and
/// height)
///
int grabFrame(Image<ColorRgb> & image);
virtual int grabFrame(Image<ColorRgb> & 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<ColorRgb> _image;

View File

@ -1,14 +1,12 @@
#pragma once
// Utils includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.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
@ -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<ColorRgb> _image;
/// The actual grabber
X11Grabber * _grabber;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
X11Grabber _grabber;
bool _init;
bool _x11SetupSuccess;
};

View File

@ -3,6 +3,7 @@
#include <QObject>
#include <cstdint>
#include <utils/ColorRgb.h>
#include <utils/Image.h>
#include <utils/VideoMode.h>
#include <utils/GrabbingMode.h>
@ -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;

View File

@ -9,14 +9,20 @@
#include <utils/Components.h>
#include <utils/GrabbingMode.h>
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessor.h>
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.h>
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 <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:
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<ColorRgb> & image, const int timeout_ms);
@ -59,6 +90,7 @@ signals:
protected:
void setColors(const std::vector<ColorRgb> &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<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.
///
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

View File

@ -42,7 +42,6 @@ public:
///
void setSize(const unsigned width, const unsigned height);
/// Returns starte of black border detector
bool blackBorderDetectorEnabled();
@ -60,6 +59,19 @@ public slots:
void setLedMappingType(int mapType);
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
/// if required and call the image-to-leds mapping to determine the mean color per led.
@ -70,20 +82,27 @@ public:
///
template <typename Pixel_T>
std::vector<ColorRgb> process(const Image<Pixel_T>& image)
{
std::vector<ColorRgb> colors;
if (image.width()>0 && image.height()>0)
{
// Ensure that the buffer-image is the proper size
setSize(image.width(), image.height());
setSize(image);
// Check black border detection
verifyBorder(image);
// Create a result vector and call the 'in place' functionl
std::vector<ColorRgb> colors;
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 colors;
@ -97,9 +116,11 @@ public:
///
template <typename Pixel_T>
void process(const Image<Pixel_T>& image, std::vector<ColorRgb>& ledColors)
{
if ( image.width()>0 && image.height()>0)
{
// Ensure that the buffer-image is the proper size
setSize(image.width(), image.height());
setSize(image);
// Check black border detection
verifyBorder(image);
@ -110,7 +131,11 @@ public:
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
///
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;
};

View File

@ -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<ColorRgb> & outputImage) const;

View File

@ -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<ColorBgr> & image)
int AmlogicGrabber::grabFrame(Image<ColorRgb> & 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<ColorBgr> & image)
return -1;
}
// If the device is not open, attempt to open it
if (_amlogicCaptureDev == -1)
{
@ -121,7 +113,7 @@ int AmlogicGrabber::grabFrame(Image<ColorBgr> & 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<ColorBgr> & 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;
}

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/AmlogicGrabber.h>
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<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);
transferFrame(_grabber);
}

View File

@ -1,6 +1,11 @@
# Find the BCM-package (VC control)
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)

View File

@ -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,25 +67,7 @@ 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<ColorRgba> & image)
int DispmanxFrameGrabber::grabFrame(Image<ColorRgb> & image)
{
int ret;
@ -106,12 +91,12 @@ void DispmanxFrameGrabber::grabFrame(Image<ColorRgba> & image)
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<ColorRgba> & 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<ColorRgba> & 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<ColorRgba> & 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<ColorRgba> & image)
// Close the displaye
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/DispmanxFrameGrabber.h>
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<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);
transferFrame(_grabber);
}

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;
unsigned capSize, bytesPerPixel;
@ -62,23 +62,15 @@ void FramebufferFrameGrabber::grabFrame(Image<ColorRgb> & image)
bytesPerPixel = vinfo.bits_per_pixel / 8;
capSize = vinfo.xres * vinfo.yres * bytesPerPixel;
if (vinfo.bits_per_pixel == 16)
{
pixelFormat = PIXELFORMAT_BGR16;
}
else if (vinfo.bits_per_pixel == 24)
{
pixelFormat = PIXELFORMAT_BGR24;
}
else if (vinfo.bits_per_pixel == 32)
{
pixelFormat = PIXELFORMAT_BGR32;
}
else
switch (vinfo.bits_per_pixel)
{
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;
return -1;
}
/* map the device to memory */
@ -95,4 +87,6 @@ void FramebufferFrameGrabber::grabFrame(Image<ColorRgb> & image)
munmap(_fbp, capSize);
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/FramebufferFrameGrabber.h>
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);
}

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);
_display = kCGDirectMainDisplay;
} else {
}
else
{
_display = displays[_screenIndex];
}
@ -35,7 +37,7 @@ OsxFrameGrabber::~OsxFrameGrabber()
{
}
void OsxFrameGrabber::grabFrame(Image<ColorRgb> & image)
int OsxFrameGrabber::grabFrame(Image<ColorRgb> & image)
{
CGImageRef dispImage;
CFDataRef imgData;
@ -52,7 +54,7 @@ void OsxFrameGrabber::grabFrame(Image<ColorRgb> & image)
if (dispImage == NULL)
{
Error(_log, "No display connected...");
return;
return -1;
}
}
imgData = CGDataProviderCopyData(CGImageGetDataProvider(dispImage));
@ -71,4 +73,6 @@ void OsxFrameGrabber::grabFrame(Image<ColorRgb> & image)
CFRelease(imgData);
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/OsxFrameGrabber.h>
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);
}

View File

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

View File

@ -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<ColorRgb>>("Image<ColorRgb>");
@ -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<ColorRgb>)), this, SLOT(newFrame(Image<ColorRgb>)), 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<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);
}
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<ColorRgb> &image)
{
emit emitImage(_priority, image, _timeout_ms);

View File

@ -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,12 +110,15 @@ 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<ColorRgb> & X11Grabber::grab()
int X11Grabber::grabFrame(Image<ColorRgb> & image, bool forceUpdate)
{
updateScreenDimensions();
if (forceUpdate)
updateScreenDimensions(forceUpdate);
if (_XRenderAvailable && !_useXGetImage)
{
@ -145,19 +149,11 @@ Image<ColorRgb> & 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<ColorRgb> & 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);
// use xshm
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
{
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<ColorRgb> & 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);
}

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

View File

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

View File

@ -2,19 +2,31 @@
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
#include <hyperion/GrabberWrapper.h>
#include <hyperion/Grabber.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)
, _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());
@ -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<ColorRgb>&, const int)), _hyperion, SLOT(setImage(int, const Image<ColorRgb>&, 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;
}

View File

@ -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

View File

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

View File

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

View File

@ -78,7 +78,15 @@ void PriorityMuxer::clearInput(const int priority)
}
}
void PriorityMuxer::clearAll()
void PriorityMuxer::clearAll(bool forceClearAll)
{
if (forceClearAll)
{
_activeInputs.clear();
_currentPriority = LOWEST_PRIORITY;
_activeInputs[_currentPriority] = _lowestPriorityInfo;
}
else
{
for(auto key : _activeInputs.keys())
{
@ -88,6 +96,7 @@ void PriorityMuxer::clearAll()
}
}
}
}
void PriorityMuxer::setCurrentTime(const int64_t& now)
{

View File

@ -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
},

View File

@ -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

View File

@ -36,7 +36,7 @@ void ImageResampler::setCropping(int cropLeft, int cropRight, int cropTop, int c
_cropBottom = cropBottom;
}
void ImageResampler::set3D(VideoMode mode)
void ImageResampler::setVideoMode(VideoMode mode)
{
_videoMode = mode;
}

View File

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

View File

@ -16,7 +16,7 @@ AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeig
const Image<ColorRgb> & 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);
}

View File

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

View File

@ -2,7 +2,12 @@ cmake_minimum_required(VERSION 2.8.12)
project(hyperion-dispmanx)
find_package(Qt5Widgets 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

View File

@ -22,7 +22,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe
const Image<ColorRgb> & 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);
}

View File

@ -40,7 +40,5 @@ private:
/// The grabber for creating screenshots
DispmanxFrameGrabber _grabber;
Image<ColorRgb> _screenshot_rgb;
Image<ColorRgba> _screenshot;
Image<ColorRgb> _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> & 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<ColorRgb> & screenshot = _grabber.grab();
emit sig_screenshot(screenshot);
_grabber.grabFrame(_screenshot, true);
emit sig_screenshot(_screenshot);
}
void X11Wrapper::setGrabbingMode(const GrabbingMode mode)

View File

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

View File

@ -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<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(
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<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, 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,

View File

@ -1,6 +1,7 @@
#pragma once
#include <QObject>
#include <QJsonObject>
#ifdef ENABLE_DISPMANX
#include <grabber/DispmanxWrapper.h>
@ -46,7 +47,7 @@
#include <boblightserver/BoblightServer.h>
#include <udplistener/UDPListener.h>
#include <utils/Stats.h>
#include <QJsonObject>
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(BCM REQUIRED)
include_directories(${BCM_INCLUDE_DIRS})
find_package(Qt5Widgets REQUIRED)
add_definitions(${QT_DEFINITIONS})
link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
add_executable(dispmanx2png
dispmanx2png.cpp)
target_link_libraries(dispmanx2png
dispmanx-grabber
Qt5::Gui)
ENDIF()