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 |