QMediaPlayer: handle resource files in a cross-platform way.

It was the backend's responsibility to handle resource files in an
appropriate way. In practice, it was either not handled at all,
or implemented in an almost identical manner in every backend
that does handle it.
This is now dealt with in QMediaPlayer, always passing to the
backend something it will be able to play. If the backend has the
StreamPlayback capability, we pass a QFile from which it streams
the data. If it doesn't, we copy the resource to a temporary
file and pass its path to the backend.

Task-number: QTBUG-36175
Task-number: QTBUG-42263
Task-number: QTBUG-43839
Change-Id: I57b355c72692d02661baeaf74e66581ca0a0bd1d
Reviewed-by: Andrew Knight <qt@panimo.net>
Reviewed-by: Peng Wu <peng.wu@intopalo.com>
Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
This commit is contained in:
Yoann Lopes
2015-02-18 16:58:02 +01:00
committed by Friedemann Kleint
parent 4d17db19f8
commit 63cff37741
25 changed files with 304 additions and 165 deletions

View File

@@ -2,6 +2,7 @@ CONFIG += testcase no_private_qt_headers_warning
TARGET = tst_qmediaplayer
QT += network multimedia-private testlib
SOURCES += tst_qmediaplayer.cpp
RESOURCES += testdata.qrc
include (../qmultimedia_common/mock.pri)
include (../qmultimedia_common/mockplayer.pri)

View File

@@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>testdata/nokia-tune.mp3</file>
</qresource>
</RCC>

Binary file not shown.

View File

@@ -133,6 +133,8 @@ private slots:
void testPlayerFlags();
void testDestructor();
void testSupportedMimeTypes();
void testQrc_data();
void testQrc();
private:
void setupCommonTestData();
@@ -976,12 +978,17 @@ void tst_QMediaPlayer::testPlaylist()
player->setPlaylist(playlist);
player->play();
QCOMPARE(ss.count(), 1);
QCOMPARE(ms.count(), 1);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(ms.last().value(0)), QMediaPlayer::LoadingMedia);
ms.clear();
mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::InvalidMedia);
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
QCOMPARE(player->mediaStatus(), QMediaPlayer::InvalidMedia);
QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadingMedia);
QCOMPARE(ss.count(), 1);
QCOMPARE(ms.count(), 1);
QCOMPARE(ms.count(), 2);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(ms.at(0).value(0)), QMediaPlayer::InvalidMedia);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(ms.at(1).value(0)), QMediaPlayer::LoadingMedia);
// NOTE: status should begin transitioning through to BufferedMedia.
QCOMPARE(player->currentMedia(), content1);
@@ -1210,5 +1217,84 @@ void tst_QMediaPlayer::testSupportedMimeTypes()
// This is empty on some platforms, and not on others, so can't test something here at the moment.
}
void tst_QMediaPlayer::testQrc_data()
{
QTest::addColumn<QMediaContent>("mediaContent");
QTest::addColumn<QMediaPlayer::MediaStatus>("status");
QTest::addColumn<QMediaPlayer::Error>("error");
QTest::addColumn<int>("errorCount");
QTest::addColumn<bool>("hasStreamFeature");
QTest::addColumn<QString>("backendMediaContentScheme");
QTest::addColumn<bool>("backendHasStream");
QTest::newRow("invalid") << QMediaContent(QUrl(QLatin1String("qrc:/invalid.mp3")))
<< QMediaPlayer::InvalidMedia
<< QMediaPlayer::ResourceError
<< 1 // error count
<< false // No StreamPlayback support
<< QString() // backend should not have got any media (empty URL scheme)
<< false; // backend should not have got any stream
QTest::newRow("valid+nostream") << QMediaContent(QUrl(QLatin1String("qrc:/testdata/nokia-tune.mp3")))
<< QMediaPlayer::LoadingMedia
<< QMediaPlayer::NoError
<< 0 // error count
<< false // No StreamPlayback support
<< QStringLiteral("file") // backend should have a got a temporary file
<< false; // backend should not have got any stream
QTest::newRow("valid+stream") << QMediaContent(QUrl(QLatin1String("qrc:/testdata/nokia-tune.mp3")))
<< QMediaPlayer::LoadingMedia
<< QMediaPlayer::NoError
<< 0 // error count
<< true // StreamPlayback support
<< QStringLiteral("qrc")
<< true; // backend should have got a stream (QFile opened from the resource)
}
void tst_QMediaPlayer::testQrc()
{
QFETCH(QMediaContent, mediaContent);
QFETCH(QMediaPlayer::MediaStatus, status);
QFETCH(QMediaPlayer::Error, error);
QFETCH(int, errorCount);
QFETCH(bool, hasStreamFeature);
QFETCH(QString, backendMediaContentScheme);
QFETCH(bool, backendHasStream);
if (hasStreamFeature)
mockProvider->setSupportedFeatures(QMediaServiceProviderHint::StreamPlayback);
QMediaPlayer player;
mockService->setState(QMediaPlayer::PlayingState, QMediaPlayer::NoMedia);
QSignalSpy mediaSpy(&player, SIGNAL(currentMediaChanged(QMediaContent)));
QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
QSignalSpy errorSpy(&player, SIGNAL(error(QMediaPlayer::Error)));
player.setMedia(mediaContent);
QTRY_COMPARE(player.mediaStatus(), status);
QCOMPARE(statusSpy.count(), 1);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)), status);
QCOMPARE(player.media(), mediaContent);
QCOMPARE(player.currentMedia(), mediaContent);
QCOMPARE(mediaSpy.count(), 1);
QCOMPARE(qvariant_cast<QMediaContent>(mediaSpy.last().value(0)), mediaContent);
QCOMPARE(player.error(), error);
QCOMPARE(errorSpy.count(), errorCount);
if (errorCount > 0) {
QCOMPARE(qvariant_cast<QMediaPlayer::Error>(errorSpy.last().value(0)), error);
QVERIFY(!player.errorString().isEmpty());
}
// Check the media actually passed to the backend
QCOMPARE(mockService->mockControl->media().canonicalUrl().scheme(), backendMediaContentScheme);
QCOMPARE(bool(mockService->mockControl->mediaStream()), backendHasStream);
}
QTEST_GUILESS_MAIN(tst_QMediaPlayer)
#include "tst_qmediaplayer.moc"

View File

@@ -91,11 +91,10 @@ public:
{
_stream = stream;
_media = content;
if (_state != QMediaPlayer::StoppedState) {
_mediaStatus = _media.isNull() ? QMediaPlayer::NoMedia : QMediaPlayer::LoadingMedia;
_mediaStatus = _media.isNull() ? QMediaPlayer::NoMedia : QMediaPlayer::LoadingMedia;
if (_state != QMediaPlayer::StoppedState)
emit stateChanged(_state = QMediaPlayer::StoppedState);
emit mediaStatusChanged(_mediaStatus);
}
emit mediaStatusChanged(_mediaStatus);
emit mediaChanged(_media = content);
}
QIODevice *mediaStream() const { return _stream; }

View File

@@ -61,6 +61,16 @@ public:
}
}
QMediaServiceProviderHint::Features supportedFeatures(const QMediaService *) const
{
return features;
}
void setSupportedFeatures(QMediaServiceProviderHint::Features f)
{
features = f;
}
QByteArray defaultDevice(const QByteArray &serviceType) const
{
if (serviceType == Q_MEDIASERVICE_CAMERA)
@@ -97,6 +107,7 @@ public:
QMediaService *service;
bool deleteServiceOnRelease;
QMediaServiceProviderHint::Features features;
};
#endif // MOCKMEDIASERVICEPROVIDER_H