Audioprobe implementation for wmf backend.
Change-Id: I63af91af870cb92c838c1ab5d4752815aa60a03f Reviewed-by: Ling Hu <ling.hu@nokia.com>
This commit is contained in:
committed by
Qt by Nokia
parent
4d13a15bae
commit
afe12ea4de
77
src/plugins/wmf/player/mfaudioprobecontrol.cpp
Normal file
77
src/plugins/wmf/player/mfaudioprobecontrol.cpp
Normal file
@@ -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);
|
||||
}
|
||||
68
src/plugins/wmf/player/mfaudioprobecontrol.h
Normal file
68
src/plugins/wmf/player/mfaudioprobecontrol.h
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
172
src/plugins/wmf/samplegrabber.cpp
Normal file
172
src/plugins/wmf/samplegrabber.cpp
Normal file
@@ -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;
|
||||
}
|
||||
95
src/plugins/wmf/samplegrabber.h
Normal file
95
src/plugins/wmf/samplegrabber.h
Normal file
@@ -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
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user