mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
V4l2 input (#825)
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <QByteArray>
|
||||
#include <QTimer>
|
||||
#include <QHostInfo>
|
||||
#include <QMultiMap>
|
||||
|
||||
// hyperion includes
|
||||
#include <leddevice/LedDeviceWrapper.h>
|
||||
@@ -489,21 +490,32 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
|
||||
QJsonArray availableV4L2devices;
|
||||
for (auto devicePath : GrabberWrapper::getInstance()->getV4L2devices())
|
||||
{
|
||||
|
||||
QJsonObject device;
|
||||
device["device"] = devicePath;
|
||||
device["name"] = GrabberWrapper::getInstance()->getV4L2deviceName(devicePath);
|
||||
|
||||
QJsonArray availableInputs;
|
||||
QMultiMap<QString, int> inputs = GrabberWrapper::getInstance()->getV4L2deviceInputs(devicePath);
|
||||
for (auto input = inputs.begin(); input != inputs.end(); input++)
|
||||
{
|
||||
QJsonObject availableInput;
|
||||
availableInput["inputName"] = input.key();
|
||||
availableInput["inputIndex"] = input.value();
|
||||
availableInputs.append(availableInput);
|
||||
}
|
||||
device.insert("inputs", availableInputs);
|
||||
|
||||
QJsonArray availableResolutions;
|
||||
for (auto resolution : GrabberWrapper::getInstance()->getResolutions(devicePath))
|
||||
QStringList resolutions = GrabberWrapper::getInstance()->getResolutions(devicePath);
|
||||
for (auto resolution : resolutions)
|
||||
{
|
||||
availableResolutions.append(resolution);
|
||||
}
|
||||
device.insert("resolutions", availableResolutions);
|
||||
|
||||
QJsonArray availableFramerates;
|
||||
for (auto framerate : GrabberWrapper::getInstance()->getFramerates(devicePath))
|
||||
QStringList framerates = GrabberWrapper::getInstance()->getFramerates(devicePath);
|
||||
for (auto framerate : framerates)
|
||||
{
|
||||
availableFramerates.append(framerate);
|
||||
}
|
||||
|
@@ -8,6 +8,10 @@
|
||||
#include <QUuid>
|
||||
#include <QDir>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <stdexcept>
|
||||
#endif
|
||||
|
||||
// not in header because of linking
|
||||
static QString _rootPath;
|
||||
static QThreadStorage<QSqlDatabase> _databasePool;
|
||||
|
@@ -34,13 +34,13 @@ V4L2Grabber::V4L2Grabber(const QString & device
|
||||
, const unsigned width
|
||||
, const unsigned height
|
||||
, const unsigned fps
|
||||
, const unsigned input
|
||||
, VideoStandard videoStandard
|
||||
, PixelFormat pixelFormat
|
||||
, int pixelDecimation
|
||||
)
|
||||
: Grabber("V4L2:"+device)
|
||||
, _deviceName()
|
||||
, _input(-1)
|
||||
, _videoStandard(videoStandard)
|
||||
, _ioMethod(IO_METHOD_MMAP)
|
||||
, _fileDescriptor(-1)
|
||||
@@ -66,6 +66,7 @@ V4L2Grabber::V4L2Grabber(const QString & device
|
||||
getV4Ldevices();
|
||||
|
||||
// init
|
||||
setInput(input);
|
||||
setWidthHeight(width, height);
|
||||
setFramerate(fps);
|
||||
setDeviceVideoStandard(device, videoStandard);
|
||||
@@ -147,7 +148,7 @@ bool V4L2Grabber::init()
|
||||
if (open_device())
|
||||
{
|
||||
opened = true;
|
||||
init_device(_videoStandard, _input);
|
||||
init_device(_videoStandard);
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
@@ -214,6 +215,21 @@ void V4L2Grabber::getV4Ldevices()
|
||||
|
||||
V4L2Grabber::DeviceProperties properties;
|
||||
|
||||
// collect available device inputs (index & name)
|
||||
int inputIndex;
|
||||
if (xioctl(fd, VIDIOC_G_INPUT, &inputIndex) == 0)
|
||||
{
|
||||
struct v4l2_input input;
|
||||
CLEAR(input);
|
||||
|
||||
input.index = 0;
|
||||
while (xioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0)
|
||||
{
|
||||
properties.inputs.insert(QString((char*)input.name), input.index);
|
||||
input.index++;
|
||||
}
|
||||
}
|
||||
|
||||
// collect available device resolutions & frame rates
|
||||
struct v4l2_frmsizeenum frmsizeenum;
|
||||
CLEAR(frmsizeenum);
|
||||
@@ -485,7 +501,7 @@ void V4L2Grabber::init_userp(unsigned int buffer_size)
|
||||
}
|
||||
}
|
||||
|
||||
void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
void V4L2Grabber::init_device(VideoStandard videoStandard)
|
||||
{
|
||||
struct v4l2_capability cap;
|
||||
CLEAR(cap);
|
||||
@@ -566,16 +582,13 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
// set input if needed and supported
|
||||
struct v4l2_input v4l2Input;
|
||||
CLEAR(v4l2Input);
|
||||
v4l2Input.index = _input;
|
||||
|
||||
v4l2Input.index = input;
|
||||
|
||||
if (input >= 0 && 0 == xioctl(VIDIOC_ENUMINPUT,&v4l2Input))
|
||||
if (_input >= 0 && 0 == xioctl(VIDIOC_ENUMINPUT, &v4l2Input))
|
||||
{
|
||||
if (-1 == xioctl(VIDIOC_S_INPUT, &input))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_S_INPUT");
|
||||
return;
|
||||
}
|
||||
(-1 == xioctl(VIDIOC_S_INPUT, &_input))
|
||||
? Debug(_log, "Input settings not supported.")
|
||||
: Debug(_log, "Set device input to: %s", v4l2Input.name);
|
||||
}
|
||||
|
||||
// set the video standard if needed and supported
|
||||
@@ -1316,9 +1329,9 @@ void V4L2Grabber::setDeviceVideoStandard(QString device, VideoStandard videoStan
|
||||
}
|
||||
}
|
||||
|
||||
bool V4L2Grabber::setFramerate(int fps)
|
||||
bool V4L2Grabber::setInput(int input)
|
||||
{
|
||||
if(Grabber::setFramerate(fps))
|
||||
if(Grabber::setInput(input))
|
||||
{
|
||||
bool started = _initialized;
|
||||
uninit();
|
||||
@@ -1340,6 +1353,18 @@ bool V4L2Grabber::setWidthHeight(int width, int height)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool V4L2Grabber::setFramerate(int fps)
|
||||
{
|
||||
if(Grabber::setFramerate(fps))
|
||||
{
|
||||
bool started = _initialized;
|
||||
uninit();
|
||||
if(started) start();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList V4L2Grabber::getV4L2devices()
|
||||
{
|
||||
QStringList result = QStringList();
|
||||
@@ -1355,6 +1380,11 @@ QString V4L2Grabber::getV4L2deviceName(QString devicePath)
|
||||
return _deviceProperties.value(devicePath).name;
|
||||
}
|
||||
|
||||
QMultiMap<QString, int> V4L2Grabber::getV4L2deviceInputs(QString devicePath)
|
||||
{
|
||||
return _deviceProperties.value(devicePath).inputs;
|
||||
}
|
||||
|
||||
QStringList V4L2Grabber::getResolutions(QString devicePath)
|
||||
{
|
||||
return _deviceProperties.value(devicePath).resolutions;
|
||||
|
@@ -9,6 +9,7 @@ V4L2Wrapper::V4L2Wrapper(const QString &device,
|
||||
const unsigned grabWidth,
|
||||
const unsigned grabHeight,
|
||||
const unsigned fps,
|
||||
const unsigned input,
|
||||
VideoStandard videoStandard,
|
||||
PixelFormat pixelFormat,
|
||||
int pixelDecimation )
|
||||
@@ -17,6 +18,7 @@ V4L2Wrapper::V4L2Wrapper(const QString &device,
|
||||
grabWidth,
|
||||
grabHeight,
|
||||
fps,
|
||||
input,
|
||||
videoStandard,
|
||||
pixelFormat,
|
||||
pixelDecimation)
|
||||
|
@@ -8,6 +8,7 @@ Grabber::Grabber(QString grabberName, int width, int height, int cropLeft, int c
|
||||
, _width(width)
|
||||
, _height(height)
|
||||
, _fps(15)
|
||||
, _input(-1)
|
||||
, _cropLeft(0)
|
||||
, _cropRight(0)
|
||||
, _cropTop(0)
|
||||
@@ -70,6 +71,17 @@ void Grabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTo
|
||||
}
|
||||
}
|
||||
|
||||
bool Grabber::setInput(int input)
|
||||
{
|
||||
if((input >= 0) && (_input != input))
|
||||
{
|
||||
_input = input;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Grabber::setWidthHeight(int width, int height)
|
||||
{
|
||||
// eval changes with crop
|
||||
@@ -91,7 +103,10 @@ bool Grabber::setWidthHeight(int width, int height)
|
||||
bool Grabber::setFramerate(int fps)
|
||||
{
|
||||
if((fps > 0) && (_fps != fps))
|
||||
{
|
||||
_fps = fps;
|
||||
return true;
|
||||
}
|
||||
|
||||
return (fps > 0) && (_fps != fps);
|
||||
return false;
|
||||
}
|
||||
|
@@ -160,6 +160,9 @@ void GrabberWrapper::handleSettingsUpdate(const settings::type& type, const QJso
|
||||
obj["cropTop"].toInt(0),
|
||||
obj["cropBottom"].toInt(0));
|
||||
|
||||
// device input
|
||||
_ggrabber->setInput(obj["input"].toInt(-1));
|
||||
|
||||
// device resolution
|
||||
_ggrabber->setWidthHeight(obj["width"].toInt(0), obj["height"].toInt(0));
|
||||
|
||||
@@ -236,6 +239,14 @@ QString GrabberWrapper::getV4L2deviceName(QString devicePath)
|
||||
return QString();
|
||||
}
|
||||
|
||||
QMultiMap<QString, int> GrabberWrapper::getV4L2deviceInputs(QString devicePath)
|
||||
{
|
||||
if(_grabberName.startsWith("V4L"))
|
||||
return _ggrabber->getV4L2deviceInputs(devicePath);
|
||||
|
||||
return QMultiMap<QString, int>();
|
||||
}
|
||||
|
||||
QStringList GrabberWrapper::getResolutions(QString devicePath)
|
||||
{
|
||||
if(_grabberName.startsWith("V4L"))
|
||||
|
@@ -14,7 +14,19 @@
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 2,
|
||||
"comment" : "The 'available_device' settings are dynamically inserted into the WebUI under PropertyOrder '1'."
|
||||
"comment" : "The 'available_devices' settings are dynamically inserted into the WebUI under PropertyOrder '1'."
|
||||
},
|
||||
"input" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_enum_custom",
|
||||
"default" : 0,
|
||||
"options" : {
|
||||
"hidden":true
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 4,
|
||||
"comment" : "The 'device_inputs' settings are dynamically inserted into the WebUI under PropertyOrder '3'."
|
||||
},
|
||||
"standard" :
|
||||
{
|
||||
@@ -26,7 +38,7 @@
|
||||
"enum_titles" : ["edt_conf_enum_NO_CHANGE", "edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM"]
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 3
|
||||
"propertyOrder" : 5
|
||||
},
|
||||
"width" :
|
||||
{
|
||||
@@ -39,8 +51,8 @@
|
||||
"hidden":true
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 5,
|
||||
"comment" : "The 'resolution' settings are dynamically inserted into the WebUI under PropertyOrder '4'."
|
||||
"propertyOrder" : 7,
|
||||
"comment" : "The 'resolutions' settings are dynamically inserted into the WebUI under PropertyOrder '6'."
|
||||
},
|
||||
"height" :
|
||||
{
|
||||
@@ -53,7 +65,7 @@
|
||||
"hidden":true
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 6
|
||||
"propertyOrder" : 8
|
||||
},
|
||||
"fps" :
|
||||
{
|
||||
@@ -66,8 +78,8 @@
|
||||
"hidden":true
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 8,
|
||||
"comment" : "The 'frames per second' setting is dynamically inserted into the WebUI under PropertyOrder '7'."
|
||||
"propertyOrder" : 10,
|
||||
"comment" : "The 'framerates' setting is dynamically inserted into the WebUI under PropertyOrder '9'."
|
||||
},
|
||||
"sizeDecimation" :
|
||||
{
|
||||
@@ -77,7 +89,7 @@
|
||||
"maximum" : 30,
|
||||
"default" : 6,
|
||||
"required" : true,
|
||||
"propertyOrder" : 9
|
||||
"propertyOrder" : 11
|
||||
},
|
||||
"cropLeft" :
|
||||
{
|
||||
@@ -87,7 +99,7 @@
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 10
|
||||
"propertyOrder" : 12
|
||||
},
|
||||
"cropRight" :
|
||||
{
|
||||
@@ -97,7 +109,7 @@
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 11
|
||||
"propertyOrder" : 13
|
||||
},
|
||||
"cropTop" :
|
||||
{
|
||||
@@ -107,7 +119,7 @@
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 12
|
||||
"propertyOrder" : 14
|
||||
},
|
||||
"cropBottom" :
|
||||
{
|
||||
@@ -117,7 +129,7 @@
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 13
|
||||
"propertyOrder" : 15
|
||||
},
|
||||
"signalDetection" :
|
||||
{
|
||||
@@ -125,7 +137,7 @@
|
||||
"title" : "edt_conf_v4l2_signalDetection_title",
|
||||
"default" : false,
|
||||
"required" : true,
|
||||
"propertyOrder" : 14
|
||||
"propertyOrder" : 16
|
||||
},
|
||||
"redSignalThreshold" :
|
||||
{
|
||||
@@ -141,7 +153,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 15
|
||||
"propertyOrder" : 17
|
||||
},
|
||||
"greenSignalThreshold" :
|
||||
{
|
||||
@@ -157,7 +169,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 16
|
||||
"propertyOrder" : 18
|
||||
},
|
||||
"blueSignalThreshold" :
|
||||
{
|
||||
@@ -173,7 +185,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 17
|
||||
"propertyOrder" : 19
|
||||
},
|
||||
"sDVOffsetMin" :
|
||||
{
|
||||
@@ -189,7 +201,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 18
|
||||
"propertyOrder" : 20
|
||||
},
|
||||
"sDVOffsetMax" :
|
||||
{
|
||||
@@ -205,7 +217,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 19
|
||||
"propertyOrder" : 21
|
||||
},
|
||||
"sDHOffsetMin" :
|
||||
{
|
||||
@@ -221,7 +233,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 20
|
||||
"propertyOrder" : 22
|
||||
},
|
||||
"sDHOffsetMax" :
|
||||
{
|
||||
@@ -237,7 +249,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 21
|
||||
"propertyOrder" : 23
|
||||
}
|
||||
},
|
||||
"additionalProperties" : true
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <effectengine/EffectModule.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <stdexcept>
|
||||
#define STRINGIFY2(x) #x
|
||||
#define STRINGIFY(x) STRINGIFY2(x)
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user