Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qgstreamervideooutput.cpp
Go to the documentation of this file.
1
// Copyright (C) 2021 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
"qgstreamervideooutput_p.h"
5
6
#
include
<
QtMultimedia
/
qvideosink
.
h
>
7
8
#
include
<
QtCore
/
qloggingcategory
.
h
>
9
10
#
include
<
common
/
qgstreamervideosink_p
.
h
>
11
#
include
<
common
/
qgstsubtitlesink_p
.
h
>
12
13
Q_STATIC_LOGGING_CATEGORY
(qLcMediaVideoOutput,
"qt.multimedia.videooutput"
);
14
15
QT_BEGIN_NAMESPACE
16
17
static
QGstElement makeVideoConvertScale(
const
char
*name)
18
{
19
QGstElementFactoryHandle factory = QGstElement::findFactory(
"videoconvertscale"
);
20
if
(factory)
// videoconvertscale is only available in gstreamer 1.20
21
return
QGstElement::createFromFactory(factory, name);
22
23
return
QGstBin::createFromPipelineDescription(
"videoconvert ! videoscale"
, name,
24
/*ghostUnlinkedPads=*/
true
);
25
}
26
27
q23::expected<QGstreamerVideoOutput *, QString>
QGstreamerVideoOutput
::create(QObject *parent)
28
{
29
QGstElementFactoryHandle factory = QGstElement::findFactory(
"videoconvertscale"
);
30
31
static
std::optional<QString> elementCheck = []() -> std::optional<QString> {
32
std::optional<QString> error = qGstErrorMessageIfElementsNotAvailable(
"fakesink"
,
"queue"
);
33
if
(error)
34
return
error;
35
36
QGstElementFactoryHandle factory = QGstElement::findFactory(
"videoconvertscale"
);
37
if
(factory)
38
return
std::nullopt;
39
40
return
qGstErrorMessageIfElementsNotAvailable(
"videoconvert"
,
"videoscale"
);
41
}();
42
43
if
(elementCheck)
44
return
q23::unexpected{ *elementCheck };
45
46
return
new
QGstreamerVideoOutput
(parent);
47
}
48
49
QGstreamerVideoOutput
::QGstreamerVideoOutput(QObject *parent)
50
: QObject(parent),
51
m_outputBin{
52
QGstBin::create(
"videoOutput"
),
53
},
54
m_videoQueue{
55
QGstElement::createFromFactory(
"queue"
,
"videoQueue"
),
56
},
57
m_videoConvertScale{
58
makeVideoConvertScale(
"videoConvertScale"
),
59
},
60
m_videoSink{
61
QGstElement::createFromFactory(
"fakesink"
,
"fakeVideoSink"
),
62
}
63
{
64
m_videoSink.set(
"sync"
,
true
);
65
66
m_outputBin.add(m_videoQueue, m_videoConvertScale, m_videoSink);
67
qLinkGstElements(m_videoQueue, m_videoConvertScale, m_videoSink);
68
69
m_subtitleSink = QGstSubtitleSink::createSink(
this
);
70
71
m_outputBin.addGhostPad(m_videoQueue,
"sink"
);
72
}
73
74
QGstreamerVideoOutput
::~
QGstreamerVideoOutput
()
75
{
76
QObject::disconnect(m_subtitleConnection);
77
m_outputBin.setStateSync(GST_STATE_NULL);
78
}
79
80
void
QGstreamerVideoOutput
::
setVideoSink
(
QGstreamerRelayVideoSink
*sink)
81
{
82
using
namespace
std::chrono_literals;
83
84
if
(sink == m_gstVideoSink)
85
return
;
86
87
m_gstVideoSink = sink;
88
if
(m_gstVideoSink) {
89
m_gstVideoSink->setActive(m_isActive);
90
if
(m_nativeSize.isValid())
91
m_gstVideoSink->setNativeSize(m_nativeSize);
92
}
93
QGstElement
videoSink;
94
if
(m_gstVideoSink) {
95
videoSink = m_gstVideoSink->gstSink();
96
}
else
{
97
videoSink
=
QGstElement
::
createFromFactory
(
"fakesink"
,
"fakevideosink"
)
;
98
Q_ASSERT(videoSink);
99
videoSink.set(
"sync"
,
true
);
100
}
101
102
QObject::disconnect(m_subtitleConnection);
103
if
(sink) {
104
m_subtitleConnection = QObject::connect(
this
, &QGstreamerVideoOutput::subtitleChanged, sink,
105
[sink](
const
QString &subtitle) {
106
sink->setSubtitleText(subtitle);
107
});
108
sink->setSubtitleText(m_lastSubtitleString);
109
}
110
111
if
(m_videoSink == videoSink)
112
return
;
113
114
m_videoConvertScale.src().modifyPipelineInIdleProbe([&] {
115
if
(m_videoSink)
116
m_outputBin.stopAndRemoveElements(m_videoSink);
117
118
m_videoSink = std::move(videoSink);
119
m_outputBin.add(m_videoSink);
120
121
qLinkGstElements(m_videoConvertScale, m_videoSink);
122
123
GstEvent *event = gst_event_new_reconfigure();
124
gst_element_send_event(m_videoSink.element(), event);
125
m_videoSink.syncStateWithParent();
126
});
127
128
qCDebug(qLcMediaVideoOutput) <<
"sinkChanged"
<< m_videoSink.name();
129
m_videoConvertScale.dumpPipelineGraph(m_videoSink.name().constData());
130
}
131
132
void
QGstreamerVideoOutput
::
setActive
(
bool
isActive)
133
{
134
if
(m_isActive == isActive)
135
return
;
136
137
m_isActive = isActive;
138
if
(m_gstVideoSink)
139
m_gstVideoSink->setActive(isActive);
140
}
141
142
void
QGstreamerVideoOutput
::updateNativeSize()
143
{
144
if
(!m_gstVideoSink)
145
return
;
146
147
m_gstVideoSink->setNativeSize(qRotatedFrameSize(m_nativeSize, m_rotation));
148
}
149
150
void
QGstreamerVideoOutput
::
setIsPreview
()
151
{
152
// configures the queue to be fast and lightweight for camera preview
153
// also avoids blocking the queue in case we have an encodebin attached to the tee as well
154
m_videoQueue.set(
"leaky"
, 2
/*downstream*/
);
155
m_videoQueue.set(
"silent"
,
true
);
156
m_videoQueue.set(
"max-size-buffers"
,
int
(1));
157
m_videoQueue.set(
"max-size-bytes"
,
unsigned
(0));
158
m_videoQueue.set(
"max-size-time"
, uint64_t(0));
159
}
160
161
void
QGstreamerVideoOutput
::
flushSubtitles
()
162
{
163
if
(m_subtitleSink) {
164
auto
pad = m_subtitleSink.staticPad(
"sink"
);
165
auto
*event = gst_event_new_flush_start();
166
pad.sendEvent(event);
167
event = gst_event_new_flush_stop(
false
);
168
pad.sendEvent(event);
169
}
170
}
171
172
void
QGstreamerVideoOutput
::
setNativeSize
(QSize sz)
173
{
174
m_nativeSize = sz;
175
updateNativeSize();
176
}
177
178
void
QGstreamerVideoOutput
::
setRotation
(QtVideo::Rotation rot)
179
{
180
m_rotation = rot;
181
updateNativeSize();
182
}
183
184
void
QGstreamerVideoOutput
::
updateSubtitle
(QString string)
185
{
186
// GStreamer thread
187
188
QMetaObject::invokeMethod(
this
, [
this
, string = std::move(string)]()
mutable
{
189
m_lastSubtitleString = string;
190
Q_EMIT subtitleChanged(std::move(string));
191
});
192
}
193
194
QT_END_NAMESPACE
195
196
#
include
"moc_qgstreamervideooutput_p.cpp"
QGstElement
Definition
qgst_p.h:608
QGstElement::operator=
QGstElement & operator=(QGstElement &&) noexcept=default
QGstElement::createFromFactory
static QGstElement createFromFactory(const char *factory, const char *name=nullptr)
Definition
qgst.cpp:1017
QGstreamerRelayVideoSink
Definition
qgstreamervideosink_p.h:30
QGstreamerVideoOutput
Definition
qgstreamervideooutput_p.h:32
QGstreamerVideoOutput::setVideoSink
void setVideoSink(QGstreamerRelayVideoSink *sink)
Definition
qgstreamervideooutput.cpp:80
QGstreamerVideoOutput::setNativeSize
void setNativeSize(QSize)
Definition
qgstreamervideooutput.cpp:172
QGstreamerVideoOutput::~QGstreamerVideoOutput
~QGstreamerVideoOutput() override
Definition
qgstreamervideooutput.cpp:74
QGstreamerVideoOutput::setIsPreview
void setIsPreview()
Definition
qgstreamervideooutput.cpp:150
QGstreamerVideoOutput::updateSubtitle
void updateSubtitle(QString) override
Definition
qgstreamervideooutput.cpp:184
QGstreamerVideoOutput::flushSubtitles
void flushSubtitles()
Definition
qgstreamervideooutput.cpp:161
QGstreamerVideoOutput::setActive
void setActive(bool)
Definition
qgstreamervideooutput.cpp:132
QGstreamerVideoOutput::setRotation
void setRotation(QtVideo::Rotation)
Definition
qgstreamervideooutput.cpp:178
Q_STATIC_LOGGING_CATEGORY
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
qtmultimedia
src
plugins
multimedia
gstreamer
common
qgstreamervideooutput.cpp
Generated on
for Qt by
1.18.0