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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user