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>
This commit is contained in:
Yoann Lopes
2015-11-07 18:07:34 +01:00
parent 8ed8f33c18
commit 2b7c617e09
2 changed files with 90 additions and 75 deletions

View File

@@ -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,14 +313,21 @@ 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;
// 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(streamDesc, mediaType, topology, 0);
IMFTopologyNode *outputNode = addOutputNode(mediaType, topology, 0);
if (outputNode) {
bool connected = false;
if (mediaType == Audio) {
@@ -314,10 +340,11 @@ void MFPlayerSession::setupPlaybackTopology(IMFMediaSource *source, IMFPresentat
if (!connected)
hr = sourceNode->ConnectOutput(0, outputNode, 0);
if (FAILED(hr)) {
emit error(QMediaPlayer::FormatError, tr("Unable to play any stream."), false);
}
else {
} else {
streamAdded = true;
succeededCount++;
m_mediaTypes |= mediaType;
switch (mediaType) {
@@ -333,6 +360,11 @@ void MFPlayerSession::setupPlaybackTopology(IMFMediaSource *source, IMFPresentat
}
sourceNode->Release();
}
}
if (fSelected && !streamAdded)
sourcePD->DeselectStream(i);
streamDesc->Release();
}
}
@@ -377,27 +409,16 @@ 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;
if (mediaType == Audio) {
activate = m_playerService->audioEndpointControl()->createActivate();
} else if (MFMediaType_Video == guidMajorType) {
mediaType = Video;
} else if (mediaType == Video) {
if (m_playerService->videoRendererControl()) {
activate = m_playerService->videoRendererControl()->createActivate();
} else if (m_playerService->videoWindowControl()) {
@@ -410,23 +431,16 @@ IMFTopologyNode* MFPlayerSession::addOutputNode(IMFStreamDescriptor *streamDesc,
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;
}
}
}
}
}
handler->Release();
}
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();
return NULL;
node = NULL;
}
return node;
}
bool MFPlayerSession::addAudioSampleGrabberNode(IMFTopology *topology)

View File

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