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

@@ -13,7 +13,7 @@
#include <sys/types.h>
// Local includes
#include "AmlogicGrabber.h"
#include <grabber/AmlogicGrabber.h>
// Flags copied from 'include/linux/amlogic/amports/amvideocap.h' at https://github.com/codesnake/linux-amlogic
#define AMVIDEOCAP_IOC_MAGIC 'V'

View File

@@ -1,58 +0,0 @@
#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

@@ -9,7 +9,7 @@
// Amlogic grabber includes
#include <grabber/AmlogicWrapper.h>
#include "AmlogicGrabber.h"
#include <grabber/AmlogicGrabber.h>
AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) :
@@ -26,6 +26,7 @@ AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeig
// Configure the timer to generate events every n milliseconds
_timer.setInterval(_updateInterval_ms);
_timer.setSingleShot(false);
_forward = _hyperion->getForwarder()->protoForwardingEnabled();
_processor->setSize(grabWidth, grabHeight);
@@ -55,8 +56,14 @@ void AmlogicWrapper::action()
return;
}
_processor->process(_image, _ledColors);
if ( _forward )
{
Image<ColorRgb> image_rgb;
_image.toRgb(image_rgb);
emit emitImage(_priority, image_rgb, _timeout_ms);
}
_processor->process(_image, _ledColors);
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
}

View File

@@ -7,7 +7,7 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic)
SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h)
SET(AmlogicHEADERS
${CURRENT_SOURCE_DIR}/AmlogicGrabber.h
${CURRENT_HEADER_DIR}/AmlogicGrabber.h
)
SET(AmlogicSOURCES
@@ -15,7 +15,11 @@ SET(AmlogicSOURCES
${CURRENT_SOURCE_DIR}/AmlogicGrabber.cpp
)
if(ENABLE_QT5)
QT5_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS})
else(ENABLE_QT5)
QT4_WRAP_CPP(AmlogicHEADERS_MOC ${AmlogicQT_HEADERS})
endif(ENABLE_QT5)
add_library(amlogic-grabber
${AmlogicHEADERS}

View File

@@ -9,28 +9,33 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx)
# Group the headers that go through the MOC compiler
SET(DispmanxGrabberQT_HEADERS
${CURRENT_HEADER_DIR}/DispmanxWrapper.h
${CURRENT_HEADER_DIR}/DispmanxWrapper.h
)
SET(DispmanxGrabberHEADERS
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.h
${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h
)
SET(DispmanxGrabberSOURCES
${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp
${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp
${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp
)
QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
if(ENABLE_QT5)
QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
else(ENABLE_QT5)
QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS})
endif(ENABLE_QT5)
add_library(dispmanx-grabber
${DispmanxGrabberHEADERS}
${DispmanxGrabberQT_HEADERS}
${DispmanxGrabberHEADERS_MOC}
${DispmanxGrabberSOURCES}
${DispmanxGrabberHEADERS}
${DispmanxGrabberQT_HEADERS}
${DispmanxGrabberHEADERS_MOC}
${DispmanxGrabberSOURCES}
)
target_link_libraries(dispmanx-grabber
hyperion
${QT_LIBRARIES}
${BCM_LIBRARIES})
hyperion
${QT_LIBRARIES}
${BCM_LIBRARIES}
)

View File

@@ -4,7 +4,7 @@
#include <iostream>
// Local includes
#include "DispmanxFrameGrabber.h"
#include "grabber/DispmanxFrameGrabber.h"
DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height) :
_vc_display(0),

View File

@@ -1,71 +0,0 @@
#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

@@ -9,7 +9,7 @@
// Dispmanx grabber includes
#include <grabber/DispmanxWrapper.h>
#include "DispmanxFrameGrabber.h"
#include <grabber/DispmanxFrameGrabber.h>
DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) :
@@ -28,6 +28,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe
_timer.setSingleShot(false);
_processor->setSize(grabWidth, grabHeight);
_forward = _hyperion->getForwarder()->protoForwardingEnabled();
// Connect the QTimer to this
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(action()));
@@ -51,10 +52,17 @@ void DispmanxWrapper::action()
// Grab frame into the allocated image
_frameGrabber->grabFrame(_image);
_processor->process(_image, _ledColors);
if ( _forward )
{
Image<ColorRgb> image_rgb;
_image.toRgb(image_rgb);
emit emitImage(_priority, image_rgb, _timeout_ms);
}
_processor->process(_image, _ledColors);
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
}
void DispmanxWrapper::stop()
{
// Stop the timer, effectivly stopping the process

View File

@@ -21,7 +21,11 @@ SET(FramebufferGrabberSOURCES
${CURRENT_SOURCE_DIR}/FramebufferFrameGrabber.cpp
)
if(ENABLE_QT5)
QT5_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS})
else(ENABLE_QT5)
QT4_WRAP_CPP(FramebufferGrabberHEADERS_MOC ${FramebufferGrabberQT_HEADERS})
endif(ENABLE_QT5)
add_library(framebuffer-grabber
${FramebufferGrabberHEADERS}

View File

@@ -46,8 +46,9 @@ void FramebufferWrapper::action()
// Grab frame into the allocated image
_frameGrabber->grabFrame(_image);
_processor->process(_image, _ledColors);
emit emitImage(_priority, _image, _timeout_ms);
_processor->process(_image, _ledColors);
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
}
void FramebufferWrapper::stop()

View File

@@ -16,7 +16,11 @@ SET(OsxGrabberSOURCES
${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp
)
if(ENABLE_QT5)
QT5_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS})
else(ENABLE_QT5)
QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS})
endif(ENABLE_QT5)
add_library(osx-grabber
${OsxGrabberHEADERS}

View File

@@ -46,8 +46,9 @@ void OsxWrapper::action()
// Grab frame into the allocated image
_frameGrabber->grabFrame(_image);
_processor->process(_image, _ledColors);
emit emitImage(_priority, _image, _timeout_ms);
_processor->process(_image, _ledColors);
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
}
void OsxWrapper::stop()

View File

@@ -16,7 +16,11 @@ SET(V4L2_SOURCES
${CURRENT_SOURCE_DIR}/V4L2Wrapper.cpp
)
if(ENABLE_QT5)
QT5_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
else(ENABLE_QT5)
QT4_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
endif(ENABLE_QT5)
add_library(v4l2-grabber
${V4L2_HEADERS}
@@ -25,6 +29,10 @@ add_library(v4l2-grabber
${V4L2_HEADERS_MOC}
)
if(ENABLE_QT5)
qt5_use_modules(v4l2-grabber Widgets)
endif(ENABLE_QT5)
target_link_libraries(v4l2-grabber
hyperion
${QT_LIBRARIES}

View File

@@ -94,6 +94,9 @@ void V4L2Wrapper::newFrame(const Image<ColorRgb> &image)
// process the new image
_processor->process(image, _ledColors);
// forward to other hyperions
emit emitImage(_priority, image, _timeout_ms);
// send colors to Hyperion
emit emitColors(_priority, _ledColors, _timeout_ms);
}

View File

@@ -22,7 +22,11 @@ SET(X11_SOURCES
${CURRENT_SOURCE_DIR}/X11Grabber.cpp
)
if(ENABLE_QT5)
QT5_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS})
else(ENABLE_QT5)
QT4_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS})
endif(ENABLE_QT5)
add_library(x11-grabber
${X11_HEADERS}

View File

@@ -17,82 +17,116 @@ X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom,
_x11Display(nullptr),
_screenWidth(0),
_screenHeight(0),
_croppedWidth(0),
_croppedHeight(0),
_image(0,0)
{
_imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation);
_imageResampler.setVerticalPixelDecimation(verticalPixelDecimation);
_imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XGetImage
_imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage
}
X11Grabber::~X11Grabber()
{
if (_x11Display != nullptr)
{
freeResources();
XCloseDisplay(_x11Display);
}
}
int X11Grabber::open()
void X11Grabber::freeResources()
{
const char * display_name = nullptr;
_x11Display = XOpenDisplay(display_name);
// Cleanup allocated resources of the X11 grab
XShmDetach(_x11Display, &_shminfo);
XDestroyImage(_xImage);
shmdt(_shminfo.shmaddr);
shmctl(_shminfo.shmid, IPC_RMID, 0);
}
void X11Grabber::setupResources()
{
_xImage = XShmCreateImage(_x11Display, _windowAttr.visual,
_windowAttr.depth, ZPixmap, NULL, &_shminfo,
_croppedWidth, _croppedHeight);
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
_shminfo.shmaddr = _xImage->data = (char*)shmat(_shminfo.shmid,0,0);
_shminfo.readOnly = False;
XShmAttach(_x11Display, &_shminfo);
}
bool X11Grabber::Setup()
{
_x11Display = XOpenDisplay(NULL);
if (_x11Display == nullptr)
{
std::cerr << "Failed to open the default X11-display" << std::endl;
return -1;
}
std::cerr << "Unable to open display";
if (getenv("DISPLAY"))
std::cerr << " " << std::string(getenv("DISPLAY")) << std::endl;
else
std::cerr << ". DISPLAY environment variable not set" << std::endl;
return false;
}
_window = DefaultRootWindow(_x11Display);
return 0;
}
return true;
}
Image<ColorRgb> & X11Grabber::grab()
{
if (_x11Display == nullptr)
{
open();
}
updateScreenDimensions();
const unsigned croppedWidth = _screenWidth - _cropLeft - _cropRight;
const unsigned croppedHeight = _screenHeight - _cropTop - _cropBottom;
// Capture the current screen
XImage * xImage = XGetImage(_x11Display, DefaultRootWindow(_x11Display), _cropLeft, _cropTop, croppedWidth, croppedHeight, AllPlanes, ZPixmap);
if (xImage == nullptr)
XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, 0x00FFFFFF);
if (_xImage == nullptr)
{
std::cerr << "Grab failed" << std::endl;
return _image;
}
_imageResampler.processImage(reinterpret_cast<const uint8_t *>(xImage->data), xImage->width, xImage->height, xImage->bytes_per_line, PIXELFORMAT_BGR32, _image);
// Cleanup allocated resources of the X11 grab
XDestroyImage(xImage);
_imageResampler.processImage(reinterpret_cast<const uint8_t *>(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image);
return _image;
}
int X11Grabber::updateScreenDimensions()
{
XWindowAttributes window_attributes_return;
const Status status = XGetWindowAttributes(_x11Display, DefaultRootWindow(_x11Display), &window_attributes_return);
const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr);
if (status == 0)
{
std::cerr << "Failed to obtain window attributes" << std::endl;
return -1;
}
if (_screenWidth == unsigned(window_attributes_return.width) && _screenHeight == unsigned(window_attributes_return.height))
if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height))
{
// No update required
return 0;
}
std::cout << "Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => ";
_screenWidth = window_attributes_return.width;
_screenHeight = window_attributes_return.height;
if (_screenWidth || _screenHeight)
freeResources();
_screenWidth = _windowAttr.width;
_screenHeight = _windowAttr.height;
std::cout << "[" << _screenWidth << "x" << _screenHeight <<"]" << std::endl;
if (_screenWidth > unsigned(_cropLeft + _cropRight))
_croppedWidth = _screenWidth - _cropLeft - _cropRight;
else
_croppedWidth = _screenWidth;
if (_screenHeight > unsigned(_cropTop + _cropBottom))
_croppedHeight = _screenHeight - _cropTop - _cropBottom;
else
_croppedHeight = _screenHeight;
setupResources();
return 0;
}