1// Copyright (C) 2022 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 <qgstreamerintegration_p.h>
5#include <qgstreamerformatinfo_p.h>
6#include <qgstreamervideodevices_p.h>
7#include <audio/qgstreameraudiodevice_p.h>
8#include <audio/qgstreameraudiodecoder_p.h>
9#include <common/qgstreameraudioinput_p.h>
10#include <common/qgstreameraudiooutput_p.h>
11#include <common/qgstreamermediaplayer_p.h>
12#include <common/qgstreamervideosink_p.h>
13#include <mediacapture/qgstreamercamera_p.h>
14#include <mediacapture/qgstreamerimagecapture_p.h>
15#include <mediacapture/qgstreamermediacapturesession_p.h>
16#include <mediacapture/qgstreamermediarecorder_p.h>
17#include <uri_handler/qgstreamer_qiodevice_handler_p.h>
18#include <uri_handler/qgstreamer_qrc_handler_p.h>
19
20#include <QtCore/qloggingcategory.h>
21#include <QtMultimedia/private/qmediaplayer_p.h>
22#include <QtMultimedia/private/qmediacapturesession_p.h>
23#include <QtMultimedia/private/qcameradevice_p.h>
24
25QT_BEGIN_NAMESPACE
26
27static_assert(GST_CHECK_VERSION(1, 20, 0), "Minimum required GStreamer version is 1.20");
28
29static thread_local bool inCustomCameraConstruction = false;
30static thread_local QGstElement pendingCameraElement{};
31
32QGStreamerPlatformSpecificInterfaceImplementation::
33 ~QGStreamerPlatformSpecificInterfaceImplementation() = default;
34
35QAudioDevice QGStreamerPlatformSpecificInterfaceImplementation::makeCustomGStreamerAudioInput(
36 const QByteArray &gstreamerPipeline)
37{
38 return qMakeCustomGStreamerAudioInput(gstreamerPipeline);
39}
40
41QAudioDevice QGStreamerPlatformSpecificInterfaceImplementation::makeCustomGStreamerAudioOutput(
42 const QByteArray &gstreamerPipeline)
43{
44 return qMakeCustomGStreamerAudioOutput(gstreamerPipeline);
45}
46
47QCamera *QGStreamerPlatformSpecificInterfaceImplementation::makeCustomGStreamerCamera(
48 const QByteArray &gstreamerPipeline, QObject *parent)
49{
50 QCameraDevicePrivate *info = new QCameraDevicePrivate;
51 info->id = gstreamerPipeline;
52 QCameraDevice device = info->create();
53
54 inCustomCameraConstruction = true;
55 auto guard = qScopeGuard(f: [] {
56 inCustomCameraConstruction = false;
57 });
58
59 return new QCamera(device, parent);
60}
61
62QCamera *
63QGStreamerPlatformSpecificInterfaceImplementation::makeCustomGStreamerCamera(GstElement *element,
64 QObject *parent)
65{
66 QCameraDevicePrivate *info = new QCameraDevicePrivate;
67 info->id = "Custom Camera from GstElement";
68 QCameraDevice device = info->create();
69
70 pendingCameraElement = QGstElement{
71 element,
72 QGstElement::NeedsRef,
73 };
74
75 inCustomCameraConstruction = true;
76 auto guard = qScopeGuard(f: [] {
77 inCustomCameraConstruction = false;
78 Q_ASSERT(!pendingCameraElement);
79 });
80
81 return new QCamera(device, parent);
82}
83
84GstPipeline *QGStreamerPlatformSpecificInterfaceImplementation::gstPipeline(QMediaPlayer *player)
85{
86 auto *priv = reinterpret_cast<QMediaPlayerPrivate *>(QMediaPlayerPrivate::get(session: player));
87 if (!priv)
88 return nullptr;
89
90 QGstreamerMediaPlayer *gstreamerPlayer = dynamic_cast<QGstreamerMediaPlayer *>(priv->control);
91 return gstreamerPlayer ? gstreamerPlayer->pipeline().pipeline() : nullptr;
92}
93
94GstPipeline *
95QGStreamerPlatformSpecificInterfaceImplementation::gstPipeline(QMediaCaptureSession *session)
96{
97 auto *priv = QMediaCaptureSessionPrivate::get(session);
98 if (!priv)
99 return nullptr;
100
101 QGstreamerMediaCaptureSession *gstreamerCapture =
102 dynamic_cast<QGstreamerMediaCaptureSession *>(priv->captureSession.get());
103 return gstreamerCapture ? gstreamerCapture->pipeline().pipeline() : nullptr;
104}
105
106Q_LOGGING_CATEGORY(lcGstreamer, "qt.multimedia.gstreamer")
107
108namespace {
109
110void rankDownPlugin(GstRegistry *reg, const char *name)
111{
112 QGstPluginFeatureHandle pluginFeature{
113 gst_registry_lookup_feature(registry: reg, name),
114 QGstPluginFeatureHandle::HasRef,
115 };
116 if (pluginFeature)
117 gst_plugin_feature_set_rank(feature: pluginFeature.get(), rank: GST_RANK_PRIMARY - 1);
118}
119
120// https://gstreamer.freedesktop.org/documentation/vaapi/index.html
121constexpr auto vaapiPluginNames = {
122 "vaapidecodebin", "vaapih264dec", "vaapih264enc", "vaapih265dec",
123 "vaapijpegdec", "vaapijpegenc", "vaapimpeg2dec", "vaapipostproc",
124 "vaapisink", "vaapivp8dec", "vaapivp9dec",
125};
126
127// https://gstreamer.freedesktop.org/documentation/va/index.html
128constexpr auto vaPluginNames = {
129 "vaav1dec", "vacompositor", "vadeinterlace", "vah264dec", "vah264enc", "vah265dec",
130 "vajpegdec", "vampeg2dec", "vapostproc", "vavp8dec", "vavp9dec",
131};
132
133// https://gstreamer.freedesktop.org/documentation/nvcodec/index.html
134constexpr auto nvcodecPluginNames = {
135 "cudaconvert", "cudaconvertscale", "cudadownload", "cudaipcsink", "cudaipcsrc",
136 "cudascale", "cudaupload", "nvautogpuh264enc", "nvautogpuh265enc", "nvav1dec",
137 "nvcudah264enc", "nvcudah265enc", "nvd3d11h264enc", "nvd3d11h265enc", "nvh264dec",
138 "nvh264enc", "nvh265dec", "nvh265enc", "nvjpegdec", "nvjpegenc",
139 "nvmpeg2videodec", "nvmpeg4videodec", "nvmpegvideodec", "nvvp8dec", "nvvp9dec",
140};
141
142} // namespace
143
144QGstreamerIntegration::QGstreamerIntegration()
145 : QPlatformMediaIntegration(QLatin1String("gstreamer"))
146{
147 gst_init(argc: nullptr, argv: nullptr);
148 qCDebug(lcGstreamer) << "Using gstreamer version: " << gst_version_string();
149
150 GstRegistry *reg = gst_registry_get();
151
152 if constexpr (!GST_CHECK_VERSION(1, 22, 0)) {
153 GstRegistry* reg = gst_registry_get();
154 for (const char *name : vaapiPluginNames)
155 rankDownPlugin(reg, name);
156 }
157
158 if (qEnvironmentVariableIsSet(varName: "QT_GSTREAMER_DISABLE_VA")) {
159 for (const char *name : vaPluginNames)
160 rankDownPlugin(reg, name);
161 }
162
163 if (qEnvironmentVariableIsSet(varName: "QT_GSTREAMER_DISABLE_NVCODEC")) {
164 for (const char *name : nvcodecPluginNames)
165 rankDownPlugin(reg, name);
166 }
167
168 qGstRegisterQRCHandler(plugin: nullptr);
169 qGstRegisterQIODeviceHandler(plugin: nullptr);
170}
171
172QPlatformMediaFormatInfo *QGstreamerIntegration::createFormatInfo()
173{
174 return new QGstreamerFormatInfo();
175}
176
177QPlatformVideoDevices *QGstreamerIntegration::createVideoDevices()
178{
179 return new QGstreamerVideoDevices(this);
180}
181
182const QGstreamerFormatInfo *QGstreamerIntegration::gstFormatsInfo()
183{
184 return static_cast<const QGstreamerFormatInfo *>(formatInfo());
185}
186
187QMaybe<QPlatformAudioDecoder *> QGstreamerIntegration::createAudioDecoder(QAudioDecoder *decoder)
188{
189 return QGstreamerAudioDecoder::create(parent: decoder);
190}
191
192QMaybe<QPlatformMediaCaptureSession *> QGstreamerIntegration::createCaptureSession()
193{
194 return QGstreamerMediaCaptureSession::create();
195}
196
197QMaybe<QPlatformMediaPlayer *> QGstreamerIntegration::createPlayer(QMediaPlayer *player)
198{
199 return QGstreamerMediaPlayer::create(parent: player);
200}
201
202QMaybe<QPlatformCamera *> QGstreamerIntegration::createCamera(QCamera *camera)
203{
204 if (inCustomCameraConstruction) {
205 QGstElement element = std::exchange(obj&: pendingCameraElement, new_val: {});
206 return element ? new QGstreamerCustomCamera{ camera, std::move(element) }
207 : new QGstreamerCustomCamera{ camera };
208 }
209
210 return QGstreamerCamera::create(camera);
211}
212
213QMaybe<QPlatformMediaRecorder *> QGstreamerIntegration::createRecorder(QMediaRecorder *recorder)
214{
215 return new QGstreamerMediaRecorder(recorder);
216}
217
218QMaybe<QPlatformImageCapture *> QGstreamerIntegration::createImageCapture(QImageCapture *imageCapture)
219{
220 return QGstreamerImageCapture::create(parent: imageCapture);
221}
222
223QMaybe<QPlatformVideoSink *> QGstreamerIntegration::createVideoSink(QVideoSink *sink)
224{
225 return new QGstreamerVideoSink(sink);
226}
227
228QMaybe<QPlatformAudioInput *> QGstreamerIntegration::createAudioInput(QAudioInput *q)
229{
230 return QGstreamerAudioInput::create(parent: q);
231}
232
233QMaybe<QPlatformAudioOutput *> QGstreamerIntegration::createAudioOutput(QAudioOutput *q)
234{
235 return QGstreamerAudioOutput::create(parent: q);
236}
237
238GstDevice *QGstreamerIntegration::videoDevice(const QByteArray &id)
239{
240 const auto devices = videoDevices();
241 return devices ? static_cast<QGstreamerVideoDevices *>(devices)->videoDevice(id) : nullptr;
242}
243
244QAbstractPlatformSpecificInterface *QGstreamerIntegration::platformSpecificInterface()
245{
246 return &m_platformSpecificImplementation;
247}
248
249QT_END_NAMESPACE
250

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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