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
26QT_BEGIN_NAMESPACE
27
28class QGstreamerCameraBase : public QPlatformCamera
29{
30public:
31 using QPlatformCamera::QPlatformCamera;
32
33 virtual QGstElement gstElement() const = 0;
34};
35
36class QGstreamerCamera : public QGstreamerCameraBase
37{
38public:
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
73private:
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
150class QGstreamerCustomCamera : public QGstreamerCameraBase
151{
152public:
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
162private:
163 QGstElement gstCamera;
164 bool m_active{};
165 const bool m_userProvidedGstElement;
166};
167
168QT_END_NAMESPACE
169
170#endif // QGSTREAMERCAMERACONTROL_H
171

source code of qtmultimedia/src/plugins/multimedia/gstreamer/mediacapture/qgstreamercamera_p.h