summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-07-28 13:37:09 +0200
committerLars Knoll <lars.knoll@qt.io>2021-07-30 09:54:28 +0200
commitc917c16293fa9fb385fd54e08d95f11302e32337 (patch)
tree3f71372997ca5827f95a8d78387102173bc21e60
parentb2dfc5c090e16240aea11f96be289b8800d0a8bb (diff)
Add some fixes to gstreamer audio output handling
Use the regular 'pause pipeline, do changes, play' mechanism to manipulate the pipeline instead of doing the change while running. This mechanism is much more reliable, and we can issue a proper flush of the pipeline to get immediate audio changes. Also improve the code that sets the QAudioOutput in the gstreamer media player so that it can dynamically handle changes there as well. Change-Id: I38ad302ec8c81417f0d920e26ec2db213093cd9a Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: André de la Rocha <andre.rocha@qt.io>
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreameraudiooutput.cpp47
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreameraudiooutput_p.h9
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp71
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h1
4 files changed, 62 insertions, 66 deletions
diff --git a/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput.cpp b/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput.cpp
index a7a531e7f..461a7e146 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput.cpp
@@ -89,30 +89,21 @@ void QGstreamerAudioOutput::setPipeline(const QGstPipeline &pipeline)
gstPipeline = pipeline;
}
-bool QGstreamerAudioOutput::setAudioOutput(const QAudioDevice &info)
+void QGstreamerAudioOutput::setAudioDevice(const QAudioDevice &info)
{
if (info == m_audioOutput)
- return true;
+ return;
qCDebug(qLcMediaAudioOutput) << "setAudioOutput" << info.description() << info.isNull();
m_audioOutput = info;
- if (gstPipeline.isNull() || gstPipeline.state() != GST_STATE_PLAYING)
- return changeAudioOutput();
-
- auto pad = audioVolume.staticPad("src");
- pad.addProbe<&QGstreamerAudioOutput::prepareAudioOutputChange>(this, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM);
-
- return true;
-}
+ auto state = gstPipeline.isNull() ? GST_STATE_NULL : gstPipeline.state();
+ if (state == GST_STATE_PLAYING)
+ gstPipeline.setStateSync(GST_STATE_PAUSED);
+ audioSink.setStateSync(GST_STATE_NULL);
-bool QGstreamerAudioOutput::changeAudioOutput()
-{
- qCDebug(qLcMediaAudioOutput) << "Changing audio output";
QGstElement newSink;
auto *deviceInfo = static_cast<const QGStreamerAudioDeviceInfo *>(m_audioOutput.handle());
- if (!deviceInfo)
- newSink = QGstElement("fakesink", "fakeaudiosink");
- else if (deviceInfo->gstDevice)
+ if (deviceInfo && deviceInfo->gstDevice)
newSink = gst_device_create_element(deviceInfo->gstDevice , "audiosink");
if (newSink.isNull())
@@ -123,26 +114,12 @@ bool QGstreamerAudioOutput::changeAudioOutput()
gstAudioOutput.add(audioSink);
audioVolume.link(audioSink);
- return true;
-}
-
-void QGstreamerAudioOutput::prepareAudioOutputChange(const QGstPad &/*pad*/)
-{
- qCDebug(qLcMediaAudioOutput) << "Reconfiguring audio output";
-
- auto state = gstPipeline.state();
- if (state == GST_STATE_PLAYING)
- gstPipeline.setStateSync(GST_STATE_PAUSED);
- audioSink.setStateSync(GST_STATE_NULL);
- changeAudioOutput();
- audioSink.setStateSync(GST_STATE_PAUSED);
+ if (state != GST_STATE_NULL) {
+ audioSink.setState(GST_STATE_PAUSED);
+ gstPipeline.flush();
+ }
if (state == GST_STATE_PLAYING)
- gstPipeline.setStateSync(state);
-}
-
-QAudioDevice QGstreamerAudioOutput::audioOutput() const
-{
- return m_audioOutput;
+ gstPipeline.setState(state);
}
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput_p.h b/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput_p.h
index fc1a8b8db..c3b33c4f4 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput_p.h
@@ -73,11 +73,7 @@ public:
QGstreamerAudioOutput(QAudioOutput *parent);
~QGstreamerAudioOutput();
- bool setAudioOutput(const QAudioDevice &);
- QAudioDevice audioOutput() const;
-
- void setAudioDevice(const QAudioDevice &) override
- { setAudioOutput(device); }
+ void setAudioDevice(const QAudioDevice &) override;
void setVolume(float volume) override;
void setMuted(bool muted) override;
@@ -90,9 +86,6 @@ Q_SIGNALS:
void volumeChanged(int);
private:
- void prepareAudioOutputChange(const QGstPad &pad);
- bool changeAudioOutput();
-
QAudioDevice m_audioOutput;
// Gst elements
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp
index cc6771d97..b0c1c7201 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp
@@ -388,26 +388,17 @@ void QGstreamerMediaPlayer::decoderPadAdded(const QGstElement &src, const QGstPa
qCDebug(qLcMediaPlayer) << " " << caps.toString();
TrackType streamType = NTrackTypes;
- QGstElement output;
if (type.startsWith("video/x-raw")) {
streamType = VideoStream;
- output = gstVideoOutput->gstElement();
} else if (type.startsWith("audio/x-raw")) {
streamType = AudioStream;
- if (gstAudioOutput)
- output = gstAudioOutput->gstElement();
} else if (type.startsWith("text/")) {
streamType = SubtitleStream;
} else {
qCWarning(qLcMediaPlayer) << "Ignoring unknown media stream:" << pad.name() << type;
return;
}
- if (!selectorIsConnected[streamType] && !output.isNull()) {
- playerPipeline.add(output);
- inputSelector[streamType].link(output);
- output.setState(GST_STATE_PAUSED);
- selectorIsConnected[streamType] = true;
- }
+ connectOutput(streamType);
QGstPad sinkPad = inputSelector[streamType].getRequestPad("sink_%u");
if (!pad.link(sinkPad))
@@ -473,20 +464,40 @@ void QGstreamerMediaPlayer::removeAllOutputs()
videoAvailableChanged(false);
}
+void QGstreamerMediaPlayer::connectOutput(TrackType t)
+{
+ if (selectorIsConnected[t])
+ return;
+
+ QGstElement e;
+ if (t == AudioStream)
+ e = gstAudioOutput->gstElement();
+ else if (t == VideoStream)
+ e = gstVideoOutput->gstElement();
+ if (!e.isNull()) {
+ qCDebug(qLcMediaPlayer) << "connecting output for track type" << t;
+ playerPipeline.add(e);
+ inputSelector[t].link(e);
+ e.setState(GST_STATE_PAUSED);
+ selectorIsConnected[t] = true;
+ }
+}
+
void QGstreamerMediaPlayer::removeOutput(TrackType t)
{
- if (selectorIsConnected[t]) {
- QGstElement e;
- if (t == AudioStream)
- e = gstAudioOutput->gstElement();
- else if (t == VideoStream)
- e = gstVideoOutput->gstElement();
- if (!e.isNull()) {
- qCDebug(qLcMediaPlayer) << "removing output for track type" << t;
- e.setState(GST_STATE_NULL);
- playerPipeline.remove(e);
- selectorIsConnected[t] = false;
- }
+ if (!selectorIsConnected[t])
+ return;
+
+ QGstElement e;
+ if (t == AudioStream)
+ e = gstAudioOutput->gstElement();
+ else if (t == VideoStream)
+ e = gstVideoOutput->gstElement();
+ if (!e.isNull()) {
+ qCDebug(qLcMediaPlayer) << "removing output for track type" << t;
+ e.setState(GST_STATE_NULL);
+ playerPipeline.remove(e);
+ selectorIsConnected[t] = false;
}
}
@@ -590,8 +601,20 @@ void QGstreamerMediaPlayer::setAudioOutput(QPlatformAudioOutput *output)
{
if (gstAudioOutput == output)
return;
+ auto state = playerPipeline.state();
+ if (state == GST_STATE_PLAYING)
+ playerPipeline.setStateSync(GST_STATE_PAUSED);
+ if (gstAudioOutput) {
+ removeOutput(AudioStream);
+ gstAudioOutput->setPipeline({});
+ }
gstAudioOutput = static_cast<QGstreamerAudioOutput *>(output);
- // ### Connect it if we're already running!
+ if (gstAudioOutput) {
+ gstAudioOutput->setPipeline(playerPipeline);
+ connectOutput(AudioStream);
+ }
+ if (state == GST_STATE_PLAYING)
+ playerPipeline.setState(GST_STATE_PLAYING);
}
QMediaMetaData QGstreamerMediaPlayer::metaData() const
@@ -699,6 +722,8 @@ QMediaMetaData QGstreamerMediaPlayer::trackMetaData(QPlatformMediaPlayer::TrackT
GstTagList *tagList;
g_object_get(s.at(index).object(), "tags", &tagList, nullptr);
+ if (!tagList)
+ return {};
QMediaMetaData md = QGstreamerMetaData::fromGstTagList(tagList);
return md;
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h
index 37a51e4ab..f73bc3c78 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h
@@ -122,6 +122,7 @@ private:
void decoderPadRemoved(const QGstElement &src, const QGstPad &pad);
static void uridecodebinElementAddedCallback(GstElement *uridecodebin, GstElement *child, QGstreamerMediaPlayer *that);
void parseStreamsAndMetadata();
+ void connectOutput(TrackType t);
void removeOutput(TrackType t);
void removeAllOutputs();