diff options
author | Jøger Hansegård <joger.hansegard@qt.io> | 2023-08-10 14:17:01 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-08-10 16:33:44 +0000 |
commit | c52c908d94ac84a90f2d3c82564d3a7b2550b830 (patch) | |
tree | 17acb7ee06b095817867189d4edbe3cbc2f01ad3 | |
parent | e41b9c4d355fa10f473f83a82dc99013801851f2 (diff) |
Fix mediaplayer scroll issue if stream duration is missing
If a media file is missing per stream duration data, the mediaplayer
slider operations to scroll in video would restart the video from start.
The cause of the issue was that the mediaplayer duration was calculated
from the stream durations and became 0.
The ffmpeg demuxer already has more advanced heuristics to calculate the
media file duration, and this patch fixes the issue by also taking the
media file duration into account.
Fixes: QTBUG-115747
Change-Id: I906f62c15ffdccadf1da07a75a109961d897b1b0
Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
(cherry picked from commit 42107b9d263802d361451c00c8b623fcd45e6922)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/plugins/multimedia/ffmpeg/playbackengine/qffmpegmediadataholder.cpp | 6 | ||||
-rw-r--r-- | tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp | 72 |
2 files changed, 65 insertions, 13 deletions
diff --git a/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegmediadataholder.cpp b/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegmediadataholder.cpp index 2133548f3..fdb03a806 100644 --- a/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegmediadataholder.cpp +++ b/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegmediadataholder.cpp @@ -233,6 +233,12 @@ void MediaDataHolder::updateStreams() m_streamMap[trackType].append({ (int)i, isDefault, metaData }); } + // With some media files, streams may be lacking duration info. Let's + // get it from ffmpeg's duration estimation instead. + if (m_duration == 0 && m_context->duration > 0ll) { + m_duration = m_context->duration; + } + for (auto trackType : { QPlatformMediaPlayer::VideoStream, QPlatformMediaPlayer::AudioStream }) { auto &requestedStream = m_requestedStreams[trackType]; diff --git a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp index fbf5ce2b3..0cc943818 100644 --- a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp +++ b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp @@ -74,6 +74,7 @@ private slots: void multiplePlaybackRateChangingStressTest(); void multipleSeekStressTest(); void playbackRateChanging(); + void durationDetectionIssues_data(); void durationDetectionIssues(); void finiteLoops(); void infiniteLoops(); @@ -98,8 +99,6 @@ private: QUrl localCompressedSoundFile; QUrl localFileWithMetadata; QUrl localVideoFile3ColorsWithSound; - QUrl videoWithDurationIssues; // ffmpeg detects stream an incorrect stream duration, so we take - // the correct duration from the metadata const std::array<QRgb, 3> video3Colors = { { 0xFF0000, 0x00FF00, 0x0000FF } }; @@ -233,9 +232,6 @@ void tst_QMediaPlayerBackend::initTestCase() localFileWithMetadata = MediaFileSelector::selectMediaFile(QStringList() << "qrc:/testdata/nokia-tune.mp3"); - videoWithDurationIssues = MediaFileSelector::selectMediaFile( - QStringList() << "qrc:/testdata/duration_issues.webm"); - qgetenv("QT_TEST_CI").toInt(&m_inCISystem,10); } @@ -1705,10 +1701,49 @@ void tst_QMediaPlayerBackend::position() QVERIFY(player.position() < 550); } +void tst_QMediaPlayerBackend::durationDetectionIssues_data() +{ + QTest::addColumn<QString>("mediaFile"); + QTest::addColumn<qint64>("expectedDuration"); + QTest::addColumn<int>("expectedVideoTrackCount"); + QTest::addColumn<qint64>("expectedVideoTrackDuration"); + QTest::addColumn<int>("expectedAudioTrackCount"); + QTest::addColumn<QVariant>("expectedAudioTrackDuration"); + + // clang-format off + + QTest::newRow("stream-duration-in-metadata") + << QString{ "qrc:/testdata/duration_issues.webm" } + << 400ll // Total media duration + << 1 // Number of video tracks in file + << 400ll // Video stream duration + << 0 // Number of audio tracks in file + << QVariant{}; // Audio stream duration (unused) + + QTest::newRow("no-stream-duration-in-metadata") + << QString{ "qrc:/testdata/nokia-tune.mkv" } + << 7531ll // Total media duration + << 0 // Number of video tracks in file + << 0ll // Video stream duration (unused) + << 1 // Number of audio tracks in file + << QVariant{}; // Audio stream duration (not present on file) + + // clang-format on +} + void tst_QMediaPlayerBackend::durationDetectionIssues() { - if (videoWithDurationIssues.isEmpty()) - QSKIP("No supported video file"); + QFETCH(QString, mediaFile); + QFETCH(qint64, expectedDuration); + QFETCH(int, expectedVideoTrackCount); + QFETCH(qint64, expectedVideoTrackDuration); + QFETCH(int, expectedAudioTrackCount); + QFETCH(QVariant, expectedAudioTrackDuration); + + // ffmpeg detects stream an incorrect stream duration, so we take + // the correct duration from the metadata + const QUrl videoWithDurationIssues = + MediaFileSelector::selectMediaFile({ mediaFile }); TestVideoSink surface(false); QAudioOutput output; @@ -1720,15 +1755,26 @@ void tst_QMediaPlayerBackend::durationDetectionIssues() player.setAudioOutput(&output); player.setSource(videoWithDurationIssues); + // Duration event received QCOMPARE(durationSpy.size(), 1); - QCOMPARE(durationSpy.front().front(), QVariant(qint64(400))); + QCOMPARE(durationSpy.front().front(), expectedDuration); + + // Duration property + QCOMPARE(player.duration(), expectedDuration); + QCOMPARE(player.metaData().value(QMediaMetaData::Duration), expectedDuration); + + // Track duration properties + const auto videoTracks = player.videoTracks(); + QCOMPARE(videoTracks.size(), expectedVideoTrackCount); + + if (expectedVideoTrackCount != 0) + QCOMPARE(videoTracks.front().value(QMediaMetaData::Duration), expectedVideoTrackDuration); - QCOMPARE(player.duration(), 400); - QCOMPARE(player.metaData().value(QMediaMetaData::Duration), QVariant(qint64(400))); + const auto audioTracks = player.audioTracks(); + QCOMPARE(audioTracks.size(), expectedAudioTrackCount); - auto videoTracks = player.videoTracks(); - QCOMPARE(videoTracks.size(), 1); - QCOMPARE(videoTracks.front().value(QMediaMetaData::Duration), QVariant(qint64(400))); + if (expectedAudioTrackCount != 0) + QCOMPARE(audioTracks.front().value(QMediaMetaData::Duration), expectedAudioTrackDuration); } static std::vector<std::pair<qint64, qint64>> |