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/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");
40 const QByteArray &gstreamerPipeline)
42 return qMakeCustomGStreamerAudioInput(gstreamerPipeline);
46 const QByteArray &gstreamerPipeline)
48 return qMakeCustomGStreamerAudioOutput(gstreamerPipeline);
52 const QByteArray &gstreamerPipeline, QObject *parent)
54 QCameraDevicePrivate *info =
new QCameraDevicePrivate;
55 info->id = gstreamerPipeline;
56 QCameraDevice device = info->create();
59 auto guard = qScopeGuard([] {
63 return new QCamera(device, parent);
70 QCameraDevicePrivate *info =
new QCameraDevicePrivate;
71 info->id =
"Custom Camera from GstElement";
72 QCameraDevice device = info->create();
74 pendingCameraElement = QGstElement{
76 QGstElement::NeedsRef,
80 auto guard = qScopeGuard([] {
85 return new QCamera(device, parent);
90 auto *priv =
reinterpret_cast<QMediaPlayerPrivate *>(QMediaPlayerPrivate::get(player));
95 return gstreamerPlayer ? gstreamerPlayer
->pipeline().pipeline() :
nullptr;
101 auto *priv = QMediaCaptureSessionPrivate::get(session);
105 QGstreamerMediaCaptureSession *gstreamerCapture =
106 dynamic_cast<QGstreamerMediaCaptureSession *>(priv->captureSession.get());
107 return gstreamerCapture ? gstreamerCapture
->pipeline().pipeline() :
nullptr;
112 QHwVideoBuffer *hwBuffer = QVideoFramePrivate::hwBuffer(frame);
115 QGstVideoBuffer *gstBuffer =
dynamic_cast<QGstVideoBuffer *>(hwBuffer);
116 return gstBuffer ? gstBuffer->gstBuffer() :
nullptr;
120 GstBuffer *buffer,
const GstVideoInfo &videoInfo)
123 return QVideoFrame();
127 return qCreateFrameFromGstBuffer(QGstBufferHandle{ buffer, QGstBufferHandle::NeedsRef },
132 GstBuffer *buffer,
const GstVideoInfoDmaDrm &videoInfoDmaDrm)
136 Q_UNUSED(videoInfoDmaDrm);
137 qWarning() << QStringLiteral(
"GstVideoInfoDmaDrm unsupported, minimum GStreamer version required: 1.24");
138 return QVideoFrame();
141 return QVideoFrame();
143 QGstVideoInfo qtVideoInfo{ { }, videoInfoDmaDrm.drm_modifier };
144 if (!gst_video_info_dma_drm_to_video_info(&videoInfoDmaDrm, &qtVideoInfo.gstVideoInfo))
145 qWarning() <<
"Failed to create QGstVideoInfo from GstVideoInfoDmaDrm";
147 return qCreateFrameFromGstBuffer(QGstBufferHandle{ buffer, QGstBufferHandle::NeedsRef },
156void rankDownPlugin(GstRegistry *reg,
const char *name)
158 QGstPluginFeatureHandle pluginFeature{
159 gst_registry_lookup_feature(reg, name),
160 QGstPluginFeatureHandle::HasRef,
163 gst_plugin_feature_set_rank(pluginFeature.get(), GST_RANK_PRIMARY - 1);
167constexpr auto vaapiPluginNames = {
168 "vaapidecodebin",
"vaapih264dec",
"vaapih264enc",
"vaapih265dec",
169 "vaapijpegdec",
"vaapijpegenc",
"vaapimpeg2dec",
"vaapipostproc",
170 "vaapisink",
"vaapivp8dec",
"vaapivp9dec",
174constexpr auto vaPluginNames = {
175 "vaav1dec",
"vacompositor",
"vadeinterlace",
"vah264dec",
"vah264enc",
"vah265dec",
176 "vajpegdec",
"vampeg2dec",
"vapostproc",
"vavp8dec",
"vavp9dec",
180constexpr auto nvcodecPluginNames = {
181 "cudaconvert",
"cudaconvertscale",
"cudadownload",
"cudaipcsink",
"cudaipcsrc",
182 "cudascale",
"cudaupload",
"nvautogpuh264enc",
"nvautogpuh265enc",
"nvav1dec",
183 "nvcudah264enc",
"nvcudah265enc",
"nvd3d11h264enc",
"nvd3d11h265enc",
"nvh264dec",
184 "nvh264enc",
"nvh265dec",
"nvh265enc",
"nvjpegdec",
"nvjpegenc",
185 "nvmpeg2videodec",
"nvmpeg4videodec",
"nvmpegvideodec",
"nvvp8dec",
"nvvp9dec",
193 gst_init(
nullptr,
nullptr);
195 const QGString version{ gst_version_string() };
196 qCInfo(lcGstreamer) <<
"Using Qt multimedia with GStreamer version:" << version.asStringView();
198 GstRegistry *reg = gst_registry_get();
200 if constexpr (!GST_CHECK_VERSION(1, 22, 0)) {
201 for (
const char *name : vaapiPluginNames)
202 rankDownPlugin(reg, name);
205 if (qEnvironmentVariableIsSet(
"QT_GSTREAMER_DISABLE_VA")) {
206 for (
const char *name : vaPluginNames)
207 rankDownPlugin(reg, name);
210 if (qEnvironmentVariableIsSet(
"QT_GSTREAMER_DISABLE_NVCODEC")) {
211 for (
const char *name : nvcodecPluginNames)
212 rankDownPlugin(reg, name);
224 if (qEnvironmentVariableIsSet(
"QT_GSTREAMER_DEINIT"))
235 return new QGstreamerVideoDevices(
this);
245 return QGstreamerAudioDecoder::create(decoder);
250 return QGstreamerMediaCaptureSession::create();
255 return QGstreamerMediaPlayer::create(player);
261 QGstElement element = std::exchange(pendingCameraElement, {});
266 return QGstreamerCamera::create(camera);
276 return QGstreamerImageCapture::create(imageCapture);
286 return QGstreamerAudioInput::create(q);
291 return QGstreamerAudioOutput::create(q);
296 const GstElementOrDescription &elementOrDesc)
298#if QT_CONFIG(gstreamer_qt_api)
299 using namespace Qt::Literals;
300 auto createImpl = [videoSource](
const auto &arg) -> q23::expected<QPlatformCamera *, QString> {
302 if constexpr (std::is_same_v<
decltype(arg),
const QString &>) {
304 return q23::unexpected{ u"GstBin description is empty"_s };
305 element = QGstBin::createFromPipelineDescription(arg.toUtf8(),
nullptr,
308 return q23::unexpected{ u"Failed to create GstBin from description"_s };
311 return q23::unexpected{ u"GstElement is null"_s };
313 element = QGstElement{ arg, QGstElement::NeedsRef };
316 return new QGstreamerCustomCamera(videoSource, std::move(element));
318 return std::visit(createImpl, elementOrDesc);
320 return QPlatformMediaIntegration::createGStreamerVideoSource(videoSource, elementOrDesc);
326 const auto devices = videoDevices();
327 return devices ?
static_cast<QGstreamerVideoDevices *>(devices)->videoDevice(id) :
nullptr;
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
QGStreamerPlatformSpecificInterfaceImplementation m_platformSpecificImplementation
QAbstractPlatformSpecificInterface * platformSpecificInterface() 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
q23::expected< QPlatformCamera *, QString > createGStreamerVideoSource(QGStreamerVideoSource *, const GstElementOrDescription &) override
GstDevice * videoDevice(const QByteArray &id)
q23::expected< QPlatformAudioInput *, QString > createAudioInput(QAudioInput *) override
Combined button and popup list for selecting options.
#define QT_GSTREAMER_SUPPORTS_GST_VIDEO_FORMAT_DMA_DRM
void qGstRegisterQIODeviceHandler(GstPlugin *plugin)
QT_BEGIN_NAMESPACE void qGstRegisterQRCHandler(GstPlugin *plugin)
static bool inCustomCameraConstruction
static QGstElement pendingCameraElement
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)