summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/wmf/player/mfaudioprobecontrol.cpp77
-rw-r--r--src/plugins/wmf/player/mfaudioprobecontrol.h68
-rw-r--r--src/plugins/wmf/player/mfplayerservice.cpp16
-rw-r--r--src/plugins/wmf/player/mfplayersession.cpp163
-rw-r--r--src/plugins/wmf/player/mfplayersession.h12
-rw-r--r--src/plugins/wmf/player/player.pri6
-rw-r--r--src/plugins/wmf/samplegrabber.cpp172
-rw-r--r--src/plugins/wmf/samplegrabber.h95
-rw-r--r--src/plugins/wmf/wmf.pro6
9 files changed, 610 insertions, 5 deletions
diff --git a/src/plugins/wmf/player/mfaudioprobecontrol.cpp b/src/plugins/wmf/player/mfaudioprobecontrol.cpp
new file mode 100644
index 000000000..c76ab913f
--- /dev/null
+++ b/src/plugins/wmf/player/mfaudioprobecontrol.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mfaudioprobecontrol.h"
+
+MFAudioProbeControl::MFAudioProbeControl(QObject *parent):
+ QMediaAudioProbeControl(parent)
+{
+}
+
+MFAudioProbeControl::~MFAudioProbeControl()
+{
+}
+
+void MFAudioProbeControl::bufferProbed(const char *data, quint32 size, const QAudioFormat& format, qint64 startTime)
+{
+ if (!format.isValid())
+ return;
+
+ QAudioBuffer audioBuffer = QAudioBuffer(QByteArray(data, size), format, startTime);
+
+ {
+ QMutexLocker locker(&m_bufferMutex);
+ m_pendingBuffer = audioBuffer;
+ QMetaObject::invokeMethod(this, "bufferProbed", Qt::QueuedConnection);
+ }
+}
+
+void MFAudioProbeControl::bufferProbed()
+{
+ QAudioBuffer audioBuffer;
+ {
+ QMutexLocker locker(&m_bufferMutex);
+ if (!m_pendingBuffer.isValid())
+ return;
+ audioBuffer = m_pendingBuffer;
+ }
+ emit audioBufferProbed(audioBuffer);
+}
diff --git a/src/plugins/wmf/player/mfaudioprobecontrol.h b/src/plugins/wmf/player/mfaudioprobecontrol.h
new file mode 100644
index 000000000..878d00d53
--- /dev/null
+++ b/src/plugins/wmf/player/mfaudioprobecontrol.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MFAUDIOPROBECONTROL_H
+#define MFAUDIOPROBECONTROL_H
+
+#include <qmediaaudioprobecontrol.h>
+#include <QtCore/qmutex.h>
+#include <qaudiobuffer.h>
+
+QT_USE_NAMESPACE
+
+class MFAudioProbeControl : public QMediaAudioProbeControl
+{
+ Q_OBJECT
+public:
+ explicit MFAudioProbeControl(QObject *parent);
+ virtual ~MFAudioProbeControl();
+
+ void bufferProbed(const char *data, quint32 size, const QAudioFormat& format, qint64 startTime);
+
+private slots:
+ void bufferProbed();
+
+private:
+ QAudioBuffer m_pendingBuffer;
+ QMutex m_bufferMutex;
+};
+
+#endif
diff --git a/src/plugins/wmf/player/mfplayerservice.cpp b/src/plugins/wmf/player/mfplayerservice.cpp
index 33720550e..aad1abefb 100644
--- a/src/plugins/wmf/player/mfplayerservice.cpp
+++ b/src/plugins/wmf/player/mfplayerservice.cpp
@@ -49,6 +49,7 @@
#endif
#include "mfvideorenderercontrol.h"
#include "mfaudioendpointcontrol.h"
+#include "mfaudioprobecontrol.h"
#include "mfplayerservice.h"
#include "mfplayersession.h"
#include "mfmetadatacontrol.h"
@@ -105,6 +106,13 @@ QMediaControl* MFPlayerService::requestControl(const char *name)
return m_videoWindowControl;
}
#endif
+ } else if (qstrcmp(name,QMediaAudioProbeControl_iid) == 0) {
+ if (m_session) {
+ MFAudioProbeControl *probe = new MFAudioProbeControl(this);
+ m_session->addProbe(probe);
+ return probe;
+ }
+ return 0;
}
return 0;
@@ -125,6 +133,14 @@ void MFPlayerService::releaseControl(QMediaControl *control)
m_videoWindowControl = 0;
#endif
}
+
+ MFAudioProbeControl* audioProbe = qobject_cast<MFAudioProbeControl*>(control);
+ if (audioProbe) {
+ if (m_session)
+ m_session->removeProbe(audioProbe);
+ delete audioProbe;
+ return;
+ }
}
MFAudioEndpointControl* MFPlayerService::audioEndpointControl() const
diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp
index 2d56aff3d..bd51bba03 100644
--- a/src/plugins/wmf/player/mfplayersession.cpp
+++ b/src/plugins/wmf/player/mfplayersession.cpp
@@ -63,6 +63,7 @@
#include <Mferror.h>
#include <nserror.h>
#include "sourceresolver.h"
+#include "samplegrabber.h"
//#define DEBUG_MEDIAFOUNDATION
//#define TEST_STREAMING
@@ -416,6 +417,8 @@ MFPlayerSession::MFPlayerSession(MFPlayerService *playerService)
, m_scrubbing(false)
, m_restoreRate(1)
, m_mediaTypes(0)
+ , m_audioSampleGrabber(0)
+ , m_audioSampleGrabberNode(0)
{
m_hCloseEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_sourceResolver = new SourceResolver();
@@ -437,6 +440,8 @@ MFPlayerSession::MFPlayerSession(MFPlayerService *playerService)
PropVariantInit(&m_varStart);
m_varStart.vt = VT_I8;
m_varStart.uhVal.QuadPart = 0;
+
+ m_audioSampleGrabber = new AudioSampleGrabberCallback;
}
void MFPlayerSession::close()
@@ -470,8 +475,19 @@ void MFPlayerSession::close()
CloseHandle(m_hCloseEvent);
}
+void MFPlayerSession::addProbe(MFAudioProbeControl *probe)
+{
+ m_audioSampleGrabber->addProbe(probe);
+}
+
+void MFPlayerSession::removeProbe(MFAudioProbeControl *probe)
+{
+ m_audioSampleGrabber->removeProbe(probe);
+}
+
MFPlayerSession::~MFPlayerSession()
{
+ m_audioSampleGrabber->Release();
}
@@ -579,7 +595,12 @@ void MFPlayerSession::setupPlaybackTopology(IMFMediaSource *source, IMFPresentat
if (sourceNode) {
IMFTopologyNode *outputNode = addOutputNode(streamDesc, mediaType, topology, 0);
if (outputNode) {
- hr = sourceNode->ConnectOutput(0, outputNode, 0);
+ // Only install audio sample grabber for the first audio stream.
+ if (mediaType != Audio || m_audioSampleGrabberNode || !setupAudioSampleGrabber(topology, sourceNode, outputNode)) {
+ hr = sourceNode->ConnectOutput(0, outputNode, 0);
+ } else {
+ hr = S_OK;
+ }
if (FAILED(hr)) {
emit error(QMediaPlayer::FormatError, tr("Unable to play some stream"), false);
}
@@ -689,6 +710,133 @@ IMFTopologyNode* MFPlayerSession::addOutputNode(IMFStreamDescriptor *streamDesc,
return NULL;
}
+bool MFPlayerSession::addAudioSampleGrabberNode(IMFTopology *topology)
+{
+ HRESULT hr = S_OK;
+ IMFMediaType *pType = 0;
+ IMFActivate *sinkActivate = 0;
+ do {
+ hr = MFCreateMediaType(&pType);
+ if (FAILED(hr))
+ break;
+
+ hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
+ if (FAILED(hr))
+ break;
+
+ hr = pType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
+ if (FAILED(hr))
+ break;
+
+ hr = MFCreateSampleGrabberSinkActivate(pType, m_audioSampleGrabber, &sinkActivate);
+ if (FAILED(hr))
+ break;
+
+ // Note: Data is distorted if this attribute is enabled
+ hr = sinkActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, FALSE);
+ if (FAILED(hr))
+ break;
+
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &m_audioSampleGrabberNode);
+ if (FAILED(hr))
+ break;
+
+ hr = m_audioSampleGrabberNode->SetObject(sinkActivate);
+ if (FAILED(hr))
+ break;
+
+ hr = m_audioSampleGrabberNode->SetUINT32(MF_TOPONODE_STREAMID, 0); // Identifier of the stream sink.
+ if (FAILED(hr))
+ break;
+
+ hr = m_audioSampleGrabberNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);
+ if (FAILED(hr))
+ break;
+
+ hr = topology->AddNode(m_audioSampleGrabberNode);
+ if (FAILED(hr))
+ break;
+
+ pType->Release();
+ sinkActivate->Release();
+ return true;
+ } while (false);
+
+ if (pType)
+ pType->Release();
+ if (sinkActivate)
+ sinkActivate->Release();
+ if (m_audioSampleGrabberNode) {
+ m_audioSampleGrabberNode->Release();
+ m_audioSampleGrabberNode = NULL;
+ }
+ return false;
+}
+
+bool MFPlayerSession::setupAudioSampleGrabber(IMFTopology *topology, IMFTopologyNode *sourceNode, IMFTopologyNode *outputNode)
+{
+ if (!addAudioSampleGrabberNode(topology))
+ return false;
+
+ HRESULT hr = S_OK;
+ IMFTopologyNode *pTeeNode = NULL;
+
+ IMFMediaTypeHandler *typeHandler = NULL;
+ IMFMediaType *mediaType = NULL;
+ do {
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &pTeeNode);
+ if (FAILED(hr))
+ break;
+ hr = sourceNode->ConnectOutput(0, pTeeNode, 0);
+ if (FAILED(hr))
+ break;
+ hr = pTeeNode->ConnectOutput(0, outputNode, 0);
+ if (FAILED(hr))
+ break;
+ hr = pTeeNode->ConnectOutput(1, m_audioSampleGrabberNode, 0);
+ if (FAILED(hr))
+ break;
+ } while (false);
+
+ if (pTeeNode)
+ pTeeNode->Release();
+ if (mediaType)
+ mediaType->Release();
+ if (typeHandler)
+ typeHandler->Release();
+ return hr == S_OK;
+}
+
+QAudioFormat MFPlayerSession::audioFormatForMFMediaType(IMFMediaType *mediaType) const
+{
+ WAVEFORMATEX *wfx = 0;
+ UINT32 size;
+ HRESULT hr = MFCreateWaveFormatExFromMFMediaType(mediaType, &wfx, &size, MFWaveFormatExConvertFlag_Normal);
+ if (FAILED(hr))
+ return QAudioFormat();
+
+ if (size < sizeof(WAVEFORMATEX)) {
+ CoTaskMemFree(wfx);
+ return QAudioFormat();
+ }
+
+ if (wfx->wFormatTag != WAVE_FORMAT_PCM) {
+ CoTaskMemFree(wfx);
+ return QAudioFormat();
+ }
+
+ QAudioFormat format;
+ format.setSampleRate(wfx->nSamplesPerSec);
+ format.setChannelCount(wfx->nChannels);
+ format.setSampleSize(wfx->wBitsPerSample);
+ format.setCodec("audio/pcm");
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+
+ CoTaskMemFree(wfx);
+ return format;
+}
+
void MFPlayerSession::stop(bool immediate)
{
#ifdef DEBUG_MEDIAFOUNDATION
@@ -1270,6 +1418,15 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
}
break;
case MESessionTopologySet: {
+ if (m_audioSampleGrabberNode) {
+ IMFMediaType *mediaType = 0;
+ hr = MFGetTopoNodeCurrentType(m_audioSampleGrabberNode, 0, FALSE, &mediaType);
+ if (SUCCEEDED(hr)) {
+ m_audioSampleGrabber->setFormat(audioFormatForMFMediaType(mediaType));
+ mediaType->Release();
+ }
+ }
+
if (SUCCEEDED(MFGetService(m_session, MR_POLICY_VOLUME_SERVICE, IID_PPV_ARGS(&m_volumeControl)))) {
m_volumeControl->SetMasterVolume(m_volume);
m_volumeControl->SetMute(m_muted);
@@ -1402,4 +1559,8 @@ void MFPlayerSession::clear()
m_netsourceStatistics->Release();
m_netsourceStatistics = NULL;
}
+ if (m_audioSampleGrabberNode) {
+ m_audioSampleGrabberNode->Release();
+ m_audioSampleGrabberNode = NULL;
+ }
}
diff --git a/src/plugins/wmf/player/mfplayersession.h b/src/plugins/wmf/player/mfplayersession.h
index 70ce92562..969fd2491 100644
--- a/src/plugins/wmf/player/mfplayersession.h
+++ b/src/plugins/wmf/player/mfplayersession.h
@@ -54,6 +54,7 @@
#include <QtCore/qmutex.h>
#include <QtCore/qurl.h>
#include <QtCore/qwaitcondition.h>
+#include <QtMultimedia/qaudioformat.h>
QT_BEGIN_NAMESPACE
class QMediaContent;
@@ -70,6 +71,8 @@ class MFVideoRendererControl;
class MFPlayerControl;
class MFMetaDataControl;
class MFPlayerService;
+class AudioSampleGrabberCallback;
+class MFAudioProbeControl;
class MFPlayerSession : public QObject, public IMFAsyncCallback
{
@@ -115,6 +118,9 @@ public:
void close();
+ void addProbe(MFAudioProbeControl* probe);
+ void removeProbe(MFAudioProbeControl* probe);
+
Q_SIGNALS:
void error(QMediaPlayer::Error error, QString errorString, bool isFatal);
void sessionEvent(IMFMediaEvent *sessionEvent);
@@ -211,6 +217,12 @@ private:
IMFTopologyNode* addSourceNode(IMFTopology* topology, IMFMediaSource* source,
IMFPresentationDescriptor* presentationDesc, IMFStreamDescriptor *streamDesc);
IMFTopologyNode* addOutputNode(IMFStreamDescriptor *streamDesc, MediaType& mediaType, IMFTopology* topology, DWORD sinkID);
+
+ bool addAudioSampleGrabberNode(IMFTopology* topology);
+ bool setupAudioSampleGrabber(IMFTopology *topology, IMFTopologyNode *sourceNode, IMFTopologyNode *outputNode);
+ QAudioFormat audioFormatForMFMediaType(IMFMediaType *mediaType) const;
+ AudioSampleGrabberCallback *m_audioSampleGrabber;
+ IMFTopologyNode *m_audioSampleGrabberNode;
};
diff --git a/src/plugins/wmf/player/player.pri b/src/plugins/wmf/player/player.pri
index 733c790ed..8f28b5225 100644
--- a/src/plugins/wmf/player/player.pri
+++ b/src/plugins/wmf/player/player.pri
@@ -10,7 +10,8 @@ HEADERS += \
$$PWD/mfplayercontrol.h \
$$PWD/mfvideorenderercontrol.h \
$$PWD/mfaudioendpointcontrol.h \
- $$PWD/mfmetadatacontrol.h
+ $$PWD/mfmetadatacontrol.h \
+ $$PWD/mfaudioprobecontrol.h
SOURCES += \
$$PWD/mfplayerservice.cpp \
@@ -18,7 +19,8 @@ SOURCES += \
$$PWD/mfplayercontrol.cpp \
$$PWD/mfvideorenderercontrol.cpp \
$$PWD/mfaudioendpointcontrol.cpp \
- $$PWD/mfmetadatacontrol.cpp
+ $$PWD/mfmetadatacontrol.cpp \
+ $$PWD/mfaudioprobecontrol.cpp
!isEmpty(QT.widgets.name):!simulator {
HEADERS += $$PWD/evr9videowindowcontrol.h
diff --git a/src/plugins/wmf/samplegrabber.cpp b/src/plugins/wmf/samplegrabber.cpp
new file mode 100644
index 000000000..98757b609
--- /dev/null
+++ b/src/plugins/wmf/samplegrabber.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "samplegrabber.h"
+#include "mfaudioprobecontrol.h"
+
+STDMETHODIMP SampleGrabberCallback::QueryInterface(REFIID riid, void** ppv)
+{
+ if (!ppv)
+ return E_POINTER;
+ if (riid == IID_IMFSampleGrabberSinkCallback) {
+ *ppv = static_cast<IMFSampleGrabberSinkCallback*>(this);
+ } else if (riid == IID_IMFClockStateSink) {
+ *ppv = static_cast<IMFClockStateSink*>(this);
+ } else if (riid == IID_IUnknown) {
+ *ppv = static_cast<IUnknown*>(this);
+ } else {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+ AddRef();
+ return S_OK;
+}
+
+STDMETHODIMP_(ULONG) SampleGrabberCallback::AddRef()
+{
+ return InterlockedIncrement(&m_cRef);
+}
+
+STDMETHODIMP_(ULONG) SampleGrabberCallback::Release()
+{
+ ULONG cRef = InterlockedDecrement(&m_cRef);
+ if (cRef == 0) {
+ delete this;
+ }
+ return cRef;
+
+}
+
+// IMFClockStateSink methods.
+
+STDMETHODIMP SampleGrabberCallback::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset)
+{
+ Q_UNUSED(hnsSystemTime);
+ Q_UNUSED(llClockStartOffset);
+ return S_OK;
+}
+
+STDMETHODIMP SampleGrabberCallback::OnClockStop(MFTIME hnsSystemTime)
+{
+ Q_UNUSED(hnsSystemTime);
+ return S_OK;
+}
+
+STDMETHODIMP SampleGrabberCallback::OnClockPause(MFTIME hnsSystemTime)
+{
+ Q_UNUSED(hnsSystemTime);
+ return S_OK;
+}
+
+STDMETHODIMP SampleGrabberCallback::OnClockRestart(MFTIME hnsSystemTime)
+{
+ Q_UNUSED(hnsSystemTime);
+ return S_OK;
+}
+
+STDMETHODIMP SampleGrabberCallback::OnClockSetRate(MFTIME hnsSystemTime, float flRate)
+{
+ Q_UNUSED(hnsSystemTime);
+ Q_UNUSED(flRate);
+ return S_OK;
+}
+
+// IMFSampleGrabberSink methods.
+
+STDMETHODIMP SampleGrabberCallback::OnSetPresentationClock(IMFPresentationClock* pClock)
+{
+ Q_UNUSED(pClock);
+ return S_OK;
+}
+
+STDMETHODIMP SampleGrabberCallback::OnShutdown()
+{
+ return S_OK;
+}
+
+void AudioSampleGrabberCallback::addProbe(MFAudioProbeControl* probe)
+{
+ QMutexLocker locker(&m_audioProbeMutex);
+
+ if (m_audioProbes.contains(probe))
+ return;
+
+ m_audioProbes.append(probe);
+}
+
+void AudioSampleGrabberCallback::removeProbe(MFAudioProbeControl* probe)
+{
+ QMutexLocker locker(&m_audioProbeMutex);
+ m_audioProbes.removeOne(probe);
+}
+
+void AudioSampleGrabberCallback::setFormat(const QAudioFormat& format)
+{
+ m_format = format;
+}
+
+STDMETHODIMP AudioSampleGrabberCallback::OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags,
+ LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer,
+ DWORD dwSampleSize)
+{
+ Q_UNUSED(dwSampleFlags);
+ Q_UNUSED(llSampleTime);
+ Q_UNUSED(llSampleDuration);
+
+ if (guidMajorMediaType != GUID_NULL && guidMajorMediaType != MFMediaType_Audio)
+ return S_OK;
+
+ QMutexLocker locker(&m_audioProbeMutex);
+
+ if (m_audioProbes.isEmpty())
+ return S_OK;
+
+ // Check if sample has a presentation time
+ if (llSampleTime == _I64_MAX) {
+ // Set default QAudioBuffer start time
+ llSampleTime = -1;
+ }
+
+ foreach (MFAudioProbeControl* probe, m_audioProbes)
+ probe->bufferProbed((const char*)pSampleBuffer, dwSampleSize, m_format, llSampleTime);
+
+ return S_OK;
+}
diff --git a/src/plugins/wmf/samplegrabber.h b/src/plugins/wmf/samplegrabber.h
new file mode 100644
index 000000000..e639eac21
--- /dev/null
+++ b/src/plugins/wmf/samplegrabber.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SAMPLEGRABBER_H
+#define SAMPLEGRABBER_H
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qlist.h>
+#include <QtMultimedia/qaudioformat.h>
+#include <mfapi.h>
+#include <mfidl.h>
+
+class MFAudioProbeControl;
+
+class SampleGrabberCallback : public IMFSampleGrabberSinkCallback
+{
+public:
+ // IUnknown methods
+ STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ // IMFClockStateSink methods
+ STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset);
+ STDMETHODIMP OnClockStop(MFTIME hnsSystemTime);
+ STDMETHODIMP OnClockPause(MFTIME hnsSystemTime);
+ STDMETHODIMP OnClockRestart(MFTIME hnsSystemTime);
+ STDMETHODIMP OnClockSetRate(MFTIME hnsSystemTime, float flRate);
+
+ // IMFSampleGrabberSinkCallback methods
+ STDMETHODIMP OnSetPresentationClock(IMFPresentationClock* pClock);
+ STDMETHODIMP OnShutdown();
+
+protected:
+ SampleGrabberCallback() : m_cRef(1) {}
+
+private:
+ long m_cRef;
+};
+
+class AudioSampleGrabberCallback: public SampleGrabberCallback {
+public:
+ void addProbe(MFAudioProbeControl* probe);
+ void removeProbe(MFAudioProbeControl* probe);
+ void setFormat(const QAudioFormat& format);
+
+ STDMETHODIMP OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags,
+ LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer,
+ DWORD dwSampleSize);
+
+private:
+ QList<MFAudioProbeControl*> m_audioProbes;
+ QMutex m_audioProbeMutex;
+ QAudioFormat m_format;
+};
+
+#endif // SAMPLEGRABBER_H
diff --git a/src/plugins/wmf/wmf.pro b/src/plugins/wmf/wmf.pro
index d7f596d46..87555dd64 100644
--- a/src/plugins/wmf/wmf.pro
+++ b/src/plugins/wmf/wmf.pro
@@ -18,12 +18,14 @@ INCLUDEPATH += .
HEADERS += \
wmfserviceplugin.h \
mfstream.h \
- sourceresolver.h
+ sourceresolver.h \
+ samplegrabber.h
SOURCES += \
wmfserviceplugin.cpp \
mfstream.cpp \
- sourceresolver.cpp
+ sourceresolver.cpp \
+ samplegrabber.cpp
include (player/player.pri)
include (decoder/decoder.pri)