summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorArtem Dyomin <artem.dyomin@qt.io>2023-05-02 16:07:32 +0200
committerArtem Dyomin <artem.dyomin@qt.io>2023-06-02 11:56:29 +0000
commit3d9cca86bfb59d6cfefad2b32d53268d3ad205bf (patch)
tree71d2e8d2ba631f7770b9f5b90af8d5991f11c351 /tests
parent24c854fff9af00461b0920074b23d156e345a804 (diff)
Handle QMediaPlayer outputs corner cases
- Clean-up the video sink frame after stop, QMediaPlayer deleting, and after setting new media. - ensure no frames lost if change QVideoSink - ensure no frames sent after changing of outputs. The patch fixes problems with tests on Android, summarizing of the related commits: codereview.qt-project.org/c/qt/qtmultimedia/+/472214 codereview.qt-project.org/c/qt/qtmultimedia/+/470890 codereview.qt-project.org/c/qt/qtmultimedia/+/472052 Users want to have flush mode customization as it was it Qt5. It might be added in 6.6 afterwards. Fixes: QTBUG-112173 Task-number: QTBUG-111912 Change-Id: I0e4d34de06fcf23adf8a5736cbff4119478e9baf Reviewed-by: Lars Knoll <lars@knoll.priv.no>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp164
1 files changed, 162 insertions, 2 deletions
diff --git a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
index 35c7e3f09..fb7d1066c 100644
--- a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
+++ b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
@@ -45,9 +45,11 @@ public slots:
private slots:
void construction();
void loadInvalidMedia();
+ void loadInvalidMediaWhilePlayingAndRestore();
void loadMedia();
void unloadMedia();
void loadMediaInLoadingState();
+ void loadMediaWhilePlaying();
void playPauseStop();
void processEOS();
void deleteLaterAtEOS();
@@ -77,6 +79,8 @@ private slots:
void infiniteLoops();
void seekOnLoops();
void changeLoopsOnTheFly();
+ void changeVideoOutputNoFramesLost();
+ void cleanSinkAndNoMoreFramesAfterStop();
void lazyLoadVideo();
void videoSinkSignals();
void nonAsciiFileName();
@@ -123,7 +127,7 @@ public:
return spy.wait() ? spy.at(0).at(0).value<QVideoFrame>() : QVideoFrame{};
}
-public Q_SLOTS:
+private Q_SLOTS:
void addVideoFrame(const QVideoFrame &frame) {
// qDebug() << m_elapsedTimer.elapsed() << frame.startTime() << frame.endTime() <<
// frame.toImage().pixelColor(1, 1);
@@ -150,6 +154,11 @@ private:
bool m_storeFrames;
};
+static void setVideoSinkAsyncFramesCounter(QVideoSink &sink, std::atomic_int &counter)
+{
+ QObject::connect(&sink, &QVideoSink::videoFrameChanged, [&counter]() { ++counter; });
+}
+
void tst_QMediaPlayerBackend::init()
{
}
@@ -246,7 +255,7 @@ void tst_QMediaPlayerBackend::loadInvalidMedia()
QSKIP("Sound format is not supported");
QAudioOutput output;
- TestVideoSink surface;
+ TestVideoSink surface(false);
QMediaPlayer player;
QSignalSpy stateSpy(&player, &QMediaPlayer::playbackStateChanged);
@@ -281,6 +290,49 @@ void tst_QMediaPlayerBackend::loadInvalidMedia()
QCOMPARE(player.mediaStatus(), QMediaPlayer::InvalidMedia);
}
+void tst_QMediaPlayerBackend::loadInvalidMediaWhilePlayingAndRestore()
+{
+ QMediaPlayer player;
+ QAudioOutput output;
+ QVideoSink surface;
+ std::atomic_int framesCount = 0;
+ setVideoSinkAsyncFramesCounter(surface, framesCount);
+
+ QSignalSpy stateSpy(&player, &QMediaPlayer::playbackStateChanged);
+ QSignalSpy errorSpy(&player, &QMediaPlayer::errorOccurred);
+
+ player.setAudioOutput(&output);
+ player.setVideoOutput(&surface);
+
+ player.setSource(localVideoFile3ColorsWithSound);
+ player.play();
+
+ QTRY_VERIFY(framesCount > 0);
+ QCOMPARE(errorSpy.size(), 0);
+
+ player.setSource(QUrl("Some not existing media"));
+ const int savedFramesCount = framesCount;
+
+ QCOMPARE(player.source(), QUrl("Some not existing media"));
+
+ QTRY_COMPARE(player.playbackState(), QMediaPlayer::StoppedState);
+ QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::InvalidMedia);
+ QTRY_COMPARE(player.error(), QMediaPlayer::ResourceError);
+
+ QVERIFY(!surface.videoFrame().isValid());
+
+ QCOMPARE(errorSpy.size(), 1);
+
+ QTest::qWait(20);
+ QCOMPARE(framesCount, savedFramesCount);
+
+ // restore playing
+ player.setSource(localVideoFile3ColorsWithSound);
+ player.play();
+ QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(player.error(), QMediaPlayer::NoError);
+}
+
void tst_QMediaPlayerBackend::loadMedia()
{
if (!isWavSupported())
@@ -389,6 +441,43 @@ void tst_QMediaPlayerBackend::loadMediaInLoadingState()
QCOMPARE(player.mediaStatus(), QMediaPlayer::LoadingMedia);
}
+void tst_QMediaPlayerBackend::loadMediaWhilePlaying()
+{
+ QMediaPlayer player;
+ QAudioOutput output;
+ TestVideoSink surface(false);
+
+ player.setAudioOutput(&output);
+ player.setVideoOutput(&surface);
+
+ player.setSource(localVideoFile3ColorsWithSound);
+ player.play();
+ QCOMPARE(player.playbackState(), QMediaPlayer::PlayingState);
+ QVERIFY(surface.waitForFrame().isValid());
+ QVERIFY(player.hasAudio());
+ QVERIFY(player.hasVideo());
+
+ QSignalSpy stateSpy(&player, &QMediaPlayer::playbackStateChanged);
+ QSignalSpy errorSpy(&player, &QMediaPlayer::errorChanged);
+
+ player.setSource(localWavFile2);
+ QCOMPARE(player.source(), localWavFile2);
+ QCOMPARE(player.playbackState(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.size(), 1);
+ QCOMPARE(errorSpy.size(), 0);
+ QVERIFY(player.hasAudio());
+ QVERIFY(!player.hasVideo());
+ QVERIFY(!surface.videoFrame().isValid());
+
+ player.play();
+
+ player.setSource(localVideoFile2);
+ QCOMPARE(player.playbackState(), QMediaPlayer::StoppedState);
+ QVERIFY(player.hasVideo());
+ QVERIFY(!player.hasAudio());
+ QCOMPARE(errorSpy.size(), 0);
+}
+
void tst_QMediaPlayerBackend::playPauseStop()
{
if (!isWavSupported())
@@ -1858,6 +1947,77 @@ void tst_QMediaPlayerBackend::changeLoopsOnTheFly()
QCOMPARE(intervals[1], std::make_pair(qint64(0), player.duration()));
}
+void tst_QMediaPlayerBackend::changeVideoOutputNoFramesLost()
+{
+ QVideoSink sinks[4];
+ std::atomic_int framesCount[4] = {
+ 0,
+ };
+ for (int i = 0; i < 4; ++i)
+ setVideoSinkAsyncFramesCounter(sinks[i], framesCount[i]);
+
+ QMediaPlayer player;
+
+ player.setPlaybackRate(10);
+
+ player.setVideoOutput(&sinks[0]);
+ player.setSource(localVideoFile3ColorsWithSound);
+ player.play();
+ QTRY_VERIFY(!player.isPlaying());
+
+ player.setPlaybackRate(4);
+ player.setVideoOutput(&sinks[1]);
+ player.play();
+
+ QTRY_VERIFY(framesCount[1] >= framesCount[0] / 4);
+ player.setVideoOutput(&sinks[2]);
+ const int savedFrameNumber1 = framesCount[1];
+
+ QTRY_VERIFY(framesCount[2] >= (framesCount[0] - savedFrameNumber1) / 2);
+ player.setVideoOutput(&sinks[3]);
+ const int savedFrameNumber2 = framesCount[2];
+
+ QTRY_VERIFY(!player.isPlaying());
+
+ // check if no frames sent to old sinks
+ QCOMPARE(framesCount[1], savedFrameNumber1);
+ QCOMPARE(framesCount[2], savedFrameNumber2);
+
+ // no frames lost
+ QCOMPARE(framesCount[1] + framesCount[2] + framesCount[3], framesCount[0]);
+}
+
+void tst_QMediaPlayerBackend::cleanSinkAndNoMoreFramesAfterStop()
+{
+ QVideoSink sink;
+ std::atomic_int framesCount = 0;
+ setVideoSinkAsyncFramesCounter(sink, framesCount);
+ QMediaPlayer player;
+
+ player.setPlaybackRate(10);
+ player.setVideoOutput(&sink);
+
+ player.setSource(localVideoFile3ColorsWithSound);
+
+ // Run a few time to have more chances to detect race conditions
+ for (int i = 0; i < 8; ++i) {
+ player.play();
+ QTRY_VERIFY(framesCount > 0);
+
+ player.stop();
+
+ QVERIFY(!sink.videoFrame().isValid());
+
+ QCOMPARE_NE(framesCount, 0);
+ framesCount = 0;
+
+ QTest::qWait(30);
+
+ // check if nothing changed after short waiting
+ QCOMPARE(framesCount, 0);
+ }
+}
+
void tst_QMediaPlayerBackend::lazyLoadVideo()
{
QQmlEngine engine;