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:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user