diff options
author | Christian Strømme <christian.stromme@theqtcompany.com> | 2016-01-15 17:27:32 +0100 |
---|---|---|
committer | Christian Strømme <christian.stromme@theqtcompany.com> | 2016-01-15 17:28:17 +0100 |
commit | 84e426c3af2a3bb1b7f916e54263aea758db38d0 (patch) | |
tree | 4fe09a8da5b15ba466e5771239d06f29a6c123da /src/plugins/wmf/player | |
parent | 84aaa48fdfc1f35c9870518a3d4b6f08a1f99449 (diff) | |
parent | 924dc7f48c7003b46079623738ae531f34aed903 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts:
src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
src/plugins/wmf/mftvideo.cpp
Change-Id: I78868b416ea4baec89ca3e2dc9eb4712db16d5fc
Diffstat (limited to 'src/plugins/wmf/player')
-rw-r--r-- | src/plugins/wmf/player/mfplayersession.cpp | 181 | ||||
-rw-r--r-- | src/plugins/wmf/player/mfplayersession.h | 3 | ||||
-rw-r--r-- | src/plugins/wmf/player/mfvideorenderercontrol.cpp | 111 | ||||
-rw-r--r-- | src/plugins/wmf/player/mfvideorenderercontrol.h | 6 |
4 files changed, 174 insertions, 127 deletions
diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index e4c498b76..0ac1c3d66 100644 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ b/src/plugins/wmf/player/mfplayersession.cpp @@ -266,6 +266,25 @@ void MFPlayerSession::handleMediaSourceReady() } } +MFPlayerSession::MediaType MFPlayerSession::getStreamType(IMFStreamDescriptor *stream) const +{ + if (!stream) + return Unknown; + + IMFMediaTypeHandler *typeHandler = NULL; + if (SUCCEEDED(stream->GetMediaTypeHandler(&typeHandler))) { + GUID guidMajorType; + if (SUCCEEDED(typeHandler->GetMajorType(&guidMajorType))) { + if (guidMajorType == MFMediaType_Audio) + return Audio; + else if (guidMajorType == MFMediaType_Video) + return Video; + } + } + + return Unknown; +} + void MFPlayerSession::setupPlaybackTopology(IMFMediaSource *source, IMFPresentationDescriptor *sourcePD) { HRESULT hr = S_OK; @@ -294,45 +313,58 @@ void MFPlayerSession::setupPlaybackTopology(IMFMediaSource *source, IMFPresentat for (DWORD i = 0; i < cSourceStreams; i++) { BOOL fSelected = FALSE; + bool streamAdded = false; IMFStreamDescriptor *streamDesc = NULL; HRESULT hr = sourcePD->GetStreamDescriptorByIndex(i, &fSelected, &streamDesc); if (SUCCEEDED(hr)) { - MediaType mediaType = Unknown; - IMFTopologyNode *sourceNode = addSourceNode(topology, source, sourcePD, streamDesc); - if (sourceNode) { - IMFTopologyNode *outputNode = addOutputNode(streamDesc, mediaType, topology, 0); - if (outputNode) { - bool connected = false; - if (mediaType == Audio) { - if (!m_audioSampleGrabberNode) - connected = setupAudioSampleGrabber(topology, sourceNode, outputNode); - } else if (mediaType == Video && outputNodeId == -1) { - // Remember video output node ID. - outputNode->GetTopoNodeID(&outputNodeId); - } + // The media might have multiple audio and video streams, + // only use one of each kind, and only if it is selected by default. + MediaType mediaType = getStreamType(streamDesc); + if (mediaType != Unknown + && ((m_mediaTypes & mediaType) == 0) // Check if this type isn't already added + && fSelected) { + + IMFTopologyNode *sourceNode = addSourceNode(topology, source, sourcePD, streamDesc); + if (sourceNode) { + IMFTopologyNode *outputNode = addOutputNode(mediaType, topology, 0); + if (outputNode) { + bool connected = false; + if (mediaType == Audio) { + if (!m_audioSampleGrabberNode) + connected = setupAudioSampleGrabber(topology, sourceNode, outputNode); + } else if (mediaType == Video && outputNodeId == -1) { + // Remember video output node ID. + outputNode->GetTopoNodeID(&outputNodeId); + } - if (!connected) - hr = sourceNode->ConnectOutput(0, outputNode, 0); - if (FAILED(hr)) { - emit error(QMediaPlayer::FormatError, tr("Unable to play any stream."), false); - } - else { - succeededCount++; - m_mediaTypes |= mediaType; - switch (mediaType) { - case Audio: - emit audioAvailable(); - break; - case Video: - emit videoAvailable(); - break; + if (!connected) + hr = sourceNode->ConnectOutput(0, outputNode, 0); + + if (FAILED(hr)) { + emit error(QMediaPlayer::FormatError, tr("Unable to play any stream."), false); + } else { + streamAdded = true; + succeededCount++; + m_mediaTypes |= mediaType; + switch (mediaType) { + case Audio: + emit audioAvailable(); + break; + case Video: + emit videoAvailable(); + break; + } } + outputNode->Release(); } - outputNode->Release(); + sourceNode->Release(); } - sourceNode->Release(); } + + if (fSelected && !streamAdded) + sourcePD->DeselectStream(i); + streamDesc->Release(); } } @@ -377,56 +409,38 @@ IMFTopologyNode* MFPlayerSession::addSourceNode(IMFTopology* topology, IMFMediaS return NULL; } -IMFTopologyNode* MFPlayerSession::addOutputNode(IMFStreamDescriptor *streamDesc, MediaType& mediaType, IMFTopology* topology, DWORD sinkID) +IMFTopologyNode* MFPlayerSession::addOutputNode(MediaType mediaType, IMFTopology* topology, DWORD sinkID) { IMFTopologyNode *node = NULL; - HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node); - if (FAILED(hr)) + if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node))) return NULL; - node->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE); - mediaType = Unknown; - IMFMediaTypeHandler *handler = NULL; - hr = streamDesc->GetMediaTypeHandler(&handler); - if (SUCCEEDED(hr)) { - GUID guidMajorType; - hr = handler->GetMajorType(&guidMajorType); - if (SUCCEEDED(hr)) { - IMFActivate *activate = NULL; - if (MFMediaType_Audio == guidMajorType) { - mediaType = Audio; - activate = m_playerService->audioEndpointControl()->createActivate(); - } else if (MFMediaType_Video == guidMajorType) { - mediaType = Video; - if (m_playerService->videoRendererControl()) { - activate = m_playerService->videoRendererControl()->createActivate(); - } else if (m_playerService->videoWindowControl()) { - activate = m_playerService->videoWindowControl()->createActivate(); - } else { - qWarning() << "no videoWindowControl or videoRendererControl, unable to add output node for video data"; - } - } else { - // Unknown stream type. - emit error(QMediaPlayer::FormatError, tr("Unknown stream type."), false); - } - - if (activate) { - hr = node->SetObject(activate); - if (SUCCEEDED(hr)) { - hr = node->SetUINT32(MF_TOPONODE_STREAMID, sinkID); - if (SUCCEEDED(hr)) { - if (SUCCEEDED(topology->AddNode(node))) { - handler->Release(); - return node; - } - } - } - } + IMFActivate *activate = NULL; + if (mediaType == Audio) { + activate = m_playerService->audioEndpointControl()->createActivate(); + } else if (mediaType == Video) { + if (m_playerService->videoRendererControl()) { + activate = m_playerService->videoRendererControl()->createActivate(); + } else if (m_playerService->videoWindowControl()) { + activate = m_playerService->videoWindowControl()->createActivate(); + } else { + qWarning() << "no videoWindowControl or videoRendererControl, unable to add output node for video data"; } - handler->Release(); + } else { + // Unknown stream type. + emit error(QMediaPlayer::FormatError, tr("Unknown stream type."), false); } - node->Release(); - return NULL; + + if (!activate + || FAILED(node->SetObject(activate)) + || FAILED(node->SetUINT32(MF_TOPONODE_STREAMID, sinkID)) + || FAILED(node->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE)) + || FAILED(topology->AddNode(node))) { + node->Release(); + node = NULL; + } + + return node; } bool MFPlayerSession::addAudioSampleGrabberNode(IMFTopology *topology) @@ -692,7 +706,6 @@ IMFTopology *MFPlayerSession::insertMFT(IMFTopology *topology, TOPOID outputNode IUnknown *element = 0; IMFTopologyNode *node = 0; IUnknown *outputObject = 0; - IMFMediaTypeHandler *videoSink = 0; IMFTopologyNode *inputNode = 0; IMFTopologyNode *mftNode = 0; bool mftAdded = false; @@ -711,22 +724,10 @@ IMFTopology *MFPlayerSession::insertMFT(IMFTopology *topology, TOPOID outputNode if (id != outputNodeId) break; - // Use output supported media types for the MFT if (FAILED(node->GetObject(&outputObject))) break; - if (FAILED(outputObject->QueryInterface(IID_IMFMediaTypeHandler, (void**)&videoSink))) - break; - - DWORD mtCount; - if (FAILED(videoSink->GetMediaTypeCount(&mtCount))) - break; - - for (DWORD i = 0; i < mtCount; ++i) { - IMFMediaType *type = 0; - if (SUCCEEDED(videoSink->GetMediaTypeByIndex(i, &type))) - m_videoProbeMFT->addSupportedMediaType(type); - } + m_videoProbeMFT->setVideoSink(outputObject); // Insert MFT between the output node and the node connected to it. DWORD outputIndex = 0; @@ -760,13 +761,13 @@ IMFTopology *MFPlayerSession::insertMFT(IMFTopology *topology, TOPOID outputNode node->Release(); if (element) element->Release(); - if (videoSink) - videoSink->Release(); if (outputObject) outputObject->Release(); if (mftAdded) break; + else + m_videoProbeMFT->setVideoSink(NULL); } } while (false); diff --git a/src/plugins/wmf/player/mfplayersession.h b/src/plugins/wmf/player/mfplayersession.h index 1d136ba55..5bbf8e212 100644 --- a/src/plugins/wmf/player/mfplayersession.h +++ b/src/plugins/wmf/player/mfplayersession.h @@ -215,9 +215,10 @@ private: void createSession(); void setupPlaybackTopology(IMFMediaSource *source, IMFPresentationDescriptor *sourcePD); + MediaType getStreamType(IMFStreamDescriptor *stream) const; IMFTopologyNode* addSourceNode(IMFTopology* topology, IMFMediaSource* source, IMFPresentationDescriptor* presentationDesc, IMFStreamDescriptor *streamDesc); - IMFTopologyNode* addOutputNode(IMFStreamDescriptor *streamDesc, MediaType& mediaType, IMFTopology* topology, DWORD sinkID); + IMFTopologyNode* addOutputNode(MediaType mediaType, IMFTopology* topology, DWORD sinkID); bool addAudioSampleGrabberNode(IMFTopology* topology); bool setupAudioSampleGrabber(IMFTopology *topology, IMFTopologyNode *sourceNode, IMFTopologyNode *outputNode); diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp index 683dd4b71..222d74ef2 100644 --- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp +++ b/src/plugins/wmf/player/mfvideorenderercontrol.cpp @@ -32,15 +32,9 @@ ****************************************************************************/ #include "mfvideorenderercontrol.h" -#include "mfglobal.h" +#include "mfactivate.h" -#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC) -#define MAYBE_ANGLE -#endif - -#ifdef MAYBE_ANGLE #include "evrcustompresenter.h" -#endif #include <qabstractvideosurface.h> #include <qvideosurfaceformat.h> @@ -2226,6 +2220,27 @@ namespace }; } + +class EVRCustomPresenterActivate : public MFAbstractActivate +{ +public: + EVRCustomPresenterActivate(); + ~EVRCustomPresenterActivate() + { } + + STDMETHODIMP ActivateObject(REFIID riid, void **ppv); + STDMETHODIMP ShutdownObject(); + STDMETHODIMP DetachObject(); + + void setSurface(QAbstractVideoSurface *surface); + +private: + EVRCustomPresenter *m_presenter; + QAbstractVideoSurface *m_surface; + QMutex m_mutex; +}; + + MFVideoRendererControl::MFVideoRendererControl(QObject *parent) : QVideoRendererControl(parent) , m_surface(0) @@ -2245,13 +2260,11 @@ void MFVideoRendererControl::clear() if (m_surface) m_surface->stop(); -#ifdef MAYBE_ANGLE if (m_presenterActivate) { m_presenterActivate->ShutdownObject(); m_presenterActivate->Release(); m_presenterActivate = NULL; } -#endif if (m_currentActivate) { m_currentActivate->ShutdownObject(); @@ -2280,12 +2293,9 @@ void MFVideoRendererControl::setSurface(QAbstractVideoSurface *surface) connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged())); } -#ifdef MAYBE_ANGLE if (m_presenterActivate) m_presenterActivate->setSurface(m_surface); - else -#endif - if (m_currentActivate) + else if (m_currentActivate) static_cast<VideoRendererActivate*>(m_currentActivate)->setSurface(m_surface); } @@ -2323,11 +2333,9 @@ void MFVideoRendererControl::customEvent(QEvent *event) void MFVideoRendererControl::supportedFormatsChanged() { -#ifdef MAYBE_ANGLE if (m_presenterActivate) - m_presenterActivate->supportedFormatsChanged(); - else -#endif + return; + if (m_currentActivate) static_cast<VideoRendererActivate*>(m_currentActivate)->supportedFormatsChanged(); } @@ -2347,26 +2355,67 @@ IMFActivate* MFVideoRendererControl::createActivate() clear(); -#ifdef MAYBE_ANGLE - // We can use the EVR with our custom presenter only if the surface supports OpenGL - // texture handles. We also require ANGLE (due to the D3D interop). - if (!m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty() - && QMediaOpenGLHelper::isANGLE()) { - // Create the EVR media sink, but replace the presenter with our own - if (SUCCEEDED(MFCreateVideoRendererActivate(::GetShellWindow(), &m_currentActivate))) { - m_presenterActivate = new EVRCustomPresenterActivate; - m_currentActivate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, m_presenterActivate); - } - } -#endif - - if (!m_currentActivate) + // Create the EVR media sink, but replace the presenter with our own + if (SUCCEEDED(MFCreateVideoRendererActivate(::GetShellWindow(), &m_currentActivate))) { + m_presenterActivate = new EVRCustomPresenterActivate; + m_currentActivate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, m_presenterActivate); + } else { m_currentActivate = new VideoRendererActivate(this); + } setSurface(m_surface); return m_currentActivate; } + +EVRCustomPresenterActivate::EVRCustomPresenterActivate() + : MFAbstractActivate() + , m_presenter(0) + , m_surface(0) +{ } + +HRESULT EVRCustomPresenterActivate::ActivateObject(REFIID riid, void **ppv) +{ + if (!ppv) + return E_INVALIDARG; + QMutexLocker locker(&m_mutex); + if (!m_presenter) { + m_presenter = new EVRCustomPresenter; + if (m_surface) + m_presenter->setSurface(m_surface); + } + return m_presenter->QueryInterface(riid, ppv); +} + +HRESULT EVRCustomPresenterActivate::ShutdownObject() +{ + // The presenter does not implement IMFShutdown so + // this function is the same as DetachObject() + return DetachObject(); +} + +HRESULT EVRCustomPresenterActivate::DetachObject() +{ + QMutexLocker locker(&m_mutex); + if (m_presenter) { + m_presenter->Release(); + m_presenter = 0; + } + return S_OK; +} + +void EVRCustomPresenterActivate::setSurface(QAbstractVideoSurface *surface) +{ + QMutexLocker locker(&m_mutex); + if (m_surface == surface) + return; + + m_surface = surface; + + if (m_presenter) + m_presenter->setSurface(surface); +} + #include "moc_mfvideorenderercontrol.cpp" #include "mfvideorenderercontrol.moc" diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.h b/src/plugins/wmf/player/mfvideorenderercontrol.h index ca3b95d10..224fcea51 100644 --- a/src/plugins/wmf/player/mfvideorenderercontrol.h +++ b/src/plugins/wmf/player/mfvideorenderercontrol.h @@ -38,14 +38,10 @@ #include <mfapi.h> #include <mfidl.h> -QT_BEGIN_NAMESPACE +QT_USE_NAMESPACE class EVRCustomPresenterActivate; -QT_END_NAMESPACE - -QT_USE_NAMESPACE - class MFVideoRendererControl : public QVideoRendererControl { Q_OBJECT |