mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Merge remote-tracking branch 'origin/grabberDiscovery' into mediafoundation
This commit is contained in:
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
};
|
||||
|
@@ -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;
|
||||
};
|
@@ -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;
|
||||
};
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
};
|
47
include/grabber/VideoWrapper.h
Normal file
47
include/grabber/VideoWrapper.h
Normal 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
|
||||
};
|
@@ -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;
|
||||
};
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user