mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
new frame grabber handling (#137)
* - implement framegrabber type option - framegrabber autoselect - integrate x11 grabber in hyperiond * add doxy * v4l: select device by name hyperiond: fix x11 grabber connection to kodichecker config: tune default prios of boblight and v4l * make v4l name finding case insensitive
This commit is contained in:
parent
01ec4a3655
commit
30b9c20611
@ -19,10 +19,10 @@ SET ( HYPERION_VERSION_PATCH 0 )
|
||||
|
||||
SET ( DEFAULT_AMLOGIC OFF )
|
||||
SET ( DEFAULT_DISPMANX OFF )
|
||||
SET ( DEFAULT_FB OFF )
|
||||
SET ( DEFAULT_FB ON )
|
||||
SET ( DEFAULT_OSX OFF )
|
||||
SET ( DEFAULT_X11 OFF )
|
||||
SET ( DEFAULT_SPIDEV OFF )
|
||||
SET ( DEFAULT_SPIDEV ON )
|
||||
SET ( DEFAULT_WS2812BPWM OFF )
|
||||
SET ( DEFAULT_WS281XPWM OFF )
|
||||
SET ( DEFAULT_V4L2 ON )
|
||||
@ -30,8 +30,10 @@ SET ( DEFAULT_USE_SHARED_AVAHI_LIBS OFF )
|
||||
SET ( DEFAULT_TESTS OFF )
|
||||
|
||||
if (APPLE)
|
||||
SET ( DEFAULT_OSX ON )
|
||||
SET ( DEFAULT_V4l2 OFF )
|
||||
SET ( DEFAULT_OSX ON )
|
||||
SET ( DEFAULT_V4l2 OFF )
|
||||
SET ( DEFAULT_SPIDEV OFF )
|
||||
SET ( DEFAULT_FB OFF )
|
||||
else ()
|
||||
if ( NOT DEFINED PLATFORM )
|
||||
if ( "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "x86" )
|
||||
@ -56,24 +58,18 @@ else ()
|
||||
|
||||
if ( "${PLATFORM}" STREQUAL "rpi" )
|
||||
SET ( DEFAULT_DISPMANX ON )
|
||||
SET ( DEFAULT_SPIDEV ON )
|
||||
elseif ( "${PLATFORM}" STREQUAL "rpi-pwm" )
|
||||
SET ( DEFAULT_DISPMANX ON )
|
||||
SET ( DEFAULT_WS2812BPWM ON )
|
||||
SET ( DEFAULT_WS281XPWM ON )
|
||||
SET ( DEFAULT_SPIDEV ON )
|
||||
elseif ( "${PLATFORM}" STREQUAL "wetek" )
|
||||
SET ( DEFAULT_AMLOGIC ON )
|
||||
SET ( DEFAULT_FB ON )
|
||||
elseif ( "${PLATFORM}" STREQUAL "x86" )
|
||||
SET ( DEFAULT_X11 ON )
|
||||
SET ( DEFAULT_FB ON )
|
||||
SET ( DEFAULT_USE_SHARED_AVAHI_LIBS ON )
|
||||
elseif ( "${PLATFORM}" STREQUAL "x86-dev" )
|
||||
SET ( DEFAULT_X11 ON )
|
||||
SET ( DEFAULT_FB ON )
|
||||
SET ( DEFAULT_AMLOGIC ON)
|
||||
SET ( DEFAULT_SPIDEV ON )
|
||||
SET ( DEFAULT_WS281XPWM ON )
|
||||
SET ( DEFAULT_USE_SHARED_AVAHI_LIBS ON )
|
||||
SET ( DEFAULT_TESTS ON )
|
||||
@ -122,18 +118,6 @@ option(ENABLE_PROFILER "enable profiler capabilities - not for release code" OFF
|
||||
message(STATUS "ENABLE_PROFILER = " ${ENABLE_PROFILER})
|
||||
|
||||
|
||||
if(ENABLE_FB AND ENABLE_DISPMANX)
|
||||
message(FATAL_ERROR "dispmanx grabber and framebuffer grabber cannot be used at the same time")
|
||||
endif()
|
||||
|
||||
if(ENABLE_FB AND ENABLE_OSX)
|
||||
message(FATAL_ERROR "osx grabber and framebuffer grabber cannot be used at the same time")
|
||||
endif()
|
||||
|
||||
if(ENABLE_OSX AND ENABLE_DISPMANX)
|
||||
message(FATAL_ERROR "dispmanx grabber and osx grabber cannot be used at the same time")
|
||||
endif()
|
||||
|
||||
SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto )
|
||||
SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto )
|
||||
|
||||
|
@ -27,6 +27,9 @@
|
||||
// Define to enable the osx grabber
|
||||
#cmakedefine ENABLE_OSX
|
||||
|
||||
// Define to enable the x11 grabber
|
||||
#cmakedefine ENABLE_X11
|
||||
|
||||
// Define to enable profiler for development purpose
|
||||
#cmakedefine ENABLE_PROFILER
|
||||
|
||||
|
@ -44,11 +44,11 @@ void setup() {
|
||||
|
||||
// initial RGB flash
|
||||
LEDS.showColor(CRGB(255, 0, 0));
|
||||
delay(500);
|
||||
delay(250);
|
||||
LEDS.showColor(CRGB(0, 255, 0));
|
||||
delay(500);
|
||||
delay(250);
|
||||
LEDS.showColor(CRGB(0, 0, 255));
|
||||
delay(500);
|
||||
delay(250);
|
||||
LEDS.showColor(CRGB(0, 0, 0));
|
||||
|
||||
Serial.begin(serialRate);
|
||||
|
@ -172,7 +172,7 @@
|
||||
"height" : -1,
|
||||
"frameDecimation" : 2,
|
||||
"sizeDecimation" : 8,
|
||||
"priority" : 900,
|
||||
"priority" : 890,
|
||||
"mode" : "2D",
|
||||
"cropLeft" : 0,
|
||||
"cropRight" : 0,
|
||||
@ -185,6 +185,7 @@
|
||||
|
||||
/// The configuration for the frame-grabber, contains the following items:
|
||||
/// * enable : true if the framegrabber (platform grabber) should be activated
|
||||
/// * type : type of grabber. (auto|osx|dispmanx|amlogic|x11|framebuffer) [auto]
|
||||
/// * width : The width of the grabbed frames [pixels]
|
||||
/// * height : The height of the grabbed frames [pixels]
|
||||
/// * frequency_Hz : The frequency of the frame grab [Hz]
|
||||
@ -192,11 +193,29 @@
|
||||
/// * ATTENTION : Power-of-Two resolution is not supported and leads to unexpected behaviour!
|
||||
"framegrabber" :
|
||||
{
|
||||
// for all type of grabbers
|
||||
"enable" : true,
|
||||
"type" : "framebuffer",
|
||||
"frequency_Hz" : 10,
|
||||
"priority" : 890,
|
||||
|
||||
// valid for grabber: osx|dispmanx|amlogic|framebuffer
|
||||
"width" : 96,
|
||||
"height" : 96,
|
||||
"frequency_Hz" : 10.0,
|
||||
"priority" : 890
|
||||
|
||||
// valid for x11
|
||||
"useXGetImage" : false,
|
||||
"horizontalPixelDecimation" : 8,
|
||||
"verticalPixelDecimation" : 8,
|
||||
|
||||
// valid for dispmanx and x11
|
||||
"cropLeft" : 0,
|
||||
"cropRight" : 0,
|
||||
"cropTop" : 0,
|
||||
"cropBottom" : 0,
|
||||
|
||||
// valid for framebuffer
|
||||
"device" : "/dev/fb0"
|
||||
},
|
||||
|
||||
/// The black border configuration, contains the following items:
|
||||
|
@ -102,7 +102,7 @@
|
||||
"height" : -1,
|
||||
"frameDecimation" : 2,
|
||||
"sizeDecimation" : 8,
|
||||
"priority" : 900,
|
||||
"priority" : 890,
|
||||
"mode" : "2D",
|
||||
"cropLeft" : 0,
|
||||
"cropRight" : 0,
|
||||
@ -116,6 +116,7 @@
|
||||
"framegrabber" :
|
||||
{
|
||||
"enable" : true,
|
||||
"type" : "auto",
|
||||
"width" : 96,
|
||||
"height" : 96,
|
||||
"frequency_Hz" : 10.0,
|
||||
|
@ -28,6 +28,26 @@ 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
|
||||
/// _height)
|
||||
///
|
||||
/// @param[out] image The snapped screenshot (should be initialized with correct width and
|
||||
/// height)
|
||||
///
|
||||
int grabFrame(Image<ColorRgb> & image);
|
||||
|
||||
///
|
||||
/// update dimension according current screen
|
||||
int updateScreenDimensions();
|
||||
|
||||
/// gets resulting height of image
|
||||
const unsigned getImageWidth() { return _croppedWidth; };
|
||||
|
||||
/// gets resulting width of image
|
||||
const unsigned getImageHeight() { return _croppedHeight; };
|
||||
|
||||
private:
|
||||
ImageResampler _imageResampler;
|
||||
@ -63,7 +83,6 @@ private:
|
||||
void freeResources();
|
||||
void setupResources();
|
||||
|
||||
int updateScreenDimensions();
|
||||
|
||||
Logger * _log;
|
||||
};
|
||||
|
100
include/grabber/X11Wrapper.h
Normal file
100
include/grabber/X11Wrapper.h
Normal file
@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
// QT includes
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
// Utils includes
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
#include <utils/GrabbingMode.h>
|
||||
#include <utils/VideoMode.h>
|
||||
|
||||
// Forward class declaration
|
||||
class X11Grabber;
|
||||
class Hyperion;
|
||||
class ImageProcessor;
|
||||
|
||||
///
|
||||
/// The X11Wrapper uses an instance of the X11Grabber 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 X11Wrapper: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
///
|
||||
/// Constructs the framebuffer frame grabber with a specified grab size and update rate.
|
||||
///
|
||||
/// @param[in] device X11 device name/path
|
||||
/// @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]
|
||||
///
|
||||
X11Wrapper(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation, const unsigned updateRate_Hz, const int priority);
|
||||
|
||||
///
|
||||
/// Destructor of this framebuffer frame grabber. Releases any claimed resources.
|
||||
///
|
||||
virtual ~X11Wrapper();
|
||||
|
||||
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);
|
||||
|
||||
signals:
|
||||
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
|
||||
|
||||
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
|
||||
X11Grabber * _grabber;
|
||||
/// 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;
|
||||
|
||||
bool _init;
|
||||
bool _x11SetupSuccess;
|
||||
};
|
||||
|
@ -80,11 +80,24 @@ bool V4L2Grabber::init()
|
||||
if (! _initialized)
|
||||
{
|
||||
getV4Ldevices();
|
||||
if ( _deviceName == "auto" )
|
||||
std::string v4lDevices_str;
|
||||
|
||||
// show list only once
|
||||
if ( ! QString(_deviceName.c_str()).startsWith("/dev/") )
|
||||
{
|
||||
for (auto& dev: _v4lDevices)
|
||||
{
|
||||
Debug(_log, "check v4l2 device: %s (%s)",dev.first.c_str(), dev.second.c_str());
|
||||
v4lDevices_str += "\t"+ dev.first + "\t" + dev.second + "\n";
|
||||
}
|
||||
Info(_log, "available V4L2 devices:\n%s", v4lDevices_str.c_str());
|
||||
}
|
||||
|
||||
if ( _deviceName == "auto" )
|
||||
{
|
||||
_deviceName = "unknown";
|
||||
for (auto& dev: _v4lDevices)
|
||||
{
|
||||
//Debug(_log, "check v4l2 device: %s (%s)",dev.first.c_str(), dev.second.c_str());
|
||||
_deviceName = dev.first;
|
||||
if ( init() )
|
||||
{
|
||||
@ -93,6 +106,18 @@ bool V4L2Grabber::init()
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( ! QString(_deviceName.c_str()).startsWith("/dev/") )
|
||||
{
|
||||
for (auto& dev: _v4lDevices)
|
||||
{
|
||||
if ( QString(_deviceName.c_str()).toLower() == QString(dev.second.c_str()).toLower() )
|
||||
{
|
||||
_deviceName = dev.first;
|
||||
Info(_log, "found v4l2 device with configured name: %s (%s)", dev.second.c_str(), dev.first.c_str() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Info(_log, "configured v4l device: %s", _deviceName.c_str());
|
||||
|
@ -9,6 +9,9 @@ include_directories(
|
||||
${QT_INCLUDES}
|
||||
${X11_INCLUDES}
|
||||
)
|
||||
SET(X11_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/X11Wrapper.h
|
||||
)
|
||||
|
||||
SET(X11_HEADERS
|
||||
${CURRENT_HEADER_DIR}/X11Grabber.h
|
||||
@ -16,6 +19,7 @@ SET(X11_HEADERS
|
||||
|
||||
SET(X11_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/X11Grabber.cpp
|
||||
${CURRENT_SOURCE_DIR}/X11Wrapper.cpp
|
||||
)
|
||||
|
||||
QT5_WRAP_CPP(X11_HEADERS_MOC ${X11_QT_HEADERS})
|
||||
@ -29,5 +33,7 @@ add_library(x11-grabber
|
||||
|
||||
target_link_libraries(x11-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES}
|
||||
${X11_LIBRARIES}
|
||||
${X11_Xrender_LIB}
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
@ -162,6 +162,49 @@ Image<ColorRgb> & X11Grabber::grab()
|
||||
return _image;
|
||||
}
|
||||
|
||||
int X11Grabber::grabFrame(Image<ColorRgb> & image)
|
||||
{
|
||||
if (_XRenderAvailable && !_useXGetImage) {
|
||||
XRenderComposite( _x11Display, // *dpy,
|
||||
PictOpSrc, // op,
|
||||
_srcPicture, // src
|
||||
None, // mask
|
||||
_dstPicture, // dst
|
||||
_cropLeft, // src_x
|
||||
_cropTop, // src_y
|
||||
0, // mask_x
|
||||
0, // mask_y
|
||||
0, // dst_x
|
||||
0, // dst_y
|
||||
_croppedWidth, // width
|
||||
_croppedHeight); // height
|
||||
|
||||
XSync(_x11Display, False);
|
||||
|
||||
if (_XShmAvailable) {
|
||||
XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes);
|
||||
} else {
|
||||
_xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap);
|
||||
}
|
||||
} else {
|
||||
if (_XShmAvailable && !_useXGetImage) {
|
||||
XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes);
|
||||
} else {
|
||||
_xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap);
|
||||
}
|
||||
}
|
||||
|
||||
if (_xImage == nullptr)
|
||||
{
|
||||
Error(_log, "Grab Failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
_imageResampler.processImage(reinterpret_cast<const uint8_t *>(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, image);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int X11Grabber::updateScreenDimensions()
|
||||
{
|
||||
const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr);
|
||||
@ -176,18 +219,15 @@ int X11Grabber::updateScreenDimensions()
|
||||
// No update required
|
||||
return 0;
|
||||
}
|
||||
|
||||
Info(_log, "Update of screen resolution: [%dx%d]", _screenWidth, _screenHeight);
|
||||
|
||||
if (_screenWidth || _screenHeight) {
|
||||
freeResources();
|
||||
}
|
||||
|
||||
Info(_log, "Update of screen resolution: [%dx%d] to [%dx%d]", _screenWidth, _screenHeight, _windowAttr.width, _windowAttr.height);
|
||||
_screenWidth = _windowAttr.width;
|
||||
_screenHeight = _windowAttr.height;
|
||||
|
||||
Info(_log, " to [%dx%d]", _screenWidth, _screenHeight);
|
||||
|
||||
_croppedWidth = (_screenWidth > unsigned(_cropLeft + _cropRight))
|
||||
? (_screenWidth - _cropLeft - _cropRight)
|
||||
: _screenWidth;
|
||||
@ -204,5 +244,5 @@ int X11Grabber::updateScreenDimensions()
|
||||
|
||||
setupResources();
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
111
libsrc/grabber/x11/X11Wrapper.cpp
Normal file
111
libsrc/grabber/x11/X11Wrapper.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
// 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)
|
||||
: _updateInterval_ms(1000/updateRate_Hz)
|
||||
, _timeout_ms(2 * _updateInterval_ms)
|
||||
, _priority(priority)
|
||||
, _timer()
|
||||
// , _image(grabWidth, grabHeight)
|
||||
, _grabber(new X11Grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation))
|
||||
, _processor(ImageProcessorFactory::getInstance().newImageProcessor())
|
||||
, _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb{0,0,0})
|
||||
, _hyperion(Hyperion::getInstance())
|
||||
, _init(false)
|
||||
, _x11SetupSuccess(false)
|
||||
{
|
||||
// Configure the timer to generate events every n milliseconds
|
||||
_timer.setInterval(_updateInterval_ms);
|
||||
_timer.setSingleShot(false);
|
||||
|
||||
// Connect the QTimer to this
|
||||
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(action()));
|
||||
}
|
||||
|
||||
X11Wrapper::~X11Wrapper()
|
||||
{
|
||||
// Cleanup used resources (ImageProcessor and FrameGrabber)
|
||||
delete _processor;
|
||||
delete _grabber;
|
||||
}
|
||||
|
||||
void X11Wrapper::start()
|
||||
{
|
||||
if (! _init )
|
||||
{
|
||||
_init = true;
|
||||
_x11SetupSuccess = _grabber->Setup();
|
||||
if ( _x11SetupSuccess )
|
||||
{
|
||||
_x11SetupSuccess = (_grabber->updateScreenDimensions() >= 0);
|
||||
_processor->setSize(_grabber->getImageWidth(), _grabber->getImageHeight());
|
||||
_image.resize(_grabber->getImageWidth(), _grabber->getImageHeight());
|
||||
}
|
||||
}
|
||||
// Start the timer with the pre configured interval
|
||||
if ( _x11SetupSuccess )
|
||||
{
|
||||
_timer.start();
|
||||
_hyperion->registerPriority("X11 Grabber", _priority);
|
||||
}
|
||||
|
||||
ErrorIf( ! _x11SetupSuccess, Logger::getInstance("X11"), "X11 Grabber start failed");
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
|
||||
}
|
||||
void X11Wrapper::stop()
|
||||
{
|
||||
// Stop the timer, effectivly stopping the process
|
||||
_timer.stop();
|
||||
_hyperion->unRegisterPriority("X11 Grabber");
|
||||
}
|
||||
|
||||
void X11Wrapper::setGrabbingMode(const GrabbingMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case GRABBINGMODE_VIDEO:
|
||||
case GRABBINGMODE_PAUSE:
|
||||
case GRABBINGMODE_AUDIO:
|
||||
case GRABBINGMODE_PHOTO:
|
||||
case GRABBINGMODE_MENU:
|
||||
case GRABBINGMODE_SCREENSAVER:
|
||||
case GRABBINGMODE_INVALID:
|
||||
start();
|
||||
break;
|
||||
case GRABBINGMODE_OFF:
|
||||
stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void X11Wrapper::setVideoMode(const VideoMode mode)
|
||||
{
|
||||
_grabber->setVideoMode(mode);
|
||||
}
|
@ -499,15 +499,20 @@
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"type" :
|
||||
{
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"width" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
"required" : false
|
||||
},
|
||||
"height" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"required" : true
|
||||
"required" : false
|
||||
},
|
||||
"frequency_Hz" :
|
||||
{
|
||||
@ -520,7 +525,7 @@
|
||||
"required" : true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
"additionalProperties" : true
|
||||
},
|
||||
"blackborderdetector" :
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
|
||||
device = new LedDeviceAdalight(
|
||||
deviceConfig["output"].asString(),
|
||||
deviceConfig["rate"].asInt(),
|
||||
deviceConfig.get("delayAfterConnect",1000).asInt()
|
||||
deviceConfig.get("delayAfterConnect",500).asInt()
|
||||
);
|
||||
}
|
||||
else if (type == "adalightapa102")
|
||||
@ -76,7 +76,7 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
|
||||
device = new LedDeviceAdalightApa102(
|
||||
deviceConfig["output"].asString(),
|
||||
deviceConfig["rate"].asInt(),
|
||||
deviceConfig.get("delayAfterConnect",1000).asInt()
|
||||
deviceConfig.get("delayAfterConnect",500).asInt()
|
||||
);
|
||||
}
|
||||
#ifdef ENABLE_SPIDEV
|
||||
|
@ -35,6 +35,10 @@ if (ENABLE_AMLOGIC)
|
||||
target_link_libraries(hyperiond amlogic-grabber)
|
||||
endif ()
|
||||
|
||||
if (ENABLE_X11)
|
||||
target_link_libraries(hyperiond x11-grabber )
|
||||
endif ()
|
||||
|
||||
install ( TARGETS hyperiond DESTINATION "bin" COMPONENT ambilight )
|
||||
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/effects DESTINATION "share/hyperion/" COMPONENT ambilight )
|
||||
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" COMPONENT ambilight )
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <unistd.h>
|
||||
#include <cassert>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QResource>
|
||||
@ -36,6 +37,7 @@ HyperionDaemon::HyperionDaemon(std::string configFile, QObject *parent)
|
||||
, _udpListener(nullptr)
|
||||
, _v4l2Grabber(nullptr)
|
||||
, _dispmanx(nullptr)
|
||||
, _x11Grabber(nullptr)
|
||||
, _amlGrabber(nullptr)
|
||||
, _fbGrabber(nullptr)
|
||||
, _osxGrabber(nullptr)
|
||||
@ -92,9 +94,7 @@ void HyperionDaemon::run()
|
||||
|
||||
// ---- grabber -----
|
||||
createGrabberV4L2();
|
||||
createGrabberDispmanx();
|
||||
createGrabberAmlogic();
|
||||
createGrabberFramebuffer();
|
||||
createSystemFrameGrabber();
|
||||
|
||||
#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) && !defined(ENABLE_FB)
|
||||
ErrorIf(_config.isMember("framegrabber"), _log, "No grabber can be instantiated, because all grabbers have been left out from the build");
|
||||
@ -255,7 +255,7 @@ void HyperionDaemon::startNetworkServices()
|
||||
{
|
||||
const Json::Value & boblightServerConfig = _config["boblightServer"];
|
||||
_boblightServer = new BoblightServer(
|
||||
boblightServerConfig.get("priority",900).asInt(),
|
||||
boblightServerConfig.get("priority",899).asInt(),
|
||||
boblightServerConfig["port"].asUInt()
|
||||
);
|
||||
Debug(_log, "Boblight server created");
|
||||
@ -319,40 +319,186 @@ void HyperionDaemon::startNetworkServices()
|
||||
Debug(_log, "Proto mDNS responder started");
|
||||
}
|
||||
|
||||
void HyperionDaemon::createGrabberDispmanx()
|
||||
|
||||
void HyperionDaemon::createSystemFrameGrabber()
|
||||
{
|
||||
if (_config.isMember("framegrabber"))
|
||||
{
|
||||
const Json::Value & grabberConfig = _config["framegrabber"];
|
||||
if (grabberConfig.get("enable", true).asBool())
|
||||
{
|
||||
#ifdef ENABLE_OSX
|
||||
std::string type = "osx";
|
||||
#else
|
||||
std::string type = grabberConfig.get("type", "auto").asString();
|
||||
#endif
|
||||
|
||||
QFile amvideo("/dev/amvideo");
|
||||
// auto eval of type
|
||||
if ( type == "auto" )
|
||||
{
|
||||
// dispmanx -> on raspi
|
||||
// TODO currently a compile option
|
||||
#ifdef ENABLE_DISPMANX
|
||||
if (true)
|
||||
#else
|
||||
if (false)
|
||||
#endif
|
||||
{
|
||||
type = "dispmanx";
|
||||
}
|
||||
// amlogic -> /dev/amvideo exists
|
||||
else if ( amvideo.exists() )
|
||||
{
|
||||
type = "amlogic";
|
||||
}
|
||||
// x11 -> if DISPLAY is set
|
||||
else if (getenv("DISPLAY") != NULL )
|
||||
{
|
||||
type = "x11";
|
||||
}
|
||||
// framebuffer -> if nothing other applies
|
||||
else
|
||||
{
|
||||
type == "framebuffer";
|
||||
}
|
||||
InfoIf( type != "auto", _log, "set screen capture device to '%s'", type.c_str());
|
||||
}
|
||||
|
||||
if (type == "framebuffer") createGrabberFramebuffer(grabberConfig);
|
||||
else if (type == "dispmanx") createGrabberDispmanx(grabberConfig);
|
||||
else if (type == "amlogic") createGrabberAmlogic(grabberConfig);
|
||||
else if (type == "osx") createGrabberOsx(grabberConfig);
|
||||
else if (type == "x11") createGrabberX11(grabberConfig);
|
||||
else WarningIf( type != "", _log, "unknown framegrabber type '%s'", type.c_str());
|
||||
InfoIf( type == "", _log, "screen capture device disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HyperionDaemon::createGrabberDispmanx(const Json::Value & grabberConfig)
|
||||
{
|
||||
#ifdef ENABLE_DISPMANX
|
||||
// Construct and start the dispmanx grabber if the configuration is present
|
||||
if (_config.isMember("framegrabber"))
|
||||
{
|
||||
const Json::Value & frameGrabberConfig = _config["framegrabber"];
|
||||
if (frameGrabberConfig.get("enable", true).asBool())
|
||||
{
|
||||
_dispmanx = new DispmanxWrapper(
|
||||
frameGrabberConfig["width"].asUInt(),
|
||||
frameGrabberConfig["height"].asUInt(),
|
||||
frameGrabberConfig["frequency_Hz"].asUInt(),
|
||||
frameGrabberConfig.get("priority",900).asInt());
|
||||
_dispmanx->setCropping(
|
||||
frameGrabberConfig.get("cropLeft", 0).asInt(),
|
||||
frameGrabberConfig.get("cropRight", 0).asInt(),
|
||||
frameGrabberConfig.get("cropTop", 0).asInt(),
|
||||
frameGrabberConfig.get("cropBottom", 0).asInt());
|
||||
_dispmanx = new DispmanxWrapper(
|
||||
grabberConfig["width"].asUInt(),
|
||||
grabberConfig["height"].asUInt(),
|
||||
grabberConfig.get("frequency_Hz",10).asUInt(),
|
||||
grabberConfig.get("priority",900).asInt());
|
||||
_dispmanx->setCropping(
|
||||
grabberConfig.get("cropLeft", 0).asInt(),
|
||||
grabberConfig.get("cropRight", 0).asInt(),
|
||||
grabberConfig.get("cropTop", 0).asInt(),
|
||||
grabberConfig.get("cropBottom", 0).asInt());
|
||||
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _dispmanx, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(videoMode(VideoMode)), _dispmanx, SLOT(setVideoMode(VideoMode)));
|
||||
QObject::connect(_dispmanx, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _dispmanx, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(videoMode(VideoMode)), _dispmanx, SLOT(setVideoMode(VideoMode)));
|
||||
QObject::connect(_dispmanx, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
|
||||
_dispmanx->start();
|
||||
Info(_log, "DISPMANX frame grabber created and started");
|
||||
}
|
||||
}
|
||||
_dispmanx->start();
|
||||
Info(_log, "DISPMANX frame grabber created and started");
|
||||
#else
|
||||
ErrorIf(_config.isMember("framegrabber"), _log, "The dispmanx framegrabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void HyperionDaemon::createGrabberAmlogic(const Json::Value & grabberConfig)
|
||||
{
|
||||
#ifdef ENABLE_AMLOGIC
|
||||
// Construct and start the amlogic grabber if the configuration is present
|
||||
_amlGrabber = new AmlogicWrapper(
|
||||
grabberConfig["width"].asUInt(),
|
||||
grabberConfig["height"].asUInt(),
|
||||
grabberConfig.get("frequency_Hz",10).asUInt(),
|
||||
grabberConfig.get("priority",900).asInt());
|
||||
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _amlGrabber, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(videoMode(VideoMode)), _amlGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
QObject::connect(_amlGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
|
||||
_amlGrabber->start();
|
||||
Info(_log, "AMLOGIC grabber created and started");
|
||||
#else
|
||||
Error( _log, "The AMLOGIC grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
void HyperionDaemon::createGrabberX11(const Json::Value & grabberConfig)
|
||||
{
|
||||
#ifdef ENABLE_X11
|
||||
// Construct and start the amlogic grabber if the configuration is present
|
||||
_x11Grabber = new X11Wrapper(
|
||||
grabberConfig.get("useXGetImage",false).asBool(),
|
||||
grabberConfig.get("cropLeft", 0).asInt(),
|
||||
grabberConfig.get("cropRight", 0).asInt(),
|
||||
grabberConfig.get("cropTop", 0).asInt(),
|
||||
grabberConfig.get("cropBottom", 0).asInt(),
|
||||
grabberConfig.get("horizontalPixelDecimation", 8).asInt(),
|
||||
grabberConfig.get("verticalPixelDecimation", 8).asInt(),
|
||||
grabberConfig.get("frequency_Hz",10).asUInt(),
|
||||
grabberConfig.get("priority",900).asInt()
|
||||
);
|
||||
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _x11Grabber, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(videoMode(VideoMode)), _x11Grabber, SLOT(setVideoMode(VideoMode)));
|
||||
QObject::connect(_x11Grabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
|
||||
_x11Grabber->start();
|
||||
Info(_log, "X11 grabber created and started");
|
||||
#else
|
||||
Error(_log, "The X11 grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void HyperionDaemon::createGrabberFramebuffer(const Json::Value & grabberConfig)
|
||||
{
|
||||
#ifdef ENABLE_FB
|
||||
// Construct and start the framebuffer grabber if the configuration is present
|
||||
_fbGrabber = new FramebufferWrapper(
|
||||
grabberConfig.get("device", "/dev/fb0").asString(),
|
||||
grabberConfig["width"].asUInt(),
|
||||
grabberConfig["height"].asUInt(),
|
||||
grabberConfig.get("frequency_Hz",10).asUInt(),
|
||||
grabberConfig.get("priority",900).asInt());
|
||||
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _fbGrabber, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(videoMode(VideoMode)), _fbGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
QObject::connect(_fbGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
|
||||
_fbGrabber->start();
|
||||
Info(_log, "Framebuffer grabber created and started");
|
||||
#else
|
||||
Error(_log, "The framebuffer grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void HyperionDaemon::createGrabberOsx(const Json::Value & grabberConfig)
|
||||
{
|
||||
#ifdef ENABLE_OSX
|
||||
// Construct and start the osx grabber if the configuration is present
|
||||
_osxGrabber = new OsxWrapper(
|
||||
grabberConfig.get("display", 0).asUInt(),
|
||||
grabberConfig["width"].asUInt(),
|
||||
grabberConfig["height"].asUInt(),
|
||||
grabberConfig.get("frequency_Hz",10).asUInt(),
|
||||
grabberConfig.get("priority",900).asInt());
|
||||
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _osxGrabber, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(videoMode(VideoMode)), _osxGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
QObject::connect(_osxGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
|
||||
_osxGrabber->start();
|
||||
Info(_log, "OSX grabber created and started");
|
||||
#else
|
||||
Error(_log, "The osx grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void HyperionDaemon::createGrabberV4L2()
|
||||
{
|
||||
// construct and start the v4l2 grabber if the configuration is present
|
||||
@ -372,7 +518,7 @@ void HyperionDaemon::createGrabberV4L2()
|
||||
grabberConfig.get("redSignalThreshold", 0.0).asDouble(),
|
||||
grabberConfig.get("greenSignalThreshold", 0.0).asDouble(),
|
||||
grabberConfig.get("blueSignalThreshold", 0.0).asDouble(),
|
||||
grabberConfig.get("priority", 900).asInt());
|
||||
grabberConfig.get("priority", 890).asInt());
|
||||
_v4l2Grabber->set3D(parse3DMode(grabberConfig.get("mode", "2D").asString()));
|
||||
_v4l2Grabber->setCropping(
|
||||
grabberConfig.get("cropLeft", 0).asInt(),
|
||||
@ -391,91 +537,3 @@ void HyperionDaemon::createGrabberV4L2()
|
||||
ErrorIf(_config.isMember("grabber-v4l2"), _log, "The v4l2 grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
void HyperionDaemon::createGrabberAmlogic()
|
||||
{
|
||||
#ifdef ENABLE_AMLOGIC
|
||||
// Construct and start the amlogic grabber if the configuration is present
|
||||
if (_config.isMember("amlgrabber"))
|
||||
{
|
||||
const Json::Value & grabberConfig = _config["amlgrabber"];
|
||||
if (grabberConfig.get("enable", true).asBool())
|
||||
{
|
||||
_amlGrabber = new AmlogicWrapper(
|
||||
grabberConfig["width"].asUInt(),
|
||||
grabberConfig["height"].asUInt(),
|
||||
grabberConfig["frequency_Hz"].asUInt(),
|
||||
grabberConfig.get("priority",900).asInt());
|
||||
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _amlGrabber, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(videoMode(VideoMode)), _amlGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
QObject::connect(_amlGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
|
||||
_amlGrabber->start();
|
||||
Info(_log, "AMLOGIC grabber created and started");
|
||||
}
|
||||
}
|
||||
#else
|
||||
ErrorIf(_config.isMember("amlgrabber"), _log, "The AMLOGIC grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void HyperionDaemon::createGrabberFramebuffer()
|
||||
{
|
||||
#ifdef ENABLE_FB
|
||||
// Construct and start the framebuffer grabber if the configuration is present
|
||||
if (_config.isMember("framebuffergrabber"))
|
||||
{
|
||||
const Json::Value & grabberConfig = _config["framebuffergrabber"];
|
||||
if (grabberConfig.get("enable", true).asBool())
|
||||
{
|
||||
_fbGrabber = new FramebufferWrapper(
|
||||
grabberConfig.get("device", "/dev/fb0").asString(),
|
||||
grabberConfig["width"].asUInt(),
|
||||
grabberConfig["height"].asUInt(),
|
||||
grabberConfig["frequency_Hz"].asUInt(),
|
||||
grabberConfig.get("priority",900).asInt());
|
||||
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _fbGrabber, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(videoMode(VideoMode)), _fbGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
QObject::connect(_fbGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
|
||||
_fbGrabber->start();
|
||||
Info(_log, "Framebuffer grabber created and started");
|
||||
}
|
||||
}
|
||||
#else
|
||||
ErrorIf(_config.isMember("framebuffergrabber"), _log, "The framebuffer grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void HyperionDaemon::createGrabberOsx()
|
||||
{
|
||||
#ifdef ENABLE_OSX
|
||||
// Construct and start the osx grabber if the configuration is present
|
||||
if (_config.isMember("osxgrabber"))
|
||||
{
|
||||
const Json::Value & grabberConfig = _config["osxgrabber"];
|
||||
if (grabberConfig.get("enable", true).asBool())
|
||||
{
|
||||
_osxGrabber = new OsxWrapper(
|
||||
grabberConfig.get("display", 0).asUInt(),
|
||||
grabberConfig["width"].asUInt(),
|
||||
grabberConfig["height"].asUInt(),
|
||||
grabberConfig["frequency_Hz"].asUInt(),
|
||||
grabberConfig.get("priority",900).asInt());
|
||||
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), _osxGrabber, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
QObject::connect(_kodiVideoChecker, SIGNAL(videoMode(VideoMode)), _osxGrabber, SLOT(setVideoMode(VideoMode)));
|
||||
QObject::connect(_osxGrabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)) );
|
||||
|
||||
_osxGrabber->start();
|
||||
Info(_log, "OSX grabber created and started");
|
||||
}
|
||||
}
|
||||
#else
|
||||
ErrorIf(_config.isMember("osxgrabber"), _log, "The osx grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
@ -32,6 +32,12 @@
|
||||
typedef QObject OsxWrapper;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_X11
|
||||
#include <grabber/X11Wrapper.h>
|
||||
#else
|
||||
typedef QObject X11Wrapper;
|
||||
#endif
|
||||
|
||||
#include <utils/Logger.h>
|
||||
|
||||
#include <kodivideochecker/KODIVideoChecker.h>
|
||||
@ -55,13 +61,16 @@ public:
|
||||
void startNetworkServices();
|
||||
|
||||
// grabber creators
|
||||
void createGrabberDispmanx();
|
||||
void createGrabberV4L2();
|
||||
void createGrabberAmlogic();
|
||||
void createGrabberFramebuffer();
|
||||
void createGrabberOsx();
|
||||
void createSystemFrameGrabber();
|
||||
|
||||
private:
|
||||
void createGrabberDispmanx(const Json::Value & grabberConfig);
|
||||
void createGrabberAmlogic(const Json::Value & grabberConfig);
|
||||
void createGrabberFramebuffer(const Json::Value & grabberConfig);
|
||||
void createGrabberOsx(const Json::Value & grabberConfig);
|
||||
void createGrabberX11(const Json::Value & grabberConfig);
|
||||
|
||||
Logger* _log;
|
||||
Json::Value _config;
|
||||
KODIVideoChecker* _kodiVideoChecker;
|
||||
@ -71,6 +80,7 @@ private:
|
||||
UDPListener* _udpListener;
|
||||
V4L2Wrapper* _v4l2Grabber;
|
||||
DispmanxWrapper* _dispmanx;
|
||||
X11Wrapper* _x11Grabber;
|
||||
AmlogicWrapper* _amlGrabber;
|
||||
FramebufferWrapper* _fbGrabber;
|
||||
OsxWrapper* _osxGrabber;
|
||||
|
Loading…
Reference in New Issue
Block a user