diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-07-28 12:14:40 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-07-30 09:54:22 +0200 |
commit | b2dfc5c090e16240aea11f96be289b8800d0a8bb (patch) | |
tree | 46719c0ad1d5af35320b41a4d925281ca48ac211 | |
parent | 82367bd22c3d6c793bf05d91b641a3356f687d5b (diff) |
Move rate handling into QGstPipeline
This makes it possible to keep state there, simplifies the API and
makes it possible to add a flush() call there that can be accessed
from outside the QGStreamerMediaPlayer class.
Change-Id: I34bbc2111b72139c9c06132ba2a6bf278e8be07d
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: André de la Rocha <andre.rocha@qt.io>
3 files changed, 47 insertions, 27 deletions
diff --git a/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h b/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h index 1f4f6ee05..28ccba6e8 100644 --- a/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h @@ -112,19 +112,35 @@ public: #endif } + void flush() { seek(position(), m_rate); } + bool seek(qint64 pos, double rate) { - return gst_element_seek(element(), rate, GST_FORMAT_TIME, - GstSeekFlags(GST_SEEK_FLAG_FLUSH), - GST_SEEK_TYPE_SET, pos, - GST_SEEK_TYPE_SET, -1); + // always adjust the rate, so it can be set before playback starts + // setting position needs a loaded media file that's seekable + m_rate = rate; + bool success = gst_element_seek(element(), rate, GST_FORMAT_TIME, + GstSeekFlags(GST_SEEK_FLAG_FLUSH), + GST_SEEK_TYPE_SET, pos, + GST_SEEK_TYPE_SET, -1); + if (!success) + return false; + + m_position = pos; + return true; } - qint64 duration() const + bool setPlaybackRate(double rate) { - gint64 d; - if (!gst_element_query_duration(element(), GST_FORMAT_TIME, &d)) - return 0.; - return d; + if (rate == m_rate) + return false; + seek(position(), rate); + return true; + } + double playbackRate() const { return m_rate; } + + bool setPosition(qint64 pos) + { + return seek(pos, m_rate); } qint64 position() const { @@ -134,7 +150,17 @@ public: return m_position; } + qint64 duration() const + { + gint64 d; + if (!gst_element_query_duration(element(), GST_FORMAT_TIME, &d)) + return 0.; + return d; + } + +private: mutable qint64 m_position = 0; + double m_rate = 1.; }; QT_END_NAMESPACE diff --git a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp index 64786a1e8..cc6771d97 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp @@ -123,16 +123,13 @@ QMediaTimeRange QGstreamerMediaPlayer::availablePlaybackRanges() const qreal QGstreamerMediaPlayer::playbackRate() const { - return m_playbackRate; + return playerPipeline.playbackRate(); } void QGstreamerMediaPlayer::setPlaybackRate(qreal rate) { - if (rate == m_playbackRate) - return; - m_playbackRate = rate; - playerPipeline.seek(playerPipeline.position(), m_playbackRate); - emit playbackRateChanged(rate); + if (playerPipeline.setPlaybackRate(rate)) + playbackRateChanged(rate); } void QGstreamerMediaPlayer::setPosition(qint64 pos) @@ -141,7 +138,7 @@ void QGstreamerMediaPlayer::setPosition(qint64 pos) if (pos == currentPos) return; playerPipeline.finishStateChange(); - playerPipeline.seek(pos*1e6, m_playbackRate); + playerPipeline.setPosition(pos*1e6); qCDebug(qLcMediaPlayer) << Q_FUNC_INFO << pos << playerPipeline.position()/1e6; if (mediaStatus() == QMediaPlayer::EndOfMedia) mediaStatusChanged(QMediaPlayer::LoadedMedia); @@ -155,16 +152,16 @@ void QGstreamerMediaPlayer::play() *playerPipeline.inStoppedState() = false; if (mediaStatus() == QMediaPlayer::EndOfMedia) { - playerPipeline.seek(0, m_playbackRate); + playerPipeline.setPosition(0); updatePosition(); } qCDebug(qLcMediaPlayer) << "play()."; int ret = playerPipeline.setState(GST_STATE_PLAYING); if (m_requiresSeekOnPlay) { - // This causes a flush of the pipeline and is required to get track changes + // Flushing the pipeline is required to get track changes // immediately, when they happen while paused. - playerPipeline.seek(playerPipeline.position(), m_playbackRate); + playerPipeline.flush(); m_requiresSeekOnPlay = false; } if (ret == GST_STATE_CHANGE_FAILURE) @@ -183,13 +180,13 @@ void QGstreamerMediaPlayer::pause() positionUpdateTimer.stop(); if (*playerPipeline.inStoppedState()) { *playerPipeline.inStoppedState() = false; - playerPipeline.seek(playerPipeline.position(), m_playbackRate); + playerPipeline.flush(); } int ret = playerPipeline.setState(GST_STATE_PAUSED); if (ret == GST_STATE_CHANGE_FAILURE) qCDebug(qLcMediaPlayer) << "Unable to set the pipeline to the paused state."; if (mediaStatus() == QMediaPlayer::EndOfMedia) { - playerPipeline.seek(0, m_playbackRate); + playerPipeline.setPosition(0); mediaStatusChanged(QMediaPlayer::BufferedMedia); } updatePosition(); @@ -211,7 +208,7 @@ void QGstreamerMediaPlayer::stopOrEOS(bool eos) if (!ret) qCDebug(qLcMediaPlayer) << "Unable to set the pipeline to the stopped state."; if (!eos) - playerPipeline.seek(0, m_playbackRate); + playerPipeline.setPosition(0); updatePosition(); emit stateChanged(QMediaPlayer::StoppedState); mediaStatusChanged(eos ? QMediaPlayer::EndOfMedia : QMediaPlayer::LoadedMedia); @@ -296,9 +293,6 @@ bool QGstreamerMediaPlayer::processBusMessage(const QGstreamerMessage &message) parseStreamsAndMetadata(); - if (!qFuzzyCompare(m_playbackRate, qreal(1.0))) - playerPipeline.seek(playerPipeline.position(), m_playbackRate); - emit tracksChanged(); mediaStatusChanged(QMediaPlayer::LoadedMedia); } @@ -588,6 +582,7 @@ void QGstreamerMediaPlayer::setMedia(const QUrl &content, QIODevice *stream) qCWarning(qLcMediaPlayer) << "Unable to set the pipeline to the paused state."; } + playerPipeline.setPosition(0); positionChanged(0); } @@ -742,7 +737,7 @@ void QGstreamerMediaPlayer::setActiveTrack(QPlatformMediaPlayer::TrackType type, selector.set("active-pad", streams.at(index)); // seek to force an immediate change of the stream if (playerPipeline.state() == GST_STATE_PLAYING) - playerPipeline.seek(playerPipeline.position(), m_playbackRate); + playerPipeline.flush(); else m_requiresSeekOnPlay = true; } diff --git a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h index 9caa432e3..37a51e4ab 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h @@ -135,7 +135,6 @@ private: QIODevice *m_stream = nullptr; bool prerolling = false; - double m_playbackRate = 1.; bool m_requiresSeekOnPlay = false; qint64 m_duration = 0; QTimer positionUpdateTimer; |