diff options
author | Yoann Lopes <yoann.lopes@theqtcompany.com> | 2015-11-07 15:53:18 +0100 |
---|---|---|
committer | Yoann Lopes <yoann.lopes@theqtcompany.com> | 2015-12-04 11:41:42 +0000 |
commit | a6164acd2f35daca98e6b79b97b8fb55d1d4359a (patch) | |
tree | baf5fe98b89e28e0b947615b9aecb35822ed1932 /src/plugins/wmf | |
parent | 43f3d14a99431da5e0ebd29f6c1f27526a6e2d48 (diff) |
WMF: fix type negotiation in video probe transform.
- report supported types (same as the video sink)
- handle type changes coming from upstream
Change-Id: I922fc4869ecac3999e055c39adf1b847127a0012
Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
Diffstat (limited to 'src/plugins/wmf')
-rw-r--r-- | src/plugins/wmf/mftvideo.cpp | 142 | ||||
-rw-r--r-- | src/plugins/wmf/mftvideo.h | 4 | ||||
-rw-r--r-- | src/plugins/wmf/player/mfplayersession.cpp | 19 |
3 files changed, 87 insertions, 78 deletions
diff --git a/src/plugins/wmf/mftvideo.cpp b/src/plugins/wmf/mftvideo.cpp index b141d49a2..5f32f1f61 100644 --- a/src/plugins/wmf/mftvideo.cpp +++ b/src/plugins/wmf/mftvideo.cpp @@ -52,6 +52,7 @@ MFTransform::MFTransform(): m_inputType(0), m_outputType(0), m_sample(0), + m_videoSinkTypeHandler(0), m_bytesPerLine(0) { } @@ -64,8 +65,8 @@ MFTransform::~MFTransform() if (m_outputType) m_outputType->Release(); - for (int i = 0; i < m_mediaTypes.size(); ++i) - m_mediaTypes[i]->Release(); + if (m_videoSinkTypeHandler) + m_videoSinkTypeHandler->Release(); } void MFTransform::addProbe(MFVideoProbeControl *probe) @@ -84,12 +85,18 @@ void MFTransform::removeProbe(MFVideoProbeControl *probe) m_videoProbes.removeOne(probe); } -void MFTransform::addSupportedMediaType(IMFMediaType *type) +void MFTransform::setVideoSink(IUnknown *videoSink) { - if (!type) - return; - QMutexLocker locker(&m_mutex); - m_mediaTypes.append(type); + // This transform supports the same input types as the video sink. + // Store its type handler interface in order to report the correct supported types. + + if (m_videoSinkTypeHandler) { + m_videoSinkTypeHandler->Release(); + m_videoSinkTypeHandler = NULL; + } + + if (videoSink) + videoSink->QueryInterface(IID_PPV_ARGS(&m_videoSinkTypeHandler)); } STDMETHODIMP MFTransform::QueryInterface(REFIID riid, void** ppv) @@ -228,20 +235,42 @@ STDMETHODIMP MFTransform::AddInputStreams(DWORD cStreams, DWORD *adwStreamIDs) STDMETHODIMP MFTransform::GetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType) { - // This MFT does not have a list of preferred input types - Q_UNUSED(dwInputStreamID); - Q_UNUSED(dwTypeIndex); - Q_UNUSED(ppType); - return E_NOTIMPL; + // We support the same input types as the video sink + if (!m_videoSinkTypeHandler) + return E_NOTIMPL; + + if (dwInputStreamID > 0) + return MF_E_INVALIDSTREAMNUMBER; + + if (!ppType) + return E_POINTER; + + return m_videoSinkTypeHandler->GetMediaTypeByIndex(dwTypeIndex, ppType); } -STDMETHODIMP MFTransform::GetOutputAvailableType(DWORD dwOutputStreamID,DWORD dwTypeIndex, IMFMediaType **ppType) +STDMETHODIMP MFTransform::GetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType) { - // This MFT does not have a list of preferred output types - Q_UNUSED(dwOutputStreamID); - Q_UNUSED(dwTypeIndex); - Q_UNUSED(ppType); - return E_NOTIMPL; + // Since we don't modify the samples, the output type must be the same as the input type. + // Report our input type as the only available output type. + + if (dwOutputStreamID > 0) + return MF_E_INVALIDSTREAMNUMBER; + + if (!ppType) + return E_POINTER; + + // Input type must be set first + if (!m_inputType) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (dwTypeIndex > 0) + return MF_E_NO_MORE_TYPES; + + // Return a copy to make sure our type is not modified + if (FAILED(MFCreateMediaType(ppType))) + return E_OUTOFMEMORY; + + return m_inputType->CopyAllItems(*ppType); } STDMETHODIMP MFTransform::SetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags) @@ -257,17 +286,14 @@ STDMETHODIMP MFTransform::SetInputType(DWORD dwInputStreamID, IMFMediaType *pTyp if (!isMediaTypeSupported(pType)) return MF_E_INVALIDMEDIATYPE; - DWORD flags = 0; - if (pType && !m_inputType && m_outputType && m_outputType->IsEqual(pType, &flags) != S_OK) - return MF_E_INVALIDMEDIATYPE; - if (dwFlags == MFT_SET_TYPE_TEST_ONLY) return pType ? S_OK : E_POINTER; if (m_inputType) { m_inputType->Release(); // Input type has changed, discard output type (if it's set) so it's reset later on - if (m_outputType && m_outputType->IsEqual(pType, &flags) != S_OK) { + DWORD flags = 0; + if (m_outputType && m_outputType->IsEqual(pType, &flags) != S_OK) { m_outputType->Release(); m_outputType = 0; } @@ -286,29 +312,27 @@ STDMETHODIMP MFTransform::SetOutputType(DWORD dwOutputStreamID, IMFMediaType *pT if (dwOutputStreamID > 0) return MF_E_INVALIDSTREAMNUMBER; + if (dwFlags == MFT_SET_TYPE_TEST_ONLY && !pType) + return E_POINTER; + QMutexLocker locker(&m_mutex); + // Input type must be set first + if (!m_inputType) + return MF_E_TRANSFORM_TYPE_NOT_SET; + if (m_sample) return MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING; - if (!isMediaTypeSupported(pType)) - return MF_E_INVALIDMEDIATYPE; - DWORD flags = 0; - if (pType && !m_outputType && m_inputType && m_inputType->IsEqual(pType, &flags) != S_OK) + if (pType && m_inputType->IsEqual(pType, &flags) != S_OK) return MF_E_INVALIDMEDIATYPE; if (dwFlags == MFT_SET_TYPE_TEST_ONLY) return pType ? S_OK : E_POINTER; - if (m_outputType) { + if (m_outputType) m_outputType->Release(); - // Output type has changed, discard input type (if it's set) so it's reset later on - if (m_inputType && m_inputType->IsEqual(pType, &flags) != S_OK) { - m_inputType->Release(); - m_inputType = 0; - } - } m_outputType = pType; @@ -333,10 +357,11 @@ STDMETHODIMP MFTransform::GetInputCurrentType(DWORD dwInputStreamID, IMFMediaTyp if (!m_inputType) return MF_E_TRANSFORM_TYPE_NOT_SET; - *ppType = m_inputType; - (*ppType)->AddRef(); + // Return a copy to make sure our type is not modified + if (FAILED(MFCreateMediaType(ppType))) + return E_OUTOFMEMORY; - return S_OK; + return m_inputType->CopyAllItems(*ppType); } STDMETHODIMP MFTransform::GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType) @@ -349,19 +374,14 @@ STDMETHODIMP MFTransform::GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaT QMutexLocker locker(&m_mutex); - if (!m_outputType) { - if (m_inputType) { - *ppType = m_inputType; - (*ppType)->AddRef(); - return S_OK; - } + if (!m_outputType) return MF_E_TRANSFORM_TYPE_NOT_SET; - } - *ppType = m_outputType; - (*ppType)->AddRef(); + // Return a copy to make sure our type is not modified + if (FAILED(MFCreateMediaType(ppType))) + return E_OUTOFMEMORY; - return S_OK; + return m_outputType->CopyAllItems(*ppType); } STDMETHODIMP MFTransform::GetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags) @@ -374,7 +394,7 @@ STDMETHODIMP MFTransform::GetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags) QMutexLocker locker(&m_mutex); - if (!m_inputType) + if (!m_inputType || !m_outputType) return MF_E_TRANSFORM_TYPE_NOT_SET; if (m_sample) @@ -392,7 +412,7 @@ STDMETHODIMP MFTransform::GetOutputStatus(DWORD *pdwFlags) QMutexLocker locker(&m_mutex); - if (!m_outputType) + if (!m_inputType || !m_outputType) return MF_E_TRANSFORM_TYPE_NOT_SET; if (m_sample) @@ -464,7 +484,7 @@ STDMETHODIMP MFTransform::ProcessInput(DWORD dwInputStreamID, IMFSample *pSample QMutexLocker locker(&m_mutex); - if (!m_inputType || !m_outputType) + if (!m_inputType) return MF_E_TRANSFORM_TYPE_NOT_SET; if (m_sample) @@ -510,6 +530,14 @@ STDMETHODIMP MFTransform::ProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, QMutexLocker locker(&m_mutex); + if (!m_inputType) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (!m_outputType) { + pOutputSamples[0].dwStatus = MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; + return MF_E_TRANSFORM_STREAM_CHANGE; + } + if (!m_sample) return MF_E_TRANSFORM_NEED_MORE_INPUT; @@ -728,16 +756,10 @@ QByteArray MFTransform::dataFromBuffer(IMFMediaBuffer *buffer, int height, int * bool MFTransform::isMediaTypeSupported(IMFMediaType *type) { - // if the list is empty, it supports all formats - if (!type || m_mediaTypes.isEmpty()) + // If we don't have the video sink's type handler, + // assume it supports anything... + if (!m_videoSinkTypeHandler || !type) return true; - for (int i = 0; i < m_mediaTypes.size(); ++i) { - DWORD flags = 0; - m_mediaTypes.at(i)->IsEqual(type, &flags); - if (flags & MF_MEDIATYPE_EQUAL_FORMAT_TYPES) - return true; - } - - return false; + return m_videoSinkTypeHandler->IsMediaTypeSupported(type, NULL) == S_OK; } diff --git a/src/plugins/wmf/mftvideo.h b/src/plugins/wmf/mftvideo.h index 1a188c4db..c37c8f700 100644 --- a/src/plugins/wmf/mftvideo.h +++ b/src/plugins/wmf/mftvideo.h @@ -53,7 +53,7 @@ public: void addProbe(MFVideoProbeControl* probe); void removeProbe(MFVideoProbeControl* probe); - void addSupportedMediaType(IMFMediaType *type); + void setVideoSink(IUnknown *videoSink); // IUnknown methods STDMETHODIMP QueryInterface(REFIID iid, void** ppv); @@ -99,7 +99,7 @@ private: IMFSample *m_sample; QMutex m_mutex; - QList<IMFMediaType*> m_mediaTypes; + IMFMediaTypeHandler *m_videoSinkTypeHandler; QList<MFVideoProbeControl*> m_videoProbes; QMutex m_videoProbeMutex; diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index e4c498b76..9fb1762ef 100644 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ b/src/plugins/wmf/player/mfplayersession.cpp @@ -692,7 +692,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 +710,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 +747,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); |