diff options
author | Yoann Lopes <yoann.lopes@theqtcompany.com> | 2015-11-07 18:07:34 +0100 |
---|---|---|
committer | Yoann Lopes <yoann.lopes@theqtcompany.com> | 2015-12-04 11:41:52 +0000 |
commit | 2b7c617e090f495bbf62c1257c822f5849c21742 (patch) | |
tree | d0cc7fe70bdc9c86cfca16cd1d3b811c1cc3fe73 /src/plugins/wmf | |
parent | 8ed8f33c18764735cc065203d8d21ad7a2862e82 (diff) | |
download | qtmultimedia-2b7c617e090f495bbf62c1257c822f5849c21742.tar.gz |
WMF: correctly handle media with multiple streams.
Only use the default streams and make sure only one stream of each kind
(audio/video) is added to the topology.
Change-Id: Ied37174fa722068b4cd1b5f91b60e0cef5c1d7b3
Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
Diffstat (limited to 'src/plugins/wmf')
-rw-r--r-- | src/plugins/wmf/player/mfplayersession.cpp | 162 | ||||
-rw-r--r-- | src/plugins/wmf/player/mfplayersession.h | 3 |
2 files changed, 90 insertions, 75 deletions
diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index 9fb1762ef..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) 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); |