- refactored framebuffer grabber to use ImageResampler

- added OsxGrabber for OSX
- added binary for imx6 (cubox-i) and updated install script


Former-commit-id: 2c55e292c842c67e54ce36bd91e4f6303b98687a
This commit is contained in:
Gamadril 2015-01-24 23:42:22 +01:00
parent 3488f23603
commit 3fd20ec5fa
20 changed files with 514 additions and 89 deletions

View File

@ -35,10 +35,21 @@ endif(ENABLE_V4L2 AND NOT ENABLE_PROTOBUF)
option(ENABLE_FB "Enable the framebuffer grabber" OFF) option(ENABLE_FB "Enable the framebuffer grabber" OFF)
message(STATUS "ENABLE_FB = " ${ENABLE_FB}) message(STATUS "ENABLE_FB = " ${ENABLE_FB})
option(ENABLE_OSX "Enable the osx grabber" OFF)
message(STATUS "ENABLE_OSX = " ${ENABLE_OSX})
if(ENABLE_FB AND ENABLE_DISPMANX) if(ENABLE_FB AND ENABLE_DISPMANX)
message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time") message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time")
endif(ENABLE_FB AND ENABLE_DISPMANX) endif(ENABLE_FB AND ENABLE_DISPMANX)
if(ENABLE_FB AND ENABLE_OSX)
message(FATAL_ERROR "osx grabber and framebuffer grabber cannot be used at the same time")
endif(ENABLE_FB AND ENABLE_OSX)
if(ENABLE_OSX AND ENABLE_DISPMANX)
message(FATAL_ERROR "dispmanx grabber and osx grabber cannot be used at the same time")
endif(ENABLE_OSX AND ENABLE_DISPMANX)
# Createt the configuration file # Createt the configuration file
# configure a header file to pass some of the CMake settings # configure a header file to pass some of the CMake settings
# to the source code # to the source code
@ -89,6 +100,10 @@ if(NOT APPLE)
link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
endif() endif()
if(ENABLE_OSX)
set(CMAKE_EXE_LINKER_FLAGS "-framework CoreGraphics")
endif()
configure_file(bin/install_hyperion.sh ${LIBRARY_OUTPUT_PATH} @ONLY) configure_file(bin/install_hyperion.sh ${LIBRARY_OUTPUT_PATH} @ONLY)
configure_file(config/hyperion.config.json ${LIBRARY_OUTPUT_PATH} @ONLY) configure_file(config/hyperion.config.json ${LIBRARY_OUTPUT_PATH} @ONLY)
configure_file(config/hyperion_x86.config.json ${LIBRARY_OUTPUT_PATH} @ONLY) configure_file(config/hyperion_x86.config.json ${LIBRARY_OUTPUT_PATH} @ONLY)

View File

@ -28,6 +28,10 @@ cmake ..
cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON .. cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON ..
# as an alternative for the dispmanx grabber on non-rpi devices (e.g. cubox-i) you could try the framebuffer grabber # as an alternative for the dispmanx grabber on non-rpi devices (e.g. cubox-i) you could try the framebuffer grabber
cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON .. cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON ..
# for OSX build you need XCode, qt4 libraries and cmake. You can use macport (homebrew might work too) to install them
sudo port install qt4-mac
sudo port install cmake
cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_V4L2=OFF -DENABLE_OSX=ON .
# run make to build Hyperion # run make to build Hyperion
make make

View File

@ -21,3 +21,6 @@
// Define to enable the framebuffer grabber // Define to enable the framebuffer grabber
#cmakedefine ENABLE_FB #cmakedefine ENABLE_FB
// Define to enable the osx grabber
#cmakedefine ENABLE_OSX

View File

@ -10,6 +10,9 @@ IS_XBIAN=`cat /etc/issue | grep XBian | wc -l`
IS_RASPBMC=`cat /etc/issue | grep Raspbmc | wc -l` IS_RASPBMC=`cat /etc/issue | grep Raspbmc | wc -l`
IS_OPENELEC=`cat /etc/issue | grep -m 1 OpenELEC | wc -l` IS_OPENELEC=`cat /etc/issue | grep -m 1 OpenELEC | wc -l`
# Find out if its an imx6 device
IS_IMX6=`cat /proc/cpuinfo | grep i.MX6 | wc -l`
# check which init script we should use # check which init script we should use
USE_INITCTL=`which /sbin/initctl | wc -l` USE_INITCTL=`which /sbin/initctl | wc -l`
USE_SERVICE=`which /usr/sbin/service | wc -l` USE_SERVICE=`which /usr/sbin/service | wc -l`
@ -34,14 +37,21 @@ fi
echo 'Downloading hyperion' echo 'Downloading hyperion'
if [ $IS_OPENELEC -eq 1 ]; then if [ $IS_OPENELEC -eq 1 ]; then
# OpenELEC has a readonly file system. Use alternative location # OpenELEC has a readonly file system. Use alternative location
if [ $IS_IMX6 -eq 1 ]; then
curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_imx6.tar.gz | tar -C /storage -xz
else
curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz | tar -C /storage -xz curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz | tar -C /storage -xz
fi
curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.deps.openelec-rpi.tar.gz | tar -C /storage/hyperion/bin -xz curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.deps.openelec-rpi.tar.gz | tar -C /storage/hyperion/bin -xz
# modify the default config to have a correct effect path # modify the default config to have a correct effect path
sed -i 's:/opt:/storage:g' /storage/hyperion/config/hyperion.config.json sed -i 's:/opt:/storage:g' /storage/hyperion/config/hyperion.config.json
else
if [ $IS_IMX6 -eq 1 ]; then
wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_imx6.tar.gz -O - | tar -C /opt -xz
else else
wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz -O - | tar -C /opt -xz wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz -O - | tar -C /opt -xz
fi fi
fi
# create links to the binaries # create links to the binaries
if [ $IS_OPENELEC -ne 1 ]; then if [ $IS_OPENELEC -ne 1 ]; then
@ -51,7 +61,7 @@ if [ $IS_OPENELEC -ne 1 ]; then
fi fi
# create link to the gpio changer (gpio->spi) # create link to the gpio changer (gpio->spi)
if [ $IS_RASPBMC -eq 1 ]; then if [ $IS_RASPBMC -eq 1 ] && [ $IS_IMX6 -ne 1 ]; then
ln -fs /opt/hyperion/bin/gpio2spi /usr/bin/gpio2spi ln -fs /opt/hyperion/bin/gpio2spi /usr/bin/gpio2spi
fi fi

View File

@ -0,0 +1 @@
12dce43d5b0f92cd013594f1b3d5045d5578de98

View File

@ -7,7 +7,6 @@
// Utils includes // Utils includes
#include <utils/Image.h> #include <utils/Image.h>
#include <utils/ColorRgb.h> #include <utils/ColorRgb.h>
#include <utils/ColorRgba.h>
#include <utils/GrabbingMode.h> #include <utils/GrabbingMode.h>
#include <utils/VideoMode.h> #include <utils/VideoMode.h>
@ -81,7 +80,7 @@ private:
QTimer _timer; QTimer _timer;
/// The image used for grabbing frames /// The image used for grabbing frames
Image<ColorRgba> _image; Image<ColorRgb> _image;
/// The actual grabber /// The actual grabber
FramebufferFrameGrabber * _frameGrabber; FramebufferFrameGrabber * _frameGrabber;
/// The processor for transforming images to led colors /// The processor for transforming images to led colors

View File

@ -0,0 +1,95 @@
#pragma once
// QT includes
#include <QObject>
#include <QTimer>
// Utils includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/ColorRgba.h>
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
// Forward class declaration
class OsxFrameGrabber;
class Hyperion;
class ImageProcessor;
///
/// The OsxWrapper uses an instance of the OsxFrameGrabber to obtain ImageRgb's from the
/// displayed content. This ImageRgb is processed to a ColorRgb for each led and commmited to the
/// attached Hyperion.
///
class OsxWrapper: public QObject
{
Q_OBJECT
public:
///
/// Constructs the osx frame grabber with a specified grab size and update rate.
///
/// @param[in] display Index of the display to grab
/// @param[in] grabWidth The width of the grabbed image [pixels]
/// @param[in] grabHeight The height of the grabbed images [pixels]
/// @param[in] updateRate_Hz The image grab rate [Hz]
/// @param[in] hyperion The instance of Hyperion used to write the led values
///
OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion);
///
/// Destructor of this osx frame grabber. Releases any claimed resources.
///
virtual ~OsxWrapper();
public slots:
///
/// Starts the grabber wich produces led values with the specified update rate
///
void start();
///
/// Performs a single frame grab and computes the led-colors
///
void action();
///
/// Stops the grabber
///
void stop();
///
/// Set the grabbing mode
/// @param[in] mode The new grabbing mode
///
void setGrabbingMode(const GrabbingMode mode);
///
/// 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 priority of the led colors
const int _priority;
/// The timer for generating events with the specified update rate
QTimer _timer;
/// The image used for grabbing frames
Image<ColorRgb> _image;
/// The actual grabber
OsxFrameGrabber * _frameGrabber;
/// The processor for transforming images to led colors
ImageProcessor * _processor;
/// The list with computed led colors
std::vector<ColorRgb> _ledColors;
/// Pointer to Hyperion for writing led values
Hyperion * _hyperion;
};

View File

@ -9,6 +9,8 @@
enum PixelFormat { enum PixelFormat {
PIXELFORMAT_YUYV, PIXELFORMAT_YUYV,
PIXELFORMAT_UYVY, PIXELFORMAT_UYVY,
PIXELFORMAT_BGR16,
PIXELFORMAT_BGR24,
PIXELFORMAT_RGB32, PIXELFORMAT_RGB32,
PIXELFORMAT_BGR32, PIXELFORMAT_BGR32,
PIXELFORMAT_NO_CHANGE PIXELFORMAT_NO_CHANGE
@ -27,6 +29,14 @@ inline PixelFormat parsePixelFormat(std::string pixelFormat)
{ {
return PIXELFORMAT_UYVY; return PIXELFORMAT_UYVY;
} }
else if (pixelFormat == "bgr16")
{
return PIXELFORMAT_BGR16;
}
else if (pixelFormat == "bgr24")
{
return PIXELFORMAT_BGR24;
}
else if (pixelFormat == "rgb32") else if (pixelFormat == "rgb32")
{ {
return PIXELFORMAT_RGB32; return PIXELFORMAT_RGB32;

View File

@ -13,3 +13,7 @@ endif (ENABLE_V4L2)
if (ENABLE_X11) if (ENABLE_X11)
add_subdirectory(x11) add_subdirectory(x11)
endif() endif()
if (ENABLE_OSX)
add_subdirectory(osx)
endif()

View File

@ -5,10 +5,8 @@
#include <linux/fb.h> #include <linux/fb.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <math.h>
// STL includes // STL includes
#include <cassert>
#include <iostream> #include <iostream>
// Local includes // Local includes
@ -20,59 +18,48 @@ FramebufferFrameGrabber::FramebufferFrameGrabber(const std::string & device, con
_fbDevice(device), _fbDevice(device),
_width(width), _width(width),
_height(height), _height(height),
_xScale(1), _imgResampler(new ImageResampler())
_yScale(1)
{ {
int result; int result;
struct fb_var_screeninfo vinfo; struct fb_var_screeninfo vinfo;
// Check if the framebuffer device can be opened and display the current resolution // Check if the framebuffer device can be opened and display the current resolution
_fbfd = open(_fbDevice.c_str(), O_RDONLY); _fbfd = open(_fbDevice.c_str(), O_RDONLY);
assert(_fbfd > 0); if (_fbfd == 0)
{
// get variable screen information std::cerr << "Error openning " << _fbDevice << std::endl;
result = ioctl (_fbfd, FBIOGET_VSCREENINFO, &vinfo); }
assert(result == 0); else
{
std::cout << "Framebuffer opened with resolution: " << vinfo.xres << "x" << vinfo.yres << "@" << vinfo.bits_per_pixel << "bit" << std::endl; // get variable screen information
result = ioctl (_fbfd, FBIOGET_VSCREENINFO, &vinfo);
close(_fbfd); if (result != 0)
{
std::cerr << "Could not get screen information" << std::endl;
}
else
{
std::cout << "Framebuffer opened with resolution: " << vinfo.xres << "x" << vinfo.yres << "@" << vinfo.bits_per_pixel << "bit" << std::endl;
}
close(_fbfd);
}
} }
FramebufferFrameGrabber::~FramebufferFrameGrabber() FramebufferFrameGrabber::~FramebufferFrameGrabber()
{ {
delete _imgResampler;
} }
void FramebufferFrameGrabber::setVideoMode(const VideoMode videoMode) void FramebufferFrameGrabber::setVideoMode(const VideoMode videoMode)
{ {
switch (videoMode) { _imgResampler->set3D(videoMode);
case VIDEO_3DSBS:
_xScale = 2;
_yScale = 1;
break;
case VIDEO_3DTAB:
_xScale = 1;
_yScale = 2;
break;
case VIDEO_2D:
default:
_xScale = 1;
_yScale = 1;
break;
}
} }
void FramebufferFrameGrabber::grabFrame(Image<ColorRgba> & image) void FramebufferFrameGrabber::grabFrame(Image<ColorRgb> & image)
{ {
struct fb_var_screeninfo vinfo; struct fb_var_screeninfo vinfo;
unsigned capSize, px, py, index, bytesPerPixel; unsigned capSize, bytesPerPixel;
float x_scale, y_scale; PixelFormat pixelFormat;
/* resize the given image if needed */
if (image.width() != _width || image.height() != _height)
{
image.resize(_width, _height);
}
/* Open the framebuffer device */ /* Open the framebuffer device */
_fbfd = open(_fbDevice.c_str(), O_RDONLY); _fbfd = open(_fbDevice.c_str(), O_RDONLY);
@ -82,41 +69,37 @@ void FramebufferFrameGrabber::grabFrame(Image<ColorRgba> & image)
bytesPerPixel = vinfo.bits_per_pixel / 8; bytesPerPixel = vinfo.bits_per_pixel / 8;
capSize = vinfo.xres * vinfo.yres * bytesPerPixel; capSize = vinfo.xres * vinfo.yres * bytesPerPixel;
if (vinfo.bits_per_pixel == 16)
{
pixelFormat = PIXELFORMAT_BGR16;
}
else if (vinfo.bits_per_pixel == 24)
{
pixelFormat = PIXELFORMAT_BGR24;
}
else if (vinfo.bits_per_pixel == 32)
{
pixelFormat = PIXELFORMAT_BGR32;
}
else
{
std::cerr << "Unknown pixel format: " << vinfo.bits_per_pixel << " bits per pixel" << std::endl;
close(_fbfd);
return;
}
/* map the device to memory */ /* map the device to memory */
_fbp = (unsigned char*)mmap(0, capSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, _fbfd, 0); _fbp = (unsigned char*)mmap(0, capSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, _fbfd, 0);
/* nearest neighbor downscaling */ _imgResampler->setHorizontalPixelDecimation(vinfo.xres/_width);
x_scale = (vinfo.xres / float(_xScale)) / float(_width); _imgResampler->setVerticalPixelDecimation(vinfo.yres/_height);
y_scale = (vinfo.yres / float(_yScale)) / float(_height); _imgResampler->processImage(_fbp,
vinfo.xres,
ColorRgba *pPixel = image.memptr(); vinfo.yres,
for (unsigned i=0; i < _height; i++) { vinfo.xres * bytesPerPixel,
for (unsigned j=0; j < _width; j++) { pixelFormat,
px = floor(j * x_scale); image);
py = floor(i * y_scale);
index = (py * vinfo.xres + px) * bytesPerPixel;
if (vinfo.bits_per_pixel == 16) {
pPixel->blue = (_fbp[index] & 0x1f) << 3;
pPixel->green = (((_fbp[index + 1] & 0x7) << 3) | (_fbp[index] & 0xE0) >> 5) << 2;
pPixel->red = (_fbp[index + 1] & 0xF8);
pPixel->alpha = 255;
} else if(vinfo.bits_per_pixel == 24) {
pPixel->blue = _fbp[index];
pPixel->green = _fbp[index + 1];
pPixel->red = _fbp[index + 2];
pPixel->alpha = 255;
} else if(vinfo.bits_per_pixel == 32) {
pPixel->blue = _fbp[index];
pPixel->green = _fbp[index + 1];
pPixel->red = _fbp[index + 2];
pPixel->alpha = _fbp[index + 3];
}
pPixel++;
}
}
munmap(_fbp, capSize); munmap(_fbp, capSize);
close(_fbfd); close(_fbfd);

View File

@ -2,8 +2,9 @@
// Utils includes // Utils includes
#include <utils/Image.h> #include <utils/Image.h>
#include <utils/ColorRgba.h> #include <utils/ColorRgb.h>
#include <utils/VideoMode.h> #include <utils/VideoMode.h>
#include <utils/ImageResampler.h>
/// ///
/// The FramebufferFrameGrabber is used for creating snapshots of the display (screenshots) /// The FramebufferFrameGrabber is used for creating snapshots of the display (screenshots)
@ -35,7 +36,7 @@ public:
/// @param[out] image The snapped screenshot (should be initialized with correct width and /// @param[out] image The snapped screenshot (should be initialized with correct width and
/// height) /// height)
/// ///
void grabFrame(Image<ColorRgba> & image); void grabFrame(Image<ColorRgb> & image);
private: private:
/// Framebuffer file descriptor /// Framebuffer file descriptor
@ -53,9 +54,6 @@ private:
/// Height of the captured snapshot [pixels] /// Height of the captured snapshot [pixels]
const unsigned _height; const unsigned _height;
/// width scale factor for 3D image processing /// Image resampler for downscaling the image
float _xScale; ImageResampler * _imgResampler;
/// height scale factor for 3D image processing
float _yScale;
}; };

View File

@ -0,0 +1,30 @@
# Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/osx)
# Group the headers that go through the MOC compiler
SET(OsxGrabberQT_HEADERS
${CURRENT_HEADER_DIR}/OsxWrapper.h
)
SET(OsxGrabberHEADERS
${CURRENT_SOURCE_DIR}/OsxFrameGrabber.h
)
SET(OsxGrabberSOURCES
${CURRENT_SOURCE_DIR}/OsxWrapper.cpp
${CURRENT_SOURCE_DIR}/OsxFrameGrabber.cpp
)
QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS})
add_library(osx-grabber
${OsxGrabberHEADERS}
${OsxGrabberQT_HEADERS}
${OsxGrabberHEADERS_MOC}
${OsxGrabberSOURCES}
)
target_link_libraries(osx-grabber
hyperion
${QT_LIBRARIES})

View File

@ -0,0 +1,82 @@
// STL includes
#include <cassert>
#include <iostream>
// Local includes
#include "OsxFrameGrabber.h"
OsxFrameGrabber::OsxFrameGrabber(const unsigned display, const unsigned width, const unsigned height) :
_screenIndex(display),
_width(width),
_height(height),
_imgResampler(new ImageResampler())
{
CGImageRef image;
CGDisplayCount displayCount;
CGDirectDisplayID displays[8];
// get list of displays
CGGetActiveDisplayList(8, displays, &displayCount);
if (_screenIndex + 1 > displayCount)
{
std::cerr << "OSX display with index " << _screenIndex << " is not available. Using main display" << std::endl;
_display = kCGDirectMainDisplay;
} else {
_display = displays[_screenIndex];
}
image = CGDisplayCreateImage(_display);
assert(image != NULL);
std::cout << "OSX display opened with resolution: " << CGImageGetWidth(image) << "x" << CGImageGetHeight(image) << "@" << CGImageGetBitsPerPixel(image) << "bit" << std::endl;
CGImageRelease(image);
}
OsxFrameGrabber::~OsxFrameGrabber()
{
delete _imgResampler;
}
void OsxFrameGrabber::setVideoMode(const VideoMode videoMode)
{
_imgResampler->set3D(videoMode);
}
void OsxFrameGrabber::grabFrame(Image<ColorRgb> & image)
{
CGImageRef dispImage;
CFDataRef imgData;
unsigned char * pImgData;
unsigned dspWidth, dspHeight;
dispImage = CGDisplayCreateImage(_display);
// dsiplay lost, use main
if (dispImage == NULL && _display)
{
dispImage = CGDisplayCreateImage(kCGDirectMainDisplay);
// no displays connected, return
if (dispImage == NULL)
{
std::cerr << "OSX no display connected..." << std::endl;
return;
}
}
imgData = CGDataProviderCopyData(CGImageGetDataProvider(dispImage));
pImgData = (unsigned char*) CFDataGetBytePtr(imgData);
dspWidth = CGImageGetWidth(dispImage);
dspHeight = CGImageGetHeight(dispImage);
_imgResampler->setHorizontalPixelDecimation(dspWidth/_width);
_imgResampler->setVerticalPixelDecimation(dspHeight/_height);
_imgResampler->processImage( pImgData,
dspWidth,
dspHeight,
CGImageGetBytesPerRow(dispImage),
PIXELFORMAT_BGR32,
image);
CFRelease(imgData);
CGImageRelease(dispImage);
}

View File

@ -0,0 +1,59 @@
#pragma once
// OSX includes
#include <CoreGraphics/CoreGraphics.h>
// Utils includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.h>
#include <utils/ImageResampler.h>
///
/// The OsxFrameGrabber is used for creating snapshots of the display (screenshots)
///
class OsxFrameGrabber
{
public:
///
/// Construct a OsxFrameGrabber that will capture snapshots with specified dimensions.
///
/// @param[in] display The index of the display to capture
/// @param[in] width The width of the captured screenshot
/// @param[in] height The heigth of the captured screenshot
///
OsxFrameGrabber(const unsigned display, const unsigned width, const unsigned height);
~OsxFrameGrabber();
///
/// 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<ColorRgb> & image);
private:
/// display
const unsigned _screenIndex;
/// With of the captured snapshot [pixels]
const unsigned _width;
/// Height of the captured snapshot [pixels]
const unsigned _height;
/// Reference to the captured diaplay
CGDirectDisplayID _display;
/// Image resampler for downscaling the image
ImageResampler * _imgResampler;
};

View File

@ -0,0 +1,79 @@
// Hyperion includes
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
// Osx grabber includes
#include <grabber/OsxWrapper.h>
#include "OsxFrameGrabber.h"
OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) :
_updateInterval_ms(1000/updateRate_Hz),
_timeout_ms(2 * _updateInterval_ms),
_priority(1000),
_timer(),
_image(grabWidth, grabHeight),
_frameGrabber(new OsxFrameGrabber(display, grabWidth, grabHeight)),
_processor(ImageProcessorFactory::getInstance().newImageProcessor()),
_ledColors(hyperion->getLedCount(), ColorRgb{0,0,0}),
_hyperion(hyperion)
{
// Configure the timer to generate events every n milliseconds
_timer.setInterval(_updateInterval_ms);
_timer.setSingleShot(false);
_processor->setSize(grabWidth, grabHeight);
// Connect the QTimer to this
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(action()));
}
OsxWrapper::~OsxWrapper()
{
// Cleanup used resources (ImageProcessor and FrameGrabber)
delete _processor;
delete _frameGrabber;
}
void OsxWrapper::start()
{
// Start the timer with the pre configured interval
_timer.start();
}
void OsxWrapper::action()
{
// Grab frame into the allocated image
_frameGrabber->grabFrame(_image);
_processor->process(_image, _ledColors);
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
}
void OsxWrapper::stop()
{
// Stop the timer, effectivly stopping the process
_timer.stop();
}
void OsxWrapper::setGrabbingMode(const GrabbingMode mode)
{
switch (mode)
{
case GRABBINGMODE_VIDEO:
case GRABBINGMODE_AUDIO:
case GRABBINGMODE_PHOTO:
case GRABBINGMODE_MENU:
case GRABBINGMODE_INVALID:
start();
break;
case GRABBINGMODE_OFF:
stop();
break;
}
}
void OsxWrapper::setVideoMode(const VideoMode mode)
{
_frameGrabber->setVideoMode(mode);
}

View File

@ -4,10 +4,6 @@
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
// Linux includes
#include <fcntl.h>
#include <sys/ioctl.h>
// hyperion local includes // hyperion local includes
#include "LedDeviceTpm2.h" #include "LedDeviceTpm2.h"

View File

@ -1,7 +1,6 @@
// STL includes // STL includes
#include <cstring> #include <cstring>
#include <cstdio>
#include <iostream> #include <iostream>
// Qt includes // Qt includes

View File

@ -91,6 +91,22 @@ void ImageResampler::processImage(const uint8_t * data, int width, int height, i
yuv2rgb(y, u, v, rgb.red, rgb.green, rgb.blue); yuv2rgb(y, u, v, rgb.red, rgb.green, rgb.blue);
} }
break; break;
case PIXELFORMAT_BGR16:
{
int index = lineLength * ySource + xSource * 2;
rgb.blue = (data[index] & 0x1f) << 3;
rgb.green = (((data[index+1] & 0x7) << 3) | (data[index] & 0xE0) >> 5) << 2;
rgb.red = (data[index+1] & 0xF8);
}
break;
case PIXELFORMAT_BGR24:
{
int index = lineLength * ySource + xSource * 3;
rgb.blue = data[index ];
rgb.green = data[index+1];
rgb.red = data[index+2];
}
break;
case PIXELFORMAT_RGB32: case PIXELFORMAT_RGB32:
{ {
int index = lineLength * ySource + xSource * 4; int index = lineLength * ySource + xSource * 4;

View File

@ -18,6 +18,10 @@ if (ENABLE_FB)
target_link_libraries(hyperiond framebuffer-grabber) target_link_libraries(hyperiond framebuffer-grabber)
endif (ENABLE_FB) endif (ENABLE_FB)
if (ENABLE_OSX)
target_link_libraries(hyperiond osx-grabber)
endif (ENABLE_OSX)
if (ENABLE_V4L2) if (ENABLE_V4L2)
target_link_libraries(hyperiond v4l2-grabber) target_link_libraries(hyperiond v4l2-grabber)
endif (ENABLE_V4L2) endif (ENABLE_V4L2)

View File

@ -31,6 +31,11 @@
#include <grabber/FramebufferWrapper.h> #include <grabber/FramebufferWrapper.h>
#endif #endif
#ifdef ENABLE_OSX
// OSX grabber includes
#include <grabber/OsxWrapper.h>
#endif
// XBMC Video checker includes // XBMC Video checker includes
#include <xbmcvideochecker/XBMCVideoChecker.h> #include <xbmcvideochecker/XBMCVideoChecker.h>
@ -187,7 +192,7 @@ int main(int argc, char** argv)
std::cout << "Frame grabber created and started" << std::endl; std::cout << "Frame grabber created and started" << std::endl;
} }
#else #else
#ifndef ENABLE_FB #if !defined(ENABLE_OSX) && !defined(ENABLE_FB)
if (config.isMember("framegrabber")) if (config.isMember("framegrabber"))
{ {
std::cerr << "The dispmanx framegrabber can not be instantiated, becuse it has been left out from the build" << std::endl; std::cerr << "The dispmanx framegrabber can not be instantiated, becuse it has been left out from the build" << std::endl;
@ -238,7 +243,6 @@ int main(int argc, char** argv)
if (config.isMember("framegrabber")) if (config.isMember("framegrabber"))
{ {
const Json::Value & grabberConfig = config["framegrabber"]; const Json::Value & grabberConfig = config["framegrabber"];
// TODO get device from config
fbGrabber = new FramebufferWrapper( fbGrabber = new FramebufferWrapper(
grabberConfig.get("device", "/dev/fb0").asString(), grabberConfig.get("device", "/dev/fb0").asString(),
grabberConfig["width"].asUInt(), grabberConfig["width"].asUInt(),
@ -256,13 +260,44 @@ int main(int argc, char** argv)
std::cout << "Framebuffer grabber created and started" << std::endl; std::cout << "Framebuffer grabber created and started" << std::endl;
} }
#else #else
#ifndef ENABLE_DISPMANX #if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX)
if (config.isMember("framegrabber")) if (config.isMember("framegrabber"))
{ {
std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl; std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
} }
#endif #endif
#endif #endif
#ifdef ENABLE_OSX
// Construct and start the osx grabber if the configuration is present
OsxWrapper * osxGrabber = nullptr;
if (config.isMember("framegrabber"))
{
const Json::Value & grabberConfig = config["framegrabber"];
osxGrabber = new OsxWrapper(
grabberConfig.get("display", 0).asUInt(),
grabberConfig["width"].asUInt(),
grabberConfig["height"].asUInt(),
grabberConfig["frequency_Hz"].asUInt(),
&hyperion);
if (xbmcVideoChecker != nullptr)
{
QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), osxGrabber, SLOT(setGrabbingMode(GrabbingMode)));
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), osxGrabber, SLOT(setVideoMode(VideoMode)));
}
osxGrabber->start();
std::cout << "OSX grabber created and started" << std::endl;
}
#else
#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_FB)
if (config.isMember("framegrabber"))
{
std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
}
#endif
#endif
// Create Json server if configuration is present // Create Json server if configuration is present
JsonServer * jsonServer = nullptr; JsonServer * jsonServer = nullptr;
@ -304,6 +339,9 @@ int main(int argc, char** argv)
#ifdef ENABLE_FB #ifdef ENABLE_FB
delete fbGrabber; delete fbGrabber;
#endif #endif
#ifdef ENABLE_OSX
delete osxGrabber;
#endif
#ifdef ENABLE_V4L2 #ifdef ENABLE_V4L2
delete v4l2Grabber; delete v4l2Grabber;
#endif #endif