From da727b5aadf64128de0eb39fc1ce26e587211272 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 8 Feb 2010 17:50:42 +1000 Subject: Fix stall in graph when removing video and audio outputs. Must remove the decoder as well as the output otherwise the graph wont be able to resume because a disconnected decoder cant. And the graph must be stopped to connect a new output. --- .../mediaplayer/directshowplayerservice.cpp | 107 +++++++++++++++++---- .../mediaplayer/directshowplayerservice.h | 1 + 2 files changed, 89 insertions(+), 19 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp index fdbee81..3c0a43a 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp @@ -319,6 +319,13 @@ void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker) void DirectShowPlayerService::doRender(QMutexLocker *locker) { + m_pendingTasks |= m_executedTasks & (Play | Pause); + + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + control->Release(); + } + if (m_pendingTasks & SetAudioOutput) { m_graph->AddFilter(m_audioOutput, L"AudioOutput"); @@ -358,7 +365,7 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) IPin *peer = 0; if (pin->ConnectedTo(&peer) == S_OK) { PIN_INFO peerInfo; - if (peer->QueryPinInfo(&peerInfo) == S_OK) + if (SUCCEEDED(peer->QueryPinInfo(&peerInfo))) filters.append(peerInfo.pFilter); peer->Release(); } else { @@ -374,13 +381,15 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) } } } + + pins->Release(); + if (outputs == 0) rendered = true; } filter->Release(); } - if (m_audioOutput && !isConnected(m_audioOutput, PINDIR_INPUT)) { graph->RemoveFilter(m_audioOutput); @@ -604,9 +613,6 @@ void DirectShowPlayerService::doPlay(QMutexLocker *locker) control->Release(); - if (SUCCEEDED(hr)) - m_executedTasks |= Play; - if (SUCCEEDED(hr)) { m_executedTasks |= Play; @@ -851,14 +857,14 @@ void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter) m_audioOutput->AddRef(); m_pendingTasks |= SetAudioOutput; - } else { - m_pendingTasks &= ~ SetAudioOutput; - } - if (m_executedTasks & SetSource) { - m_pendingTasks |= Render; + if (m_executedTasks & SetSource) { + m_pendingTasks |= Render; - ::SetEvent(m_taskHandle); + ::SetEvent(m_taskHandle); + } + } else { + m_pendingTasks &= ~ SetAudioOutput; } } else { if (m_audioOutput) @@ -882,7 +888,20 @@ void DirectShowPlayerService::doReleaseAudioOutput(QMutexLocker *locker) control->Release(); } - m_graph->RemoveFilter(m_audioOutput); + IBaseFilter *decoder = getConnected(m_audioOutput, PINDIR_INPUT); + if (!decoder) { + decoder = m_audioOutput; + decoder->AddRef(); + } + + if (IFilterChain *chain = com_cast(m_graph)) { + chain->RemoveChain(decoder, m_audioOutput); + chain->Release(); + } else { + m_graph->RemoveFilter(m_audioOutput); + } + + decoder->Release(); m_executedTasks &= ~SetAudioOutput; @@ -911,14 +930,12 @@ void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) m_videoOutput->AddRef(); m_pendingTasks |= SetVideoOutput; - } else { - m_pendingTasks &= ~ SetVideoOutput; - } - if (m_executedTasks & SetSource) { - m_pendingTasks |= Render; + if (m_executedTasks & SetSource) { + m_pendingTasks |= Render; - ::SetEvent(m_taskHandle); + ::SetEvent(m_taskHandle); + } } } else { if (m_videoOutput) @@ -940,7 +957,27 @@ void DirectShowPlayerService::doReleaseVideoOutput(QMutexLocker *locker) control->Release(); } - m_graph->RemoveFilter(m_videoOutput); + IBaseFilter *intermediate = 0; + if (!SUCCEEDED(m_graph->FindFilterByName(L"Color Space Converter", &intermediate))) { + intermediate = m_videoOutput; + intermediate->AddRef(); + } + + IBaseFilter *decoder = getConnected(intermediate, PINDIR_INPUT); + if (!decoder) { + decoder = intermediate; + decoder->AddRef(); + } + + if (IFilterChain *chain = com_cast(m_graph)) { + chain->RemoveChain(decoder, m_videoOutput); + chain->Release(); + } else { + m_graph->RemoveFilter(m_videoOutput); + } + + intermediate->Release(); + decoder->Release(); m_executedTasks &= ~SetVideoOutput; @@ -1109,6 +1146,38 @@ bool DirectShowPlayerService::isConnected(IBaseFilter *filter, PIN_DIRECTION dir return connected; } +IBaseFilter *DirectShowPlayerService::getConnected( + IBaseFilter *filter, PIN_DIRECTION direction) const +{ + IBaseFilter *connected = 0; + + IEnumPins *pins = 0; + + if (SUCCEEDED(filter->EnumPins(&pins))) { + for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { + PIN_DIRECTION dir; + if (SUCCEEDED(pin->QueryDirection(&dir)) && dir == direction) { + IPin *peer = 0; + if (SUCCEEDED(pin->ConnectedTo(&peer))) { + PIN_INFO info; + + if (SUCCEEDED(peer->QueryPinInfo(&info))) { + if (connected) { + qWarning("DirectShowPlayerService::getConnected: " + "Multiple connected filters"); + connected->Release(); + } + connected = info.pFilter; + } + peer->Release(); + } + } + } + pins->Release(); + } + return connected; +} + void DirectShowPlayerService::run() { QMutexLocker locker(&m_mutex); diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h index 576520e..906d23b 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h @@ -114,6 +114,7 @@ private: int findStreamType(IPin *pin) const; bool isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const; + IBaseFilter *getConnected(IBaseFilter *filter, PIN_DIRECTION direction) const; void run(); -- cgit v0.12