Merge remote-tracking branch 'origin/grabberDiscovery' into mediafoundation

This commit is contained in:
Paulchen Panther
2021-04-04 12:43:29 +02:00
committed by LordGrey
187 changed files with 3716 additions and 15430 deletions

View File

@@ -54,6 +54,11 @@ public:
///
virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom);
///
/// @brief Apply display index
///
void setDisplayIndex(int index) override;
private:
///
/// @brief Setup a new capture display, will free the previous one
@@ -68,6 +73,7 @@ private:
private:
int _pixelDecimation;
unsigned _display;
unsigned _displayWidth;
unsigned _displayHeight;
RECT* _srcRect;

View File

@@ -11,6 +11,9 @@
#include <QRectF>
#include <QMap>
#include <QMultiMap>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
// utils includes
#include <utils/PixelFormat.h>
@@ -38,7 +41,6 @@ class MFGrabber : public Grabber
{
Q_OBJECT
friend class SourceReaderCB;
public:
struct DeviceProperties
{
@@ -52,79 +54,72 @@ public:
GUID guid = GUID_NULL;
};
MFGrabber(const QString & device, const unsigned width, const unsigned height, const unsigned fps, int pixelDecimation, QString flipMode);
MFGrabber();
~MFGrabber() override;
void receive_image(const void *frameImageBuffer, int size);
QRectF getSignalDetectionOffset() const { return QRectF(_x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max); }
bool getSignalDetectionEnabled() const { return _signalDetectionEnabled; }
bool getCecDetectionEnabled() const { return _cecDetectionEnabled; }
QStringList getDevices() const override;
QString getDeviceName(const QString& devicePath) const override { return devicePath; }
QMultiMap<QString, int> getDeviceInputs(const QString& devicePath) const override { return { {devicePath, 0} }; }
QStringList getAvailableEncodingFormats(const QString& devicePath, const int& /*deviceInput*/) const override;
QMultiMap<int, int> getAvailableDeviceResolutions(const QString& devicePath, const int& /*deviceInput*/, const PixelFormat& encFormat) const override;
QIntList getAvailableDeviceFramerates(const QString& devicePath, const int& /*deviceInput*/, const PixelFormat& encFormat, const unsigned width, const unsigned height) const override;
void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold) override;
void setSignalDetectionOffset( double verticalMin, double horizontalMin, double verticalMax, double horizontalMax) override;
void setSignalDetectionEnable(bool enable) override;
void setPixelDecimation(int pixelDecimation) override;
void setCecDetectionEnable(bool enable) override;
bool setDevice(QString device) override;
void setDevice(const QString& device);
bool setInput(int input) override;
bool setWidthHeight(int width, int height) override;
bool setFramerate(int fps) override;
void setFpsSoftwareDecimation(int decimation);
bool setEncoding(QString enc);
void setFlipMode(QString flipMode);
bool setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue);
void setEncoding(QString enc);
void setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue);
void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold);
void setSignalDetectionOffset( double verticalMin, double horizontalMin, double verticalMax, double horizontalMax);
void setSignalDetectionEnable(bool enable);
bool reload(bool force = false);
void reloadGrabber();
///
/// @brief Discover available Media Foundation USB devices (for configuration).
/// @param[in] params Parameters used to overwrite discovery default behaviour
/// @return A JSON structure holding a list of USB devices found
///
QJsonArray discover(const QJsonObject& params);
public slots:
bool prepare();
bool start();
void stop();
void newThreadFrame(unsigned int _workerIndex, const Image<ColorRgb>& image,unsigned int sourceCount);
void newThreadFrame(Image<ColorRgb> image);
signals:
void newFrame(const Image<ColorRgb> & image);
void readError(const char* err);
private:
bool init();
void uninit();
HRESULT init_device(QString device, DeviceProperties props);
void uninit_device();
void enumVideoCaptureDevices();
void start_capturing();
void process_image(const void *frameImageBuffer, int size);
void checkSignalDetectionEnabled(Image<ColorRgb> image);
QString _currentDeviceName, _newDeviceName;
QString _currentDeviceName,
_newDeviceName;
QMap<QString, QList<DeviceProperties>> _deviceProperties;
HRESULT _hr;
IMFSourceReader* _sourceReader;
SourceReaderCB* _sourceReaderCB;
PixelFormat _pixelFormat, _pixelFormatConfig;
int _pixelDecimation,
_lineLength,
MFThreadManager* _threadManager;
PixelFormat _pixelFormat,
_pixelFormatConfig;
int _lineLength,
_frameByteSize,
_noSignalCounterThreshold,
_noSignalCounter,
_fpsSoftwareDecimation,
_brightness,
_contrast,
_saturation,
_hue;
volatile unsigned int _currentFrame;
QAtomicInt _currentFrame;
ColorRgb _noSignalThresholdColor;
bool _signalDetectionEnabled,
_cecDetectionEnabled,
_noSignalDetected,
_initialized;
_initialized,
_reload;
double _x_frac_min,
_y_frac_min,
_x_frac_max,
_y_frac_max;
MFThreadManager _threadManager;
IMFSourceReader* _sourceReader;
#ifdef HAVE_TURBO_JPEG
int _subsamp;

View File

@@ -2,7 +2,6 @@
// Qt includes
#include <QThread>
#include <QSemaphore>
// util includes
#include <utils/PixelFormat.h>
@@ -15,31 +14,27 @@
#include <turbojpeg.h>
#endif
// Forward class declaration
class MFThreadManager;
/// Encoder thread for USB devices
class MFThread : public QThread
class MFThread : public QObject
{
Q_OBJECT
friend class MFThreadManager;
public:
MFThread();
explicit MFThread();
~MFThread();
void setup(
unsigned int threadIndex, PixelFormat pixelFormat, uint8_t* sharedData,
PixelFormat pixelFormat, uint8_t* sharedData,
int size, int width, int height, int lineLength,
int subsamp, unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight,
VideoMode videoMode, FlipMode flipMode, int currentFrame, int pixelDecimation);
void run();
VideoMode videoMode, FlipMode flipMode, int pixelDecimation);
bool isBusy();
void noBusy();
void process();
bool isBusy() { return _busy; }
QAtomicInt _busy = false;
signals:
void newFrame(unsigned int threadIndex, const Image<ColorRgb>& data, unsigned int sourceCount);
void newFrame(const Image<ColorRgb>& data);
private:
void processImageMjpeg();
@@ -51,73 +46,132 @@ private:
tjtransform* _xform;
#endif
static volatile bool _isActive;
volatile bool _isBusy;
QSemaphore _semaphore;
unsigned int _threadIndex;
PixelFormat _pixelFormat;
uint8_t* _localData, *_flipBuffer;
int _scalingFactorsCount, _width, _height, _lineLength, _subsamp, _currentFrame, _pixelDecimation;
unsigned long _size;
unsigned _cropLeft, _cropTop, _cropBottom, _cropRight;
FlipMode _flipMode;
ImageResampler _imageResampler;
PixelFormat _pixelFormat;
uint8_t* _localData,
*_flipBuffer;
int _scalingFactorsCount,
_width,
_height,
_lineLength,
_subsamp,
_currentFrame,
_pixelDecimation;
unsigned long _size;
unsigned _cropLeft,
_cropTop,
_cropBottom,
_cropRight;
FlipMode _flipMode;
ImageResampler _imageResampler;
};
template <typename TThread> class Thread : public QThread
{
public:
TThread *_thread;
explicit Thread(TThread *thread, QObject *parent = nullptr)
: QThread(parent)
, _thread(thread)
{
_thread->moveToThread(this);
start();
}
~Thread()
{
quit();
wait();
}
MFThread* thread() const { return qobject_cast<MFThread*>(_thread); }
void setup(
PixelFormat pixelFormat, uint8_t* sharedData,
int size, int width, int height, int lineLength,
int subsamp, unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight,
VideoMode videoMode, FlipMode flipMode, int pixelDecimation)
{
auto mfthread = qobject_cast<MFThread*>(_thread);
if (mfthread != nullptr)
mfthread->setup(pixelFormat, sharedData,
size, width, height, lineLength,
subsamp, cropLeft, cropTop, cropBottom, cropRight,
videoMode, flipMode, pixelDecimation);
}
bool isBusy()
{
auto mfthread = qobject_cast<MFThread*>(_thread);
if (mfthread != nullptr)
return mfthread->isBusy();
return true;
}
void process()
{
auto mfthread = qobject_cast<MFThread*>(_thread);
if (mfthread != nullptr)
mfthread->process();
}
protected:
void run() override
{
QThread::run();
delete _thread;
}
};
class MFThreadManager : public QObject
{
Q_OBJECT
Q_OBJECT
public:
MFThreadManager() : _threads(nullptr)
explicit MFThreadManager(QObject *parent = nullptr)
: QObject(parent)
, _threadCount(qMax(QThread::idealThreadCount(), 1))
, _threads(nullptr)
{
_maxThreads = qBound(1, (QThread::idealThreadCount() > 4 ? (QThread::idealThreadCount() - 1) : QThread::idealThreadCount()), 8);
_threads = new Thread<MFThread>*[_threadCount];
for (int i = 0; i < _threadCount; i++)
{
_threads[i] = new Thread<MFThread>(new MFThread, this);
_threads[i]->setObjectName("MFThread " + i);
}
}
~MFThreadManager()
{
if (_threads != nullptr)
{
for(unsigned i=0; i < _maxThreads; i++)
if (_threads[i] != nullptr)
{
_threads[i]->deleteLater();
_threads[i] = nullptr;
}
for(int i = 0; i < _threadCount; i++)
{
_threads[i]->deleteLater();
_threads[i] = nullptr;
}
delete[] _threads;
_threads = nullptr;
}
}
void initThreads()
void start()
{
if (_maxThreads >= 1)
{
_threads = new MFThread*[_maxThreads];
for (unsigned i=0; i < _maxThreads; i++)
_threads[i] = new MFThread();
}
if (_threads != nullptr)
for (int i = 0; i < _threadCount; i++)
connect(_threads[i]->thread(), &MFThread::newFrame, this, &MFThreadManager::newFrame);
}
void start() { MFThread::_isActive = true; }
bool isActive() { return MFThread::_isActive; }
void stop()
{
MFThread::_isActive = false;
if (_threads != nullptr)
{
for(unsigned i = 0; i < _maxThreads; i++)
if (_threads[i] != nullptr)
{
_threads[i]->quit();
_threads[i]->wait();
}
}
for(int i = 0; i < _threadCount; i++)
disconnect(_threads[i]->thread(), nullptr, nullptr, nullptr);
}
unsigned int _maxThreads;
MFThread** _threads;
int _threadCount;
Thread<MFThread>** _threads;
signals:
void newFrame(const Image<ColorRgb>& data);
};

View File

@@ -1,40 +0,0 @@
#pragma once
#include <hyperion/GrabberWrapper.h>
#include <grabber/MFGrabber.h>
class MFWrapper : public GrabberWrapper
{
Q_OBJECT
public:
MFWrapper(const QString & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned fps, int pixelDecimation, QString flipMode);
~MFWrapper() override;
bool getSignalDetectionEnable() const;
bool getCecDetectionEnable() const;
public slots:
bool start() override;
void stop() override;
void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold);
void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) override;
void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax);
void setSignalDetectionEnable(bool enable);
void setCecDetectionEnable(bool enable);
bool setDevice(const QString& device);
void setFpsSoftwareDecimation(int decimation);
bool setEncoding(QString enc);
bool setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue);
void handleSettingsUpdate(settings::type type, const QJsonDocument& config) override;
private slots:
void newFrame(const Image<ColorRgb> & image);
void action() override;
private:
/// The Media Foundation grabber
MFGrabber _grabber;
};

View File

@@ -15,7 +15,7 @@ class QtGrabber : public Grabber
{
public:
QtGrabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation, int display);
QtGrabber(int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0, int pixelDecimation=8, int display=0);
~QtGrabber() override;
@@ -39,11 +39,6 @@ public:
///
bool setWidthHeight(int width, int height) override { return true; }
///
/// @brief Apply new pixelDecimation
///
void setPixelDecimation(int pixelDecimation) override;
///
/// Set the crop values
/// @param cropLeft Left pixel crop
@@ -58,6 +53,28 @@ public:
///
void setDisplayIndex(int index) override;
///
/// @brief Discover QT screens available (for configuration).
///
/// @param[in] params Parameters used to overwrite discovery default behaviour
///
/// @return A JSON structure holding a list of devices found
///
QJsonObject discover(const QJsonObject& params);
///
/// @brief Setup a new capture display, will free the previous one
/// @return True on success, false if no display is found
///
bool setupDisplay();
///
/// @brief Opens the input device.
///
/// @return Zero, on success (i.e. device is ready), else negative
///
bool open();
private slots:
///
/// @brief is called whenever the current _screen changes it's geometry
@@ -66,11 +83,7 @@ private slots:
void geometryChanged(const QRect &geo);
private:
///
/// @brief Setup a new capture display, will free the previous one
/// @return True on success, false if no display is found
///
bool setupDisplay();
///
/// @brief Is called whenever we need new screen dimension calculations based on window geometry
@@ -84,13 +97,20 @@ private:
private:
unsigned _display;
int _display;
int _numberOfSDisplays;
int _pixelDecimation;
unsigned _calculatedWidth;
unsigned _calculatedHeight;
unsigned _src_x;
unsigned _src_y;
unsigned _src_x_max;
unsigned _src_y_max;
int _calculatedWidth;
int _calculatedHeight;
int _src_x;
int _src_y;
int _src_x_max;
int _src_y_max;
bool _isWayland;
QScreen* _screen;
bool _isVirtual;
Logger * _logger;
};

View File

@@ -21,6 +21,11 @@ public:
///
QtWrapper(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation, int display, unsigned updateRate_Hz);
///
/// Starts the grabber which produces led values with the specified update rate
///
bool open() override;
public slots:
///
/// Performs a single frame grab and computes the led-colors

View File

@@ -16,7 +16,12 @@
#include <hyperion/Grabber.h>
#include <utils/VideoStandard.h>
#include <utils/Components.h>
#include <cec/CECEvent.h>
#include <HyperionConfig.h> // Required to determine the cmake options
#if defined(ENABLE_CEC)
#include <cec/CECEvent.h>
#endif
// general JPEG decoder includes
#ifdef HAVE_JPEG_DECODER
@@ -53,8 +58,8 @@ public:
QList<VideoStandard> standards = QList<VideoStandard>();
struct EncodingProperties
{
unsigned int width = 0;
unsigned int height = 0;
int width = 0;
int height = 0;
QList<int> framerates = QList<int>();
};
QMultiMap<PixelFormat, EncodingProperties> encodingFormats = QMultiMap<PixelFormat, EncodingProperties>();
@@ -62,115 +67,40 @@ public:
QMap<int, InputProperties> inputs = QMap<int, InputProperties>();
};
V4L2Grabber(const QString & device, const unsigned width, const unsigned height, const unsigned fps, const unsigned input, VideoStandard videoStandard, PixelFormat pixelFormat, int pixelDecimation);
V4L2Grabber();
~V4L2Grabber() override;
QRectF getSignalDetectionOffset() const
{
return QRectF(_x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max);
}
bool getSignalDetectionEnabled() const { return _signalDetectionEnabled; }
bool getCecDetectionEnabled() const { return _cecDetectionEnabled; }
int grabFrame(Image<ColorRgb> &);
///
/// @brief set new PixelDecimation value to ImageResampler
/// @param pixelDecimation The new pixelDecimation value
///
void setPixelDecimation(int pixelDecimation) override;
///
/// @brief overwrite Grabber.h implementation
///
void setSignalThreshold(
double redSignalThreshold,
double greenSignalThreshold,
double blueSignalThreshold,
int noSignalCounterThreshold = 50) override;
///
/// @brief overwrite Grabber.h implementation
///
void setSignalDetectionOffset(
double verticalMin,
double horizontalMin,
double verticalMax,
double horizontalMax) override;
///
/// @brief overwrite Grabber.h implementation
///
void setSignalDetectionEnable(bool enable) override;
///
/// @brief overwrite Grabber.h implementation
///
void setCecDetectionEnable(bool enable) override;
///
/// @brief overwrite Grabber.h implementation
///
void setDeviceVideoStandard(QString device, VideoStandard videoStandard) override;
///
/// @brief overwrite Grabber.h implementation
///
void setDevice(const QString& device);
bool setInput(int input) override;
///
/// @brief overwrite Grabber.h implementation
///
bool setWidthHeight(int width, int height) override;
void setEncoding(QString enc);
void setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue);
void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold = 50);
void setSignalDetectionOffset( double verticalMin, double horizontalMin, double verticalMax, double horizontalMax);
void setSignalDetectionEnable(bool enable);
void setCecDetectionEnable(bool enable);
bool reload(bool force = false);
QRectF getSignalDetectionOffset() const { return QRectF(_x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max); } //used from hyperion-v4l2
///
/// @brief overwrite Grabber.h implementation
/// @brief Discover available V4L2 USB devices (for configuration).
/// @param[in] params Parameters used to overwrite discovery default behaviour
/// @return A JSON structure holding a list of USB devices found
///
bool setFramerate(int fps) override;
///
/// @brief overwrite Grabber.h implementation
///
QStringList getDevices() const override;
///
/// @brief overwrite Grabber.h implementation
///
QString getDeviceName(const QString& devicePath) const override;
///
/// @brief overwrite Grabber.h implementation
///
QMultiMap<QString, int> getDeviceInputs(const QString& devicePath) const override;
///
/// @brief overwrite Grabber.h implementation
///
QList<VideoStandard> getAvailableDeviceStandards(const QString& devicePath, const int& deviceInput) const override;
///
/// @brief overwrite Grabber.h implementation
///
QStringList getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const override;
///
/// @brief overwrite Grabber.h implementation
///
QMultiMap<int, int> getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const override;
///
/// @brief overwrite Grabber.h implementation
///
QIntList getAvailableDeviceFramerates(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat, const unsigned width, const unsigned height) const override;
QJsonArray discover(const QJsonObject& params);
public slots:
bool prepare() { return true; }
bool start();
void stop();
#if defined(ENABLE_CEC)
void handleCecEvent(CECEvent event);
#endif
signals:
void newFrame(const Image<ColorRgb> & image);
@@ -180,36 +110,21 @@ private slots:
int read_frame();
private:
void getV4Ldevices();
void enumVideoCaptureDevices();
bool init();
void uninit();
bool open_device();
void close_device();
void init_read(unsigned int buffer_size);
void init_mmap();
void init_userp(unsigned int buffer_size);
void init_device(VideoStandard videoStandard);
void uninit_device();
void start_capturing();
void stop_capturing();
bool process_image(const void *p, int size);
void process_image(const uint8_t *p, int size);
int xioctl(int request, void *arg);
int xioctl(int fileDescriptor, int request, void *arg);
void throw_exception(const QString & error)
@@ -264,16 +179,14 @@ private:
#endif
private:
QString _deviceName;
std::map<QString, QString> _v4lDevices;
QString _currentDeviceName, _newDeviceName;
QMap<QString, V4L2Grabber::DeviceProperties> _deviceProperties;
VideoStandard _videoStandard;
io_method _ioMethod;
int _fileDescriptor;
std::vector<buffer> _buffers;
PixelFormat _pixelFormat;
PixelFormat _pixelFormat, _pixelFormatConfig;
int _pixelDecimation;
int _lineLength;
int _frameByteSize;
@@ -281,10 +194,7 @@ private:
// signal detection
int _noSignalCounterThreshold;
ColorRgb _noSignalThresholdColor;
bool _signalDetectionEnabled;
bool _cecDetectionEnabled;
bool _cecStandbyActivated;
bool _noSignalDetected;
bool _cecDetectionEnabled, _cecStandbyActivated, _signalDetectionEnabled, _noSignalDetected;
int _noSignalCounter;
double _x_frac_min;
double _y_frac_min;
@@ -293,8 +203,7 @@ private:
QSocketNotifier *_streamNotifier;
bool _initialized;
bool _deviceAutoDiscoverEnabled;
bool _initialized, _reload;
protected:
void enumFrameIntervals(QList<int> &framerates, int fileDescriptor, int pixelformat, int width, int height);

View File

@@ -1,46 +0,0 @@
#pragma once
#include <hyperion/GrabberWrapper.h>
#include <grabber/V4L2Grabber.h>
class V4L2Wrapper : public GrabberWrapper
{
Q_OBJECT
public:
V4L2Wrapper(const QString & device,
const unsigned grabWidth,
const unsigned grabHeight,
const unsigned fps,
const unsigned input,
VideoStandard videoStandard,
PixelFormat pixelFormat,
int pixelDecimation);
~V4L2Wrapper() override;
bool getSignalDetectionEnable() const;
bool getCecDetectionEnable() const;
public slots:
bool start() override;
void stop() override;
void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold);
void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) override;
void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax);
void setSignalDetectionEnable(bool enable);
void setCecDetectionEnable(bool enable);
void setDeviceVideoStandard(const QString& device, VideoStandard videoStandard);
void handleCecEvent(CECEvent event);
void handleSettingsUpdate(settings::type type, const QJsonDocument& config) override;
private slots:
void newFrame(const Image<ColorRgb> & image);
void readError(const char* err);
void action() override;
private:
/// The V4L2 grabber
V4L2Grabber _grabber;
};

View File

@@ -0,0 +1,47 @@
#pragma once
#include <HyperionConfig.h> // Required to determine the cmake options
#include <hyperion/GrabberWrapper.h>
#if defined(ENABLE_MF)
#include <grabber/MFGrabber.h>
#elif defined(ENABLE_V4L2)
#include <grabber/V4L2Grabber.h>
#endif
#if defined(ENABLE_CEC)
#include <cec/CECEvent.h>
#endif
class VideoWrapper : public GrabberWrapper
{
Q_OBJECT
public:
VideoWrapper();
~VideoWrapper() override;
public slots:
bool start() override;
void stop() override;
#if defined(ENABLE_CEC)
void handleCecEvent(CECEvent event);
#endif
void handleSettingsUpdate(settings::type type, const QJsonDocument& config) override;
private slots:
void newFrame(const Image<ColorRgb> & image);
void readError(const char* err);
void action() override;
private:
/// The Media Foundation or V4L2 grabber
#if defined(ENABLE_MF)
MFGrabber _grabber;
#elif defined(ENABLE_V4L2)
V4L2Grabber _grabber;
#endif
};

View File

@@ -2,7 +2,13 @@
#include <QAbstractEventDispatcher>
#include <QAbstractNativeEventFilter>
#include <QCoreApplication>
// QT includes
#include <QObject>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
// Hyperion-utils includes
#include <utils/ColorRgb.h>
@@ -20,11 +26,13 @@ class X11Grabber : public Grabber , public QAbstractNativeEventFilter
{
public:
X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation);
X11Grabber(int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0, int pixelDecimation=8);
~X11Grabber() override;
bool Setup();
bool open();
bool setupDisplay();
///
/// Captures a single snapshot of the display and writes the data to the given image. The
@@ -50,7 +58,7 @@ public:
///
/// @brief Apply new pixelDecimation
///
void setPixelDecimation(int pixelDecimation) override;
bool setPixelDecimation(int pixelDecimation) override;
///
/// Set the crop values
@@ -61,20 +69,31 @@ public:
///
void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) override;
///
/// @brief Discover X11 screens available (for configuration).
///
/// @param[in] params Parameters used to overwrite discovery default behaviour
///
/// @return A JSON structure holding a list of devices found
///
QJsonObject discover(const QJsonObject& params);
protected:
bool nativeEventFilter(const QByteArray & eventType, void * message, long int * result) override;
private:
bool _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable, _XRandRAvailable;
XImage* _xImage;
XShmSegmentInfo _shminfo;
void freeResources();
void setupResources();
/// Reference to the X11 display (nullptr if not opened)
Display* _x11Display;
Window _window;
XWindowAttributes _windowAttr;
XImage* _xImage;
XShmSegmentInfo _shminfo;
Pixmap _pixmap;
XRenderPictFormat* _srcFormat;
XRenderPictFormat* _dstFormat;
@@ -92,8 +111,13 @@ private:
unsigned _src_x;
unsigned _src_y;
Image<ColorRgb> _image;
bool _XShmAvailable;
bool _XShmPixmapAvailable;
bool _XRenderAvailable;
bool _XRandRAvailable;
bool _isWayland;
void freeResources();
void setupResources();
Logger * _logger;
Image<ColorRgb> _image;
};

View File

@@ -1,7 +1,11 @@
#pragma once
#include <QAbstractNativeEventFilter>
// QT includes
#include <QObject>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <utils/ColorRgb.h>
#include <hyperion/Grabber.h>
@@ -21,17 +25,29 @@ class XcbGrabber : public Grabber, public QAbstractNativeEventFilter
Q_OBJECT
public:
XcbGrabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation);
XcbGrabber(int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0, int pixelDecimation=8);
~XcbGrabber() override;
bool Setup();
bool open();
bool setupDisplay();
int grabFrame(Image<ColorRgb> & image, bool forceUpdate = false);
int updateScreenDimensions(bool force = false);
void setVideoMode(VideoMode mode) override;
bool setWidthHeight(int width, int height) override { return true; }
void setPixelDecimation(int pixelDecimation) override;
bool setPixelDecimation(int pixelDecimation) override;
void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) override;
///
/// @brief Discover XCB screens available (for configuration).
///
/// @param[in] params Parameters used to overwrite discovery default behaviour
///
/// @return A JSON structure holding a list of devices found
///
QJsonObject discover(const QJsonObject& params);
private:
bool nativeEventFilter(const QByteArray & eventType, void * message, long int * result) override;
void freeResources();
@@ -54,6 +70,7 @@ private:
int _pixelDecimation;
int _screen_num;
unsigned _screenWidth;
unsigned _screenHeight;
unsigned _src_x;
@@ -63,6 +80,8 @@ private:
bool _XcbRandRAvailable;
bool _XcbShmAvailable;
bool _XcbShmPixmapAvailable;
bool _isWayland;
Logger * _logger;
uint8_t * _shmData;