| 1 | // Copyright (C) 2016 The Qt Company Ltd. | 
|---|---|
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | 
| 3 | |
| 4 | #ifndef QGSTREAMERCAMERACONTROL_H | 
| 5 | #define QGSTREAMERCAMERACONTROL_H | 
| 6 | |
| 7 | // | 
| 8 | // W A R N I N G | 
| 9 | // ------------- | 
| 10 | // | 
| 11 | // This file is not part of the Qt API. It exists purely as an | 
| 12 | // implementation detail. This header file may change from version to | 
| 13 | // version without notice, or even be removed. | 
| 14 | // | 
| 15 | // We mean it. | 
| 16 | // | 
| 17 | |
| 18 | #include <private/qplatformcamera_p.h> | 
| 19 | #include <private/qmultimediautils_p.h> | 
| 20 | #include <QtCore/private/quniquehandle_types_p.h> | 
| 21 | |
| 22 | #include <mediacapture/qgstreamermediacapturesession_p.h> | 
| 23 | #include <common/qgst_p.h> | 
| 24 | #include <common/qgstpipeline_p.h> | 
| 25 | |
| 26 | QT_BEGIN_NAMESPACE | 
| 27 | |
| 28 | class QGstreamerCameraBase : public QPlatformCamera | 
| 29 | { | 
| 30 | public: | 
| 31 | using QPlatformCamera::QPlatformCamera; | 
| 32 | |
| 33 | virtual QGstElement gstElement() const = 0; | 
| 34 | }; | 
| 35 | |
| 36 | class QGstreamerCamera : public QGstreamerCameraBase | 
| 37 | { | 
| 38 | public: | 
| 39 | static QMaybe<QPlatformCamera *> create(QCamera *camera); | 
| 40 | |
| 41 | ~QGstreamerCamera() override; | 
| 42 | |
| 43 | bool isActive() const override; | 
| 44 | void setActive(bool active) override; | 
| 45 | |
| 46 | void setCamera(const QCameraDevice &camera) override; | 
| 47 | bool setCameraFormat(const QCameraFormat &format) override; | 
| 48 | |
| 49 | QGstElement gstElement() const override { return gstCameraBin; } | 
| 50 | #if QT_CONFIG(gstreamer_photography) | 
| 51 | GstPhotography *photography() const; | 
| 52 | #endif | 
| 53 | |
| 54 | void setFocusMode(QCamera::FocusMode mode) override; | 
| 55 | bool isFocusModeSupported(QCamera::FocusMode mode) const override; | 
| 56 | |
| 57 | void setFlashMode(QCamera::FlashMode mode) override; | 
| 58 | bool isFlashModeSupported(QCamera::FlashMode mode) const override; | 
| 59 | bool isFlashReady() const override; | 
| 60 | |
| 61 | void setExposureMode(QCamera::ExposureMode) override; | 
| 62 | bool isExposureModeSupported(QCamera::ExposureMode mode) const override; | 
| 63 | void setExposureCompensation(float) override; | 
| 64 | void setManualIsoSensitivity(int) override; | 
| 65 | int isoSensitivity() const override; | 
| 66 | void setManualExposureTime(float) override; | 
| 67 | float exposureTime() const override; | 
| 68 | |
| 69 | bool isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const override; | 
| 70 | void setWhiteBalanceMode(QCamera::WhiteBalanceMode mode) override; | 
| 71 | void setColorTemperature(int temperature) override; | 
| 72 | |
| 73 | private: | 
| 74 | QGstreamerCamera(QCamera *camera); | 
| 75 | |
| 76 | void updateCameraProperties(); | 
| 77 | |
| 78 | #if QT_CONFIG(linux_v4l) | 
| 79 | bool isV4L2Camera() const; | 
| 80 | void initV4L2Controls(); | 
| 81 | int setV4L2ColorTemperature(int temperature); | 
| 82 | bool setV4L2Parameter(quint32 id, qint32 value); | 
| 83 | int getV4L2Parameter(quint32 id) const; | 
| 84 | |
| 85 | bool v4l2AutoWhiteBalanceSupported = false; | 
| 86 | bool v4l2ColorTemperatureSupported = false; | 
| 87 | bool v4l2AutoExposureSupported = false; | 
| 88 | bool v4l2ManualExposureSupported = false; | 
| 89 | qint32 v4l2MinColorTemp = 5600; // Daylight... | 
| 90 | qint32 v4l2MaxColorTemp = 5600; | 
| 91 | qint32 v4l2MinExposure = 0; | 
| 92 | qint32 v4l2MaxExposure = 0; | 
| 93 | qint32 v4l2MinExposureAdjustment = 0; | 
| 94 | qint32 v4l2MaxExposureAdjustment = 0; | 
| 95 | |
| 96 | template <typename Functor> | 
| 97 | auto withV4L2DeviceFileDescriptor(Functor &&f) const | 
| 98 | { | 
| 99 | using ReturnType = std::invoke_result_t<Functor, int>; | 
| 100 | Q_ASSERT(isV4L2Camera()); | 
| 101 | |
| 102 | if (int gstreamerDeviceFd = gstCamera.getInt(property: "device-fd"); gstreamerDeviceFd != -1) | 
| 103 | return f(gstreamerDeviceFd); | 
| 104 | |
| 105 | auto v4l2FileDescriptor = QUniqueFileDescriptorHandle{ | 
| 106 | QT_OPEN(pathname: m_v4l2DevicePath.toLocal8Bit().constData(), O_RDONLY), | 
| 107 | }; | 
| 108 | if (!v4l2FileDescriptor) { | 
| 109 | qWarning() << "Unable to open the camera"<< m_v4l2DevicePath | 
| 110 | << "for read to query the parameter info:"<< qt_error_string(errno); | 
| 111 | if constexpr (std::is_void_v<ReturnType>) | 
| 112 | return; | 
| 113 | else | 
| 114 | return ReturnType{}; | 
| 115 | } | 
| 116 | return f(v4l2FileDescriptor.get()); | 
| 117 | } | 
| 118 | #endif | 
| 119 | |
| 120 | QCameraDevice m_cameraDevice; | 
| 121 | |
| 122 | QGstBin gstCameraBin; | 
| 123 | QGstElement gstCamera; | 
| 124 | QGstElement gstCapsFilter; | 
| 125 | QGstElement gstDecode; | 
| 126 | QGstElement gstVideoConvert; | 
| 127 | QGstElement gstVideoScale; | 
| 128 | |
| 129 | bool m_active = false; | 
| 130 | QString m_v4l2DevicePath; | 
| 131 | |
| 132 | std::optional<QCameraFormat> m_currentCameraFormat; | 
| 133 | |
| 134 | template <typename Functor> | 
| 135 | void updateCamera(Functor &&f) | 
| 136 | { | 
| 137 | QGstPipeline pipeline = gstVideoConvert.getPipeline(); | 
| 138 | if (pipeline) | 
| 139 | pipeline.setState(GstState::GST_STATE_READY); | 
| 140 | |
| 141 | gstVideoConvert.sink().modifyPipelineInIdleProbe([&] { | 
| 142 | f(); | 
| 143 | }); | 
| 144 | |
| 145 | if (pipeline) | 
| 146 | pipeline.setState(GstState::GST_STATE_PLAYING); | 
| 147 | } | 
| 148 | }; | 
| 149 | |
| 150 | class QGstreamerCustomCamera : public QGstreamerCameraBase | 
| 151 | { | 
| 152 | public: | 
| 153 | explicit QGstreamerCustomCamera(QCamera *); | 
| 154 | explicit QGstreamerCustomCamera(QCamera *, QGstElement element); | 
| 155 | |
| 156 | QGstElement gstElement() const override { return gstCamera; } | 
| 157 | void setCamera(const QCameraDevice &) override; | 
| 158 | |
| 159 | bool isActive() const override; | 
| 160 | void setActive(bool) override; | 
| 161 | |
| 162 | private: | 
| 163 | QGstElement gstCamera; | 
| 164 | bool m_active{}; | 
| 165 | const bool m_userProvidedGstElement; | 
| 166 | }; | 
| 167 | |
| 168 | QT_END_NAMESPACE | 
| 169 | |
| 170 | #endif // QGSTREAMERCAMERACONTROL_H | 
| 171 | 
