summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-07-28 09:55:48 +0200
committerLars Knoll <lars.knoll@qt.io>2021-07-30 09:54:16 +0200
commit82367bd22c3d6c793bf05d91b641a3356f687d5b (patch)
tree1f9a51406d197ad3f3d16a9b95c870b565bb8ce5
parenta0deb18c401971b58d2581e9431c6d976d926063 (diff)
Fix media player position handling after seeking on gstreamer
After calling setPosition() while being paused, gst_element_query_position() can return false while the pipeline is still prerolling the new position. So simply return the last position in that case instead of 0. Also moved some methods that are only used on the pipeline from QGstElement to QGstPipeline so that we can cache the position there without having to add data to every element. Fixes: QTBUG-95251 Change-Id: Ice56975fcf7d519f0dd54db75103b97b025cd085 Reviewed-by: André de la Rocha <andre.rocha@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--examples/multimedia/video/mediaplayer/PlaybackSeekControl.qml26
-rw-r--r--src/multimedia/platform/gstreamer/common/qgst_p.h22
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstpipeline_p.h23
-rw-r--r--tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp24
4 files changed, 53 insertions, 42 deletions
diff --git a/examples/multimedia/video/mediaplayer/PlaybackSeekControl.qml b/examples/multimedia/video/mediaplayer/PlaybackSeekControl.qml
index 9907f7c8a..5c04d1848 100644
--- a/examples/multimedia/video/mediaplayer/PlaybackSeekControl.qml
+++ b/examples/multimedia/video/mediaplayer/PlaybackSeekControl.qml
@@ -69,7 +69,11 @@ Item {
Layout.minimumWidth: 50
Layout.minimumHeight: 18
horizontalAlignment: Text.AlignRight
- text: "0:00.0"
+ text: {
+ var m = Math.floor(mediaPlayer.position / 60000)
+ var ms = (mediaPlayer.position / 1000 - m * 60).toFixed(1)
+ return `${m}:${ms.padStart(4, 0)}`
+ }
}
Slider {
@@ -77,27 +81,9 @@ Item {
Layout.fillWidth: true
enabled: mediaPlayer.seekable
to: 1.0
- value: 0.0
+ value: mediaPlayer.position / mediaPlayer.duration
onMoved: mediaPlayer.setPosition(value * mediaPlayer.duration)
}
}
-
- Timer {
- interval: 100; repeat: true; running: true;
- onTriggered: {
- if (mediaPlayerState != MediaPlayer.StoppedState) {
- mediaSlider.value = mediaPlayer.position / mediaPlayer.duration
- mediaTime.text = function(){
- var m = Math.floor(mediaPlayer.position / 60000)
- var ms = (mediaPlayer.position / 1000 - m * 60).toFixed(1)
- return `${m}:${ms.padStart(4, 0)}`
- }()
- } else {
- mediaSlider.value = 0.0
- mediaTime.text = "0:00.0"
- }
-
- }
- }
}
diff --git a/src/multimedia/platform/gstreamer/common/qgst_p.h b/src/multimedia/platform/gstreamer/common/qgst_p.h
index 8036fb8b9..3f0321916 100644
--- a/src/multimedia/platform/gstreamer/common/qgst_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgst_p.h
@@ -480,28 +480,6 @@ public:
void sendEvent(GstEvent *event) const { gst_element_send_event(element(), event); }
void sendEos() const { sendEvent(gst_event_new_eos()); }
- 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);
- }
- qint64 duration() const
- {
- gint64 d;
- if (!gst_element_query_duration(element(), GST_FORMAT_TIME, &d))
- return 0.;
- return d;
- }
- qint64 position() const
- {
- gint64 pos;
- if (!gst_element_query_position(element(), GST_FORMAT_TIME, &pos))
- return 0.;
- return pos;
- }
-
template<auto Member, typename T>
void onPadAdded(T *instance) {
struct Impl {
diff --git a/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h b/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h
index c67e84251..1f4f6ee05 100644
--- a/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h
@@ -112,6 +112,29 @@ public:
#endif
}
+ 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);
+ }
+ qint64 duration() const
+ {
+ gint64 d;
+ if (!gst_element_query_duration(element(), GST_FORMAT_TIME, &d))
+ return 0.;
+ return d;
+ }
+ qint64 position() const
+ {
+ gint64 pos;
+ if (gst_element_query_position(element(), GST_FORMAT_TIME, &pos))
+ m_position = pos;
+ return m_position;
+ }
+
+ mutable qint64 m_position = 0;
};
QT_END_NAMESPACE
diff --git a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
index acc5138d7..dcbaf5626 100644
--- a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
+++ b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
@@ -79,6 +79,7 @@ private slots:
void playFromBuffer();
void audioVideoAvailable();
void isSeekable();
+ void positionAfterSeek();
private:
QUrl selectVideoFile(const QStringList& mediaCandidates);
@@ -1122,6 +1123,29 @@ void tst_QMediaPlayerBackend::isSeekable()
QTRY_VERIFY(player.isSeekable());
}
+void tst_QMediaPlayerBackend::positionAfterSeek()
+{
+ if (localVideoFile.isEmpty())
+ QSKIP("No supported video file");
+
+ TestVideoSink surface(false);
+ QMediaPlayer player;
+ player.setVideoOutput(&surface);
+ QVERIFY(!player.isSeekable());
+ player.setSource(localVideoFile);
+ player.pause();
+ player.setPosition(500);
+ QTRY_VERIFY(player.position() == 500);
+ player.setPosition(700);
+ QVERIFY(player.position() != 0);
+ QTRY_VERIFY(player.position() == 700);
+ player.play();
+ QTRY_VERIFY(player.position() > 700);
+ player.setPosition(200);
+ QVERIFY(player.position() != 0);
+ QTRY_VERIFY(player.position() < 700);
+}
+
QTEST_MAIN(tst_QMediaPlayerBackend)
#include "tst_qmediaplayerbackend.moc"