Merge remote-tracking branch 'refs/remotes/tvdzwan/master'

# Conflicts:
#	include/hyperion/Hyperion.h
#	libsrc/hyperion/CMakeLists.txt
#	libsrc/hyperion/Hyperion.cpp


Former-commit-id: 1144520581d4531952038d2118cb11e01bebc10e
This commit is contained in:
AEtHeLsYn
2016-03-09 19:25:04 +01:00
127 changed files with 3084 additions and 443 deletions

View File

@@ -1,3 +1,4 @@
//#include <iostream>
#pragma once
// Utils includes
@@ -49,7 +50,7 @@ namespace hyperion
/// Constructs a black-border detector
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
///
BlackBorderDetector(uint8_t blackborderThreshold);
BlackBorderDetector(double threshold);
///
/// Performs the actual black-border detection on the given image
@@ -58,8 +59,72 @@ namespace hyperion
///
/// @return The detected (or not detected) black border info
///
uint8_t calculateThreshold(double blackborderThreshold);
///
/// default detection mode (3lines 4side detection)
template <typename Pixel_T>
BlackBorder process(const Image<Pixel_T> & image)
{
// test center and 33%, 66% of width/heigth
// 33 and 66 will check left and top
// center will check right and bottom sids
int width = image.width();
int height = image.height();
int width33percent = width / 3;
int height33percent = height / 3;
int width66percent = width33percent * 2;
int height66percent = height33percent * 2;
int xCenter = width / 2;
int yCenter = height / 2;
int firstNonBlackXPixelIndex = -1;
int firstNonBlackYPixelIndex = -1;
width--; // remove 1 pixel to get end pixel index
height--;
// find first X pixel of the image
for (int x = 0; x < width33percent; ++x)
{
const Pixel_T & color1 = image( (width - x), yCenter); // right side center line check
const Pixel_T & color2 = image(x, height33percent);
const Pixel_T & color3 = image(x, height66percent);
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
{
firstNonBlackXPixelIndex = x;
break;
}
}
// find first Y pixel of the image
for (int y = 0; y < height33percent; ++y)
{
const Pixel_T & color1 = image(xCenter, (height - y)); // bottom center line check
const Pixel_T & color2 = image(width33percent, y );
const Pixel_T & color3 = image(width66percent, y);
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
{
firstNonBlackYPixelIndex = y;
break;
}
}
// Construct result
BlackBorder detectedBorder;
detectedBorder.unknown = firstNonBlackXPixelIndex == -1 || firstNonBlackYPixelIndex == -1;
detectedBorder.horizontalSize = firstNonBlackYPixelIndex;
detectedBorder.verticalSize = firstNonBlackXPixelIndex;
return detectedBorder;
}
///
/// classic detection mode (topleft single line mode)
template <typename Pixel_T>
BlackBorder process_classic(const Image<Pixel_T> & image)
{
// only test the topleft third of the image
int width = image.width() /3;
@@ -112,6 +177,67 @@ namespace hyperion
return detectedBorder;
}
///
/// osd detection mode (find x then y at detected x to avoid changes by osd overlays)
template <typename Pixel_T>
BlackBorder process_osd(const Image<Pixel_T> & image)
{
// find X position at height33 and height66 we check from the left side, Ycenter will check from right side
// then we try to find a pixel at this X position from top and bottom and right side from top
int width = image.width();
int height = image.height();
int width33percent = width / 3;
int height33percent = height / 3;
int height66percent = height33percent * 2;
int yCenter = height / 2;
int firstNonBlackXPixelIndex = -1;
int firstNonBlackYPixelIndex = -1;
width--; // remove 1 pixel to get end pixel index
height--;
// find first X pixel of the image
int x;
for (x = 0; x < width33percent; ++x)
{
const Pixel_T & color1 = image( (width - x), yCenter); // right side center line check
const Pixel_T & color2 = image(x, height33percent);
const Pixel_T & color3 = image(x, height66percent);
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
{
firstNonBlackXPixelIndex = x;
break;
}
}
// find first Y pixel of the image
for (int y = 0; y < height33percent; ++y)
{
const Pixel_T & color1 = image(x, y );// left side top check
const Pixel_T & color2 = image(x, (height - y)); // left side bottom check
const Pixel_T & color3 = image( (width - x), y); // right side top check
const Pixel_T & color4 = image( (width - x), (height - y)); // right side bottom check
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3) || !isBlack(color4))
{
// std::cout << "y " << y << " lt " << int(isBlack(color1)) << " lb " << int(isBlack(color2)) << " rt " << int(isBlack(color3)) << " rb " << int(isBlack(color4)) << std::endl;
firstNonBlackYPixelIndex = y;
break;
}
}
// Construct result
BlackBorder detectedBorder;
detectedBorder.unknown = firstNonBlackXPixelIndex == -1 || firstNonBlackYPixelIndex == -1;
detectedBorder.horizontalSize = firstNonBlackYPixelIndex;
detectedBorder.verticalSize = firstNonBlackXPixelIndex;
return detectedBorder;
}
private:
///
@@ -131,5 +257,6 @@ namespace hyperion
private:
/// Threshold for the blackborder detector [0 .. 255]
const uint8_t _blackborderThreshold;
};
} // end namespace hyperion

View File

@@ -1,6 +1,8 @@
#pragma once
// Jsoncpp includes
#include <json/json.h>
// Local Hyperion includes
#include "BlackBorderDetector.h"
@@ -23,11 +25,7 @@ namespace hyperion
/// outer pixels is blurred (black and color combined due to image scaling))
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
///
BlackBorderProcessor(
const unsigned unknownFrameCnt,
const unsigned borderFrameCnt,
const unsigned blurRemoveCnt,
uint8_t blackborderThreshold);
BlackBorderProcessor(const Json::Value &blackborderConfig);
///
/// Return the current (detected) border
@@ -48,7 +46,14 @@ namespace hyperion
bool process(const Image<Pixel_T> & image)
{
// get the border for the single image
BlackBorder imageBorder = _detector.process(image);
BlackBorder imageBorder;
if (_detectionMode == "default") {
imageBorder = _detector.process(image);
} else if (_detectionMode == "classic") {
imageBorder = _detector.process_classic(image);
} else if (_detectionMode == "osd") {
imageBorder = _detector.process_osd(image);
}
// add blur to the border
if (imageBorder.horizontalSize > 0)
{
@@ -80,9 +85,15 @@ namespace hyperion
/// The number of horizontal/vertical borders detected before it becomes the current border
const unsigned _borderSwitchCnt;
// The number of frames that are "ignored" before a new border gets set as _previousDetectedBorder
const unsigned _maxInconsistentCnt;
/// The number of pixels to increase a detected border for removing blury pixels
unsigned _blurRemoveCnt;
/// The border detection mode
const std::string _detectionMode;
/// The blackborder detector
BlackBorderDetector _detector;
@@ -94,5 +105,8 @@ namespace hyperion
/// The number of frame the previous detected border matched the incomming border
unsigned _consistentCnt;
/// The number of frame the previous detected border NOT matched the incomming border
unsigned _inconsistentCnt;
};
} // end namespace hyperion

View File

@@ -0,0 +1,58 @@
#pragma once
// STL includes
#include <cstdint>
// Utils includes
#include <utils/Image.h>
#include <utils/ColorBgr.h>
#include <utils/VideoMode.h>
///
/// The DispmanxFrameGrabber is used for creating snapshots of the display (screenshots) with a
/// downsized and scaled resolution.
///
class AmlogicGrabber
{
public:
///
/// Construct a AmlogicGrabber that will capture snapshots with specified dimensions.
///
/// @param[in] width The width of the captured screenshot
/// @param[in] height The heigth of the captured screenshot
///
AmlogicGrabber(const unsigned width, const unsigned height);
~AmlogicGrabber();
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(const VideoMode videoMode);
///
/// 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
/// _height)
///
/// @param[out] image The snapped screenshot (should be initialized with correct width and
/// height)
/// @return Zero on success else negative
///
int grabFrame(Image<ColorBgr> & image);
/**
* Returns true if video is playing over the amlogic chip
* @return True if video is playing else false
*/
bool isVideoPlaying();
private:
/// With of the captured snapshot [pixels]
const unsigned _width;
/// Height of the captured snapshot [pixels]
const unsigned _height;
/** The snapshot/capture device of the amlogic video chip */
int _amlogicCaptureDev;
};

View File

@@ -68,6 +68,9 @@ public slots:
///
void setVideoMode(const VideoMode videoMode);
signals:
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
private:
/// The update rate [Hz]
const int _updateInterval_ms;
@@ -91,4 +94,7 @@ private:
/// Pointer to Hyperion for writing led values
Hyperion * _hyperion;
// forwarding enabled
bool _forward;
};

View File

@@ -0,0 +1,71 @@
#pragma once
// BCM includes
#pragma GCC system_header
#include <bcm_host.h>
// STL includes
#include <cstdint>
// Utils includes
#include <utils/Image.h>
#include <utils/ColorRgba.h>
#include <utils/VideoMode.h>
///
/// The DispmanxFrameGrabber is used for creating snapshots of the display (screenshots) with a
/// downsized and scaled resolution.
///
class DispmanxFrameGrabber
{
public:
///
/// Construct a DispmanxFrameGrabber that will capture snapshots with specified dimensions.
///
/// @param[in] width The width of the captured screenshot
/// @param[in] height The heigth of the captured screenshot
///
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);
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(const VideoMode videoMode);
///
/// 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
/// _height)
///
/// @param[out] image The snapped screenshot (should be initialized with correct width and
/// height)
///
void grabFrame(Image<ColorRgba> & image);
private:
/// Handle to the display that is being captured
DISPMANX_DISPLAY_HANDLE_T _vc_display;
/// Handle to the resource for storing the captured snapshot
DISPMANX_RESOURCE_HANDLE_T _vc_resource;
/// Rectangle of the captured resource that is transfered to user space
VC_RECT_T _rectangle;
/// Flags (transforms) for creating snapshots
int _vc_flags;
/// With of the captured snapshot [pixels]
const unsigned _width;
/// Height of the captured snapshot [pixels]
const unsigned _height;
};

View File

@@ -68,6 +68,9 @@ public slots:
///
void setVideoMode(const VideoMode videoMode);
signals:
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
private:
/// The update rate [Hz]
const int _updateInterval_ms;
@@ -91,4 +94,7 @@ private:
/// Pointer to Hyperion for writing led values
Hyperion * _hyperion;
// forwarding enabled
bool _forward;
};

View File

@@ -68,6 +68,9 @@ public slots:
///
void setVideoMode(const VideoMode videoMode);
signals:
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
private:
/// The update rate [Hz]
const int _updateInterval_ms;

View File

@@ -69,6 +69,9 @@ public slots:
///
void setVideoMode(const VideoMode videoMode);
signals:
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
private:
/// The update rate [Hz]
const int _updateInterval_ms;

View File

@@ -44,6 +44,7 @@ public slots:
signals:
void emitColors(int priority, const std::vector<ColorRgb> &ledColors, const int timeout_ms);
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
private slots:
void newFrame(const Image<ColorRgb> & image);

View File

@@ -7,6 +7,11 @@
// X11 includes
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>
class X11Grabber
{
public:
@@ -16,6 +21,8 @@ public:
virtual ~X11Grabber();
int open();
bool Setup();
Image<ColorRgb> & grab();
@@ -26,14 +33,24 @@ private:
int _cropRight;
int _cropTop;
int _cropBottom;
XImage* _xImage;
XShmSegmentInfo _shminfo;
/// Reference to the X11 display (nullptr if not opened)
Display * _x11Display;
Display* _x11Display;
Window _window;
XWindowAttributes _windowAttr;
unsigned _screenWidth;
unsigned _screenHeight;
unsigned _croppedWidth;
unsigned _croppedHeight;
Image<ColorRgb> _image;
void freeResources();
void setupResources();
int updateScreenDimensions();
};

View File

@@ -106,7 +106,7 @@ private:
/// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
///
ImageProcessor(const LedString &ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold);
ImageProcessor(const LedString &ledString, const Json::Value &blackborderConfig);
///
/// Performs black-border detection (if enabled) on the given image

View File

@@ -33,7 +33,7 @@ public:
/// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
///
void init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold);
void init(const LedString& ledString, const Json::Value &blackborderConfig);
///
/// Creates a new ImageProcessor. The onwership of the processor is transferred to the caller.
@@ -46,9 +46,6 @@ private:
/// The Led-string specification
LedString _ledString;
/// Flag indicating if the black border detector should be used
bool _enableBlackBorderDetector;
/// Threshold for the blackborder detector [0 .. 255]
uint8_t _blackborderThreshold;
// Reference to the blackborder json configuration values
Json::Value _blackborderConfig;
};

View File

@@ -0,0 +1,38 @@
#pragma once
// STL includes
#include <vector>
#include <map>
#include <cstdint>
#include <limits>
// QT includes
#include <QList>
#include <QStringList>
#include <QHostAddress>
// Utils includes
#include <utils/ColorRgb.h>
class MessageForwarder
{
public:
struct JsonSlaveAddress {
QHostAddress addr;
quint16 port;
};
MessageForwarder();
~MessageForwarder();
void addJsonSlave(std::string slave);
void addProtoSlave(std::string slave);
bool protoForwardingEnabled();
QStringList getProtoSlaves();
QList<MessageForwarder::JsonSlaveAddress> getJsonSlaves();
private:
QStringList _protoSlaves;
QList<MessageForwarder::JsonSlaveAddress> _jsonSlaves;
};

View File

@@ -7,6 +7,7 @@
#include <QColor>
#include <QImage>
#include <QTcpSocket>
#include <QTimer>
#include <QMap>
// hyperion util
@@ -19,8 +20,11 @@
///
/// Connection class to setup an connection to the hyperion server and execute commands
///
class ProtoConnection
class ProtoConnection : public QObject
{
Q_OBJECT
public:
///
/// Constructor
@@ -67,10 +71,6 @@ public:
///
void clearAll();
private:
/// Try to connect to the Hyperion host
void connectToHost();
///
/// Send a command message and receive its reply
///
@@ -78,6 +78,13 @@ private:
///
void sendMessage(const proto::HyperionRequest & message);
private slots:
/// Try to connect to the Hyperion host
void connectToHost();
private:
///
/// Parse a reply message
///
@@ -99,4 +106,7 @@ private:
/// Skip receiving reply messages from Hyperion if set
bool _skipReply;
QTimer _timer;
QAbstractSocket::SocketState _prevSocketState;
};

View File

@@ -6,11 +6,23 @@
// Qt includes
#include <QTcpServer>
#include <QSet>
#include <QList>
#include <QStringList>
// Hyperion includes
#include <hyperion/Hyperion.h>
// hyperion includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
// forward decl
class ProtoClientConnection;
class ProtoConnection;
namespace proto {
class HyperionRequest;
}
///
/// This class creates a TCP server which accepts connections wich can then send
@@ -35,6 +47,9 @@ public:
///
uint16_t getPort() const;
public slots:
void sendImageToProtoSlaves(int priority, const Image<ColorRgb> & image, int duration_ms);
private slots:
///
/// Slot which is called when a client tries to create a new connection
@@ -47,6 +62,8 @@ private slots:
///
void closedConnection(ProtoClientConnection * connection);
void newMessage(const proto::HyperionRequest * message);
private:
/// Hyperion instance
Hyperion * _hyperion;
@@ -56,4 +73,9 @@ private:
/// List with open connections
QSet<ProtoClientConnection *> _openConnections;
QStringList _forwardClients;
/// Hyperion proto connection object for forwarding
QList<ProtoConnection*> _proxy_connections;
};

View File

@@ -5,6 +5,8 @@
#include <cstdint>
#include <cstring>
#include <algorithm>
#include <utils/ColorRgb.h>
template <typename Pixel_T>
class Image
@@ -183,6 +185,25 @@ public:
{
return _pixels;
}
///
/// Convert image of any color order to a RGB image.
///
/// @param[out] image The image that buffers the output
///
void toRgb(Image<ColorRgb>& image)
{
image.resize(_width, _height);
const unsigned imageSize = _width * _height;
for (unsigned idx=0; idx<imageSize; idx++)
{
const Pixel_T color = memptr()[idx];
image.memptr()[idx] = ColorRgb{color.red, color.green, color.blue};
}
}
private:
///