Audioprobe implementation for wmf backend.

Change-Id: I63af91af870cb92c838c1ab5d4752815aa60a03f
Reviewed-by: Ling Hu <ling.hu@nokia.com>
This commit is contained in:
Lev Zelenskiy
2012-07-11 15:06:40 +10:00
committed by Qt by Nokia
parent 4d13a15bae
commit afe12ea4de
9 changed files with 610 additions and 5 deletions

View File

@@ -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;
}
}