1// Copyright (C) 2021 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#include "qgstreamervideodevices_p.h"
5#include "qmediadevices.h"
6#include "private/qcameradevice_p.h"
7
8#include "qgstreameraudiosource_p.h"
9#include "qgstreameraudiosink_p.h"
10#include "qgstreameraudiodevice_p.h"
11#include "qgstutils_p.h"
12
13QT_BEGIN_NAMESPACE
14
15static gboolean deviceMonitor(GstBus *, GstMessage *message, gpointer m)
16{
17 auto *manager = static_cast<QGstreamerVideoDevices *>(m);
18 GstDevice *device = nullptr;
19
20 switch (GST_MESSAGE_TYPE (message)) {
21 case GST_MESSAGE_DEVICE_ADDED:
22 gst_message_parse_device_added(message, device: &device);
23 manager->addDevice(device);
24 break;
25 case GST_MESSAGE_DEVICE_REMOVED:
26 gst_message_parse_device_removed(message, device: &device);
27 manager->removeDevice(device);
28 break;
29 default:
30 break;
31 }
32 if (device)
33 gst_object_unref (object: device);
34
35 return G_SOURCE_CONTINUE;
36}
37
38QGstreamerVideoDevices::QGstreamerVideoDevices(QPlatformMediaIntegration *integration)
39 : QPlatformVideoDevices(integration)
40{
41 GstDeviceMonitor *monitor;
42 GstBus *bus;
43
44 monitor = gst_device_monitor_new();
45
46 gst_device_monitor_add_filter (monitor, classes: nullptr, caps: nullptr);
47
48 bus = gst_device_monitor_get_bus(monitor);
49 gst_bus_add_watch(bus, func: deviceMonitor, user_data: this);
50 gst_object_unref(object: bus);
51
52 gst_device_monitor_start(monitor);
53
54 auto devices = gst_device_monitor_get_devices(monitor);
55
56 while (devices) {
57 GstDevice *device = static_cast<GstDevice *>(devices->data);
58 addDevice(device);
59 gst_object_unref(object: device);
60 devices = g_list_delete_link(list: devices, link_: devices);
61 }
62}
63
64QList<QCameraDevice> QGstreamerVideoDevices::videoDevices() const
65{
66 QList<QCameraDevice> devices;
67
68 for (auto device : m_videoSources) {
69 QCameraDevicePrivate *info = new QCameraDevicePrivate;
70 auto *desc = gst_device_get_display_name(device: device.gstDevice);
71 info->description = QString::fromUtf8(utf8: desc);
72 g_free(mem: desc);
73 info->id = device.id;
74
75 if (QGstStructure properties = gst_device_get_properties(device: device.gstDevice); !properties.isNull()) {
76 auto def = properties["is-default"].toBool();
77 info->isDefault = def && *def;
78 properties.free();
79 }
80
81 if (info->isDefault)
82 devices.prepend(t: info->create());
83 else
84 devices.append(t: info->create());
85
86 auto caps = QGstCaps(gst_device_get_caps(device: device.gstDevice), QGstCaps::HasRef);
87 if (!caps.isNull()) {
88 QList<QCameraFormat> formats;
89 QSet<QSize> photoResolutions;
90
91 int size = caps.size();
92 for (int i = 0; i < size; ++i) {
93 auto cap = caps.at(index: i);
94
95 QSize resolution = cap.resolution();
96 if (!resolution.isValid())
97 continue;
98
99 auto pixelFormat = cap.pixelFormat();
100 auto frameRate = cap.frameRateRange();
101
102 auto *f = new QCameraFormatPrivate{
103 QSharedData(),
104 .pixelFormat: pixelFormat,
105 .resolution: resolution,
106 .minFrameRate: frameRate.min,
107 .maxFrameRate: frameRate.max
108 };
109 formats << f->create();
110 photoResolutions.insert(value: resolution);
111 }
112 info->videoFormats = formats;
113 // ### sort resolutions?
114 info->photoResolutions = photoResolutions.values();
115 }
116 }
117 return devices;
118}
119
120void QGstreamerVideoDevices::addDevice(GstDevice *device)
121{
122 if (gst_device_has_classes(device, classes: "Video/Source")) {
123 gst_object_ref(object: device);
124 m_videoSources.push_back(x: {.gstDevice: device, .id: QByteArray::number(m_idGenerator)});
125 emit videoInputsChanged();
126 m_idGenerator++;
127 }
128}
129
130void QGstreamerVideoDevices::removeDevice(GstDevice *device)
131{
132 auto it = std::find_if(first: m_videoSources.begin(), last: m_videoSources.end(),
133 pred: [=](const QGstDevice &a) { return a.gstDevice == device; });
134
135 if (it != m_videoSources.end()) {
136 m_videoSources.erase(position: it);
137 emit videoInputsChanged();
138 }
139
140 gst_object_unref(object: device);
141}
142
143GstDevice *QGstreamerVideoDevices::videoDevice(const QByteArray &id) const
144{
145 auto it = std::find_if(first: m_videoSources.begin(), last: m_videoSources.end(),
146 pred: [=](const QGstDevice &a) { return a.id == id; });
147 return it != m_videoSources.end() ? it->gstDevice : nullptr;
148}
149
150QT_END_NAMESPACE
151

source code of qtmultimedia/src/plugins/multimedia/gstreamer/qgstreamervideodevices.cpp