summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-07-28 12:14:40 +0200
committerLars Knoll <lars.knoll@qt.io>2021-07-30 09:54:22 +0200
commitb2dfc5c090e16240aea11f96be289b8800d0a8bb (patch)
tree46719c0ad1d5af35320b41a4d925281ca48ac211
parent82367bd22c3d6c793bf05d91b641a3356f687d5b (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>
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstpipeline_p.h44
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp29
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h1
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;