From e0c0afda943a63d5e6ce888e158096428c6654df Mon Sep 17 00:00:00 2001 From: jk Date: Tue, 7 Feb 2023 15:44:24 -0800 Subject: 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. --- avstream/sampledevicemft/basepin.cpp | 53 ++++++------ avstream/sampledevicemft/basepin.h | 14 ++-- avstream/sampledevicemft/common.h | 6 +- avstream/sampledevicemft/multipinmft.cpp | 57 +++++-------- avstream/sampledevicemft/multipinmft.h | 4 +- avstream/sampledevicemft/multipinmfthelpers.cpp | 105 +++++++++++------------- avstream/sampledevicemft/multipinmfthelpers.h | 13 ++- avstream/sampledevicemft/stdafx.h | 4 +- 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 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 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 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( pNewMediaType.Get(), pMediaType)); + m_TranslatedMediaTypes.insert(std::pair, ComPtr>( 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::iterator found = std::find_if(m_TranslatedMediaTypes.begin(), m_TranslatedMediaTypes.end(), - [&](std::pair p) + auto found = std::find_if(m_TranslatedMediaTypes.begin(), m_TranslatedMediaTypes.end(), + [&](std::pair, ComPtr> 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 spMediaType = (*found).second; + ComPtr 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 m_spSourceTransform; /*Source Transform i.e. DevProxy*/ + ComPtr m_spSourceTransform; /*Source Transform i.e. DevProxy*/ GUID m_stStreamType; /*GUID representing the GUID*/ ComPtr 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 m_TranslatedMediaTypes; + map, ComPtr> 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 > IMFMediaTypeArray; +typedef std::vector > CBasePinArray; +typedef std::vector > IMFSampleList; typedef std::pair< std::multimap::iterator, std::multimap::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 spoPin; BOOL bCustom = FALSE; - ComPtr spiPin = ( CInPin * )m_InPins[ ulIndex ]; + ComPtr 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 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 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 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 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 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 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 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 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 spoPin = (COutPin *)m_OutPins[dwIndex]; + ComPtr 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(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(m_InPins[ulIndex]); + CInPin* pInPin = static_cast(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 m_spDeviceManagerUnk; // D3D Manager set, when MFT_MESSAGE_SET_D3D_MANAGER is called through ProcessMessage - ComPtr m_spSourceTransform; // The sources transform. This is the pipeline DevProxy + ComPtr 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 nulltee = wil::make_unique_nothrow(this); - RETURN_IF_NULL_ALLOC(nulltee); + ComPtr 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 sampleCopytee; - RETURN_IF_NULL_ALLOC(sampleCopytee); - (void)sampleCopytee->SetD3DManager(punkManager); - + ComPtr spSampleCopytee; if (allocatorUsage == MFSampleAllocatorUsage_UsesProvidedAllocator) { RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator); - sampleCopytee = wil::make_unique_nothrow(nulltee.release(), pinCategory(), pAllocator); + spSampleCopytee = new (std::nothrow) CSampleCopytee(spNulltee.Get(), pinCategory(), pAllocator); } else { - sampleCopytee = wil::make_unique_nothrow(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 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 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 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 spOutputSample; CAutoLock lock(m_Lock); ComPtr 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 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 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 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 -- cgit v1.3.1 From 2639b5d65fa4777c669c45be8f1a13142b0e49a0 Mon Sep 17 00:00:00 2001 From: jk Date: Fri, 25 Aug 2023 15:16:49 -0700 Subject: [avstream/sampledevicemft] Fix format change error for YUY2 (#984) --- avstream/sampledevicemft/basepin.cpp | 4 +-- avstream/sampledevicemft/basepin.h | 12 ++++++- avstream/sampledevicemft/multipinmfthelpers.cpp | 48 ++++++++++++++++++------- avstream/sampledevicemft/multipinmfthelpers.h | 5 +-- avstream/sampledevicemft/multipinmftutils.cpp | 5 ++- 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/avstream/sampledevicemft/basepin.cpp b/avstream/sampledevicemft/basepin.cpp index 471bbca7..5195acc5 100644 --- a/avstream/sampledevicemft/basepin.cpp +++ b/avstream/sampledevicemft/basepin.cpp @@ -30,7 +30,7 @@ CBasePin::CBasePin( _In_ ULONG id, _In_ CMultipinMft *parent) : , m_setMediaType(nullptr) , m_nRefCount(0) , m_state(DeviceStreamState_Stop) - , m_dwWorkQueueId(MFASYNC_CALLBACK_QUEUE_UNDEFINED) + , m_dwWorkQueueId(MFASYNC_CALLBACK_QUEUE_MULTITHREADED) { } @@ -505,7 +505,7 @@ STDMETHODIMP COutPin::AddPin( } #if defined MF_DEVICEMFT_ADD_GRAYSCALER_ // Take this out to remove the gray scaler - m_queue = new (std::nothrow) CPinQueueWithGrayScale(inputPinId); + m_queue = new (std::nothrow) CPinQueueWithGrayScale(inputPinId,Parent()); #else m_queue = new (std::nothrow) CPinQueue(inputPinId,Parent()); #endif diff --git a/avstream/sampledevicemft/basepin.h b/avstream/sampledevicemft/basepin.h index d3e45c93..2feff7ae 100644 --- a/avstream/sampledevicemft/basepin.h +++ b/avstream/sampledevicemft/basepin.h @@ -638,7 +638,17 @@ class CTranslateOutPin : public COutPin { MFVideoFormat_H264, MFVideoFormat_MJPG }; - // @@@@README : This is what the compressed media types will be translated into + + // @@@@README + // If you translate to YUY2 in D3D mode it is a suboptimal path, because the + // pipeline i.e. Frameserver will lock the surface into a staging buffer and + // map it to the client process like Teams, Camera App etc. + // Ideally when translating to YUY2, don't pass the D3D Manager to the + // Decoder (CDecoderTee) or the Video Processor (CXVPTee). The pipeline will + // shove the system buffer back into the DX surface on the client side, if the App + // demands DX surfaces. NV12 is sharable from frameserver to clients and hence + // the preferred format to decode into. + // The below subtype is what the compressed media types will be translated into. const GUID translatedGUID = MFVideoFormat_NV12; // Translating to NV12 public: CTranslateOutPin(_In_ ULONG id = 0, diff --git a/avstream/sampledevicemft/multipinmfthelpers.cpp b/avstream/sampledevicemft/multipinmfthelpers.cpp index 0d720c3d..79c029b8 100644 --- a/avstream/sampledevicemft/multipinmfthelpers.cpp +++ b/avstream/sampledevicemft/multipinmfthelpers.cpp @@ -224,7 +224,7 @@ STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatyp ||IsEqualCLSID(gInputSubType, MFVideoFormat_RGB32)) { CGrayTee *pTee = NULL; - pTee = new (std::nothrow) CGrayTee(m_spTeer); + pTee = new (std::nothrow) CGrayTee(m_spTeer.Get()); DMFTCHECKHR_GOTO(pTee->SetMediaTypes(inMediatype, outMediatype), done); m_spTeer = dynamic_cast< Ctee* >(pTee); } @@ -305,7 +305,7 @@ HRESULT CVideoProcTee::SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMe HRESULT hr = S_OK; ComPtr spTransform; DMFTCHECKHR_GOTO(CWrapTee::SetMediaTypes(pInMediaType, pOutMediaType),done); - DMFTCHECKHR_GOTO(Configure(pInMediaType, pOutMediaType, spTransform.GetAddressOf()), done); + DMFTCHECKHR_GOTO(Configure(pInMediaType, pOutMediaType, spTransform.ReleaseAndGetAddressOf()), done); m_spVideoProcessor = spTransform; // // Start streaming @@ -610,12 +610,14 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType, m_pOutputMediaType.Get(), spTransform.ReleaseAndGetAddressOf(), m_hwMFT))) { + m_hwMFT = TRUE; hr = ConfigDecoder(spTransform.Get(), gInSubType); } if (FAILED(hr)) { // Try creating SW deocder hr = S_OK; + m_hwMFT = FALSE; DMFTCHECKHR_GOTO(EnumSWDecoder(spTransform.ReleaseAndGetAddressOf(), gInSubType), done); DMFTCHECKHR_GOTO(ConfigDecoder(spTransform.Get(), gInSubType), done); } @@ -907,7 +909,7 @@ HRESULT CDecoderTee::ProcessFormatChange() // Also note, The platform doesn't support dynamic media type changes from the stream coming from the // source. // - ComPtr spXvpTee; + ComPtr spXvpTee; DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidPreviousSubType), done); for (DWORD i = 0; ; i++) @@ -935,9 +937,21 @@ HRESULT CDecoderTee::ProcessFormatChange() // // Create the XVP and insert it into the chain manually. set the output to the mediatype requested by the platform // - spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get() ,m_streamCategory); + if (m_bXvpAdded && m_spXvp.Get()) + { + // The XVP was already created. change the xvp to handle format change + spXvpTee = m_spXvp; + } + else + { + spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get(), m_streamCategory); + m_spXvp = spXvpTee; + } DMFTCHECKNULL_GOTO(spXvpTee.Get(), done, E_OUTOFMEMORY); - (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get()); + if(m_hwMFT) + { + (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get()); + } DMFTCHECKHR_GOTO(spXvpTee->SetMediaTypes(spDecoderOutputMediaType.Get(), m_pOutputMediaType.Get()), done); m_spObjectWrapped = spXvpTee; @@ -965,6 +979,8 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid DWORD dwMediaTypeIndex = 0; DWORD dwFlags = 0; ComPtr spDxgiManager; + DWORD dwDesiredFlags = MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_DATA; + UNREFERENCED_PARAMETER(guidSubType); DMFTCHECKNULL_GOTO(pTransform, done, E_INVALIDARG); @@ -995,7 +1011,7 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid DMFTCHECKHR_GOTO(m_pOutputMediaType->GetMajorType(&guidMajorType), done); DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done); - if (m_spDeviceManagerUnk.Get()) + if (m_hwMFT && m_spDeviceManagerUnk.Get()) { DMFTCHECKHR_GOTO(m_spDeviceManagerUnk.As(&spDxgiManager), done); if (m_D3daware && SUCCEEDED(IsDXFormatSupported(spDxgiManager.Get(), guidSubtype, nullptr, nullptr))) @@ -1025,22 +1041,30 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid spMediaType = nullptr; dwMediaTypeIndex++; } - // If cannot find a matchig mediatype, bail out. DMFTCHECKNULL_GOTO(spMediaType.Get(), done, MF_E_INVALIDMEDIATYPE); - // 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))) + hr = spMediaType->IsEqual(m_pOutputMediaType.Get(), &dwFlags); + if ((S_OK == hr) || + (hr == S_FALSE && ((dwFlags & dwDesiredFlags) == dwDesiredFlags))) + { + // Try to set output type on the MJPG decoder. + DMFTCHECKHR_GOTO(pTransform->MFTSetOutputType(m_dwMFTOutputId, spMediaType.Get(), 0), done); + } + else { + // Set the media type and also create an XVP to manage the conversion + DMFTCHECKHR_GOTO(pTransform->MFTSetOutputType(m_dwMFTOutputId, spMediaType.Get(), 0), done); ComPtr spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get(), m_streamCategory); DMFTCHECKNULL_GOTO(spXvpTee.Get(), done, E_OUTOFMEMORY); - (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get()); + if (m_hwMFT) + { + (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: diff --git a/avstream/sampledevicemft/multipinmfthelpers.h b/avstream/sampledevicemft/multipinmfthelpers.h index 4237dbf4..4181bcca 100644 --- a/avstream/sampledevicemft/multipinmfthelpers.h +++ b/avstream/sampledevicemft/multipinmfthelpers.h @@ -201,11 +201,11 @@ public: private: DWORD m_dwInPinId; /* This is the input pin */ IMFSampleList m_sampleList; /* List storing the samples */ - IMFDeviceTransform* m_pTransform; /* Weak reference to the the device MFT */ GUID m_streamCategory; ULONG m_cRef; protected: - ComPtr m_spTeer; /*Tee that acts as a passthrough or an XVP */ + IMFDeviceTransform* m_pTransform; /* Weak reference to the the device MFT */ + ComPtr m_spTeer; /*Tee that acts as a passthrough or an XVP */ }; @@ -473,6 +473,7 @@ protected: DWORD m_lNeedInputRequest; GUID m_streamCategory; // Needed for bind flags BOOL m_bXvpAdded; + ComPtr m_spXvp; DWORD m_dwMFTInputId; DWORD m_dwMFTOutputId; ComPtr m_spUnprocessedSample; diff --git a/avstream/sampledevicemft/multipinmftutils.cpp b/avstream/sampledevicemft/multipinmftutils.cpp index e4a62d52..cbd64f72 100644 --- a/avstream/sampledevicemft/multipinmftutils.cpp +++ b/avstream/sampledevicemft/multipinmftutils.cpp @@ -1292,7 +1292,10 @@ UpdateAllocatorAttributes( level = spDevice->GetFeatureLevel(); dwBindFlags |= ((level >= D3D_FEATURE_LEVEL_10_0) ? D3D11_BIND_SHADER_RESOURCE : 0); } - + else + { + dwBindFlags |= D3D11_BIND_RENDER_TARGET; + } DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_BINDFLAGS, dwBindFlags), done); done: -- cgit v1.3.1