summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-03-04 08:23:11 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-03-04 08:23:11 (GMT)
commitb3ccc9b30c3a176021b6205193b8baa416e9e813 (patch)
treebc7ce3bc52c142c83dad59fbe71564ac01c49713
parent2cb4b0a528a6d979a3edeb08611a6ac11cb54bd4 (diff)
parent5a3b9d3daf64ea686427478391d3773c5a1e024e (diff)
downloadQt-b3ccc9b30c3a176021b6205193b8baa416e9e813.zip
Qt-b3ccc9b30c3a176021b6205193b8baa416e9e813.tar.gz
Qt-b3ccc9b30c3a176021b6205193b8baa416e9e813.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-multimedia-staging into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/qt-multimedia-staging: WaveDecoder; be more permissive in handling of wave file formats. Debug media player status and media state changes. Added playlist playback modes combo box to player demo Added QMediaPlayer::StreamPlayback flag to query/select backend capable
-rw-r--r--demos/multimedia/player/player.cpp28
-rw-r--r--demos/multimedia/player/player.h3
-rw-r--r--src/multimedia/base/qmediaserviceprovider.cpp43
-rw-r--r--src/multimedia/base/qmediaserviceprovider.h3
-rw-r--r--src/multimedia/effects/wavedecoder_p.cpp21
-rw-r--r--src/multimedia/effects/wavedecoder_p.h1
-rw-r--r--src/multimedia/playback/qmediaplayer.cpp36
-rw-r--r--src/multimedia/playback/qmediaplayer.h3
-rw-r--r--tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp72
9 files changed, 188 insertions, 22 deletions
diff --git a/demos/multimedia/player/player.cpp b/demos/multimedia/player/player.cpp
index 49d18cb..af30a97 100644
--- a/demos/multimedia/player/player.cpp
+++ b/demos/multimedia/player/player.cpp
@@ -81,6 +81,22 @@ Player::Player(QWidget *parent)
connect(playlistView, SIGNAL(activated(QModelIndex)), this, SLOT(jump(QModelIndex)));
+ playbackModeBox = new QComboBox;
+ playbackModeBox->addItem(tr("Linear"),
+ QVariant::fromValue<QMediaPlaylist::PlaybackMode>(QMediaPlaylist::Linear));
+ playbackModeBox->addItem(tr("Loop"),
+ QVariant::fromValue<QMediaPlaylist::PlaybackMode>(QMediaPlaylist::Loop));
+ playbackModeBox->addItem(tr("Random"),
+ QVariant::fromValue<QMediaPlaylist::PlaybackMode>(QMediaPlaylist::Random));
+ playbackModeBox->addItem(tr("Current Item Once"),
+ QVariant::fromValue<QMediaPlaylist::PlaybackMode>(QMediaPlaylist::CurrentItemOnce));
+ playbackModeBox->addItem(tr("Current Item In Loop"),
+ QVariant::fromValue<QMediaPlaylist::PlaybackMode>(QMediaPlaylist::CurrentItemInLoop));
+ playbackModeBox->setCurrentIndex(0);
+
+ connect(playbackModeBox, SIGNAL(activated(int)), SLOT(updatePlaybackMode()));
+ updatePlaybackMode();
+
slider = new QSlider(Qt::Horizontal);
slider->setRange(0, player->duration() / 1000);
@@ -126,12 +142,16 @@ Player::Player(QWidget *parent)
else
colorButton->setEnabled(false);
+ QBoxLayout *playlistLayout = new QVBoxLayout;
+ playlistLayout->addWidget(playlistView);
+ playlistLayout->addWidget(playbackModeBox);
+
QBoxLayout *displayLayout = new QHBoxLayout;
if (videoWidget)
displayLayout->addWidget(videoWidget, 2);
else
displayLayout->addWidget(coverLabel, 2);
- displayLayout->addWidget(playlistView);
+ displayLayout->addLayout(playlistLayout);
QBoxLayout *controlLayout = new QHBoxLayout;
controlLayout->setMargin(0);
@@ -333,3 +353,9 @@ void Player::showColorDialog()
}
colorDialog->show();
}
+
+void Player::updatePlaybackMode()
+{
+ playlist->setPlaybackMode(
+ playbackModeBox->itemData(playbackModeBox->currentIndex()).value<QMediaPlaylist::PlaybackMode>());
+}
diff --git a/demos/multimedia/player/player.h b/demos/multimedia/player/player.h
index 1de8b1a..cda3eb9 100644
--- a/demos/multimedia/player/player.h
+++ b/demos/multimedia/player/player.h
@@ -57,6 +57,7 @@ class QAbstractItemView;
class QLabel;
class QModelIndex;
class QSlider;
+class QComboBox;
class QMediaPlayer;
class QVideoWidget;
class PlaylistModel;
@@ -87,6 +88,7 @@ private slots:
void bufferingProgress(int progress);
void showColorDialog();
+ void updatePlaybackMode();
private:
void setTrackInfo(const QString &info);
@@ -97,6 +99,7 @@ private:
QVideoWidget *videoWidget;
QLabel *coverLabel;
QSlider *slider;
+ QComboBox *playbackModeBox;
PlaylistModel *playlistModel;
QAbstractItemView *playlistView;
QDialog *colorDialog;
diff --git a/src/multimedia/base/qmediaserviceprovider.cpp b/src/multimedia/base/qmediaserviceprovider.cpp
index d51d682..6e11079 100644
--- a/src/multimedia/base/qmediaserviceprovider.cpp
+++ b/src/multimedia/base/qmediaserviceprovider.cpp
@@ -102,6 +102,9 @@ public:
\value RecordingSupport
The service provides audio or video recording functions.
+
+ \value StreamPlayback
+ The service is capable of playing QIODevice based streams.
*/
/*!
@@ -396,14 +399,25 @@ public:
QMediaServiceSupportedFormatsInterface *iface =
qobject_cast<QMediaServiceSupportedFormatsInterface*>(obj);
- //if low latency playback was asked, skip services known
- //not to provide low latency playback
- if (flags & QMediaPlayer::LowLatency) {
+
+ if (flags) {
QMediaServiceFeaturesInterface *iface =
qobject_cast<QMediaServiceFeaturesInterface*>(obj);
- if (iface && !(iface->supportedFeatures(serviceType) & QMediaServiceProviderHint::LowLatencyPlayback))
- continue;
+ if (iface) {
+ QMediaServiceProviderHint::Features features = iface->supportedFeatures(serviceType);
+
+ //if low latency playback was asked, skip services known
+ //not to provide low latency playback
+ if ((flags & QMediaPlayer::LowLatency) &&
+ !(features & QMediaServiceProviderHint::LowLatencyPlayback))
+ continue;
+
+ //the same for QIODevice based streams support
+ if ((flags & QMediaPlayer::StreamPlayback) &&
+ !(features & QMediaServiceProviderHint::StreamPlayback))
+ continue;
+ }
}
if (iface)
@@ -434,14 +448,25 @@ public:
QMediaServiceSupportedFormatsInterface *iface =
qobject_cast<QMediaServiceSupportedFormatsInterface*>(obj);
- // If low latency playback was asked for, skip MIME types from services known
- // not to provide low latency playback
+
if (flags & QMediaPlayer::LowLatency) {
QMediaServiceFeaturesInterface *iface =
qobject_cast<QMediaServiceFeaturesInterface*>(obj);
- if (iface && !(iface->supportedFeatures(serviceType) & QMediaServiceProviderHint::LowLatencyPlayback))
- continue;
+ if (iface) {
+ QMediaServiceProviderHint::Features features = iface->supportedFeatures(serviceType);
+
+ // If low latency playback was asked for, skip MIME types from services known
+ // not to provide low latency playback
+ if ((flags & QMediaPlayer::LowLatency) &&
+ !(features & QMediaServiceProviderHint::LowLatencyPlayback))
+ continue;
+
+ //the same for QIODevice based streams support
+ if ((flags & QMediaPlayer::StreamPlayback) &&
+ !(features & QMediaServiceProviderHint::StreamPlayback))
+ continue;
+ }
}
if (iface) {
diff --git a/src/multimedia/base/qmediaserviceprovider.h b/src/multimedia/base/qmediaserviceprovider.h
index 2ee0ae4..6e31493 100644
--- a/src/multimedia/base/qmediaserviceprovider.h
+++ b/src/multimedia/base/qmediaserviceprovider.h
@@ -64,7 +64,8 @@ public:
enum Feature {
LowLatencyPlayback = 0x01,
- RecordingSupport = 0x02
+ RecordingSupport = 0x02,
+ StreamPlayback = 0x04
};
Q_DECLARE_FLAGS(Features, Feature)
diff --git a/src/multimedia/effects/wavedecoder_p.cpp b/src/multimedia/effects/wavedecoder_p.cpp
index f2277ae..b534ded 100644
--- a/src/multimedia/effects/wavedecoder_p.cpp
+++ b/src/multimedia/effects/wavedecoder_p.cpp
@@ -55,7 +55,7 @@ WaveDecoder::WaveDecoder(QIODevice *s, QObject *parent):
{
open(QIODevice::ReadOnly | QIODevice::Unbuffered);
- if (source->bytesAvailable() >= sizeof(CombinedHeader))
+ if (source->bytesAvailable() >= qint64(sizeof(CombinedHeader) + sizeof(DATAHeader) + sizeof(quint16)))
QTimer::singleShot(0, this, SLOT(handleData()));
else
connect(source, SIGNAL(readyRead()), SLOT(handleData()));
@@ -105,7 +105,7 @@ qint64 WaveDecoder::writeData(const char *data, qint64 len)
void WaveDecoder::handleData()
{
- if (source->bytesAvailable() < sizeof(CombinedHeader))
+ if (source->bytesAvailable() < qint64(sizeof(CombinedHeader) + sizeof(DATAHeader) + sizeof(quint16)))
return;
source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData()));
@@ -114,12 +114,23 @@ void WaveDecoder::handleData()
if (qstrncmp(header.riff.descriptor.id, "RIFF", 4) != 0 ||
qstrncmp(header.riff.type, "WAVE", 4) != 0 ||
qstrncmp(header.wave.descriptor.id, "fmt ", 4) != 0 ||
- (header.wave.audioFormat != 0 && header.wave.audioFormat != 1) ||
- qstrncmp(header.data.descriptor.id, "data", 4) != 0) {
+ (header.wave.audioFormat != 0 && header.wave.audioFormat != 1)) {
emit invalidFormat();
}
else {
+ DATAHeader dataHeader;
+
+ if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader)) {
+ // Extended data available
+ quint16 extraFormatBytes;
+ source->peek((char*)&extraFormatBytes, sizeof(quint16));
+ extraFormatBytes = qFromLittleEndian<quint16>(extraFormatBytes);
+ source->read(sizeof(quint16) + extraFormatBytes); // dump it all
+ }
+
+ source->read((char*)&dataHeader, sizeof(DATAHeader));
+
int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample);
format.setCodec(QLatin1String("audio/pcm"));
@@ -129,7 +140,7 @@ void WaveDecoder::handleData()
format.setSampleSize(bps);
format.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels));
- dataSize = qFromLittleEndian<quint32>(header.data.descriptor.size);
+ dataSize = qFromLittleEndian<quint32>(dataHeader.descriptor.size);
haveFormat = true;
connect(source, SIGNAL(readyRead()), SIGNAL(readyRead()));
diff --git a/src/multimedia/effects/wavedecoder_p.h b/src/multimedia/effects/wavedecoder_p.h
index 00aa14e..fa1f77e 100644
--- a/src/multimedia/effects/wavedecoder_p.h
+++ b/src/multimedia/effects/wavedecoder_p.h
@@ -116,7 +116,6 @@ private:
{
RIFFHeader riff;
WAVEHeader wave;
- DATAHeader data;
};
bool haveFormat;
diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp
index 27bff02..9466cad 100644
--- a/src/multimedia/playback/qmediaplayer.cpp
+++ b/src/multimedia/playback/qmediaplayer.cpp
@@ -43,6 +43,7 @@
#include <QtCore/qmetaobject.h>
#include <QtCore/qtimer.h>
#include <QtCore/qpointer.h>
+#include <QtCore/qdebug.h>
#include <QtMultimedia/qmediaplayer.h>
@@ -55,6 +56,7 @@
#include <QtMultimedia/qvideowidget.h>
#include <QtMultimedia/qgraphicsvideoitem.h>
+//#define DEBUG_PLAYER_STATE
QT_BEGIN_HEADER
@@ -152,10 +154,16 @@ public:
void _q_playlistDestroyed();
};
+#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
+
void QMediaPlayerPrivate::_q_stateChanged(QMediaPlayer::State ps)
{
Q_Q(QMediaPlayer);
+#ifdef DEBUG_PLAYER_STATE
+ qDebug() << "State changed:" << ENUM_NAME(QMediaPlayer, "State", ps) << (filterStates ? "(filtered)" : "");
+#endif
+
if (filterStates)
return;
@@ -183,6 +191,10 @@ void QMediaPlayerPrivate::_q_mediaStatusChanged(QMediaPlayer::MediaStatus status
{
Q_Q(QMediaPlayer);
+#ifdef DEBUG_PLAYER_STATE
+ qDebug() << "MediaStatus changed:" << ENUM_NAME(QMediaPlayer, "MediaStatus", status);
+#endif
+
switch (status) {
case QMediaPlayer::StalledMedia:
case QMediaPlayer::BufferingMedia:
@@ -230,8 +242,12 @@ void QMediaPlayerPrivate::_q_updateMedia(const QMediaContent &media)
state = control->state();
- if (state != currentState)
+ if (state != currentState) {
+#ifdef DEBUG_PLAYER_STATE
+ qDebug() << "State changed:" << ENUM_NAME(QMediaPlayer, "State", state);
+#endif
emit q_func()->stateChanged(state);
+ }
}
void QMediaPlayerPrivate::_q_playlistDestroyed()
@@ -243,10 +259,17 @@ void QMediaPlayerPrivate::_q_playlistDestroyed()
static QMediaService *playerService(QMediaPlayer::Flags flags, QMediaServiceProvider *provider)
{
- if (flags && QMediaPlayer::LowLatency)
+ if (flags) {
+ QMediaServiceProviderHint::Features features = 0;
+ if (flags & QMediaPlayer::LowLatency)
+ features |= QMediaServiceProviderHint::LowLatencyPlayback;
+
+ if (flags & QMediaPlayer::StreamPlayback)
+ features |= QMediaServiceProviderHint::StreamPlayback;
+
return provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER,
- QMediaServiceProviderHint(QMediaServiceProviderHint::LowLatencyPlayback));
- else
+ QMediaServiceProviderHint(features));
+ } else
return provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER);
}
@@ -945,6 +968,11 @@ QStringList QMediaPlayer::supportedMimeTypes(Flags flags)
The player is expected to be used with simple audio formats,
but playback should start without significant delay.
Such playback service can be used for beeps, ringtones, etc.
+
+ \value StreamPlayback
+ The player is expected to play QIODevice based streams.
+ If passed to QMediaPlayer constructor, the service supporting
+ streams playback will be choosen.
*/
QT_END_NAMESPACE
diff --git a/src/multimedia/playback/qmediaplayer.h b/src/multimedia/playback/qmediaplayer.h
index 1b761ce..129b244 100644
--- a/src/multimedia/playback/qmediaplayer.h
+++ b/src/multimedia/playback/qmediaplayer.h
@@ -99,7 +99,8 @@ public:
enum Flag
{
- LowLatency = 0x01
+ LowLatency = 0x01,
+ StreamPlayback = 0x02
};
Q_DECLARE_FLAGS(Flags, Flag)
diff --git a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp
index 9bca189..d839fe5 100644
--- a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp
+++ b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp
@@ -213,6 +213,57 @@ public:
}
};
+class MockServicePlugin4 : public QMediaServiceProviderPlugin,
+ public QMediaServiceSupportedFormatsInterface,
+ public QMediaServiceFeaturesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedFormatsInterface)
+ Q_INTERFACES(QMediaServiceFeaturesInterface)
+public:
+ QStringList keys() const
+ {
+ return QStringList() << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER);
+ }
+
+ QMediaService* create(QString const& key)
+ {
+ if (keys().contains(key))
+ return new MockMediaService("MockServicePlugin4");
+ else
+ return 0;
+ }
+
+ void release(QMediaService *service)
+ {
+ delete service;
+ }
+
+ QtMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const
+ {
+ if (codecs.contains(QLatin1String("jpeg2000")))
+ return QtMultimedia::NotSupported;
+
+ if (supportedMimeTypes().contains(mimeType))
+ return QtMultimedia::ProbablySupported;
+
+ return QtMultimedia::MaybeSupported;
+ }
+
+ QStringList supportedMimeTypes() const
+ {
+ return QStringList() << "video/mp4" << "video/quicktime";
+ }
+
+ QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const
+ {
+ if (service == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER))
+ return QMediaServiceProviderHint::StreamPlayback;
+ else
+ return 0;
+ }
+};
+
class MockMediaServiceProvider : public QMediaServiceProvider
@@ -253,6 +304,7 @@ void tst_QMediaServiceProvider::initTestCase()
plugins << new MockServicePlugin1;
plugins << new MockServicePlugin2;
plugins << new MockServicePlugin3;
+ plugins << new MockServicePlugin4;
QMediaPluginLoader::setStaticPlugins(QLatin1String("/mediaservices"), plugins);
}
@@ -312,12 +364,32 @@ void tst_QMediaServiceProvider::testHasSupport()
QCOMPARE(QMediaPlayer::hasSupport("audio/ogg"), QtMultimedia::ProbablySupported);
QCOMPARE(QMediaPlayer::hasSupport("audio/wav"), QtMultimedia::ProbablySupported);
+ //test low latency flag support
+ QCOMPARE(QMediaPlayer::hasSupport("audio/wav", QStringList(), QMediaPlayer::LowLatency),
+ QtMultimedia::ProbablySupported);
+ //plugin1 probably supports audio/ogg, it checked because it doesn't provide features iface
+ QCOMPARE(QMediaPlayer::hasSupport("audio/ogg", QStringList(), QMediaPlayer::LowLatency),
+ QtMultimedia::ProbablySupported);
+ //Plugin4 is not checked here, sine it's known not support low latency
+ QCOMPARE(QMediaPlayer::hasSupport("video/quicktime", QStringList(), QMediaPlayer::LowLatency),
+ QtMultimedia::MaybeSupported);
+
+ //test streaming flag support
+ QCOMPARE(QMediaPlayer::hasSupport("video/quicktime", QStringList(), QMediaPlayer::StreamPlayback),
+ QtMultimedia::ProbablySupported);
+ //Plugin2 is not checked here, sine it's known not support streaming
+ QCOMPARE(QMediaPlayer::hasSupport("audio/wav", QStringList(), QMediaPlayer::StreamPlayback),
+ QtMultimedia::MaybeSupported);
+
//ensure the correct media player plugin is choosen for mime type
QMediaPlayer simplePlayer(0, QMediaPlayer::LowLatency);
QCOMPARE(simplePlayer.service()->objectName(), QLatin1String("MockServicePlugin2"));
QMediaPlayer mediaPlayer;
QVERIFY(mediaPlayer.service()->objectName() != QLatin1String("MockServicePlugin2"));
+
+ QMediaPlayer streamPlayer(0, QMediaPlayer::StreamPlayback);
+ QCOMPARE(streamPlayer.service()->objectName(), QLatin1String("MockServicePlugin4"));
}
void tst_QMediaServiceProvider::testSupportedMimeTypes()