Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qgstreamervideooverlay.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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
5
6#include <QtGui/qguiapplication.h>
7#include <QtMultimedia/private/qtmultimediaglobal_p.h>
8
10#include <common/qgst_p.h>
13#include <common/qgstutils_p.h>
14
15#include <gst/video/videooverlay.h>
16
18
20{
22 const char *gstreamerElement = nullptr;
23};
24
25// Ordered by descending priority
26static constexpr ElementMap elementMap[] = {
27 { u"xcb", "xvimagesink" },
28 { u"xcb", "ximagesink" },
29
30 // wayland
31 { u"wayland", "waylandsink" },
32};
33
35{
36 GstStateChangeReturn ret = element.setState(GST_STATE_READY);
37 if (ret == GST_STATE_CHANGE_SUCCESS) {
38 element.setState(GST_STATE_NULL);
39 return true;
40 }
41
42 return false;
43}
44
46{
47 using namespace Qt::StringLiterals;
49
50 // First, try some known video sinks, depending on the Qt platform plugin in use.
51 for (const auto &i : elementMap) {
52 if (platform != i.qtPlatform)
53 continue;
54 QGstElement choice = QGstElement::createFromFactory(i.gstreamerElement, i.gstreamerElement);
55 if (choice.isNull())
56 continue;
57
59 return choice;
60 }
61
62 // We need a native window ID to use the GstVideoOverlay interface.
63 // Bail out if the Qt platform plugin in use cannot provide a sensible WId.
64 if (platform != QStringView{ u"xcb" } && platform != QStringView{ u"wayland" })
65 return {};
66
67 QGstElement choice;
68 // If none of the known video sinks are available, try to find one that implements the
69 // GstVideoOverlay interface and has autoplugging rank.
70 GList *list = qt_gst_video_sinks();
71 for (GstElementFactory *f : QGstUtils::GListRangeAdaptor<GstElementFactory *>(list)) {
72 if (!gst_element_factory_has_interface(f, "GstVideoOverlay"))
73 continue;
74
75 choice = QGstElement::createFromFactory(f, nullptr);
76 if (choice.isNull())
77 continue;
78
80 break;
81 choice = {};
82 }
83
84 gst_plugin_feature_list_free(list);
85 if (choice.isNull())
86 qWarning() << "Could not find a valid windowed video sink";
87
88 return choice;
89}
90
92 : QObject(parent)
94 , m_gstreamerVideoSink(parent)
95{
97 if (!elementName.isEmpty())
99 else
101
103}
104
106{
107 if (!m_videoSink.isNull()) {
108 QGstPad pad = m_videoSink.staticPad("sink");
109 removeProbeFromPad(pad.pad());
110 }
111}
112
114{
115 return m_videoSink;
116}
117
119{
120 if (sink.isNull())
121 return;
122
123 m_videoSink = std::move(sink);
124
125 QGstPad pad = m_videoSink.staticPad("sink");
126 addProbeToPad(pad.pad());
127
128 auto *klass = G_OBJECT_GET_CLASS(m_videoSink.object());
129 m_hasForceAspectRatio = g_object_class_find_property(klass, "force-aspect-ratio");
130 m_hasFullscreen = g_object_class_find_property(klass, "fullscreen");
131}
132
134{
135 return m_nativeVideoSize;
136}
137
139{
140 m_windowId = id;
141
142 if (!m_videoSink.isNull() && GST_IS_VIDEO_OVERLAY(m_videoSink.object())) {
143 applyRenderRect();
144
145 // Properties need to be reset when changing the winId.
146 setAspectRatioMode(m_aspectRatioMode);
147 setFullScreen(m_fullScreen);
148 applyRenderRect();
149 }
150}
151
153{
154 renderRect = rect;
155 applyRenderRect();
156}
157
158void QGstreamerVideoOverlay::applyRenderRect()
159{
160 if (!m_windowId)
161 return;
162
163 int x = -1;
164 int y = -1;
165 int w = -1;
166 int h = -1;
167
168 if (!renderRect.isEmpty()) {
169 x = renderRect.x();
170 y = renderRect.y();
171 w = renderRect.width();
172 h = renderRect.height();
173 QSize scaledVideo = m_nativeVideoSize.scaled(w, h, m_aspectRatioMode);
174 x += (w - scaledVideo.width())/2;
175 y += (h - scaledVideo.height())/2;
176 w = scaledVideo.width();
177 h = scaledVideo.height();
178 }
179
180 if (!m_videoSink.isNull() && GST_IS_VIDEO_OVERLAY(m_videoSink.object()))
181 gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink.object()), x, y, w, h);
182}
183
185{
187 if (size != m_nativeVideoSize) {
188 m_nativeVideoSize = size;
189 m_gstreamerVideoSink->setNativeSize(m_nativeVideoSize);
190 applyRenderRect();
191 }
192}
193
195{
196 m_aspectRatioMode = mode;
197 if (m_hasForceAspectRatio)
198 m_videoSink.set("force-aspect-ratio", (mode == Qt::KeepAspectRatio));
199}
200
202{
203 m_fullScreen = fullscreen;
204 if (m_hasFullscreen)
205 m_videoSink.set("fullscreen", fullscreen);
206}
207
209{
210 if (!gst_is_video_overlay_prepare_window_handle_message(message.message()))
211 return false;
212 gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videoSink.object()), m_windowId);
213 return true;
214}
215
217
218#include "moc_qgstreamervideooverlay_p.cpp"
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
QGstStructure at(int index) const
Definition qgst.cpp:521
GstStateChangeReturn setState(GstState state)
Definition qgst.cpp:942
QGstPad staticPad(const char *name) const
Definition qgst.cpp:898
static QGstElement createFromFactory(const char *factory, const char *name=nullptr)
Definition qgst.cpp:835
void set(const char *property, const char *str)
Definition qgst.cpp:538
GstObject * object() const
Definition qgst.cpp:677
GstPad * pad() const
Definition qgst.cpp:782
QSize resolution() const
Definition qgst.cpp:190
void removeProbeFromPad(GstPad *pad)
void addProbeToPad(GstPad *pad, bool downstream=true)
QGstreamerVideoOverlay(QGstreamerVideoSink *parent=nullptr, const QByteArray &elementName=QByteArray())
void setAspectRatioMode(Qt::AspectRatioMode mode)
void setRenderRectangle(const QRect &rect)
bool processSyncMessage(const QGstreamerMessage &message) override
void probeCaps(GstCaps *caps) override
void setFullScreen(bool fullscreen)
QString platformName
The name of the underlying platform plugin.
\inmodule QtCore
Definition qobject.h:103
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
Definition qrect.h:167
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
\inmodule QtCore
Definition qsize.h:25
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
QSize scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept
Definition qsize.h:151
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
rect
[4]
Combined button and popup list for selecting options.
AspectRatioMode
@ KeepAspectRatio
static QGstElement findBestVideoSink()
static bool qt_gst_element_is_functioning(QGstElement element)
static constexpr ElementMap elementMap[]
GList * qt_gst_video_sinks()
#define qWarning
Definition qlogging.h:166
return ret
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint id
[7]
GLfloat GLfloat f
GLuint GLsizei const GLchar * message
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLenum GLboolean sink
QT_BEGIN_NAMESPACE Platform platform()
QList< int > list
[14]
const char * gstreamerElement