11#if QT_CONFIG(gstreamer_gl)
12#include <QGuiApplication>
13#include <QtGui/qopenglcontext.h>
15#include <qpa/qplatformnativeinterface.h>
16#include <gst/gl/gstglconfig.h>
18#if GST_GL_HAVE_WINDOW_X11 && __has_include("X11/Xlib-xcb.h")
19# include <gst/gl/x11/gstgldisplay_x11.h>
21#if GST_GL_HAVE_PLATFORM_EGL
22# include <gst/gl/egl/gstgldisplay_egl.h>
24# include <EGL/eglext.h>
26#if GST_GL_HAVE_WINDOW_WAYLAND && __has_include("wayland-client.h")
27# include <gst/gl/wayland/gstgldisplay_wayland.h>
31#include <QtCore/qdebug.h>
33#include <QtCore/qloggingcategory.h>
58 qgetenv(
"QT_MULTIMEDIA_GSTREAMER_OVERRIDE_VIDEO_CONVERSION_ELEMENT");
59 if (!preprocessOverride.isEmpty()) {
60 qCDebug(qLcGstVideoSink) <<
"requesting conversion element from environment: "
61 << preprocessOverride;
63 gst_element_factory_find(preprocessOverride.constData()),
69 gst_element_factory_find(
"imxvideoconvert_g2d"),
74 gst_element_factory_find(
"nvvidconv"),
78 qCDebug(qLcGstVideoSink) <<
"instantiating conversion element: "
80 gst_element_factory_get_element_type(
factory.get()));
85 bool disablePixelAspectRatio =
87 if (disablePixelAspectRatio) {
99 gst_caps_new_simple(
"video/x-raw",
"pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL),
102 g_object_set(gstCapsFilter.
element(),
"caps", capsFilterCaps.caps(), NULL);
106 sinkBin.
add(gstQueue, gstPreprocess, gstCapsFilter);
109 sinkBin.
add(gstQueue, gstCapsFilter);
135 gstPipeline = std::move(pipeline);
154 if (!gstQtSink.
isNull()) {
161void QGstreamerVideoSink::createQtSink()
170void QGstreamerVideoSink::updateSinkElement()
177 if (newSink == gstVideoSink)
181 if (!gstVideoSink.
isNull())
184 newSink.set(
"async",
false);
186 gstVideoSink = newSink;
187 sinkBin.
add(gstVideoSink);
189 gstVideoSink.
setState(GST_STATE_PAUSED);
192 gstPipeline.
dumpGraph(
"updateVideoSink");
195void QGstreamerVideoSink::unrefGstContexts()
197 m_gstGlDisplayContext.close();
198 m_gstGlLocalContext.close();
199 m_eglDisplay =
nullptr;
200 m_eglImageTargetTexture2D =
nullptr;
203void QGstreamerVideoSink::updateGstContexts()
207#if QT_CONFIG(gstreamer_gl)
212 auto glContext = nativeHandles->context;
217 m_eglDisplay = pni->nativeResourceForIntegration(
"egldisplay");
220 QGstGLDisplayHandle gstGlDisplay;
222 const char *contextName =
"eglcontext";
223 GstGLPlatform glPlatform = GST_GL_PLATFORM_EGL;
226#if GST_GL_HAVE_PLATFORM_EGL
228 GST_GL_DISPLAY_CAST(gst_gl_display_egl_new_with_egl_display(m_eglDisplay)));
229 m_eglImageTargetTexture2D = eglGetProcAddress(
"glEGLImageTargetTexture2DOES");
232 auto display = pni->nativeResourceForIntegration(
"display");
235#if GST_GL_HAVE_WINDOW_X11 && __has_include("X11/Xlib-xcb.h")
237 contextName =
"glxcontext";
238 glPlatform = GST_GL_PLATFORM_GLX;
240 gstGlDisplay.reset(GST_GL_DISPLAY_CAST(
241 gst_gl_display_x11_new_with_display(
reinterpret_cast<Display *
>(
display))));
244#if GST_GL_HAVE_WINDOW_WAYLAND && __has_include("wayland-client.h")
247 gstGlDisplay.reset(GST_GL_DISPLAY_CAST(gst_gl_display_wayland_new_with_display(
248 reinterpret_cast<struct wl_display *
>(
display))));
255 qWarning() <<
"Could not create GstGLDisplay";
259 void *nativeContext = pni->nativeResourceForContext(contextName, glContext);
261 qWarning() <<
"Could not find resource for" << contextName;
264 QGstGLContextHandle appContext{
265 gst_gl_context_new_wrapped(gstGlDisplay.get(), guintptr(nativeContext), glPlatform, glApi),
268 qWarning() <<
"Could not create wrappped context for platform:" << glPlatform;
270 gst_gl_context_activate(appContext.get(),
true);
273 gst_gl_context_fill_info(appContext.get(), &
error);
279 QGstGLContextHandle displayContext;
280 gst_gl_display_create_context(gstGlDisplay.get(), appContext.get(), &displayContext, &
error);
286 m_gstGlDisplayContext.reset(gst_context_new(GST_GL_DISPLAY_CONTEXT_TYPE,
false));
287 gst_context_set_gl_display(m_gstGlDisplayContext.get(), gstGlDisplay.get());
289 m_gstGlLocalContext.reset(gst_context_new(
"gst.gl.local_context",
false));
290 GstStructure *structure = gst_context_writable_structure(m_gstGlLocalContext.get());
291 gst_structure_set(structure,
"context", GST_TYPE_GL_CONTEXT, displayContext.get(),
nullptr);
292 displayContext.close();
294 if (!gstPipeline.
isNull())
295 gst_element_set_context(gstPipeline.
element(), m_gstGlLocalContext.get());
301#include "moc_qgstreamervideosink_p.cpp"
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void add)(const Ts &...ts)
static QGstBin create(const char *name)
void addGhostPad(const QGstElement &child, const char *name)
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void stopAndRemoveElements)(Ts... ts)
GstStateChangeReturn setState(GstState state)
GstElement * element() const
bool setStateSync(GstState state, std::chrono::nanoseconds timeout=std::chrono::seconds(1))
static QGstElement createFromFactory(const char *factory, const char *name=nullptr)
bool inStoppedState() const
void dumpGraph(const char *fileName)
void modifyPipelineWhileNotRunning(Functor &&fn)
static QGstSubtitleSink * createSink(QGstreamerVideoSink *sink)
static QGstVideoRendererSink * createSink(QGstreamerVideoSink *surface)
QGstreamerVideoSink(QVideoSink *parent=nullptr)
bool inStoppedState() const
void setPipeline(QGstPipeline pipeline)
void aboutToBeDestroyed()
void setRhi(QRhi *rhi) override
static QPlatformNativeInterface * platformNativeInterface()
QString platformName
The name of the underlying platform plugin.
static OpenGLModuleType openGLModuleType()
Returns the underlying OpenGL implementation type.
\variable QRhiGles2InitParams::format
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Implementation backend() const
const QRhiNativeHandles * nativeHandles()
\macro QT_RESTRICTED_CAST_FROM_ASCII
The QVideoSink class represents a generic sink for video data.
struct wl_display * display
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void qLinkGstElements)(const Ts &...ts)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
QLatin1StringView QLatin1String
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
QItemEditorFactory * factory