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
qgstreameraudiooutput.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
6
7#include <QtMultimedia/qaudiodevice.h>
8#include <QtMultimedia/qaudiooutput.h>
9#include <QtCore/qloggingcategory.h>
10
11#include <utility>
12
13static Q_LOGGING_CATEGORY(qLcMediaAudioOutput, "qt.multimedia.audiooutput")
14
16
18{
19 QGstElement audioconvert = QGstElement::createFromFactory("audioconvert", "audioConvert");
20 if (!audioconvert)
21 return errorMessageCannotFindElement("audioconvert");
22
23 QGstElement audioresample = QGstElement::createFromFactory("audioresample", "audioResample");
24 if (!audioresample)
25 return errorMessageCannotFindElement("audioresample");
26
27 QGstElement volume = QGstElement::createFromFactory("volume", "volume");
28 if (!volume)
29 return errorMessageCannotFindElement("volume");
30
31 QGstElement autoaudiosink = QGstElement::createFromFactory("autoaudiosink", "autoAudioSink");
32 if (!autoaudiosink)
33 return errorMessageCannotFindElement("autoaudiosink");
34
35 return new QGstreamerAudioOutput(audioconvert, audioresample, volume, autoaudiosink, parent);
36}
37
38QGstreamerAudioOutput::QGstreamerAudioOutput(QGstElement audioconvert, QGstElement audioresample,
39 QGstElement volume, QGstElement autoaudiosink,
40 QAudioOutput *parent)
41 : QObject(parent),
43 gstAudioOutput(QGstBin::create("audioOutput")),
44 audioConvert(std::move(audioconvert)),
45 audioResample(std::move(audioresample)),
46 audioVolume(std::move(volume)),
47 audioSink(std::move(autoaudiosink))
48{
49 audioQueue = QGstElement::createFromFactory("queue", "audioQueue");
50 gstAudioOutput.add(audioQueue, audioConvert, audioResample, audioVolume, audioSink);
51 qLinkGstElements(audioQueue, audioConvert, audioResample, audioVolume, audioSink);
52
53 gstAudioOutput.addGhostPad(audioQueue, "sink");
54}
55
56QGstElement QGstreamerAudioOutput::createGstElement()
57{
58 const auto *customDeviceInfo =
59 dynamic_cast<const QGStreamerCustomAudioDeviceInfo *>(m_audioOutput.handle());
60
61 if (customDeviceInfo) {
62 qCDebug(qLcMediaAudioOutput)
63 << "requesting custom audio sink element: " << customDeviceInfo->id;
64
65 QGstElement element =
66 QGstBin::createFromPipelineDescription(customDeviceInfo->id, /*name=*/nullptr,
67 /*ghostUnlinkedPads=*/true);
68 if (element)
69 return element;
70
71 qCWarning(qLcMediaAudioOutput)
72 << "Cannot create audio sink element:" << customDeviceInfo->id;
73 }
74
75 const QByteArray &id = m_audioOutput.id();
76 if constexpr (QT_CONFIG(pulseaudio)) {
77 QGstElement newSink = QGstElement::createFromFactory("pulsesink", "audiosink");
78 if (newSink) {
79 newSink.set("device", id.constData());
80 return newSink;
81 } else {
82 qWarning() << "Cannot create pulsesink";
83 }
84 } else if constexpr (QT_CONFIG(alsa)) {
85 QGstElement newSink = QGstElement::createFromFactory("alsasink", "audiosink");
86 if (newSink) {
87 newSink.set("device", id.constData());
88 return newSink;
89 } else {
90 qWarning() << "Cannot create alsasink";
91 }
92 } else {
93 auto *deviceInfo = dynamic_cast<const QGStreamerAudioDeviceInfo *>(m_audioOutput.handle());
94 if (deviceInfo && deviceInfo->gstDevice) {
95 QGstElement element = QGstElement::createFromDevice(deviceInfo->gstDevice, "audiosink");
96 if (element)
97 return element;
98 }
99 }
100 qCWarning(qLcMediaAudioOutput) << "Invalid audio device:" << m_audioOutput.id();
101 qCWarning(qLcMediaAudioOutput)
102 << "Failed to create a gst element for the audio device, using a default audio sink";
103 return QGstElement::createFromFactory("autoaudiosink", "audiosink");
104}
105
107{
108 gstAudioOutput.setStateSync(GST_STATE_NULL);
109}
110
112{
113 audioVolume.set("volume", volume);
114}
115
117{
118 audioVolume.set("mute", muted);
119}
120
122{
123 if (info == m_audioOutput)
124 return;
125 qCDebug(qLcMediaAudioOutput) << "setAudioOutput" << info.description() << info.isNull();
126
127 m_audioOutput = info;
128
129 QGstElement newSink = createGstElement();
130
132 qUnlinkGstElements(audioVolume, audioSink);
133 gstAudioOutput.stopAndRemoveElements(audioSink);
134 audioSink = std::move(newSink);
135 gstAudioOutput.add(audioSink);
136 audioSink.syncStateWithParent();
137 qLinkGstElements(audioVolume, audioSink);
138 });
139}
140
The QAudioDevice class provides an information about audio devices and their functionality.
QByteArray id
\qmlproperty string QtMultimedia::audioDevice::id
const QAudioDevicePrivate * handle() const
\qmltype AudioOutput \instantiates QAudioOutput
\inmodule QtCore
Definition qbytearray.h:57
static QGstBin createFromPipelineDescription(const QByteArray &pipelineDescription, const char *name=nullptr, bool ghostUnlinkedPads=false)
Definition qgst.cpp:1073
static QGstElement createFromDevice(const QGstDeviceHandle &, const char *name=nullptr)
Definition qgst.cpp:866
bool setStateSync(GstState state, std::chrono::nanoseconds timeout=std::chrono::seconds(1))
Definition qgst.cpp:947
static QGstElement createFromFactory(const char *factory, const char *name=nullptr)
Definition qgst.cpp:835
QGstPipeline getPipeline() const
Definition qgst.cpp:1039
void set(const char *property, const char *str)
Definition qgst.cpp:538
void modifyPipelineWhileNotRunning(Functor &&fn)
void setAudioDevice(const QAudioDevice &) override
void setVolume(float) override
\inmodule QtCore
Definition qobject.h:103
Combined button and popup list for selecting options.
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void qLinkGstElements)(const Ts &...ts)
Definition qgst_p.h:643
QString errorMessageCannotFindElement(std::string_view element)
Definition qgst_p.h:804
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define QT_CONFIG(feature)
QHostInfo info
[0]
view create()