39 gst_device_monitor_add_filter(m_deviceMonitor.get(),
"Video/Source",
nullptr);
41 m_busObserver.installMessageFilter(
this);
42 gst_device_monitor_start(m_deviceMonitor.get());
44 GList *devices = gst_device_monitor_get_devices(m_deviceMonitor.get());
46 for (GstDevice *device : QGstUtils::GListRangeAdaptor<GstDevice *>(devices)) {
47 addDevice(QGstDeviceHandle{
49 QGstDeviceHandle::HasRef,
63 QList<QCameraDevice> devices;
65 for (
const auto &device : m_videoSources) {
66 QCameraDevicePrivate *info =
new QCameraDevicePrivate;
69 gst_device_get_display_name(device.gstDevice.get()),
71 info->description = desc.toQString();
74 QUniqueGstStructureHandle properties{
75 gst_device_get_properties(device.gstDevice.get()),
78 QGstStructureView view{ properties };
79 auto def = view[
"is-default"].toBool();
80 info->isDefault = def && *def;
84 devices.prepend(info->create());
86 devices.append(info->create());
88 auto caps = QGstCaps(gst_device_get_caps(device.gstDevice.get()), QGstCaps::HasRef);
90 QList<QCameraFormat> formats;
91 QSet<QSize> photoResolutions;
93 int size = caps.size();
94 for (
int i = 0; i < size; ++i) {
95 auto cap = caps.at(i);
96 auto pixelFormat = cap.pixelFormat();
97 auto frameRate = cap.frameRateRange();
99 if (pixelFormat == QVideoFrameFormat::PixelFormat::Format_Invalid) {
100 qCDebug(ltVideoDevices) <<
"pixel format not supported:" << cap;
104 auto addFormatForResolution = [&](QSize resolution) {
105 auto *f =
new QCameraFormatPrivate{
106 QSharedData(), pixelFormat, resolution, frameRate.min, frameRate.max,
108 formats.append(f->create());
109 photoResolutions.insert(resolution);
112 std::optional<QGRange<QSize>> resolutionRange = cap.resolutionRange();
113 if (resolutionRange) {
114 addFormatForResolution(resolutionRange->min);
115 addFormatForResolution(resolutionRange->max);
117 QSize resolution = cap.resolution();
118 if (resolution.isValid())
119 addFormatForResolution(resolution);
122 info->videoFormats = formats;
124 info->photoResolutions = photoResolutions.values();
130void QGstreamerVideoDevices::
addDevice(QGstDeviceHandle device)
132 Q_ASSERT(gst_device_has_classes(device.get(),
"Video/Source"));
134#if QT_CONFIG(linux_v4l)
135 QUniqueGstStructureHandle structureHandle{
136 gst_device_get_properties(device.get()),
139 const auto *p = QGstStructureView(structureHandle.get())[
"device.path"].toString();
141 QUniqueFileDescriptorHandle fd{
142 qt_safe_open(p, O_RDONLY),
146 qCDebug(ltVideoDevices) <<
"Cannot open v4l2 device:" << p;
150 struct v4l2_capability cap;
151 if (::ioctl(fd.get(), VIDIOC_QUERYCAP, &cap) < 0) {
152 qCWarning(ltVideoDevices)
153 <<
"ioctl failed: VIDIOC_QUERYCAP" << qt_error_string(errno) << p;
157 if (cap.device_caps & V4L2_CAP_META_CAPTURE) {
158 qCDebug(ltVideoDevices) <<
"V4L2_CAP_META_CAPTURE device detected" << p;
162 constexpr uint32_t videoCaptureCapabilities =
163 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
165 if (!(cap.capabilities & videoCaptureCapabilities)) {
166 qCDebug(ltVideoDevices)
167 <<
"not a V4L2_CAP_VIDEO_CAPTURE or V4L2_CAP_VIDEO_CAPTURE_MPLANE device" << p;
170 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
171 qCDebug(ltVideoDevices) <<
"not a V4L2_CAP_STREAMING device" << p;
176 if (::ioctl(fd.get(), VIDIOC_G_INPUT, &index) < 0) {
179 qCDebug(ltVideoDevices) <<
"device does not have video inputs" << p;
183 qCWarning(ltVideoDevices)
184 <<
"ioctl failed: VIDIOC_G_INPUT" << qt_error_string(errno) << p;
189 qCDebug(ltVideoDevices) <<
"Video device not a v4l2 device:" << structureHandle;
193 auto it = std::find_if(m_videoSources.begin(), m_videoSources.end(),
194 [&](
const QGstRecordDevice &a) {
return a.gstDevice == device; });
196 if (it != m_videoSources.end())
199 m_videoSources.push_back(QGstRecordDevice{
201 QByteArray::number(m_idGenerator),
206 onVideoInputsChanged();
211 auto it = std::find_if(m_videoSources.begin(), m_videoSources.end(),
212 [&](
const QGstRecordDevice &a) {
return a.gstDevice == device; });
214 if (it != m_videoSources.end()) {
215 m_videoSources.erase(it);
216 onVideoInputsChanged();
222 QGstDeviceHandle device;
224 switch (message.type()) {
225 case GST_MESSAGE_DEVICE_ADDED:
226 gst_message_parse_device_added(message.message(), &device);
227 addDevice(std::move(device));
229 case GST_MESSAGE_DEVICE_REMOVED:
230 gst_message_parse_device_removed(message.message(), &device);
231 removeDevice(std::move(device));