diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-05-20 15:59:41 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-05-21 12:28:01 +0000 |
commit | bf0f87dc4f4480efe51b8ba5b5706f8c1ce7a4fb (patch) | |
tree | 51e28a0602ac5983cc7fe16cd0a71b61a602b832 /src | |
parent | 9d2b2a97450095de4a13fd1c3b8d06a4a012bc61 (diff) |
Improve V4L2 support
Check for exposure times and adjustments and implement support
for setting those if the camera supports them.
Check for those in the camerabackend test.
Change-Id: I860b2e7b94ef27e64a62e800cb6c05bfa6134250
Reviewed-by: André de la Rocha <andre.rocha@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp | 110 | ||||
-rw-r--r-- | src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera_p.h | 8 |
2 files changed, 92 insertions, 26 deletions
diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp index 2ac1da4b4..d1d848e4c 100644 --- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp +++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp @@ -66,7 +66,14 @@ QGstreamerCamera::QGstreamerCamera(QCamera *camera) gstCameraBin.addGhostPad(gstVideoScale, "src"); } -QGstreamerCamera::~QGstreamerCamera() = default; +QGstreamerCamera::~QGstreamerCamera() +{ +#if QT_CONFIG(linux_v4l) + if (v4l2FileDescriptor >= 0) + qt_safe_close(v4l2FileDescriptor); + v4l2FileDescriptor = -1; +#endif +} bool QGstreamerCamera::isActive() const { @@ -289,6 +296,17 @@ bool QGstreamerCamera::isFlashReady() const void QGstreamerCamera::setExposureMode(QCamera::ExposureMode mode) { +#if QT_CONFIG(linux_v4l) + if (isV4L2Camera() && v4l2AutoExposureSupported && v4l2ManualExposureSupported) { + if (mode != QCamera::ExposureAuto && mode != QCamera::ExposureManual) + return; + int value = QCamera::ExposureAuto ? V4L2_EXPOSURE_AUTO : V4L2_EXPOSURE_MANUAL; + setV4L2Parameter(V4L2_CID_EXPOSURE_AUTO, value); + exposureModeChanged(mode); + return; + } +#endif + auto *p = photography(); if (!p) return; @@ -357,14 +375,29 @@ void QGstreamerCamera::setExposureMode(QCamera::ExposureMode mode) bool QGstreamerCamera::isExposureModeSupported(QCamera::ExposureMode mode) const { + if (mode == QCamera::ExposureAuto) + return true; +#if QT_CONFIG(linux_v4l) + if (isV4L2Camera() && v4l2ManualExposureSupported && v4l2AutoExposureSupported) + return mode == QCamera::ExposureManual; +#endif if (photography()) return true; - return mode == QCamera::ExposureAuto; + return false; } void QGstreamerCamera::setExposureCompensation(float compensation) { +#if QT_CONFIG(linux_v4l) + if (isV4L2Camera() && (v4l2MinExposureAdjustment != 0 || v4l2MaxExposureAdjustment != 0)) { + int value = qBound(v4l2MinExposureAdjustment, (int)(compensation*1000), v4l2MaxExposureAdjustment); + setV4L2Parameter(V4L2_CID_AUTO_EXPOSURE_BIAS, value); + exposureCompensationChanged(value/1000.); + return; + } +#endif + if (auto *p = photography()) { if (gst_photography_set_ev_compensation(p, compensation)) exposureCompensationChanged(compensation); @@ -391,6 +424,15 @@ int QGstreamerCamera::isoSensitivity() const void QGstreamerCamera::setManualShutterSpeed(float secs) { +#if QT_CONFIG(linux_v4l) + if (isV4L2Camera() && v4l2ManualExposureSupported && v4l2AutoExposureSupported) { + int exposure = qBound(v4l2MinExposure, qRound(secs*10000.), v4l2MaxExposure); + setV4L2Parameter(V4L2_CID_EXPOSURE_ABSOLUTE, exposure); + shutterSpeedChanged(exposure/10000.); + return; + } +#endif + if (auto *p = photography()) { if (gst_photography_set_exposure(p, guint(secs*1000000))) shutterSpeedChanged(secs); @@ -526,8 +568,8 @@ void QGstreamerCamera::initV4L2Controls() const QString deviceName = v4l2Device(); Q_ASSERT(!deviceName.isEmpty()); - const int fd = qt_safe_open(deviceName.toLocal8Bit().constData(), O_RDONLY); - if (fd == -1) { + v4l2FileDescriptor = qt_safe_open(deviceName.toLocal8Bit().constData(), O_RDONLY); + if (v4l2FileDescriptor == -1) { qWarning() << "Unable to open the camera" << deviceName << "for read to query the parameter info:" << qt_error_string(errno); return; @@ -537,24 +579,42 @@ void QGstreamerCamera::initV4L2Controls() ::memset(&queryControl, 0, sizeof(queryControl)); queryControl.id = V4L2_CID_AUTO_WHITE_BALANCE; - if (::ioctl(fd, VIDIOC_QUERYCTRL, &queryControl) == 0) { + if (::ioctl(v4l2FileDescriptor, VIDIOC_QUERYCTRL, &queryControl) == 0) { v4l2AutoWhiteBalanceSupported = true; struct v4l2_control control; control.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE; control.value = true; - ::ioctl(fd, VIDIOC_S_CTRL, &control); + ::ioctl(v4l2FileDescriptor, VIDIOC_S_CTRL, &control); } ::memset(&queryControl, 0, sizeof(queryControl)); queryControl.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE; - if (::ioctl(fd, VIDIOC_QUERYCTRL, &queryControl) == 0) { + if (::ioctl(v4l2FileDescriptor, VIDIOC_QUERYCTRL, &queryControl) == 0) { v4l2MinColorTemp = queryControl.minimum; v4l2MaxColorTemp = queryControl.maximum; v4l2ColorTemperatureSupported = true; } - qt_safe_close(fd); + ::memset(&queryControl, 0, sizeof(queryControl)); + queryControl.id = V4L2_CID_EXPOSURE_AUTO; + if (::ioctl(v4l2FileDescriptor, VIDIOC_QUERYCTRL, &queryControl) == 0) { + v4l2AutoExposureSupported = true; + } + + ::memset(&queryControl, 0, sizeof(queryControl)); + queryControl.id = V4L2_CID_EXPOSURE_ABSOLUTE; + if (::ioctl(v4l2FileDescriptor, VIDIOC_QUERYCTRL, &queryControl) == 0) { + v4l2ManualExposureSupported = true; + v4l2MinExposure = queryControl.minimum; + v4l2MaxExposure = queryControl.maximum; + } + ::memset(&queryControl, 0, sizeof(queryControl)); + queryControl.id = V4L2_CID_AUTO_EXPOSURE_BIAS; + if (::ioctl(v4l2FileDescriptor, VIDIOC_QUERYCTRL, &queryControl) == 0) { + v4l2MinExposureAdjustment = queryControl.minimum; + v4l2MaxExposureAdjustment = queryControl.maximum; + } } int QGstreamerCamera::setV4L2ColorTemperature(int temperature) @@ -562,38 +622,36 @@ int QGstreamerCamera::setV4L2ColorTemperature(int temperature) struct v4l2_control control; ::memset(&control, 0, sizeof(control)); - const int fd = qt_safe_open(v4l2Device().toLocal8Bit().constData(), O_RDONLY); - if (fd == -1) { - qWarning() << "Unable to open the camera" << v4l2Device() - << "for read to get the parameter value:" << qt_error_string(errno); - return 0; - } - if (v4l2AutoWhiteBalanceSupported) { - control.id = V4L2_CID_AUTO_WHITE_BALANCE; - control.value = temperature == 0 ? true : false; - if (::ioctl(fd, VIDIOC_S_CTRL, &control) != 0) { - qWarning() << "Unable to set the V4L2 AUTO_WHITE_BALANCE property" << qt_error_string(errno); - } + setV4L2Parameter(V4L2_CID_AUTO_WHITE_BALANCE, temperature == 0 ? true : false); } else if (temperature == 0) { temperature = 5600; } if (temperature != 0 && v4l2ColorTemperatureSupported) { temperature = qBound(v4l2MinColorTemp, temperature, v4l2MaxColorTemp); - control.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE; - control.value = qBound(v4l2MinColorTemp, temperature, v4l2MaxColorTemp); - if (::ioctl(fd, VIDIOC_S_CTRL, &control) != 0) { - qWarning() << "Unable to set the V4L2 AUTO_WHITE_BALANCE property" << qt_error_string(errno); + if (!setV4L2Parameter(V4L2_CID_WHITE_BALANCE_TEMPERATURE, qBound(v4l2MinColorTemp, temperature, v4l2MaxColorTemp))) temperature = 0; - } } else { temperature = 0; } - qt_safe_close(fd); return temperature; } + +bool QGstreamerCamera::setV4L2Parameter(quint32 id, qint32 value) +{ + struct v4l2_control control; + ::memset(&control, 0, sizeof(control)); + control.id = id; + control.value = value; + if (::ioctl(v4l2FileDescriptor, VIDIOC_S_CTRL, &control) != 0) { + qWarning() << "Unable to set the V4L2 Parameter" << Qt::hex << id << "to" << value << qt_error_string(errno); + return false; + } + return true; +} + #endif #endif diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera_p.h b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera_p.h index 54064e399..82a7c2c75 100644 --- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera_p.h +++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera_p.h @@ -108,11 +108,19 @@ private: #if QT_CONFIG(linux_v4l) void initV4L2Controls(); int setV4L2ColorTemperature(int temperature); + bool setV4L2Parameter(quint32 id, qint32 value); bool v4l2AutoWhiteBalanceSupported = false; bool v4l2ColorTemperatureSupported = false; + bool v4l2AutoExposureSupported = false; + bool v4l2ManualExposureSupported = false; qint32 v4l2MinColorTemp = 5600; // Daylight... qint32 v4l2MaxColorTemp = 5600; + qint32 v4l2MinExposure = 0; + qint32 v4l2MaxExposure = 0; + qint32 v4l2MinExposureAdjustment = 0; + qint32 v4l2MaxExposureAdjustment = 0; + int v4l2FileDescriptor = -1; #endif QGstreamerMediaCapture *m_session = nullptr; |