summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjk <[email protected]>2023-02-07 15:44:24 -0800
committerAdonais Romero González <[email protected]>2023-08-25 15:28:14 -0700
commite0c0afda943a63d5e6ce888e158096428c6654df (patch)
treed18c40f2173f7252e913e765ab6b54c95240f71f
parent579de5195910865b60300055962b291212af2096 (diff)
Change the locking scheme in DMFT to unlock in setoutputstreamstate (#810)
A change in device transform manager brought about a deadlock scenario in DMFT sample. The sample now behaves like we have in the rest of the pipeline i.e. we release the lock and wait for the operations on the input pins to complete. This hang is responsible for AMD hangs.
-rw-r--r--avstream/sampledevicemft/basepin.cpp53
-rw-r--r--avstream/sampledevicemft/basepin.h14
-rw-r--r--avstream/sampledevicemft/common.h6
-rw-r--r--avstream/sampledevicemft/multipinmft.cpp57
-rw-r--r--avstream/sampledevicemft/multipinmft.h4
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.cpp105
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.h13
-rw-r--r--avstream/sampledevicemft/stdafx.h4
8 files changed, 118 insertions, 138 deletions
diff --git a/avstream/sampledevicemft/basepin.cpp b/avstream/sampledevicemft/basepin.cpp
index 563ff610..471bbca7 100644
--- a/avstream/sampledevicemft/basepin.cpp
+++ b/avstream/sampledevicemft/basepin.cpp
@@ -37,12 +37,6 @@ CBasePin::CBasePin( _In_ ULONG id, _In_ CMultipinMft *parent) :
CBasePin::~CBasePin()
{
-
- for ( ULONG ulIndex = 0, ulSize = (ULONG)m_listOfMediaTypes.size(); ulIndex < ulSize; ulIndex++ )
- {
- ComPtr<IMFMediaType> spMediaType;
- spMediaType.Attach(m_listOfMediaTypes[ulIndex]); // Releases the previously stored pointer
- }
m_listOfMediaTypes.clear();
m_spAttributes = nullptr;
}
@@ -68,7 +62,6 @@ HRESULT CBasePin::AddMediaType( _Inout_ DWORD *pos, _In_ IMFMediaType *pMediaTyp
m_listOfMediaTypes.push_back(pMediaType);
});
DMFTCHECKHR_GOTO(hr, done);
- pMediaType->AddRef();
if (pos)
{
*pos = (DWORD)(m_listOfMediaTypes.size() - 1);
@@ -89,7 +82,8 @@ HRESULT CBasePin::GetMediaTypeAt( _In_ DWORD pos, _Outptr_result_maybenull_ IMFM
{
DMFTCHECKHR_GOTO(MF_E_NO_MORE_TYPES,done);
}
- spMediaType = m_listOfMediaTypes[pos];
+ DMFTCHECKHR_GOTO(MFCreateMediaType(spMediaType.GetAddressOf()), done);
+ DMFTCHECKHR_GOTO(m_listOfMediaTypes[pos]->CopyAllItems(spMediaType.Get()), done);
*ppMediaType = spMediaType.Detach();
done:
return hr;
@@ -129,8 +123,10 @@ STDMETHODIMP_(BOOL) CBasePin::IsMediaTypeSupported
{
bFound = TRUE;
if (ppIMFMediaTypeFull) {
- *ppIMFMediaTypeFull = m_listOfMediaTypes[uIIndex];
- (*ppIMFMediaTypeFull)->AddRef();
+ ComPtr<IMFMediaType> spMediaType;
+ DMFTCHECKHR_GOTO(MFCreateMediaType(spMediaType.GetAddressOf()), done);
+ DMFTCHECKHR_GOTO(m_listOfMediaTypes[uIIndex]->CopyAllItems(spMediaType.Get()), done);
+ *ppIMFMediaTypeFull = spMediaType.Detach();
}
break;
}
@@ -219,7 +215,7 @@ CInPin::~CInPin()
}
STDMETHODIMP CInPin::Init(
- _In_ IMFTransform* pTransform
+ _In_ IMFDeviceTransform* pTransform
)
{
@@ -239,7 +235,7 @@ STDMETHODIMP CInPin::Init(
m_waitInputMediaTypeWaiter = CreateEvent( NULL,
FALSE,
FALSE,
- TEXT("MediaTypeWaiter")
+ nullptr
);
DMFTCHECKNULL_GOTO( m_waitInputMediaTypeWaiter, done, E_OUTOFMEMORY );
@@ -275,7 +271,7 @@ HRESULT CInPin::GenerateMFMediaTypeListFromDevice(
ComPtr<IMFMediaType> spMediaType;
DWORD pos = 0;
- hr = m_spSourceTransform->MFTGetOutputAvailableType(uiStreamId, iMediaType, spMediaType.GetAddressOf());
+ hr = m_spSourceTransform->GetOutputAvailableType(uiStreamId, iMediaType, spMediaType.GetAddressOf());
if (hr != S_OK)
break;
@@ -813,11 +809,6 @@ STDMETHODIMP CTranslateOutPin::AddMediaType(
DMFTCHECKHR_GOTO(pMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubType), done);
// @@@@ README the below lines show how to exclude mediatypes which we don't want
- /* if ((guidSubType != MFVideoFormat_H264))
- {
- hr = S_FALSE;
- goto done;
- }*/
if (needTranslation(pMediaType))
{
@@ -829,9 +820,21 @@ STDMETHODIMP CTranslateOutPin::AddMediaType(
DMFTCHECKHR_GOTO(MFCalculateImageSize(translatedGUID, uiWidth, uiHeight, &uiImageSize), done);
DMFTCHECKHR_GOTO(pNewMediaType->SetGUID(MF_MT_SUBTYPE, translatedGUID), done);
DMFTCHECKHR_GOTO(pNewMediaType->SetUINT32(MF_MT_SAMPLE_SIZE, uiImageSize), done);
+
+ (void)pNewMediaType->DeleteItem(MF_MT_COMPRESSED);
+ (void)pNewMediaType->DeleteItem(MF_MT_SAMPLE_SIZE);
+ (void)pNewMediaType->DeleteItem(MF_MT_AVG_BITRATE);
+ (void)pNewMediaType->DeleteItem(MF_MT_MPEG2_PROFILE);
+ (void)pNewMediaType->DeleteItem(MF_MT_MPEG2_LEVEL);
+
+ (void)pNewMediaType->DeleteItem(MF_MT_VIDEO_ROTATION);
+ (void)pNewMediaType->DeleteItem(MF_MT_MINIMUM_DISPLAY_APERTURE);
+
+ DMFTCHECKHR_GOTO(pNewMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE), done);
+ DMFTCHECKHR_GOTO(pNewMediaType->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_0_255), done);
hr = ExceptionBoundary([&]()
{
- m_TranslatedMediaTypes.insert(std::pair<IMFMediaType*, IMFMediaType*>( pNewMediaType.Get(), pMediaType));
+ m_TranslatedMediaTypes.insert(std::pair<ComPtr<IMFMediaType>, ComPtr<IMFMediaType>>( pNewMediaType.Get(), pMediaType));
});
DMFTCHECKHR_GOTO(hr, done);
}
@@ -858,18 +861,22 @@ STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
{
DWORD dwFlags = 0, dwMatchedFlags = (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_DATA);
- std::map<IMFMediaType*, IMFMediaType*>::iterator found = std::find_if(m_TranslatedMediaTypes.begin(), m_TranslatedMediaTypes.end(),
- [&](std::pair<IMFMediaType*, IMFMediaType*> p)
+ auto found = std::find_if(m_TranslatedMediaTypes.begin(), m_TranslatedMediaTypes.end(),
+ [&](std::pair<ComPtr<IMFMediaType>, ComPtr<IMFMediaType>> p)
{
- return (SUCCEEDED(pMediaType->IsEqual(p.first, &dwFlags))
+ return (SUCCEEDED(pMediaType->IsEqual(p.first.Get(), &dwFlags))
&& ((dwFlags & dwMatchedFlags) == (dwMatchedFlags)));
});
if (found != m_TranslatedMediaTypes.end())
{
- ComPtr<IMFMediaType> spMediaType = (*found).second;
+ ComPtr<IMFMediaType> spMediaType;
if (ppIMFMediaTypeFull)
{
+ if (FAILED(MFCreateMediaType(spMediaType.GetAddressOf()))|| FAILED((*found).second->CopyAllItems(spMediaType.Get())))
+ {
+ return false;
+ }
*ppIMFMediaTypeFull = spMediaType.Detach();
}
return true;
diff --git a/avstream/sampledevicemft/basepin.h b/avstream/sampledevicemft/basepin.h
index cce17d0b..d3e45c93 100644
--- a/avstream/sampledevicemft/basepin.h
+++ b/avstream/sampledevicemft/basepin.h
@@ -458,10 +458,10 @@ private:
class CInPin: public CBasePin{
public:
CInPin( _In_opt_ IMFAttributes*, _In_ ULONG ulPinId = 0, _In_ CMultipinMft *pParent=NULL);
- ~CInPin();
+ virtual ~CInPin();
STDMETHOD ( Init )(
- _In_ IMFTransform *
+ _In_ IMFDeviceTransform *
);
STDMETHOD_( VOID, ConnectPin)(
_In_ CBasePin *
@@ -514,7 +514,7 @@ public:
STDMETHOD_( VOID, ShutdownPin)();
protected:
- ComPtr<IMFTransform> m_spSourceTransform; /*Source Transform i.e. DevProxy*/
+ ComPtr<IMFDeviceTransform> m_spSourceTransform; /*Source Transform i.e. DevProxy*/
GUID m_stStreamType; /*GUID representing the GUID*/
ComPtr<CBasePin> m_outpin; //Only one output pin connected per input pin. There can be multiple pins connected and this could be a list
DeviceStreamState m_preferredStreamState;
@@ -541,7 +541,7 @@ public:
, _In_ MFSampleAllocatorUsage allocatorUsage = MFSampleAllocatorUsage_DoesNotAllocate
#endif
);
- ~COutPin();
+ virtual ~COutPin();
STDMETHODIMP FlushQueues();
STDMETHODIMP AddPin(
_In_ DWORD pinId
@@ -619,7 +619,7 @@ public:
Init();
}
STDMETHOD_(VOID, ShutdownPin)();
- ~CAsyncInPin()
+ virtual ~CAsyncInPin()
{
FlushQueues();
}
@@ -663,10 +663,10 @@ public:
_In_ IMFMediaType *pInMediatype,
_In_ IMFMediaType* pOutMediaType,
_In_ DeviceStreamState state);
-
+ virtual ~CTranslateOutPin() {}
protected:
- map<IMFMediaType*, IMFMediaType*> m_TranslatedMediaTypes;
+ map<ComPtr<IMFMediaType>, ComPtr<IMFMediaType>> m_TranslatedMediaTypes;
};
diff --git a/avstream/sampledevicemft/common.h b/avstream/sampledevicemft/common.h
index bc6bbf28..57126378 100644
--- a/avstream/sampledevicemft/common.h
+++ b/avstream/sampledevicemft/common.h
@@ -230,9 +230,9 @@ typedef enum _DMFT_conversion_type{
DeviceMftTransformTypeIllegal // We cannot satisfy the input and output combination
}DMFT_conversion_type,*PDMFT_conversion_type;
-typedef std::vector< IMFMediaType *> IMFMediaTypeArray;
-typedef std::vector< CBasePin *> CBasePinArray;
-typedef std::vector< IMFSample *> IMFSampleList;
+typedef std::vector <ComPtr<IMFMediaType>> IMFMediaTypeArray;
+typedef std::vector <ComPtr<CBasePin>> CBasePinArray;
+typedef std::vector <ComPtr<IMFSample>> IMFSampleList;
typedef std::pair< std::multimap<int, int>::iterator, std::multimap<int, int>::iterator > MMFTMMAPITERATOR;
diff --git a/avstream/sampledevicemft/multipinmft.cpp b/avstream/sampledevicemft/multipinmft.cpp
index 30c0463f..b171338a 100644
--- a/avstream/sampledevicemft/multipinmft.cpp
+++ b/avstream/sampledevicemft/multipinmft.cpp
@@ -54,21 +54,10 @@ done:
CMultipinMft::~CMultipinMft( )
{
-
-
- for ( ULONG ulIndex = 0, ulSize = (ULONG) m_InPins.size(); ulIndex < ulSize; ulIndex++ )
- {
- SAFERELEASE(m_InPins[ ulIndex ]);
- }
m_InPins.clear();
- for (ULONG ulIndex = 0, ulSize = (ULONG) m_OutPins.size(); ulIndex < ulSize; ulIndex++)
- {
- SAFERELEASE(m_OutPins[ ulIndex ]);
- }
m_OutPins.clear();
SAFE_ARRAYDELETE(m_SymbolicLink);
m_spSourceTransform = nullptr;
-
}
STDMETHODIMP_(ULONG) CMultipinMft::AddRef(
@@ -205,7 +194,7 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
DMFTCHECKHR_GOTO( m_spSourceTransform.As( &m_spIkscontrol ), done );
- DMFTCHECKHR_GOTO( m_spSourceTransform->MFTGetStreamCount( &inputStreams, &outputStreams ), done );
+ DMFTCHECKHR_GOTO( m_spSourceTransform->GetStreamCount( &inputStreams, &outputStreams ), done );
spFilterUnk = nullptr;
@@ -222,7 +211,7 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
pcOutputStreams = new (std::nothrow) DWORD[ outputStreams ];
DMFTCHECKNULL_GOTO( pcOutputStreams, done, E_OUTOFMEMORY );
- DMFTCHECKHR_GOTO( m_spSourceTransform->MFTGetStreamIDs( inputStreams, pcInputStreams,
+ DMFTCHECKHR_GOTO( m_spSourceTransform->GetStreamIDs( inputStreams, pcInputStreams,
outputStreams,
pcOutputStreams ),done );
@@ -252,7 +241,6 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
});
DMFTCHECKHR_GOTO(hr, done);
DMFTCHECKHR_GOTO( spInPin->Init(m_spSourceTransform.Get() ), done);
- spInPin.Detach();
}
//
@@ -263,7 +251,7 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
ComPtr<COutPin> spoPin;
BOOL bCustom = FALSE;
- ComPtr<CInPin> spiPin = ( CInPin * )m_InPins[ ulIndex ];
+ ComPtr<CInPin> spiPin = ( CInPin * )m_InPins[ ulIndex ].Get();
if (spiPin.Get())
{
@@ -292,7 +280,6 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
{
m_OutPins.push_back(spoPin.Get());
}), done);
- spoPin.Detach();
ulOutPinIndex++;
hr = S_OK;
}
@@ -329,15 +316,7 @@ done:
if ( FAILED( hr ) )
{
//Release the pins and the resources acquired
- for (ULONG ulIndex = 0, ulSize = (ULONG)m_InPins.size(); ulIndex < ulSize; ulIndex++)
- {
- SAFERELEASE(m_InPins[ulIndex]);
- }
m_InPins.clear();
- for (ULONG ulIndex = 0, ulSize = (ULONG)m_OutPins.size(); ulIndex < ulSize; ulIndex++)
- {
- SAFERELEASE(m_OutPins[ulIndex]);
- }
m_OutPins.clear();
//
// Simply clear the custom pins since the input pins must have deleted the pin
@@ -461,7 +440,7 @@ STDMETHODIMP CMultipinMft::GetInputAvailableType(
)
{
HRESULT hr = S_OK;
-
+ CAutoLock lock(m_critSec);
ComPtr<CInPin> spiPin = GetInPin( dwInputStreamID );
DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG);
DMFTCHECKNULL_GOTO( spiPin, done, MF_E_INVALIDSTREAMNUMBER );
@@ -721,7 +700,7 @@ STDMETHODIMP CMultipinMft::ProcessInput(
{
HRESULT hr = S_OK;
UNREFERENCED_PARAMETER( dwFlags );
-
+ CAutoLock lock(m_critSec);
ComPtr<CInPin> spInPin = GetInPin( dwInputStreamID );
DMFTCHECKNULL_GOTO(spInPin, done, MF_E_INVALIDSTREAMNUMBER);
@@ -762,6 +741,7 @@ output pins and populate the corresponding MFT_OUTPUT_DATA_BUFFER with the sampl
HRESULT hr = S_OK;
BOOL gotOne = false;
ComPtr<COutPin> spOpin;
+ CAutoLock _lock(m_critSec);
UNREFERENCED_PARAMETER( dwFlags );
if (cOutputBufferCount > m_OutputPinCount )
@@ -774,7 +754,6 @@ output pins and populate the corresponding MFT_OUTPUT_DATA_BUFFER with the sampl
{
DWORD dwStreamID = pOutputSamples[i].dwStreamID;
{
- CAutoLock _lock(m_critSec);
spOpin = nullptr;
spOpin = GetOutPin(dwStreamID);
GUID pinGuid = GUID_NULL;
@@ -828,7 +807,7 @@ STDMETHODIMP CMultipinMft::GetInputStreamAttributes(
{
HRESULT hr = S_OK;
ComPtr<CInPin> spIPin;
-
+ CAutoLock Lock(m_critSec);
DMFTCHECKNULL_GOTO( ppAttributes, done, E_INVALIDARG );
*ppAttributes = nullptr;
@@ -857,7 +836,7 @@ STDMETHODIMP CMultipinMft::GetOutputStreamAttributes(
{
HRESULT hr = S_OK;
ComPtr<COutPin> spoPin;
-
+ CAutoLock Lock(m_critSec);
DMFTCHECKNULL_GOTO(ppAttributes, done, E_INVALIDARG);
*ppAttributes = nullptr;
@@ -893,6 +872,7 @@ STDMETHODIMP CMultipinMft::SetInputStreamState(
--*/
{
HRESULT hr = S_OK;
+ CAutoLock Lock(m_critSec);
ComPtr<CInPin> spiPin = GetInPin(dwStreamID);
DMFTCHECKNULL_GOTO(spiPin, done, MF_E_INVALIDSTREAMNUMBER);
@@ -909,6 +889,7 @@ STDMETHODIMP CMultipinMft::GetInputStreamState(
)
{
HRESULT hr = S_OK;
+ CAutoLock Lock(m_critSec);
ComPtr<CInPin> piPin = GetInPin(dwStreamID);
DMFTCHECKNULL_GOTO(piPin, done, MF_E_INVALIDSTREAMNUMBER);
@@ -994,6 +975,7 @@ STDMETHODIMP CMultipinMft::GetInputStreamPreferredState(
--*/
{
HRESULT hr = S_OK;
+ CAutoLock lock(m_critSec);
ComPtr<CInPin> spiPin = GetInPin(dwStreamID);
DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG);
DMFTCHECKNULL_GOTO(spiPin, done, MF_E_INVALIDSTREAMNUMBER);
@@ -1061,7 +1043,7 @@ STDMETHODIMP_(VOID) CMultipinMft::FlushAllStreams(
CAutoLock Lock(m_critSec);
for ( DWORD dwIndex = 0, dwSize = (DWORD)m_OutPins.size(); dwIndex < dwSize; dwIndex++ )
{
- ComPtr<COutPin> spoPin = (COutPin *)m_OutPins[dwIndex];
+ ComPtr<COutPin> spoPin = (COutPin *)m_OutPins[dwIndex].Get();
oldState = spoPin->SetState(DeviceStreamState_Disabled);
spoPin->FlushQueues();
//
@@ -1391,7 +1373,7 @@ CInPin* CMultipinMft::GetInPin(
CInPin *inPin = NULL;
for (DWORD dwIndex = 0, dwSize = (DWORD)m_InPins.size(); dwIndex < dwSize; dwIndex++)
{
- inPin = (CInPin *)m_InPins[dwIndex];
+ inPin = (CInPin *)m_InPins[dwIndex].Get();
if (dwStreamId == inPin->streamId())
{
break;
@@ -1408,7 +1390,7 @@ COutPin* CMultipinMft::GetOutPin(
COutPin *outPin = NULL;
for ( DWORD dwIndex = 0, dwSize = (DWORD) m_OutPins.size(); dwIndex < dwSize; dwIndex++ )
{
- outPin = ( COutPin * )m_OutPins[ dwIndex ];
+ outPin = ( COutPin * )m_OutPins[ dwIndex ].Get();
if ( dwStreamId == outPin->streamId() )
{
@@ -1509,7 +1491,10 @@ HRESULT CMultipinMft::ChangeMediaTypeEx(
//
// The media type will be set on the input pin by the time we return from the wait
//
- DMFTCHECKHR_GOTO(spinPin->WaitForSetInputPinMediaChange(), done);
+ m_critSec.Unlock();
+ hr = spinPin->WaitForSetInputPinMediaChange();
+ m_critSec.Lock();
+ DMFTCHECKHR_GOTO(hr, done);
// Change the media type on the output..
DMFTCHECKHR_GOTO(spoPin->ChangeMediaTypeFromInpin(pFullType.Get(), pMediaType , reqState), done);
//
@@ -1728,10 +1713,8 @@ STDMETHODIMP CMultipinMft::Shutdown(
for (ULONG ulIndex = 0, ulSize = (ULONG)m_InPins.size(); ulIndex < ulSize; ulIndex++ )
{
- CInPin *pInPin = static_cast<CInPin *>(m_InPins[ulIndex]);
-
// Deref on the connected outpins to break reference loop
- (VOID)pInPin->ShutdownPin();
+ (VOID)((CInPin*)m_InPins[ulIndex].Get())->ShutdownPin();
}
#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES)
for (ULONG ulIndex = 0, ulSize = (ULONG)m_OutPins.size(); ulIndex < ulSize; ulIndex++)
@@ -1833,7 +1816,7 @@ HRESULT CMultipinMft::SetStreamingStateCustomPins(
for (ULONG ulIndex = 0; ulIndex < m_InPins.size(); ulIndex++)
{
BOOL isCustom = false;
- CInPin* pInPin = static_cast<CInPin*>(m_InPins[ulIndex]);
+ CInPin* pInPin = static_cast<CInPin*>(m_InPins[ulIndex].Get());
if ( SUCCEEDED( CheckCustomPin(pInPin, &isCustom) )
&& ( isCustom ) )
diff --git a/avstream/sampledevicemft/multipinmft.h b/avstream/sampledevicemft/multipinmft.h
index 70367f1d..be86d66b 100644
--- a/avstream/sampledevicemft/multipinmft.h
+++ b/avstream/sampledevicemft/multipinmft.h
@@ -377,7 +377,7 @@ protected:
//Inline functions
//
- __inline IMFTransform* Parent()
+ __inline IMFDeviceTransform* Parent()
{
return m_spSourceTransform.Get();
}
@@ -406,7 +406,7 @@ private:
long m_nRefCount; // Reference count
CCritSec m_critSec; // Control lock.. taken only durign state change operations
ComPtr <IUnknown> m_spDeviceManagerUnk; // D3D Manager set, when MFT_MESSAGE_SET_D3D_MANAGER is called through ProcessMessage
- ComPtr<IMFTransform> m_spSourceTransform; // The sources transform. This is the pipeline DevProxy
+ ComPtr<IMFDeviceTransform> m_spSourceTransform; // The sources transform. This is the pipeline DevProxy
MFSHUTDOWN_STATUS m_eShutdownStatus;
DWORD m_dwWorkQueueId;
LONG m_lWorkQueuePriority;
diff --git a/avstream/sampledevicemft/multipinmfthelpers.cpp b/avstream/sampledevicemft/multipinmfthelpers.cpp
index 34cebe8b..0d720c3d 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.cpp
+++ b/avstream/sampledevicemft/multipinmfthelpers.cpp
@@ -38,7 +38,6 @@ Description:
--*/
STDMETHODIMP_(VOID) CPinQueue::InsertInternal( _In_ IMFSample *pSample )
{
- pSample->AddRef();
HRESULT hr = ExceptionBoundary([&]()
{
m_sampleList.push_back(pSample);
@@ -52,8 +51,6 @@ STDMETHODIMP_(VOID) CPinQueue::InsertInternal( _In_ IMFSample *pSample )
if (FAILED(hr))
{
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
- // There is a bug in the pipeline that doesn't release the sample fed from processinput. We have to explicitly release the sample here
- SAFE_RELEASE(pSample);
}
}
@@ -78,7 +75,7 @@ STDMETHODIMP CPinQueue::Remove( _Outptr_result_maybenull_ IMFSample **ppSample)
if ( !m_sampleList.empty() )
{
- *ppSample = m_sampleList.front();
+ *ppSample = m_sampleList.front().Detach();
}
DMFTCHECKNULL_GOTO( *ppSample, done, MF_E_TRANSFORM_NEED_MORE_INPUT );
@@ -177,33 +174,31 @@ STDMETHODIMP CPinQueue::RecreateTeeByAllocatorMode(
Ctee::ReleaseTee(m_spTeer);// Should release the reference
- wistd::unique_ptr<CNullTee> nulltee = wil::make_unique_nothrow<CNullTee>(this);
- RETURN_IF_NULL_ALLOC(nulltee);
+ ComPtr<CNullTee> spNulltee = new (std::nothrow) CNullTee(this);
+ DMFTCHECKNULL_GOTO(spNulltee.Get(), done, E_OUTOFMEMORY);
if (allocatorUsage == MFSampleAllocatorUsage_DoesNotAllocate)
{
- m_spTeer.Attach(nulltee.release()); /*A simple passthrough*/
+ m_spTeer = spNulltee.Get();
}
else
{
- wistd::unique_ptr<CSampleCopytee> sampleCopytee;
- RETURN_IF_NULL_ALLOC(sampleCopytee);
- (void)sampleCopytee->SetD3DManager(punkManager);
-
+ ComPtr<CSampleCopytee> spSampleCopytee;
if (allocatorUsage == MFSampleAllocatorUsage_UsesProvidedAllocator)
{
RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator);
- sampleCopytee = wil::make_unique_nothrow<CSampleCopytee>(nulltee.release(), pinCategory(), pAllocator);
+ spSampleCopytee = new (std::nothrow) CSampleCopytee(spNulltee.Get(), pinCategory(), pAllocator);
}
else
{
- sampleCopytee = wil::make_unique_nothrow<CSampleCopytee>(nulltee.release(), pinCategory(), nullptr);
+ spSampleCopytee = new (std::nothrow) CSampleCopytee(spNulltee.Get(), pinCategory(), nullptr);
}
-
- RETURN_IF_FAILED(sampleCopytee->SetMediaTypes(inMediatype, outMediatype));
- m_spTeer.Attach(sampleCopytee.release());
+ DMFTCHECKNULL_GOTO(spSampleCopytee.Get(), done, E_OUTOFMEMORY);
+ (void)spSampleCopytee->SetD3DManager(punkManager);
+ RETURN_IF_FAILED(spSampleCopytee->SetMediaTypes(inMediatype, outMediatype));
+ m_spTeer = spSampleCopytee.Get();
}
-
+done:
return hr;
}
#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
@@ -283,28 +278,13 @@ this path traversed. This function feeds the sample to the XVP or the decoding T
STDMETHODIMP CWrapTee::PassThrough( _In_ IMFSample* pInSample )
{
HRESULT hr = S_OK;
- IMFSample* pOutSample = nullptr;
- bool newSample = false;
+ ComPtr<IMFSample> spOutSample = nullptr;
DMFTCHECKNULL_GOTO(pInSample, done, S_OK); // pass through for no sample
- DMFTCHECKHR_GOTO(Do(pInSample, &pOutSample,newSample),done);
+ DMFTCHECKHR_GOTO(Do(pInSample, spOutSample.ReleaseAndGetAddressOf()), done);
if (m_spObjectWrapped)
{
- if (SUCCEEDED(hr = m_spObjectWrapped->PassThrough( pOutSample )))
- {
- //@@@@README There is a very bad bug in the pipeline that the device transform manager
- // is not releasing the reference on the sample when it is passed to the device MFT so any
- // sample produced has to be referenced matched in the deviceMFT so that the net reference remains one
- // This goes against the ownership rules in Com, but this bug has existed in the pipeline so far,
- // so until we rev the interface we will have to live with it
- //
- if (newSample)
- {
- // If we produce the sample, then we have to release the sample
- SAFE_RELEASE(pOutSample);
- }
- }
-
+ DMFTCHECKHR_GOTO(m_spObjectWrapped->PassThrough(spOutSample.Get()), done);
}
done:
@@ -326,7 +306,7 @@ HRESULT CVideoProcTee::SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMe
ComPtr<IMFTransform> spTransform;
DMFTCHECKHR_GOTO(CWrapTee::SetMediaTypes(pInMediaType, pOutMediaType),done);
DMFTCHECKHR_GOTO(Configure(pInMediaType, pOutMediaType, spTransform.GetAddressOf()), done);
- m_spVideoProcessor = spTransform.Detach();
+ m_spVideoProcessor = spTransform;
//
// Start streaming
//
@@ -380,6 +360,15 @@ HRESULT CVideoProcTee::CreateAllocator()
return hr;
}
+CVideoProcTee::~CVideoProcTee()
+{
+ if (m_spPrivateAllocator.Get())
+ {
+ (VOID)m_spPrivateAllocator->UninitializeSampleAllocator();
+ m_spPrivateAllocator = nullptr;
+ }
+}
+
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
// @@@@ README: Video Processor functions below
//
@@ -412,10 +401,9 @@ HRESULT CXvptee::StopStreaming()
HRESULT hr = S_OK;
CAutoLock Lock(m_Lock);
SetAsyncStatus(MF_E_SHUTDOWN);
- DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0), done); // Flush the stream
- DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0), done); // Notify end of stream
- DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0), done); // Notify end of streaming
-done:
+ Transform()->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); // Flush the stream
+ Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0); // Notify end of stream
+ Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0); // Notify end of streaming
return hr;
}
@@ -429,7 +417,7 @@ outpin should be in Open state for the sample to reach the XVP and consequetivel
Output Pin.
--*/
-STDMETHODIMP CXvptee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample, _Inout_ bool &newSample)
+STDMETHODIMP CXvptee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample)
{
HRESULT hr = S_OK;
MFT_OUTPUT_DATA_BUFFER outputSample;
@@ -474,7 +462,6 @@ STDMETHODIMP CXvptee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSamp
if (spXVPOutputSample.Get())
{
- newSample = true;
*ppOutSample = spXVPOutputSample.Detach();
}
done:
@@ -554,11 +541,6 @@ CDecoderTee::~CDecoderTee()
{
(VOID)StopStreaming();
MFUnlockWorkQueue(m_dwCameraStreamWorkQueueId);
- if (m_spPrivateAllocator)
- {
- m_spPrivateAllocator->UninitializeSampleAllocator();
- m_spPrivateAllocator = nullptr;
- }
}
HRESULT CDecoderTee::StartStreaming()
@@ -584,9 +566,9 @@ HRESULT CDecoderTee::StopStreaming()
if (spTransform.Get())
{
ComPtr<IMFShutdown> spShutdown;
- DMFTCHECKHR_GOTO(spTransform->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, m_dwMFTInputId), done);
- DMFTCHECKHR_GOTO(spTransform->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0), done);
- DMFTCHECKHR_GOTO(spTransform->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0), done);
+ spTransform->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, m_dwMFTInputId);
+ spTransform->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0);
+ spTransform->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0);
// Shut it down
if (SUCCEEDED(spTransform->QueryInterface(IID_PPV_ARGS(&spShutdown))))
{
@@ -595,7 +577,6 @@ HRESULT CDecoderTee::StopStreaming()
spTransform = nullptr;
}
-done:
return hr;
}
@@ -675,14 +656,13 @@ done:
}
-STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **ppoutSample, _Inout_ bool &newSample)
+STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **ppoutSample)
{
HRESULT hr = S_OK;
ComPtr<IMFSample> spOutputSample;
CAutoLock lock(m_Lock);
ComPtr<IMFTransform> spTransform = Transform();
- newSample = false;
DMFTCHECKNULL_GOTO(ppoutSample, done, E_INVALIDARG);
*ppoutSample = nullptr;
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
@@ -983,6 +963,7 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid
GUID guidMajorType;
GUID guidSubtype;
DWORD dwMediaTypeIndex = 0;
+ DWORD dwFlags = 0;
ComPtr<IMFDXGIDeviceManager> spDxgiManager;
UNREFERENCED_PARAMETER(guidSubType);
DMFTCHECKNULL_GOTO(pTransform, done, E_INVALIDARG);
@@ -1050,6 +1031,18 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid
// Try to set output type on the MJPG decoder.
DMFTCHECKHR_GOTO(pTransform->MFTSetOutputType(m_dwMFTOutputId, spMediaType.Get(), 0), done);
+ if (S_OK != (spMediaType->IsEqual(m_pOutputMediaType.Get(), &dwFlags)))
+ {
+ ComPtr<CXvptee> spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get(), m_streamCategory);
+ DMFTCHECKNULL_GOTO(spXvpTee.Get(), done, E_OUTOFMEMORY);
+ (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get());
+ DMFTCHECKHR_GOTO(spXvpTee->SetMediaTypes(spMediaType.Get(), m_pOutputMediaType.Get()), done);
+ m_spObjectWrapped = spXvpTee;
+ m_pOutputMediaType = spMediaType;
+ //Recreate the Allocator
+ DMFTCHECKHR_GOTO(CreateAllocator(), done);
+ m_bXvpAdded = TRUE;
+ }
done:
if (FAILED(hr))
{
@@ -1125,7 +1118,7 @@ VOID CDecoderTee::ShutdownTee()
CGrayTee::CGrayTee(_In_ Ctee *tee) : CWrapTee(tee),m_transformfn(nullptr)
{
}
-STDMETHODIMP CGrayTee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample, _Inout_ bool &newSample)
+STDMETHODIMP CGrayTee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample)
{
HRESULT hr = S_OK;
ComPtr<IMFSample> spOutputSample;
@@ -1190,7 +1183,6 @@ STDMETHODIMP CGrayTee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSam
}
if (spOutputSample.Get())
{
- newSample = true;
*ppOutSample = spOutputSample.Detach();
}
done:
@@ -1275,7 +1267,7 @@ HRESULT CSampleCopytee::StopStreaming()
return S_OK;
}
-STDMETHODIMP CSampleCopytee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample, _Inout_ bool &newSample)
+STDMETHODIMP CSampleCopytee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample)
{
HRESULT hr = S_OK;
@@ -1318,7 +1310,6 @@ STDMETHODIMP CSampleCopytee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** pp
if (spXVPOutputSample.Get())
{
- newSample = true;
*ppOutSample = spXVPOutputSample.Detach();
}
diff --git a/avstream/sampledevicemft/multipinmfthelpers.h b/avstream/sampledevicemft/multipinmfthelpers.h
index 681ca071..4237dbf4 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.h
+++ b/avstream/sampledevicemft/multipinmfthelpers.h
@@ -326,7 +326,7 @@ public:
}
STDMETHODIMP PassThrough ( _In_ IMFSample* );
- virtual STDMETHODIMP Do ( _In_ IMFSample* pSample, _Out_ IMFSample ** , _Inout_ bool &newSample) = 0;
+ virtual STDMETHODIMP Do ( _In_ IMFSample* pSample, _Out_ IMFSample **) = 0;
STDMETHODIMP SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType);
//
// Inline functions
@@ -395,8 +395,7 @@ public:
}
return hr;
}
- virtual ~CVideoProcTee()
- {}
+ virtual ~CVideoProcTee();
protected:
CCritSec m_Lock;
__inline VOID SetAsyncStatus(_In_ HRESULT hrStatus)
@@ -426,7 +425,7 @@ public:
virtual ~CXvptee();
STDMETHOD(StartStreaming)();
STDMETHOD(StopStreaming)();
- STDMETHODIMP Do ( _In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
+ STDMETHODIMP Do ( _In_ IMFSample* pSample, _Outptr_ IMFSample **);
STDMETHODIMP Configure ( _In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform** );
};
@@ -453,7 +452,7 @@ public:
}
virtual ~CDecoderTee();
- STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
+ STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **);
STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
STDMETHODIMP Invoke(_In_ IMFAsyncResult*);
protected:
@@ -491,7 +490,7 @@ public:
~CSampleCopytee();
STDMETHOD(StartStreaming)();
STDMETHOD(StopStreaming)();
- STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
+ STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **);
STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
};
@@ -502,7 +501,7 @@ public:
~CGrayTee() {
}
- STDMETHODIMP Do(_In_ IMFSample* pSample, _Out_ IMFSample **, , _Inout_ bool &newSample);
+ STDMETHODIMP Do(_In_ IMFSample* pSample, _Out_ IMFSample **);
STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
private:
// Function pointer for the function that transforms the image.
diff --git a/avstream/sampledevicemft/stdafx.h b/avstream/sampledevicemft/stdafx.h
index 657208cd..a76118c0 100644
--- a/avstream/sampledevicemft/stdafx.h
+++ b/avstream/sampledevicemft/stdafx.h
@@ -54,8 +54,8 @@ using namespace Microsoft::WRL;
//
//#define MF_DEVICEMFT_ADD_GRAYSCALER_ 1
#define MF_DEVICEMFT_ASYNCPIN_NEEDED 1
-//#define MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED 0
-#define MF_DEVICEMFT_SET_SPHERICAL_ATTRIBUTES 1
+//#define MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED 1
+//#define MF_DEVICEMFT_SET_SPHERICAL_ATTRIBUTES 1
//#define MF_DEVICEMFT_ENUM_HW_DECODERS 1