mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Refactor V4L2 grabber (part 1) (#62)
This commit is contained in:
parent
c5a2b808cd
commit
c5065e76b5
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -8,7 +8,7 @@
|
|||||||
"name": "(Linux) hyperiond",
|
"name": "(Linux) hyperiond",
|
||||||
"type": "cppdbg",
|
"type": "cppdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${command:cmake.launchTargetDirectory}/hyperiond",
|
"program": "${workspaceFolder}/build/bin/hyperiond",
|
||||||
"args": ["-d"],
|
"args": ["-d"],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
|
@ -53,7 +53,7 @@ SET ( DEFAULT_EXPERIMENTAL OFF )
|
|||||||
SET ( DEFAULT_MF OFF )
|
SET ( DEFAULT_MF OFF )
|
||||||
|
|
||||||
IF ( ${CMAKE_SYSTEM} MATCHES "Linux" )
|
IF ( ${CMAKE_SYSTEM} MATCHES "Linux" )
|
||||||
SET ( DEFAULT_V4L2 OFF ) # TODO: Reactivate when refactor of V4L2 grabber is finished.
|
SET ( DEFAULT_V4L2 ON )
|
||||||
SET ( DEFAULT_SPIDEV ON )
|
SET ( DEFAULT_SPIDEV ON )
|
||||||
SET ( DEFAULT_TINKERFORGE ON )
|
SET ( DEFAULT_TINKERFORGE ON )
|
||||||
SET ( DEFAULT_FB ON )
|
SET ( DEFAULT_FB ON )
|
||||||
|
@ -61,6 +61,7 @@ public:
|
|||||||
bool getCecDetectionEnabled() const { return _cecDetectionEnabled; }
|
bool getCecDetectionEnabled() const { return _cecDetectionEnabled; }
|
||||||
QStringList getDevices() const override;
|
QStringList getDevices() const override;
|
||||||
QString getDeviceName(const QString& devicePath) const override { return devicePath; }
|
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;
|
QStringList getAvailableEncodingFormats(const QString& devicePath, const int& /*deviceInput*/) const override;
|
||||||
QStringList getAvailableDeviceResolutions(const QString& devicePath, const int& /*deviceInput*/, const PixelFormat& encFormat) const override;
|
QStringList getAvailableDeviceResolutions(const QString& devicePath, const int& /*deviceInput*/, const PixelFormat& encFormat) const override;
|
||||||
QStringList getAvailableDeviceFramerates(const QString& devicePath, const int& /*deviceInput*/, const PixelFormat& encFormat, const unsigned width, const unsigned height) const override;
|
QStringList getAvailableDeviceFramerates(const QString& devicePath, const int& /*deviceInput*/, const PixelFormat& encFormat, const unsigned width, const unsigned height) const override;
|
||||||
|
@ -35,9 +35,10 @@
|
|||||||
#include <turbojpeg.h>
|
#include <turbojpeg.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
///
|
||||||
/// Capture class for V4L2 devices
|
/// Capture class for V4L2 devices
|
||||||
///
|
///
|
||||||
/// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
|
|
||||||
class V4L2Grabber : public Grabber
|
class V4L2Grabber : public Grabber
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -45,10 +46,19 @@ class V4L2Grabber : public Grabber
|
|||||||
public:
|
public:
|
||||||
struct DeviceProperties
|
struct DeviceProperties
|
||||||
{
|
{
|
||||||
QString name = QString();
|
QString name = QString();
|
||||||
QMultiMap<QString, int> inputs = QMultiMap<QString, int>();
|
struct InputProperties
|
||||||
QStringList resolutions = QStringList();
|
{
|
||||||
QStringList framerates = QStringList();
|
QString inputName = QString();
|
||||||
|
struct EncodingProperties
|
||||||
|
{
|
||||||
|
unsigned int width = 0;
|
||||||
|
unsigned int height = 0;
|
||||||
|
QList<int> framerates = QList<int>();
|
||||||
|
};
|
||||||
|
QMultiMap<PixelFormat, EncodingProperties> encodingFormats = QMultiMap<PixelFormat, EncodingProperties>();
|
||||||
|
};
|
||||||
|
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(const QString & device, const unsigned width, const unsigned height, const unsigned fps, const unsigned input, VideoStandard videoStandard, PixelFormat pixelFormat, int pixelDecimation);
|
||||||
@ -120,27 +130,33 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief overwrite Grabber.h implementation
|
/// @brief overwrite Grabber.h implementation
|
||||||
///
|
///
|
||||||
QStringList getV4L2devices() const override;
|
QStringList getDevices() const override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief overwrite Grabber.h implementation
|
/// @brief overwrite Grabber.h implementation
|
||||||
///
|
///
|
||||||
QString getV4L2deviceName(const QString& devicePath) const override;
|
QString getDeviceName(const QString& devicePath) const override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief overwrite Grabber.h implementation
|
/// @brief overwrite Grabber.h implementation
|
||||||
///
|
///
|
||||||
QMultiMap<QString, int> getV4L2deviceInputs(const QString& devicePath) const override;
|
QMultiMap<QString, int> getDeviceInputs(const QString& devicePath) const override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief overwrite Grabber.h implementation
|
/// @brief overwrite Grabber.h implementation
|
||||||
///
|
///
|
||||||
QStringList getResolutions(const QString& devicePath) const override;
|
QStringList getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief overwrite Grabber.h implementation
|
/// @brief overwrite Grabber.h implementation
|
||||||
///
|
///
|
||||||
QStringList getFramerates(const QString& devicePath) const override;
|
QMultiMap<int, int> getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const override;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief overwrite Grabber.h implementation
|
||||||
|
///
|
||||||
|
QStringList getAvailableDeviceFramerates(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat, const unsigned width, const unsigned height) const override;
|
||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
@ -275,5 +291,5 @@ private:
|
|||||||
bool _deviceAutoDiscoverEnabled;
|
bool _deviceAutoDiscoverEnabled;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void enumFrameIntervals(QStringList &framerates, int fileDescriptor, int pixelformat, int width, int height);
|
void enumFrameIntervals(QList<int> &framerates, int fileDescriptor, int pixelformat, int width, int height);
|
||||||
};
|
};
|
||||||
|
@ -143,7 +143,7 @@ public:
|
|||||||
/// @param devicePath The device path
|
/// @param devicePath The device path
|
||||||
/// @return multi pair of name/index on success else empty pair
|
/// @return multi pair of name/index on success else empty pair
|
||||||
///
|
///
|
||||||
virtual QMultiMap<QString, int> getDeviceInputs(const QString& /*devicePath*/) const { return {{ "", 0}}; }
|
virtual QMultiMap<QString, int> getDeviceInputs(const QString& /*devicePath*/) const { return QMultiMap<QString, int>(); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get a list of all available device encoding formats depends on device input
|
/// @brief Get a list of all available device encoding formats depends on device input
|
||||||
@ -154,13 +154,13 @@ public:
|
|||||||
virtual QStringList getAvailableEncodingFormats(const QString& /*devicePath*/, const int& /*deviceInput*/) const { return QStringList(); }
|
virtual QStringList getAvailableEncodingFormats(const QString& /*devicePath*/, const int& /*deviceInput*/) const { return QStringList(); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get a list of available device resolutions depends on device input and encoding format
|
/// @brief Get a map of available device resolutions (width/heigth) depends on device input and encoding format
|
||||||
/// @param devicePath The device path
|
/// @param devicePath The device path
|
||||||
/// @param inputIndex The device input index
|
/// @param inputIndex The device input index
|
||||||
/// @param encFormat The device encoding format
|
/// @param encFormat The device encoding format
|
||||||
/// @return List of resolutions on success else empty List
|
/// @return Map of resolutions (width/heigth) on success else empty List
|
||||||
///
|
///
|
||||||
virtual QStringList getAvailableDeviceResolutions(const QString& /*devicePath*/, const int& /*deviceInput*/, const PixelFormat& /*encFormat*/) const { return QStringList(); }
|
virtual QMultiMap<int, int> getAvailableDeviceResolutions(const QString& /*devicePath*/, const int& /*deviceInput*/, const PixelFormat& /*encFormat*/) const { return QMultiMap<int, int>(); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get a list of available device framerates depends on device input, encoding format and resolution
|
/// @brief Get a list of available device framerates depends on device input, encoding format and resolution
|
||||||
|
@ -71,7 +71,7 @@ public:
|
|||||||
virtual QString getDeviceName(const QString& devicePath) const;
|
virtual QString getDeviceName(const QString& devicePath) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get a name/index pair of supported device inputs
|
/// @brief Get a map of name/index pair of supported device inputs
|
||||||
/// @param devicePath The device path
|
/// @param devicePath The device path
|
||||||
/// @return multi pair of name/index on success else empty pair
|
/// @return multi pair of name/index on success else empty pair
|
||||||
///
|
///
|
||||||
@ -86,13 +86,13 @@ public:
|
|||||||
virtual QStringList getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const;
|
virtual QStringList getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get a list of available device resolutions depends on device input and encoding format
|
/// @brief Get a map of available device resolutions (width/heigth) depends on device input and encoding format
|
||||||
/// @param devicePath The device path
|
/// @param devicePath The device path
|
||||||
/// @param inputIndex The device input index
|
/// @param inputIndex The device input index
|
||||||
/// @param encFormat The device encoding format
|
/// @param encFormat The device encoding format
|
||||||
/// @return List of resolutions on success else empty List
|
/// @return Map of resolutions (width/heigth) on success else empty List
|
||||||
///
|
///
|
||||||
virtual QStringList getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const;
|
virtual QMultiMap<int, int> getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get a list of available device framerates depends on encoding format and resolution
|
/// @brief Get a list of available device framerates depends on encoding format and resolution
|
||||||
|
@ -496,48 +496,57 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
|
|||||||
{
|
{
|
||||||
QJsonObject device;
|
QJsonObject device;
|
||||||
device["device"] = devicePath;
|
device["device"] = devicePath;
|
||||||
device["name"] = GrabberWrapper::getInstance()->getDeviceName(devicePath);
|
device["device_name"] = GrabberWrapper::getInstance()->getDeviceName(devicePath);
|
||||||
|
device["type"] = "v4l2";
|
||||||
|
|
||||||
|
QJsonArray video_inputs;
|
||||||
|
|
||||||
QJsonObject availableInputs;
|
|
||||||
QMultiMap<QString, int> inputs = GrabberWrapper::getInstance()->getDeviceInputs(devicePath);
|
QMultiMap<QString, int> inputs = GrabberWrapper::getInstance()->getDeviceInputs(devicePath);
|
||||||
for (auto input = inputs.begin(); input != inputs.end(); input++)
|
for (auto input = inputs.begin(); input != inputs.end(); input++)
|
||||||
{
|
{
|
||||||
QJsonObject availableEncodingFormats;
|
QJsonObject in;
|
||||||
availableInputs["inputName"] = input.key();
|
in["name"] = input.key();
|
||||||
availableInputs["inputIndex"] = input.value();
|
in["inputIdx"] = input.value();
|
||||||
|
|
||||||
|
QJsonArray formats;
|
||||||
QStringList encodingFormats = GrabberWrapper::getInstance()->getAvailableEncodingFormats(devicePath, input.value());
|
QStringList encodingFormats = GrabberWrapper::getInstance()->getAvailableEncodingFormats(devicePath, input.value());
|
||||||
for (auto encodingFormat : encodingFormats)
|
for (auto encodingFormat : encodingFormats)
|
||||||
{
|
{
|
||||||
QJsonArray formats;
|
QJsonObject format;
|
||||||
QStringList resolutions = GrabberWrapper::getInstance()->getAvailableDeviceResolutions(devicePath, input.value(), parsePixelFormat(encodingFormat));
|
format["format"] = encodingFormat;
|
||||||
for (auto resolution : resolutions)
|
|
||||||
{
|
|
||||||
QJsonObject format;
|
|
||||||
format["resolution"] = resolution;
|
|
||||||
|
|
||||||
QJsonArray availableFramerates;
|
QJsonArray resolutionArray;
|
||||||
QStringList framerates = GrabberWrapper::getInstance()->getAvailableDeviceFramerates(devicePath, input.value(), parsePixelFormat(encodingFormat), resolution.split("x")[0].toInt(), resolution.split("x")[1].toInt());
|
QMultiMap<int, int> deviceResolutions = GrabberWrapper::getInstance()->getAvailableDeviceResolutions(devicePath, input.value(), parsePixelFormat(encodingFormat));
|
||||||
|
for (auto width_height = deviceResolutions.begin(); width_height != deviceResolutions.end(); width_height++)
|
||||||
|
{
|
||||||
|
QJsonObject resolution;
|
||||||
|
resolution["width"] = width_height.key();
|
||||||
|
resolution["heigth"] = width_height.value();
|
||||||
|
|
||||||
|
QJsonArray fps;
|
||||||
|
QStringList framerates = GrabberWrapper::getInstance()->getAvailableDeviceFramerates(devicePath, input.value(), parsePixelFormat(encodingFormat), width_height.key(), width_height.value());
|
||||||
for (auto framerate : framerates)
|
for (auto framerate : framerates)
|
||||||
{
|
{
|
||||||
availableFramerates.append(framerate);
|
fps.append(framerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
format["framerates"] = availableFramerates;
|
resolution["fps"] = fps;
|
||||||
formats.append(format);
|
resolutionArray.append(resolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
availableEncodingFormats[encodingFormat] = formats;
|
format["resolutions"] = resolutionArray;
|
||||||
|
formats.append(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
availableInputs["encoding_formats"] = availableEncodingFormats;
|
in["formats"] = formats;
|
||||||
|
video_inputs.append(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
device["device_inputs"] = availableInputs;
|
device["video_inputs"] = video_inputs;
|
||||||
availableDevices.append(device);
|
availableDevices.append(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
grabbers["v4l2_properties"] = availableDevices;
|
grabbers["video_sources"] = availableDevices;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -30,6 +30,18 @@
|
|||||||
#define V4L2_CAP_META_CAPTURE 0x00800000 // Specified in kernel header v4.16. Required for backward compatibility.
|
#define V4L2_CAP_META_CAPTURE 0x00800000 // Specified in kernel header v4.16. Required for backward compatibility.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static PixelFormat GetPixelFormat(const unsigned int format)
|
||||||
|
{
|
||||||
|
if (format == V4L2_PIX_FMT_RGB32) return PixelFormat::RGB32;
|
||||||
|
if (format == V4L2_PIX_FMT_RGB24) return PixelFormat::BGR24;
|
||||||
|
if (format == V4L2_PIX_FMT_YUYV) return PixelFormat::YUYV;
|
||||||
|
if (format == V4L2_PIX_FMT_UYVY) return PixelFormat::UYVY;
|
||||||
|
if (format == V4L2_PIX_FMT_MJPEG) return PixelFormat::MJPEG;
|
||||||
|
if (format == V4L2_PIX_FMT_NV12) return PixelFormat::NV12;
|
||||||
|
if (format == V4L2_PIX_FMT_YUV420) return PixelFormat::I420;
|
||||||
|
return PixelFormat::NO_CHANGE;
|
||||||
|
};
|
||||||
|
|
||||||
V4L2Grabber::V4L2Grabber(const QString & device, unsigned width, unsigned height, unsigned fps, unsigned input, VideoStandard videoStandard, PixelFormat pixelFormat, int pixelDecimation)
|
V4L2Grabber::V4L2Grabber(const QString & device, unsigned width, unsigned height, unsigned fps, unsigned input, VideoStandard videoStandard, PixelFormat pixelFormat, int pixelDecimation)
|
||||||
: Grabber("V4L2:"+device)
|
: Grabber("V4L2:"+device)
|
||||||
, _deviceName()
|
, _deviceName()
|
||||||
@ -64,6 +76,7 @@ V4L2Grabber::V4L2Grabber(const QString & device, unsigned width, unsigned height
|
|||||||
setWidthHeight(width, height);
|
setWidthHeight(width, height);
|
||||||
setFramerate(fps);
|
setFramerate(fps);
|
||||||
setDeviceVideoStandard(device, videoStandard);
|
setDeviceVideoStandard(device, videoStandard);
|
||||||
|
Debug(_log,"Init pixel format: %i", static_cast<int>(_pixelFormat));
|
||||||
}
|
}
|
||||||
|
|
||||||
V4L2Grabber::~V4L2Grabber()
|
V4L2Grabber::~V4L2Grabber()
|
||||||
@ -210,42 +223,69 @@ void V4L2Grabber::getV4Ldevices()
|
|||||||
V4L2Grabber::DeviceProperties properties;
|
V4L2Grabber::DeviceProperties properties;
|
||||||
|
|
||||||
// collect available device inputs (index & name)
|
// collect available device inputs (index & name)
|
||||||
int inputIndex;
|
struct v4l2_input input;
|
||||||
if (xioctl(fd, VIDIOC_G_INPUT, &inputIndex) == 0)
|
CLEAR(input);
|
||||||
|
|
||||||
|
input.index = 0;
|
||||||
|
while (xioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0)
|
||||||
{
|
{
|
||||||
struct v4l2_input input;
|
V4L2Grabber::DeviceProperties::InputProperties inputProperties;
|
||||||
CLEAR(input);
|
inputProperties.inputName = QString((char*)input.name);
|
||||||
|
|
||||||
input.index = 0;
|
// Enumerate pixel formats
|
||||||
while (xioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0)
|
struct v4l2_fmtdesc desc;
|
||||||
|
CLEAR(desc);
|
||||||
|
|
||||||
|
desc.index = 0;
|
||||||
|
desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
while (xioctl(fd, VIDIOC_ENUM_FMT, &desc) == 0)
|
||||||
{
|
{
|
||||||
properties.inputs.insert(QString((char*)input.name), input.index);
|
PixelFormat encodingFormat = GetPixelFormat(desc.pixelformat);
|
||||||
input.index++;
|
if (encodingFormat != PixelFormat::NO_CHANGE)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// collect available device resolutions & frame rates
|
|
||||||
struct v4l2_frmsizeenum frmsizeenum;
|
|
||||||
CLEAR(frmsizeenum);
|
|
||||||
|
|
||||||
frmsizeenum.index = 0;
|
|
||||||
frmsizeenum.pixel_format = fmt.fmt.pix.pixelformat;
|
|
||||||
while (xioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) >= 0)
|
|
||||||
{
|
|
||||||
switch (frmsizeenum.type)
|
|
||||||
{
|
|
||||||
case V4L2_FRMSIZE_TYPE_DISCRETE:
|
|
||||||
{
|
{
|
||||||
properties.resolutions << QString::number(frmsizeenum.discrete.width) + "x" + QString::number(frmsizeenum.discrete.height);
|
V4L2Grabber::DeviceProperties::InputProperties::EncodingProperties encodingProperties;
|
||||||
enumFrameIntervals(properties.framerates, fd, fmt.fmt.pix.pixelformat, frmsizeenum.discrete.width, frmsizeenum.discrete.height);
|
|
||||||
|
// Enumerate frame sizes and frame rates
|
||||||
|
struct v4l2_frmsizeenum frmsizeenum;
|
||||||
|
CLEAR(frmsizeenum);
|
||||||
|
|
||||||
|
frmsizeenum.index = 0;
|
||||||
|
frmsizeenum.pixel_format = desc.pixelformat;
|
||||||
|
while (xioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) >= 0)
|
||||||
|
{
|
||||||
|
switch (frmsizeenum.type)
|
||||||
|
{
|
||||||
|
case V4L2_FRMSIZE_TYPE_DISCRETE:
|
||||||
|
{
|
||||||
|
encodingProperties.width = frmsizeenum.discrete.width;
|
||||||
|
encodingProperties.height = frmsizeenum.discrete.height;
|
||||||
|
enumFrameIntervals(encodingProperties.framerates, fd, desc.pixelformat, frmsizeenum.discrete.width, frmsizeenum.discrete.height);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
|
||||||
|
case V4L2_FRMSIZE_TYPE_STEPWISE: // We do not take care of V4L2_FRMSIZE_TYPE_CONTINUOUS or V4L2_FRMSIZE_TYPE_STEPWISE
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputProperties.encodingFormats.insert(encodingFormat, encodingProperties);
|
||||||
|
frmsizeenum.index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failsafe: In case VIDIOC_ENUM_FRAMESIZES fails, insert current heigth, width and fps.
|
||||||
|
if (xioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == -1)
|
||||||
|
{
|
||||||
|
encodingProperties.width = fmt.fmt.pix.width;
|
||||||
|
encodingProperties.height = fmt.fmt.pix.height;
|
||||||
|
enumFrameIntervals(encodingProperties.framerates, fd, desc.pixelformat, encodingProperties.width, encodingProperties.height);
|
||||||
|
inputProperties.encodingFormats.insert(encodingFormat, encodingProperties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
|
desc.index++;
|
||||||
case V4L2_FRMSIZE_TYPE_STEPWISE:
|
|
||||||
// We do not take care of V4L2_FRMSIZE_TYPE_CONTINUOUS or V4L2_FRMSIZE_TYPE_STEPWISE
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
frmsizeenum.index++;
|
|
||||||
|
properties.inputs.insert(input.index, inputProperties);
|
||||||
|
input.index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(fd) < 0) continue;
|
if (close(fd) < 0) continue;
|
||||||
@ -1238,7 +1278,7 @@ int V4L2Grabber::xioctl(int fileDescriptor, int request, void *arg)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void V4L2Grabber::enumFrameIntervals(QStringList &framerates, int fileDescriptor, int pixelformat, int width, int height)
|
void V4L2Grabber::enumFrameIntervals(QList<int> &framerates, int fileDescriptor, int pixelformat, int width, int height)
|
||||||
{
|
{
|
||||||
// collect available frame rates
|
// collect available frame rates
|
||||||
struct v4l2_frmivalenum frmivalenum;
|
struct v4l2_frmivalenum frmivalenum;
|
||||||
@ -1259,8 +1299,8 @@ void V4L2Grabber::enumFrameIntervals(QStringList &framerates, int fileDescriptor
|
|||||||
if (frmivalenum.discrete.numerator != 0)
|
if (frmivalenum.discrete.numerator != 0)
|
||||||
{
|
{
|
||||||
rate = frmivalenum.discrete.denominator / frmivalenum.discrete.numerator;
|
rate = frmivalenum.discrete.denominator / frmivalenum.discrete.numerator;
|
||||||
if (!framerates.contains(QString::number(rate)))
|
if (!framerates.contains(rate))
|
||||||
framerates.append(QString::number(rate));
|
framerates.append(rate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1270,13 +1310,24 @@ void V4L2Grabber::enumFrameIntervals(QStringList &framerates, int fileDescriptor
|
|||||||
if (frmivalenum.stepwise.min.denominator != 0)
|
if (frmivalenum.stepwise.min.denominator != 0)
|
||||||
{
|
{
|
||||||
rate = frmivalenum.stepwise.min.denominator / frmivalenum.stepwise.min.numerator;
|
rate = frmivalenum.stepwise.min.denominator / frmivalenum.stepwise.min.numerator;
|
||||||
if (!framerates.contains(QString::number(rate)))
|
if (!framerates.contains(rate))
|
||||||
framerates.append(QString::number(rate));
|
framerates.append(rate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frmivalenum.index++;
|
frmivalenum.index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If VIDIOC_ENUM_FRAMEINTERVALS fails, try to read the current fps via VIDIOC_G_PARM if possible and insert it into 'framerates'.
|
||||||
|
if (xioctl(fileDescriptor, VIDIOC_ENUM_FRAMESIZES, &frmivalenum) == -1)
|
||||||
|
{
|
||||||
|
struct v4l2_streamparm streamparms;
|
||||||
|
CLEAR(streamparms);
|
||||||
|
streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
|
||||||
|
if (xioctl(fileDescriptor, VIDIOC_G_PARM, &streamparms) >= 0)
|
||||||
|
framerates.append(streamparms.parm.capture.timeperframe.denominator / streamparms.parm.capture.timeperframe.numerator);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void V4L2Grabber::setSignalDetectionEnable(bool enable)
|
void V4L2Grabber::setSignalDetectionEnable(bool enable)
|
||||||
@ -1360,34 +1411,77 @@ bool V4L2Grabber::setFramerate(int fps)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList V4L2Grabber::getV4L2devices() const
|
QStringList V4L2Grabber::getDevices() const
|
||||||
{
|
{
|
||||||
QStringList result = QStringList();
|
QStringList result = QStringList();
|
||||||
for (auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it)
|
for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it)
|
||||||
{
|
|
||||||
result << it.key();
|
result << it.key();
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString V4L2Grabber::getV4L2deviceName(const QString& devicePath) const
|
QString V4L2Grabber::getDeviceName(const QString& devicePath) const
|
||||||
{
|
{
|
||||||
return _deviceProperties.value(devicePath).name;
|
return _deviceProperties.value(devicePath).name;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMultiMap<QString, int> V4L2Grabber::getV4L2deviceInputs(const QString& devicePath) const
|
QMultiMap<QString, int> V4L2Grabber::getDeviceInputs(const QString& devicePath) const
|
||||||
{
|
{
|
||||||
return _deviceProperties.value(devicePath).inputs;
|
QMultiMap<QString, int> result = QMultiMap<QString, int>();
|
||||||
|
for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it)
|
||||||
|
if (it.key() == devicePath)
|
||||||
|
for (auto input = it.value().inputs.begin(); input != it.value().inputs.end(); input++)
|
||||||
|
if (!result.contains(input.value().inputName, input.key()))
|
||||||
|
result.insert(input.value().inputName, input.key());
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList V4L2Grabber::getResolutions(const QString& devicePath) const
|
QStringList V4L2Grabber::getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const
|
||||||
{
|
{
|
||||||
return _deviceProperties.value(devicePath).resolutions;
|
QStringList result = QStringList();
|
||||||
|
|
||||||
|
for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it)
|
||||||
|
if (it.key() == devicePath)
|
||||||
|
for (auto input = it.value().inputs.begin(); input != it.value().inputs.end(); input++)
|
||||||
|
if (input.key() == deviceInput)
|
||||||
|
for (auto enc = input.value().encodingFormats.begin(); enc != input.value().encodingFormats.end(); enc++)
|
||||||
|
if (!result.contains(pixelFormatToString(enc.key()).toLower(), Qt::CaseInsensitive))
|
||||||
|
result << pixelFormatToString(enc.key()).toLower();
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList V4L2Grabber::getFramerates(const QString& devicePath) const
|
QMultiMap<int, int> V4L2Grabber::getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const
|
||||||
{
|
{
|
||||||
return _deviceProperties.value(devicePath).framerates;
|
QMultiMap<int, int> result = QMultiMap<int, int>();
|
||||||
|
|
||||||
|
for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it)
|
||||||
|
if (it.key() == devicePath)
|
||||||
|
for (auto input = it.value().inputs.begin(); input != it.value().inputs.end(); input++)
|
||||||
|
if (input.key() == deviceInput)
|
||||||
|
for (auto enc = input.value().encodingFormats.begin(); enc != input.value().encodingFormats.end(); enc++)
|
||||||
|
if (!result.contains(enc.value().width, enc.value().height))
|
||||||
|
result.insert(enc.value().width, enc.value().height);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList V4L2Grabber::getAvailableDeviceFramerates(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat, const unsigned width, const unsigned height) const
|
||||||
|
{
|
||||||
|
QStringList result = QStringList();
|
||||||
|
|
||||||
|
for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it)
|
||||||
|
if (it.key() == devicePath)
|
||||||
|
for (auto input = it.value().inputs.begin(); input != it.value().inputs.end(); input++)
|
||||||
|
if (input.key() == deviceInput)
|
||||||
|
for (auto enc = input.value().encodingFormats.begin(); enc != input.value().encodingFormats.end(); enc++)
|
||||||
|
if(enc.key() == encFormat && enc.value().width == width && enc.value().height == height)
|
||||||
|
for (auto fps = enc.value().framerates.begin(); fps != enc.value().framerates.end(); fps++)
|
||||||
|
if(!result.contains(QString::number(*fps)))
|
||||||
|
result << QString::number(*fps);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void V4L2Grabber::handleCecEvent(CECEvent event)
|
void V4L2Grabber::handleCecEvent(CECEvent event)
|
||||||
|
@ -128,7 +128,7 @@ void V4L2Wrapper::handleSettingsUpdate(settings::type type, const QJsonDocument&
|
|||||||
obj["cropBottom"].toInt(0));
|
obj["cropBottom"].toInt(0));
|
||||||
|
|
||||||
// device input
|
// device input
|
||||||
_grabber.setInput(obj["input"].toInt(-1));
|
_grabber.setInput(obj["input"].toInt(0));
|
||||||
|
|
||||||
// device resolution
|
// device resolution
|
||||||
_grabber.setWidthHeight(obj["width"].toInt(0), obj["height"].toInt(0));
|
_grabber.setWidthHeight(obj["width"].toInt(0), obj["height"].toInt(0));
|
||||||
|
@ -243,7 +243,7 @@ QMultiMap<QString, int> GrabberWrapper::getDeviceInputs(const QString& devicePat
|
|||||||
if(_grabberName.startsWith("V4L"))
|
if(_grabberName.startsWith("V4L"))
|
||||||
return _ggrabber->getDeviceInputs(devicePath);
|
return _ggrabber->getDeviceInputs(devicePath);
|
||||||
|
|
||||||
return {{ "", 0}};
|
return QMultiMap<QString, int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GrabberWrapper::getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const
|
QStringList GrabberWrapper::getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const
|
||||||
@ -254,12 +254,12 @@ QStringList GrabberWrapper::getAvailableEncodingFormats(const QString& devicePat
|
|||||||
return QStringList();
|
return QStringList();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GrabberWrapper::getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const
|
QMultiMap<int, int> GrabberWrapper::getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const
|
||||||
{
|
{
|
||||||
if(_grabberName.startsWith("V4L"))
|
if(_grabberName.startsWith("V4L"))
|
||||||
return _ggrabber->getAvailableDeviceResolutions(devicePath, deviceInput, encFormat);
|
return _ggrabber->getAvailableDeviceResolutions(devicePath, deviceInput, encFormat);
|
||||||
|
|
||||||
return QStringList();
|
return QMultiMap<int, int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GrabberWrapper::getAvailableDeviceFramerates(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat, const unsigned width, const unsigned height) const
|
QStringList GrabberWrapper::getAvailableDeviceFramerates(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat, const unsigned width, const unsigned height) const
|
||||||
|
Loading…
Reference in New Issue
Block a user