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>
20#if QT_CONFIG(gstreamer_qt_api)
21# include <QtMultimedia/spi/qgstreamervideosource.h>
23#include <QtCore/qloggingcategory.h>
24#include <QtMultimedia/private/qmediaplayer_p.h>
25#include <QtMultimedia/private/qmediacapturesession_p.h>
26#include <QtMultimedia/private/qcameradevice_p.h>
27#include <QtMultimedia/private/qvideoframe_p.h>
31static_assert(GST_CHECK_VERSION(1, 20, 0),
"Minimum required GStreamer version is 1.20");
33#if QT_CONFIG(gstreamer_qt_api)
37thread_local std::optional<GstElementOrDescription> customCameraContructionInput = { };
39QCamera *makeCustomGStreamerCameraImpl(QByteArray id, GstElementOrDescription elementOrDesc,
42 QCameraDevicePrivate *info =
new QCameraDevicePrivate;
43 info->id = std::move(id);
44 QCameraDevice device = info->create();
46 Q_ASSERT(!customCameraContructionInput);
47 customCameraContructionInput = std::move(elementOrDesc);
49 auto resetCustomCameraInput = qScopeGuard([] {
50 customCameraContructionInput.reset();
53 return new QCamera(device, parent);
56q23::expected<QPlatformCamera *, QString>
57createGStreamerVideoSourceImpl(QObject *videoSource,
const GstElementOrDescription &elementOrDesc)
59 using namespace Qt::Literals;
60 auto createImpl = [videoSource](
const auto &arg) -> q23::expected<QPlatformCamera *, QString> {
62 if constexpr (std::is_same_v<
decltype(arg),
const QString &>) {
64 return q23::unexpected{ u"GstBin description is empty"_s };
65 element = QGstBin::createFromPipelineDescription(arg.toUtf8(),
nullptr,
68 return q23::unexpected{ u"Failed to create GstBin from description"_s };
71 return q23::unexpected{ u"GstElement is null"_s };
73 element = QGstElement{ arg, QGstElement::NeedsRef };
76 return new QGstreamerCustomCamera(videoSource, std::move(element));
78 return std::visit(createImpl, elementOrDesc);
83QGStreamerInterfaceImplementation::~QGStreamerInterfaceImplementation() =
default;
85QAudioDevice QGStreamerInterfaceImplementation::makeCustomGStreamerAudioInput(
86 const QByteArray &gstreamerPipeline)
88 return qMakeCustomGStreamerAudioInput(gstreamerPipeline);
91QAudioDevice QGStreamerInterfaceImplementation::makeCustomGStreamerAudioOutput(
92 const QByteArray &gstreamerPipeline)
94 return qMakeCustomGStreamerAudioOutput(gstreamerPipeline);
98QGStreamerInterfaceImplementation::makeCustomGStreamerCamera(
const QByteArray &gstBinDescription,
101 return makeCustomGStreamerCameraImpl(gstBinDescription, QString::fromUtf8(gstBinDescription),
105QCamera *QGStreamerInterfaceImplementation::makeCustomGStreamerCamera(
106 GstElement *element, QObject *parent)
108 return makeCustomGStreamerCameraImpl(
"Custom Camera from GstElement", element, parent);
111GstPipeline *QGStreamerInterfaceImplementation::gstPipeline(QMediaPlayer *player)
113 auto *priv =
reinterpret_cast<QMediaPlayerPrivate *>(QMediaPlayerPrivate::get(player));
117 QGstreamerMediaPlayer *gstreamerPlayer =
dynamic_cast<QGstreamerMediaPlayer *>(priv->control);
118 return gstreamerPlayer ? gstreamerPlayer->pipeline().pipeline() :
nullptr;
122QGStreamerInterfaceImplementation::gstPipeline(QMediaCaptureSession *session)
124 auto *priv = QMediaCaptureSessionPrivate::get(session);
128 QGstreamerMediaCaptureSession *gstreamerCapture =
129 dynamic_cast<QGstreamerMediaCaptureSession *>(priv->captureSession.get());
130 return gstreamerCapture ? gstreamerCapture->pipeline().pipeline() :
nullptr;
133GstBuffer *QGStreamerInterfaceImplementation::gstBuffer(
const QVideoFrame &frame)
135 QHwVideoBuffer *hwBuffer = QVideoFramePrivate::hwBuffer(frame);
138 QGstVideoBuffer *gstBuffer =
dynamic_cast<QGstVideoBuffer *>(hwBuffer);
139 return gstBuffer ? gstBuffer->gstBuffer() :
nullptr;
142QVideoFrame QGStreamerInterfaceImplementation::createFrameFromGstBuffer(
143 GstBuffer *buffer,
const GstVideoInfo &videoInfo)
146 return QVideoFrame();
148 QGstVideoInfo qtVideoInfo{ videoInfo, std::nullopt };
150 return qCreateFrameFromGstBuffer(QGstBufferHandle{ buffer, QGstBufferHandle::NeedsRef },
154QVideoFrame QGStreamerInterfaceImplementation::createFrameFromGstBuffer(
155 GstBuffer *buffer,
const GstVideoInfoDmaDrm &videoInfoDmaDrm)
157#if !QT_GSTREAMER_SUPPORTS_GST_VIDEO_FORMAT_DMA_DRM
159 Q_UNUSED(videoInfoDmaDrm);
160 qWarning() << QStringLiteral(
"GstVideoInfoDmaDrm unsupported, minimum GStreamer version required: 1.24");
161 return QVideoFrame();
164 return QVideoFrame();
166 QGstVideoInfo qtVideoInfo{ { }, videoInfoDmaDrm.drm_modifier };
167 if (!gst_video_info_dma_drm_to_video_info(&videoInfoDmaDrm, &qtVideoInfo.gstVideoInfo))
168 qWarning() <<
"Failed to create QGstVideoInfo from GstVideoInfoDmaDrm";
170 return qCreateFrameFromGstBuffer(QGstBufferHandle{ buffer, QGstBufferHandle::NeedsRef },
181void rankDownPlugin(GstRegistry *reg,
const char *name)
183 QGstPluginFeatureHandle pluginFeature{
184 gst_registry_lookup_feature(reg, name),
185 QGstPluginFeatureHandle::HasRef,
188 gst_plugin_feature_set_rank(pluginFeature.get(), GST_RANK_PRIMARY - 1);
192constexpr auto vaapiPluginNames = {
193 "vaapidecodebin",
"vaapih264dec",
"vaapih264enc",
"vaapih265dec",
194 "vaapijpegdec",
"vaapijpegenc",
"vaapimpeg2dec",
"vaapipostproc",
195 "vaapisink",
"vaapivp8dec",
"vaapivp9dec",
199constexpr auto vaPluginNames = {
200 "vaav1dec",
"vacompositor",
"vadeinterlace",
"vah264dec",
"vah264enc",
"vah265dec",
201 "vajpegdec",
"vampeg2dec",
"vapostproc",
"vavp8dec",
"vavp9dec",
205constexpr auto nvcodecPluginNames = {
206 "cudaconvert",
"cudaconvertscale",
"cudadownload",
"cudaipcsink",
"cudaipcsrc",
207 "cudascale",
"cudaupload",
"nvautogpuh264enc",
"nvautogpuh265enc",
"nvav1dec",
208 "nvcudah264enc",
"nvcudah265enc",
"nvd3d11h264enc",
"nvd3d11h265enc",
"nvh264dec",
209 "nvh264enc",
"nvh265dec",
"nvh265enc",
"nvjpegdec",
"nvjpegenc",
210 "nvmpeg2videodec",
"nvmpeg4videodec",
"nvmpegvideodec",
"nvvp8dec",
"nvvp9dec",
218 gst_init(
nullptr,
nullptr);
220 const QGString version{ gst_version_string() };
221 qCInfo(lcGstreamer) <<
"Using Qt multimedia with GStreamer version:" << version.asStringView();
223 GstRegistry *reg = gst_registry_get();
225 if constexpr (!GST_CHECK_VERSION(1, 22, 0)) {
226 for (
const char *name : vaapiPluginNames)
227 rankDownPlugin(reg, name);
230 if (qEnvironmentVariableIsSet(
"QT_GSTREAMER_DISABLE_VA")) {
231 for (
const char *name : vaPluginNames)
232 rankDownPlugin(reg, name);
235 if (qEnvironmentVariableIsSet(
"QT_GSTREAMER_DISABLE_NVCODEC")) {
236 for (
const char *name : nvcodecPluginNames)
237 rankDownPlugin(reg, name);
249 if (qEnvironmentVariableIsSet(
"QT_GSTREAMER_DEINIT"))
260 return new QGstreamerVideoDevices(
this);
270 return QGstreamerAudioDecoder::create(decoder);
275 return QGstreamerMediaCaptureSession::create();
280 return QGstreamerMediaPlayer::create(player);
285#if QT_CONFIG(gstreamer_qt_api)
286 if (customCameraContructionInput)
287 return createGStreamerVideoSourceImpl(camera, *customCameraContructionInput);
290 return QGstreamerCamera::create(camera);
300 return QGstreamerImageCapture::create(imageCapture);
310 return QGstreamerAudioInput::create(q);
315 return QGstreamerAudioOutput::create(q);
320 const auto devices = videoDevices();
321 return devices ?
static_cast<QGstreamerVideoDevices *>(devices)->videoDevice(id) :
nullptr;
324#if QT_CONFIG(gstreamer_qt_api)
325q23::expected<QPlatformCamera *, QString>
326QGstreamerIntegration::createGStreamerVideoSource(QGStreamerVideoSource *videoSource,
327 const GstElementOrDescription &elementOrDesc)
329 return createGStreamerVideoSourceImpl(videoSource, elementOrDesc);
332QGStreamerInterface *QGstreamerIntegration::gstreamerInterface()
334 return &m_gstreamerInterface;
q23::expected< QPlatformCamera *, QString > createCamera(QCamera *) override
QPlatformVideoDevices * createVideoDevices() override
QPlatformMediaFormatInfo * createFormatInfo() override
q23::expected< QPlatformAudioOutput *, QString > createAudioOutput(QAudioOutput *) override
q23::expected< QPlatformVideoSink *, QString > createVideoSink(QVideoSink *sink) override
~QGstreamerIntegration() override
q23::expected< QPlatformMediaCaptureSession *, QString > createCaptureSession() override
q23::expected< QPlatformMediaPlayer *, QString > createPlayer(QMediaPlayer *player) override
q23::expected< QPlatformMediaRecorder *, QString > createRecorder(QMediaRecorder *) override
const QGstreamerFormatInfo * gstFormatsInfo()
q23::expected< QPlatformAudioDecoder *, QString > createAudioDecoder(QAudioDecoder *decoder) override
q23::expected< QPlatformImageCapture *, QString > createImageCapture(QImageCapture *) override
GstDevice * videoDevice(const QByteArray &id)
q23::expected< QPlatformAudioInput *, QString > createAudioInput(QAudioInput *) override
Combined button and popup list for selecting options.
void qGstRegisterQIODeviceHandler(GstPlugin *plugin)
QT_BEGIN_NAMESPACE void qGstRegisterQRCHandler(GstPlugin *plugin)
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)