Merge "Merge remote-tracking branch 'origin/5.3' into 5.4" into refs/staging/5.4
This commit is contained in:
@@ -45,9 +45,6 @@
|
||||
#include "qsoundeffect_qaudio_p.h"
|
||||
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
#include <QtCore/qthread.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qwaitcondition.h>
|
||||
#include <QtCore/qiodevice.h>
|
||||
|
||||
//#include <QDebug>
|
||||
|
||||
@@ -51,6 +51,30 @@ public:
|
||||
|
||||
virtual void parseLine(int lineIndex, const QString& line, const QUrl& root) = 0;
|
||||
|
||||
protected:
|
||||
QUrl expandToFullPath(const QUrl &root, const QString &line)
|
||||
{
|
||||
// On Linux, backslashes are not converted to forward slashes :/
|
||||
if (line.startsWith(QLatin1String("//")) || line.startsWith(QLatin1String("\\\\"))) {
|
||||
// Network share paths are not resolved
|
||||
return QUrl::fromLocalFile(line);
|
||||
}
|
||||
|
||||
QUrl url(line);
|
||||
if (url.scheme().isEmpty()) {
|
||||
// Resolve it relative to root
|
||||
if (root.isLocalFile())
|
||||
return root.resolved(QUrl::fromLocalFile(line));
|
||||
else
|
||||
return root.resolved(url);
|
||||
} else if (url.scheme().length() == 1) {
|
||||
// Assume it's a drive letter for a Windows path
|
||||
url = QUrl::fromLocalFile(line);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void newItem(const QVariant& content);
|
||||
void finished();
|
||||
@@ -138,29 +162,6 @@ public:
|
||||
return -1;
|
||||
}
|
||||
|
||||
QUrl expandToFullPath(const QUrl& root, const QString& line)
|
||||
{
|
||||
// On Linux, backslashes are not converted to forward slashes :/
|
||||
if (line.startsWith(QLatin1String("//")) || line.startsWith(QLatin1String("\\\\"))) {
|
||||
// Network share paths are not resolved
|
||||
return QUrl::fromLocalFile(line);
|
||||
}
|
||||
|
||||
QUrl url(line);
|
||||
if (url.scheme().isEmpty()) {
|
||||
// Resolve it relative to root
|
||||
if (root.isLocalFile())
|
||||
return root.resolved(QUrl::fromLocalFile(line));
|
||||
else
|
||||
return root.resolved(url);
|
||||
} else if (url.scheme().length() == 1) {
|
||||
// Assume it's a drive letter for a Windows path
|
||||
url = QUrl::fromLocalFile(line);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_extendedFormat;
|
||||
QVariantMap m_extraInfo;
|
||||
@@ -172,27 +173,9 @@ class PLSParser : public ParserBase
|
||||
public:
|
||||
PLSParser(QObject *parent)
|
||||
: ParserBase(parent)
|
||||
, m_state(Header)
|
||||
, m_count(0)
|
||||
, m_readFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
enum ReadFlags
|
||||
{
|
||||
FileRead = 0x1,
|
||||
TitleRead = 0x2,
|
||||
LengthRead = 0x4,
|
||||
All = FileRead | TitleRead | LengthRead
|
||||
};
|
||||
|
||||
enum State
|
||||
{
|
||||
Header,
|
||||
Track,
|
||||
Footer
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
The format is essentially that of an INI file structured as follows:
|
||||
@@ -231,89 +214,25 @@ NumberOfEntries=2
|
||||
|
||||
Version=2
|
||||
*/
|
||||
inline bool containsFlag(const ReadFlags& flag)
|
||||
void parseLine(int, const QString &line, const QUrl &root)
|
||||
{
|
||||
return (m_readFlags & int(flag)) == flag;
|
||||
// We ignore everything but 'File' entries, since that's the only thing we care about.
|
||||
if (!line.startsWith(QLatin1String("File")))
|
||||
return;
|
||||
|
||||
QString value = getValue(line);
|
||||
if (value.isEmpty())
|
||||
return;
|
||||
|
||||
emit newItem(expandToFullPath(root, value));
|
||||
}
|
||||
|
||||
inline void setFlag(const ReadFlags& flag)
|
||||
{
|
||||
m_readFlags |= int(flag);
|
||||
}
|
||||
|
||||
void parseLine(int lineIndex, const QString& line, const QUrl&)
|
||||
{
|
||||
switch (m_state) {
|
||||
case Header:
|
||||
if (line == QLatin1String("[playlist]")) {
|
||||
m_state = Track;
|
||||
setCount(1);
|
||||
}
|
||||
break;
|
||||
case Track:
|
||||
if (!containsFlag(FileRead) && line.startsWith(m_fileName)) {
|
||||
m_item[QLatin1String("url")] = getValue(lineIndex, line);
|
||||
setFlag(FileRead);
|
||||
} else if (!containsFlag(TitleRead) && line.startsWith(m_titleName)) {
|
||||
m_item[QMediaMetaData::Title] = getValue(lineIndex, line);
|
||||
setFlag(TitleRead);
|
||||
} else if (!containsFlag(LengthRead) && line.startsWith(m_lengthName)) {
|
||||
//convert from seconds to miliseconds
|
||||
int length = getValue(lineIndex, line).toInt();
|
||||
if (length > 0)
|
||||
m_item[QMediaMetaData::Duration] = length * 1000;
|
||||
setFlag(LengthRead);
|
||||
} else if (line.startsWith(QLatin1String("NumberOfEntries"))) {
|
||||
m_state = Footer;
|
||||
int entries = getValue(lineIndex, line).toInt();
|
||||
int count = m_readFlags == 0 ? (m_count - 1) : m_count;
|
||||
if (entries != count) {
|
||||
emit error(QPlaylistFileParser::FormatError, tr("Error parsing playlist: %1, expected count = %2").
|
||||
arg(line, QString::number(count)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (m_readFlags == int(All)) {
|
||||
emit newItem(m_item);
|
||||
setCount(m_count + 1);
|
||||
}
|
||||
break;
|
||||
case Footer:
|
||||
if (line.startsWith(QLatin1String("Version"))) {
|
||||
int version = getValue(lineIndex, line).toInt();
|
||||
if (version != 2)
|
||||
emit error(QPlaylistFileParser::FormatError, QString(tr("Error parsing playlist at line[%1], expected version = 2")).arg(line));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QString getValue(int lineIndex, const QString& line) {
|
||||
QString getValue(const QString& line) {
|
||||
int start = line.indexOf('=');
|
||||
if (start < 0) {
|
||||
emit error(QPlaylistFileParser::FormatError, QString(tr("Error parsing playlist at line[%1]:%2")).arg(QString::number(lineIndex), line));
|
||||
if (start < 0)
|
||||
return QString();
|
||||
}
|
||||
return line.midRef(start + 1).trimmed().toString();
|
||||
}
|
||||
|
||||
void setCount(int count) {
|
||||
m_count = count;
|
||||
m_fileName = QStringLiteral("File%1").arg(count);
|
||||
m_titleName = QStringLiteral("Title%1").arg(count);
|
||||
m_lengthName = QStringLiteral("Length%1").arg(count);
|
||||
m_item.clear();
|
||||
m_readFlags = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
State m_state;
|
||||
int m_count;
|
||||
QString m_titleName;
|
||||
QString m_fileName;
|
||||
QString m_lengthName;
|
||||
QVariantMap m_item;
|
||||
int m_readFlags;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,8 @@ void QMediaNetworkPlaylistProviderPrivate::_q_handleParserError(QPlaylistFilePar
|
||||
break;
|
||||
}
|
||||
|
||||
parser.stop();
|
||||
|
||||
emit q->loadFailed(playlistError, errorMessage);
|
||||
}
|
||||
|
||||
|
||||
@@ -760,7 +760,7 @@ qint64 QAlsaAudioInput::elapsedUSecs() const
|
||||
if (deviceState == QAudio::StoppedState)
|
||||
return 0;
|
||||
|
||||
return clockStamp.elapsed()*1000;
|
||||
return clockStamp.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
void QAlsaAudioInput::reset()
|
||||
|
||||
@@ -774,7 +774,7 @@ qint64 QAlsaAudioOutput::elapsedUSecs() const
|
||||
if (deviceState == QAudio::StoppedState)
|
||||
return 0;
|
||||
|
||||
return clockStamp.elapsed()*1000;
|
||||
return clockStamp.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
void QAlsaAudioOutput::reset()
|
||||
|
||||
@@ -474,7 +474,7 @@ qint64 QOpenSLESAudioInput::elapsedUSecs() const
|
||||
if (m_deviceState == QAudio::StoppedState)
|
||||
return 0;
|
||||
|
||||
return m_clockStamp.elapsed() * 1000;
|
||||
return m_clockStamp.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
void QOpenSLESAudioInput::setVolume(qreal vol)
|
||||
|
||||
@@ -273,7 +273,7 @@ qint64 QOpenSLESAudioOutput::elapsedUSecs() const
|
||||
if (m_state == QAudio::StoppedState)
|
||||
return 0;
|
||||
|
||||
return m_clockStamp.elapsed() * 1000;
|
||||
return m_clockStamp.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
void QOpenSLESAudioOutput::reset()
|
||||
|
||||
@@ -684,7 +684,7 @@ qint64 QPulseAudioInput::elapsedUSecs() const
|
||||
if (m_deviceState == QAudio::StoppedState)
|
||||
return 0;
|
||||
|
||||
return m_clockStamp.elapsed() * 1000;
|
||||
return m_clockStamp.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
void QPulseAudioInput::reset()
|
||||
|
||||
@@ -596,7 +596,7 @@ qint64 QPulseAudioOutput::elapsedUSecs() const
|
||||
if (m_deviceState == QAudio::StoppedState)
|
||||
return 0;
|
||||
|
||||
return m_clockStamp.elapsed() * 1000;
|
||||
return m_clockStamp.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
void QPulseAudioOutput::reset()
|
||||
|
||||
@@ -186,7 +186,7 @@ qint64 QnxAudioInput::elapsedUSecs() const
|
||||
if (m_state == QAudio::StoppedState)
|
||||
return 0;
|
||||
|
||||
return m_clockStamp.elapsed() * 1000;
|
||||
return m_clockStamp.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
QAudio::Error QnxAudioInput::error() const
|
||||
|
||||
@@ -172,7 +172,7 @@ qint64 QnxAudioOutput::elapsedUSecs() const
|
||||
if (m_state == QAudio::StoppedState)
|
||||
return 0;
|
||||
else
|
||||
return m_startTimeStamp.elapsed() * 1000;
|
||||
return m_startTimeStamp.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
QAudio::Error QnxAudioOutput::error() const
|
||||
|
||||
@@ -538,6 +538,7 @@ void MmRendererMediaPlayerControl::play()
|
||||
return;
|
||||
}
|
||||
|
||||
m_stopEventsToIgnore = 0; // once playing, stop events must be proccessed
|
||||
setState( QMediaPlayer::PlayingState);
|
||||
}
|
||||
|
||||
|
||||
@@ -698,7 +698,7 @@ qint64 QWindowsAudioInput::elapsedUSecs() const
|
||||
if (deviceState == QAudio::StoppedState)
|
||||
return 0;
|
||||
|
||||
return timeStampOpened.elapsed()*1000;
|
||||
return timeStampOpened.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
void QWindowsAudioInput::reset()
|
||||
|
||||
@@ -674,7 +674,7 @@ qint64 QWindowsAudioOutput::elapsedUSecs() const
|
||||
if (deviceState == QAudio::StoppedState)
|
||||
return 0;
|
||||
|
||||
return timeStampOpened.elapsed()*1000;
|
||||
return timeStampOpened.elapsed() * qint64(1000);
|
||||
}
|
||||
|
||||
QAudio::Error QWindowsAudioOutput::error() const
|
||||
|
||||
@@ -236,7 +236,6 @@ void MFAudioDecoderControl::handleMediaSourceReady()
|
||||
}
|
||||
|
||||
if (m_sourceResolver->mediaSource()) {
|
||||
IMFPresentationDescriptor *pd = 0;
|
||||
if (mediaType && m_resampler) {
|
||||
HRESULT hr = S_OK;
|
||||
hr = m_resampler->SetInputType(m_mfInputStreamID, mediaType, 0);
|
||||
@@ -246,9 +245,11 @@ void MFAudioDecoderControl::handleMediaSourceReady()
|
||||
qWarning() << "MFAudioDecoderControl: failed to SetInputType of resampler" << hr;
|
||||
}
|
||||
}
|
||||
IMFPresentationDescriptor *pd;
|
||||
if (SUCCEEDED(m_sourceResolver->mediaSource()->CreatePresentationDescriptor(&pd))) {
|
||||
UINT64 duration = 0;
|
||||
pd->GetUINT64(MF_PD_DURATION, &duration);
|
||||
pd->Release();
|
||||
duration /= 10000;
|
||||
if (m_duration != qint64(duration)) {
|
||||
m_duration = qint64(duration);
|
||||
|
||||
@@ -258,6 +258,7 @@ void MFPlayerSession::handleMediaSourceReady()
|
||||
//convert from 100 nanosecond to milisecond
|
||||
emit durationUpdate(qint64(m_duration / 10000));
|
||||
setupPlaybackTopology(mediaSource, sourcePD);
|
||||
sourcePD->Release();
|
||||
} else {
|
||||
changeStatus(QMediaPlayer::InvalidMedia);
|
||||
emit error(QMediaPlayer::ResourceError, tr("Cannot create presentation descriptor."), true);
|
||||
@@ -415,12 +416,15 @@ IMFTopologyNode* MFPlayerSession::addOutputNode(IMFStreamDescriptor *streamDesc,
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = node->SetUINT32(MF_TOPONODE_STREAMID, sinkID);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (SUCCEEDED(topology->AddNode(node)))
|
||||
if (SUCCEEDED(topology->AddNode(node))) {
|
||||
handler->Release();
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
handler->Release();
|
||||
}
|
||||
node->Release();
|
||||
return NULL;
|
||||
@@ -609,42 +613,39 @@ HRESULT BindOutputNode(IMFTopologyNode *pNode)
|
||||
// Sets the IMFStreamSink pointers on all of the output nodes in a topology.
|
||||
HRESULT BindOutputNodes(IMFTopology *pTopology)
|
||||
{
|
||||
DWORD cNodes = 0;
|
||||
|
||||
IMFCollection *collection = NULL;
|
||||
IUnknown *element = NULL;
|
||||
IMFTopologyNode *node = NULL;
|
||||
IMFCollection *collection;
|
||||
|
||||
// Get the collection of output nodes.
|
||||
HRESULT hr = pTopology->GetOutputNodeCollection(&collection);
|
||||
|
||||
// Enumerate all of the nodes in the collection.
|
||||
if (SUCCEEDED(hr))
|
||||
if (SUCCEEDED(hr)) {
|
||||
DWORD cNodes;
|
||||
hr = collection->GetElementCount(&cNodes);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
for (DWORD i = 0; i < cNodes; i++) {
|
||||
hr = collection->GetElement(i, &element);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
if (SUCCEEDED(hr)) {
|
||||
for (DWORD i = 0; i < cNodes; i++) {
|
||||
IUnknown *element;
|
||||
hr = collection->GetElement(i, &element);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
hr = element->QueryInterface(IID_IMFTopologyNode, (void**)&node);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
IMFTopologyNode *node;
|
||||
hr = element->QueryInterface(IID_IMFTopologyNode, (void**)&node);
|
||||
element->Release();
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
// Bind this node.
|
||||
hr = BindOutputNode(node);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
// Bind this node.
|
||||
hr = BindOutputNode(node);
|
||||
node->Release();
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
}
|
||||
}
|
||||
collection->Release();
|
||||
}
|
||||
|
||||
if (collection)
|
||||
collection->Release();
|
||||
if (element)
|
||||
element->Release();
|
||||
if (node)
|
||||
node->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
@@ -1502,8 +1503,11 @@ HRESULT MFPlayerSession::Invoke(IMFAsyncResult *pResult)
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_closing)
|
||||
if (!m_closing) {
|
||||
emit sessionEvent(pEvent);
|
||||
} else {
|
||||
pEvent->Release();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1626,9 +1630,6 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(MFGetService(m_session, MR_STREAM_VOLUME_SERVICE, IID_PPV_ARGS(&m_volumeControl))))
|
||||
setVolumeInternal(m_muted ? 0 : m_volume);
|
||||
|
||||
DWORD dwCharacteristics = 0;
|
||||
m_sourceResolver->mediaSource()->GetCharacteristics(&dwCharacteristics);
|
||||
emit seekableUpdate(MFMEDIASOURCE_CAN_SEEK & dwCharacteristics);
|
||||
@@ -1699,6 +1700,9 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
|
||||
}
|
||||
}
|
||||
MFGetService(m_session, MFNETSOURCE_STATISTICS_SERVICE, IID_PPV_ARGS(&m_netsourceStatistics));
|
||||
|
||||
if (SUCCEEDED(MFGetService(m_session, MR_STREAM_VOLUME_SERVICE, IID_PPV_ARGS(&m_volumeControl))))
|
||||
setVolumeInternal(m_muted ? 0 : m_volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,6 +155,9 @@ STDMETHODIMP AudioSampleGrabberCallback::OnProcessSample(REFGUID guidMajorMediaT
|
||||
if (llSampleTime == _I64_MAX) {
|
||||
// Set default QAudioBuffer start time
|
||||
llSampleTime = -1;
|
||||
} else {
|
||||
// WMF uses 100-nanosecond units, Qt uses microseconds
|
||||
llSampleTime /= 10;
|
||||
}
|
||||
|
||||
foreach (MFAudioProbeControl* probe, m_audioProbes)
|
||||
|
||||
Reference in New Issue
Block a user