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_inputType(0),
|
||||||
m_outputType(0),
|
m_outputType(0),
|
||||||
m_sample(0),
|
m_sample(0),
|
||||||
|
m_videoSinkTypeHandler(0),
|
||||||
m_bytesPerLine(0)
|
m_bytesPerLine(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -64,8 +65,8 @@ MFTransform::~MFTransform()
|
|||||||
if (m_outputType)
|
if (m_outputType)
|
||||||
m_outputType->Release();
|
m_outputType->Release();
|
||||||
|
|
||||||
for (int i = 0; i < m_mediaTypes.size(); ++i)
|
if (m_videoSinkTypeHandler)
|
||||||
m_mediaTypes[i]->Release();
|
m_videoSinkTypeHandler->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MFTransform::addProbe(MFVideoProbeControl *probe)
|
void MFTransform::addProbe(MFVideoProbeControl *probe)
|
||||||
@@ -84,12 +85,18 @@ void MFTransform::removeProbe(MFVideoProbeControl *probe)
|
|||||||
m_videoProbes.removeOne(probe);
|
m_videoProbes.removeOne(probe);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MFTransform::addSupportedMediaType(IMFMediaType *type)
|
void MFTransform::setVideoSink(IUnknown *videoSink)
|
||||||
{
|
{
|
||||||
if (!type)
|
// This transform supports the same input types as the video sink.
|
||||||
return;
|
// Store its type handler interface in order to report the correct supported types.
|
||||||
QMutexLocker locker(&m_mutex);
|
|
||||||
m_mediaTypes.append(type);
|
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)
|
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)
|
STDMETHODIMP MFTransform::GetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
|
||||||
{
|
{
|
||||||
// This MFT does not have a list of preferred input types
|
// We support the same input types as the video sink
|
||||||
Q_UNUSED(dwInputStreamID);
|
if (!m_videoSinkTypeHandler)
|
||||||
Q_UNUSED(dwTypeIndex);
|
return E_NOTIMPL;
|
||||||
Q_UNUSED(ppType);
|
|
||||||
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
|
// Since we don't modify the samples, the output type must be the same as the input type.
|
||||||
Q_UNUSED(dwOutputStreamID);
|
// Report our input type as the only available output type.
|
||||||
Q_UNUSED(dwTypeIndex);
|
|
||||||
Q_UNUSED(ppType);
|
if (dwOutputStreamID > 0)
|
||||||
return E_NOTIMPL;
|
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)
|
STDMETHODIMP MFTransform::SetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
|
||||||
@@ -257,17 +286,14 @@ STDMETHODIMP MFTransform::SetInputType(DWORD dwInputStreamID, IMFMediaType *pTyp
|
|||||||
if (!isMediaTypeSupported(pType))
|
if (!isMediaTypeSupported(pType))
|
||||||
return MF_E_INVALIDMEDIATYPE;
|
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)
|
if (dwFlags == MFT_SET_TYPE_TEST_ONLY)
|
||||||
return pType ? S_OK : E_POINTER;
|
return pType ? S_OK : E_POINTER;
|
||||||
|
|
||||||
if (m_inputType) {
|
if (m_inputType) {
|
||||||
m_inputType->Release();
|
m_inputType->Release();
|
||||||
// Input type has changed, discard output type (if it's set) so it's reset later on
|
// 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->Release();
|
||||||
m_outputType = 0;
|
m_outputType = 0;
|
||||||
}
|
}
|
||||||
@@ -286,29 +312,27 @@ STDMETHODIMP MFTransform::SetOutputType(DWORD dwOutputStreamID, IMFMediaType *pT
|
|||||||
if (dwOutputStreamID > 0)
|
if (dwOutputStreamID > 0)
|
||||||
return MF_E_INVALIDSTREAMNUMBER;
|
return MF_E_INVALIDSTREAMNUMBER;
|
||||||
|
|
||||||
|
if (dwFlags == MFT_SET_TYPE_TEST_ONLY && !pType)
|
||||||
|
return E_POINTER;
|
||||||
|
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
|
// Input type must be set first
|
||||||
|
if (!m_inputType)
|
||||||
|
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||||
|
|
||||||
if (m_sample)
|
if (m_sample)
|
||||||
return MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
|
return MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
|
||||||
|
|
||||||
if (!isMediaTypeSupported(pType))
|
|
||||||
return MF_E_INVALIDMEDIATYPE;
|
|
||||||
|
|
||||||
DWORD flags = 0;
|
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;
|
return MF_E_INVALIDMEDIATYPE;
|
||||||
|
|
||||||
if (dwFlags == MFT_SET_TYPE_TEST_ONLY)
|
if (dwFlags == MFT_SET_TYPE_TEST_ONLY)
|
||||||
return pType ? S_OK : E_POINTER;
|
return pType ? S_OK : E_POINTER;
|
||||||
|
|
||||||
if (m_outputType) {
|
if (m_outputType)
|
||||||
m_outputType->Release();
|
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;
|
m_outputType = pType;
|
||||||
|
|
||||||
@@ -333,10 +357,11 @@ STDMETHODIMP MFTransform::GetInputCurrentType(DWORD dwInputStreamID, IMFMediaTyp
|
|||||||
if (!m_inputType)
|
if (!m_inputType)
|
||||||
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||||
|
|
||||||
*ppType = m_inputType;
|
// Return a copy to make sure our type is not modified
|
||||||
(*ppType)->AddRef();
|
if (FAILED(MFCreateMediaType(ppType)))
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
return S_OK;
|
return m_inputType->CopyAllItems(*ppType);
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP MFTransform::GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
|
STDMETHODIMP MFTransform::GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
|
||||||
@@ -349,19 +374,14 @@ STDMETHODIMP MFTransform::GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaT
|
|||||||
|
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
if (!m_outputType) {
|
if (!m_outputType)
|
||||||
if (m_inputType) {
|
|
||||||
*ppType = m_inputType;
|
|
||||||
(*ppType)->AddRef();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||||
}
|
|
||||||
|
|
||||||
*ppType = m_outputType;
|
// Return a copy to make sure our type is not modified
|
||||||
(*ppType)->AddRef();
|
if (FAILED(MFCreateMediaType(ppType)))
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
return S_OK;
|
return m_outputType->CopyAllItems(*ppType);
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP MFTransform::GetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
|
STDMETHODIMP MFTransform::GetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
|
||||||
@@ -374,7 +394,7 @@ STDMETHODIMP MFTransform::GetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
|
|||||||
|
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
if (!m_inputType)
|
if (!m_inputType || !m_outputType)
|
||||||
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||||
|
|
||||||
if (m_sample)
|
if (m_sample)
|
||||||
@@ -392,7 +412,7 @@ STDMETHODIMP MFTransform::GetOutputStatus(DWORD *pdwFlags)
|
|||||||
|
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
if (!m_outputType)
|
if (!m_inputType || !m_outputType)
|
||||||
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||||
|
|
||||||
if (m_sample)
|
if (m_sample)
|
||||||
@@ -464,7 +484,7 @@ STDMETHODIMP MFTransform::ProcessInput(DWORD dwInputStreamID, IMFSample *pSample
|
|||||||
|
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
if (!m_inputType || !m_outputType)
|
if (!m_inputType)
|
||||||
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||||
|
|
||||||
if (m_sample)
|
if (m_sample)
|
||||||
@@ -510,6 +530,14 @@ STDMETHODIMP MFTransform::ProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount,
|
|||||||
|
|
||||||
QMutexLocker locker(&m_mutex);
|
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)
|
if (!m_sample)
|
||||||
return MF_E_TRANSFORM_NEED_MORE_INPUT;
|
return MF_E_TRANSFORM_NEED_MORE_INPUT;
|
||||||
|
|
||||||
@@ -728,16 +756,10 @@ QByteArray MFTransform::dataFromBuffer(IMFMediaBuffer *buffer, int height, int *
|
|||||||
|
|
||||||
bool MFTransform::isMediaTypeSupported(IMFMediaType *type)
|
bool MFTransform::isMediaTypeSupported(IMFMediaType *type)
|
||||||
{
|
{
|
||||||
// if the list is empty, it supports all formats
|
// If we don't have the video sink's type handler,
|
||||||
if (!type || m_mediaTypes.isEmpty())
|
// assume it supports anything...
|
||||||
|
if (!m_videoSinkTypeHandler || !type)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (int i = 0; i < m_mediaTypes.size(); ++i) {
|
return m_videoSinkTypeHandler->IsMediaTypeSupported(type, NULL) == S_OK;
|
||||||
DWORD flags = 0;
|
|
||||||
m_mediaTypes.at(i)->IsEqual(type, &flags);
|
|
||||||
if (flags & MF_MEDIATYPE_EQUAL_FORMAT_TYPES)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
void addProbe(MFVideoProbeControl* probe);
|
void addProbe(MFVideoProbeControl* probe);
|
||||||
void removeProbe(MFVideoProbeControl* probe);
|
void removeProbe(MFVideoProbeControl* probe);
|
||||||
|
|
||||||
void addSupportedMediaType(IMFMediaType *type);
|
void setVideoSink(IUnknown *videoSink);
|
||||||
|
|
||||||
// IUnknown methods
|
// IUnknown methods
|
||||||
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
|
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
|
||||||
@@ -99,7 +99,7 @@ private:
|
|||||||
IMFSample *m_sample;
|
IMFSample *m_sample;
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
|
|
||||||
QList<IMFMediaType*> m_mediaTypes;
|
IMFMediaTypeHandler *m_videoSinkTypeHandler;
|
||||||
|
|
||||||
QList<MFVideoProbeControl*> m_videoProbes;
|
QList<MFVideoProbeControl*> m_videoProbes;
|
||||||
QMutex m_videoProbeMutex;
|
QMutex m_videoProbeMutex;
|
||||||
|
|||||||
@@ -692,7 +692,6 @@ IMFTopology *MFPlayerSession::insertMFT(IMFTopology *topology, TOPOID outputNode
|
|||||||
IUnknown *element = 0;
|
IUnknown *element = 0;
|
||||||
IMFTopologyNode *node = 0;
|
IMFTopologyNode *node = 0;
|
||||||
IUnknown *outputObject = 0;
|
IUnknown *outputObject = 0;
|
||||||
IMFMediaTypeHandler *videoSink = 0;
|
|
||||||
IMFTopologyNode *inputNode = 0;
|
IMFTopologyNode *inputNode = 0;
|
||||||
IMFTopologyNode *mftNode = 0;
|
IMFTopologyNode *mftNode = 0;
|
||||||
bool mftAdded = false;
|
bool mftAdded = false;
|
||||||
@@ -711,22 +710,10 @@ IMFTopology *MFPlayerSession::insertMFT(IMFTopology *topology, TOPOID outputNode
|
|||||||
if (id != outputNodeId)
|
if (id != outputNodeId)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Use output supported media types for the MFT
|
|
||||||
if (FAILED(node->GetObject(&outputObject)))
|
if (FAILED(node->GetObject(&outputObject)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (FAILED(outputObject->QueryInterface(IID_IMFMediaTypeHandler, (void**)&videoSink)))
|
m_videoProbeMFT->setVideoSink(outputObject);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert MFT between the output node and the node connected to it.
|
// Insert MFT between the output node and the node connected to it.
|
||||||
DWORD outputIndex = 0;
|
DWORD outputIndex = 0;
|
||||||
@@ -760,13 +747,13 @@ IMFTopology *MFPlayerSession::insertMFT(IMFTopology *topology, TOPOID outputNode
|
|||||||
node->Release();
|
node->Release();
|
||||||
if (element)
|
if (element)
|
||||||
element->Release();
|
element->Release();
|
||||||
if (videoSink)
|
|
||||||
videoSink->Release();
|
|
||||||
if (outputObject)
|
if (outputObject)
|
||||||
outputObject->Release();
|
outputObject->Release();
|
||||||
|
|
||||||
if (mftAdded)
|
if (mftAdded)
|
||||||
break;
|
break;
|
||||||
|
else
|
||||||
|
m_videoProbeMFT->setVideoSink(NULL);
|
||||||
}
|
}
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user