summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Corley <[email protected]>2018-07-19 15:21:37 -0700
committerGitHub <[email protected]>2018-07-19 15:21:37 -0700
commit021af44b09f91a9d0ced14d26654cc238802f307 (patch)
treedc7f5e99b796ea9fd918907411595501bf086a63
parent30ddbb997660fa4ae3608759b9d2d0789774ccdc (diff)
parent84a856eda909e1084fa6b5978f9701398b67ec45 (diff)
Merge branch 'master' into rs4-update
-rw-r--r--avstream/sampledevicemft/basepin.cpp235
-rw-r--r--avstream/sampledevicemft/basepin.h137
-rw-r--r--avstream/sampledevicemft/common.h103
-rw-r--r--avstream/sampledevicemft/multipinmft.cpp301
-rw-r--r--avstream/sampledevicemft/multipinmft.h16
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.cpp1027
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.h306
-rw-r--r--avstream/sampledevicemft/multipinmftutils.cpp718
-rw-r--r--avstream/sampledevicemft/stdafx.h24
-rw-r--r--network/wlan/WDI/COMMON/HashTable.c2
-rw-r--r--network/wlan/WDI/COMMON/QosGen.c2
-rw-r--r--network/wlan/WDI/HEADER/HashTable.h2
-rw-r--r--setup/devcon/devcon.sln12
-rw-r--r--setup/devcon/devcon.vcxproj72
14 files changed, 2253 insertions, 704 deletions
diff --git a/avstream/sampledevicemft/basepin.cpp b/avstream/sampledevicemft/basepin.cpp
index 5e4ba038..d4220397 100644
--- a/avstream/sampledevicemft/basepin.cpp
+++ b/avstream/sampledevicemft/basepin.cpp
@@ -29,6 +29,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)
{
}
@@ -59,6 +60,7 @@ HRESULT CBasePin::AddMediaType( _Inout_ DWORD *pos, _In_ IMFMediaType *pMediaTyp
{
HRESULT hr = S_OK;
CAutoLock Lock(lock());
+
DMFTCHECKNULL_GOTO(pMediaType, done, E_INVALIDARG);
hr = ExceptionBoundary([&]()
{
@@ -140,7 +142,6 @@ done:
return SUCCEEDED(hr) ? TRUE : FALSE;
}
-
STDMETHODIMP CBasePin::GetOutputAvailableType(
_In_ DWORD dwTypeIndex,
_Out_opt_ IMFMediaType** ppType)
@@ -148,7 +149,6 @@ STDMETHODIMP CBasePin::GetOutputAvailableType(
return GetMediaTypeAt( dwTypeIndex, ppType );
}
-
HRESULT CBasePin::QueryInterface(
_In_ REFIID iid,
_Outptr_result_maybenull_ void** ppv
@@ -179,10 +179,17 @@ HRESULT CBasePin::QueryInterface(
done:
return hr;
}
-
-
-
-
+VOID CBasePin::SetD3DManager(_In_opt_ IUnknown* pManager)
+{
+ //
+ // Should release the old dxgi manager.. We will not invalidate the pins or allocators
+ // We will recreate all allocator when the media types are set, so we should be fine
+ // And the pipeline will not set the dxgimanager when the pipeline is already built
+ //
+ CAutoLock Lock(lock());
+ m_spDxgiManager = pManager;
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Setting D3DManager on pin %d", m_StreamId);
+}
//
//Input Pin implementation
//
@@ -199,8 +206,6 @@ CInPin::CInPin(
setAttributes(pAttributes);
}
-
-
CInPin::~CInPin()
{
setAttributes( nullptr );
@@ -212,8 +217,6 @@ CInPin::~CInPin()
}
}
-
-
STDMETHODIMP CInPin::Init(
_In_ IMFTransform* pTransform
)
@@ -258,7 +261,6 @@ done:
return hr;
}
-
HRESULT CInPin::GenerateMFMediaTypeListFromDevice(
_In_ UINT uiStreamId
)
@@ -277,7 +279,7 @@ HRESULT CInPin::GenerateMFMediaTypeListFromDevice(
break;
DMFTCHECKHR_GOTO(AddMediaType(&pos, spMediaType.Get()), done);
- }
+ }
done:
if (hr == MF_E_NO_MORE_TYPES) {
hr = S_OK;
@@ -298,7 +300,7 @@ STDMETHODIMP CInPin::SendSample(
COutPin *poPin = static_cast<COutPin*>(m_outpin.Get());
DMFTCHECKNULL_GOTO(pSample, done, S_OK);
DMFTCHECKHR_GOTO(poPin->AddSample(pSample, this), done);
- DMFTCHECKHR_GOTO(Parent()->QueueEvent(METransformHaveOutput, GUID_NULL, S_OK, NULL),done);
+
done:
return hr;
}
@@ -312,7 +314,6 @@ STDMETHODIMP_(VOID) CInPin::ConnectPin( _In_ CBasePin * poPin )
}
}
-
STDMETHODIMP CInPin::WaitForSetInputPinMediaChange()
{
DWORD dwWait = 0;
@@ -385,6 +386,7 @@ HRESULT CInPin::SetInputStreamState(
void CInPin::ReleaseConnectedPins()
{
+ m_spSourceTransform = nullptr;
m_outpin = nullptr;
}
@@ -452,46 +454,15 @@ STDMETHODIMP COutPin::AddPin(
#if defined MF_DEVICEMFT_ADD_GRAYSCALER_ // Take this out to remove the gray scaler
m_queue = new (std::nothrow) CPinQueueWithGrayScale(inputPinId);
#else
- m_queue = new (std::nothrow) CPinQueue(inputPinId);
+ m_queue = new (std::nothrow) CPinQueue(inputPinId,Parent());
#endif
DMFTCHECKNULL_GOTO(m_queue, done, E_OUTOFMEMORY );
- //
- //Just ramdonmize media types for odd numbered pins
- //
- if ( streamId() != 0 && streamId() % 2 != 0 )
- {
- RandomnizeMediaTypes(m_listOfMediaTypes);
- }
-
done:
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
return S_OK;
}
-
-/*++
-COutPin::AddSampleInternal
-Description:
-Called from AddSample if the Output Pin is in open state. This function looks for the queue
-corresponding to the input pin and adds it in the queue.
---*/
-
-STDMETHODIMP COutPin::AddSampleInternal(
- _In_ IMFSample *pSample,
- _In_ CBasePin *pPin )
-{
- HRESULT hr = S_OK;
- UNREFERENCED_PARAMETER(pPin);
- CAutoLock Lock( lock() );
- //
- // Add the sample into the queue. Add Ref the Sample
- //
- DMFTCHECKHR_GOTO(m_queue->Insert(pSample), done);
-done:
-return hr;
- }
-
/*++
COutPin::AddSample
Description:
@@ -504,15 +475,24 @@ STDMETHODIMP COutPin::AddSample(
_In_ CBasePin *pPin)
{
HRESULT hr = S_OK;
- CAutoLock lock( lock() );
+ UNREFERENCED_PARAMETER(pPin);
+
+ CAutoLock Lock(lock()); // Serialize
+
DMFTCHECKNULL_GOTO(pSample, done, E_INVALIDARG);
if (FAILED(Active()))
{
goto done;
}
- DMFTCHECKHR_GOTO( AddSampleInternal( pSample, pPin ),done );
-
+ DMFTCHECKHR_GOTO(m_queue->Insert(pSample), done);
done:
+ if (FAILED(hr))
+ {
+ // @@@@ Readme : This is how to throw error to the pipeline and inform it that there is an Error.
+ // This will destroy the pipeline and the App will need to recreate the source
+ //
+ DMFTCHECKHR_GOTO(Parent()->QueueEvent(MEError, GUID_NULL, hr, NULL), done);
+ }
return hr;
}
@@ -554,7 +534,6 @@ HRESULT COutPin::ChangeMediaTypeFromInpin(
_In_ DeviceStreamState state)
{
HRESULT hr = S_OK;
- ComPtr<IUnknown> spD3DManagerUnk = NULL;
CAutoLock Lock(lock());
//
//Set the state to disabled and while going out we will reset the state back to the requested state
@@ -563,8 +542,7 @@ HRESULT COutPin::ChangeMediaTypeFromInpin(
SetState(DeviceStreamState_Disabled);
DMFTCHECKHR_GOTO(FlushQueues(),done);
DMFTCHECKNULL_GOTO(m_queue,done, E_UNEXPECTED); // The queue should alwaye be set
- (VOID)Parent()->GetD3DDeviceManager(spD3DManagerUnk.GetAddressOf());
- hr = m_queue->RecreateTee( pInMediatype, pOutMediaType, spD3DManagerUnk.Get() );
+ hr = m_queue->RecreateTee(pInMediatype, pOutMediaType, m_spDxgiManager.Get());
if ( SUCCEEDED( hr ) )
{
(VOID)setMediaType( pOutMediaType );
@@ -585,7 +563,6 @@ STDMETHODIMP COutPin::GetOutputStreamInfo(
{
HRESULT hr = S_OK;
IMFMediaType* pMediatype = nullptr;
-
getMediaType( &pMediatype );
if (SUCCEEDED(hr) && !pMediatype) {
@@ -602,6 +579,7 @@ STDMETHODIMP COutPin::GetOutputStreamInfo(
return hr;
}
+
/*++
COutPin::ProcessOutput
Description:
@@ -619,19 +597,19 @@ STDMETHODIMP COutPin::ProcessOutput(_In_ DWORD dwFlags,
HRESULT hr = S_OK;
ComPtr<IMFSample> spSample;
MFTIME llTime = 0L;
-
UNREFERENCED_PARAMETER(pdwStatus);
UNREFERENCED_PARAMETER(dwFlags);
CAutoLock lock(lock());
-
+
if (FAILED(Active()))
{
goto done;
}
-
DMFTCHECKNULL_GOTO(m_queue, done, MF_E_INVALID_STREAM_STATE);
pOutputSample->dwStatus = S_OK;
+
DMFTCHECKHR_GOTO(m_queue->Remove(spSample.GetAddressOf()), done);
+
if (FAILED(spSample->GetSampleTime(&llTime)))
{
llTime = MFGetSystemTime();
@@ -687,16 +665,7 @@ STDMETHODIMP CAsyncInPin::SendSample(_In_ IMFSample *pSample)
CAutoLock Lock(lock());
if (!m_bFlushing)
{
- if (m_dwWorkQueueId == MFASYNC_CALLBACK_QUEUE_UNDEFINED)
- {
- //
- // Set the queue now
- // We will have the work queue id set before we start streaming
- //
- m_dwWorkQueueId = Parent()->GetQueueId();
- }
- DMFTCHECKHR_GOTO(MFPutWorkItem(m_dwWorkQueueId, &m_asyncCallback, pSample), done);
- pSample->AddRef();
+ DMFTCHECKHR_GOTO(MFPutWorkItem(m_dwWorkQueueId, static_cast<IMFAsyncCallback*>(m_asyncCallback.Get()), pSample), done);
if (1 == InterlockedIncrement(&m_dwSamplesInFlight))
{
ResetEvent(m_hHandle);
@@ -711,38 +680,42 @@ done:
return hr;
}
-STDMETHODIMP CAsyncInPin::SendSampleInternal(_In_ IMFSample *pSample)
+STDMETHODIMP CAsyncInPin::Init()
{
- HRESULT hr = S_OK;
- CAutoLock Lock(lock());
- DMFTCHECKNULL_GOTO(pSample, done, E_INVALIDARG);
- hr = CInPin::SendSample(pSample);
- pSample->Release();
- if (0 == InterlockedDecrement(&m_dwSamplesInFlight))
- {
- // No samples in flight.. Set the Event
- SetEvent(m_hHandle);
- }
-done:
- return hr;
+ m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CAsyncInPin, &CAsyncInPin::Invoke>(this);
+ if (!m_asyncCallback)
+ throw bad_alloc();
+ return S_OK;
}
-STDMETHODIMP CAsyncInPin::CDMFTAsyncCallback::Invoke(_In_ IMFAsyncResult* pResult)
+
+HRESULT CAsyncInPin::Invoke( _In_ IMFAsyncResult* pResult )
{
HRESULT hr = S_OK;
ComPtr<IUnknown> spUnknown;
ComPtr<IMFSample> spSample;
+
DMFTCHECKNULL_GOTO(pResult, done, E_UNEXPECTED);
DMFTCHECKHR_GOTO(pResult->GetState(&spUnknown), done);
- DMFTCHECKHR_GOTO(spUnknown->QueryInterface(__uuidof(IUnknown), reinterpret_cast<PVOID*>(spSample.GetAddressOf())), done);
- CAsyncInPin *pPin = GetParent();
- DMFTCHECKNULL_GOTO(pPin, done, E_UNEXPECTED);
- DMFTCHECKHR_GOTO(pPin->SendSampleInternal(spSample.Get()), done);
+
+ DMFTCHECKHR_GOTO(spUnknown->QueryInterface(__uuidof(IMFSample), reinterpret_cast<PVOID*>(spSample.GetAddressOf())), done);
+
+ DMFTCHECKNULL_GOTO(spSample.Get(), done, E_INVALIDARG);
+
+ COutPin *poPin = static_cast<COutPin*>(m_outpin.Get());
+ DMFTCHECKHR_GOTO(poPin->AddSample(spSample.Get(), this), done);
+
+ if (0 == InterlockedDecrement(&m_dwSamplesInFlight))
+ {
+ // No samples in flight.. Set the Event
+ SetEvent(m_hHandle);
+ }
+
done:
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
return hr;
}
+
STDMETHODIMP CAsyncInPin::FlushQueues()
{
HRESULT hr = S_OK;
@@ -770,4 +743,96 @@ done:
return hr;
}
+//
+// Pins that need translation like from MJPEG to NV12 or H264 to NV12
+// Return Value: S_OK: media type added, S_FALSE: mediatype skipped. Not an Error
+// Failure: any other catastrophic failure
+//
+STDMETHODIMP CTranslateOutPin::AddMediaType(
+ _Inout_ DWORD *pos,
+ _In_ IMFMediaType *pMediaType)
+{
+ HRESULT hr = S_OK;
+ ComPtr<IMFMediaType> pNewMediaType = nullptr;
+ GUID guidSubType = GUID_NULL;
+ auto needTranslation = [&](IMFMediaType* pMediaType) {
+ if (SUCCEEDED(pMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubType)))
+ {
+ for (UINT32 uiIndex = 0; uiIndex < ARRAYSIZE(tranlateGUIDS); uiIndex++)
+ {
+ if (IsEqualGUID(guidSubType, tranlateGUIDS[uiIndex]))
+ return true;
+ }
+ }
+ return false;
+ };
+ DMFTCHECKNULL_GOTO(pMediaType, done, E_INVALIDARG);
+ 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))
+ {
+ UINT32 uiWidth = 0, uiHeight = 0, uiImageSize = 0;
+
+ DMFTCHECKHR_GOTO(MFGetAttributeRatio(pMediaType, MF_MT_FRAME_SIZE, &uiWidth, &uiHeight), done);
+ DMFTCHECKHR_GOTO(MFCreateMediaType(pNewMediaType.GetAddressOf()), done);
+ DMFTCHECKHR_GOTO(pMediaType->CopyAllItems(pNewMediaType.Get()), done);
+ 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);
+ hr = ExceptionBoundary([&]()
+ {
+ m_TranslatedMediaTypes.insert(std::pair<IMFMediaType*, IMFMediaType*>( pNewMediaType.Get(), pMediaType));
+ });
+ DMFTCHECKHR_GOTO(hr, done);
+ }
+ else
+ {
+ pNewMediaType = pMediaType;
+ }
+ // Set custom properties here
+ //@@@@ README .. add these lines if you want this media types to be understood as a spherical media type
+#if defined MF_DEVICEMFT_SET_SPHERICAL_ATTRIBUTES
+ pNewMediaType->SetUINT32(MF_SD_VIDEO_SPHERICAL, TRUE);
+ pNewMediaType->SetUINT32(MF_SD_VIDEO_SPHERICAL_FORMAT, MFVideoSphericalFormat_Equirectangular);
+#endif
+ // Add it to the pin media type
+ hr = CBasePin::AddMediaType(pos, pNewMediaType.Get());
+done:
+ return hr;
+}
+STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
+ _In_ IMFMediaType *pMediaType,
+ _When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_)
+ IMFMediaType **ppIMFMediaTypeFull)
+{
+ 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)
+ {
+ return (SUCCEEDED(pMediaType->IsEqual(p.first, &dwFlags))
+ && ((dwFlags & dwMatchedFlags) == (dwMatchedFlags)));
+ });
+
+ if (found != m_TranslatedMediaTypes.end())
+ {
+ if (ppIMFMediaTypeFull)
+ {
+ *ppIMFMediaTypeFull = (*found).second;
+ }
+ return true;
+ }
+ else
+ {
+ // Check if we can find it in the Base list.. maybe the mediatype is originally an uncompressed media type
+ return CBasePin::IsMediaTypeSupported(pMediaType,ppIMFMediaTypeFull);
+ }
+}
diff --git a/avstream/sampledevicemft/basepin.h b/avstream/sampledevicemft/basepin.h
index 24c2e765..faafd759 100644
--- a/avstream/sampledevicemft/basepin.h
+++ b/avstream/sampledevicemft/basepin.h
@@ -8,6 +8,7 @@
#pragma once
#include "stdafx.h"
#include "common.h"
+#include "multipinmfthelpers.h"
extern DeviceStreamState pinStateTransition[][4];
@@ -402,13 +403,13 @@ public:
return QueryInterface( IID_PPV_ARGS(ppAttributes) );
}
- STDMETHODIMP AddMediaType(
+ STDMETHOD(AddMediaType)(
_Inout_ DWORD *pos,
_In_ IMFMediaType *pMediatype); /*Filling the media types data structure*/
STDMETHODIMP GetMediaTypeAt(
_In_ DWORD pos,
_Outptr_result_maybenull_ IMFMediaType **pMediaType); /* getting the data from the data structure*/
- STDMETHODIMP_(BOOL) IsMediaTypeSupported(
+ STDMETHOD_(BOOL, IsMediaTypeSupported)(
_In_ IMFMediaType *pMediaType,
_When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_)
IMFMediaType **ppIMFMediaTypeFull);
@@ -416,6 +417,11 @@ public:
_In_ DWORD dwTypeIndex,
_Out_opt_ IMFMediaType **ppType);
+ VOID SetD3DManager(_In_opt_ IUnknown* pManager);
+ VOID SetWorkQueue(_In_ DWORD dwQueueId)
+ {
+ m_dwWorkQueueId = dwQueueId;
+ }
protected:
//
//Inline helper functions
@@ -437,6 +443,8 @@ protected:
ComPtr<IMFAttributes> m_spAttributes;
ComPtr<IKsControl> m_spIkscontrol;
DeviceStreamState m_state;
+ ComPtr<IUnknown> m_spDxgiManager;
+ DWORD m_dwWorkQueueId;
private:
ULONG m_StreamId; /*Device Stream Id*/
CCritSec m_lock; /*This is only used to change the reference count i.e. active users of this stream*/
@@ -506,9 +514,7 @@ public:
void ReleaseConnectedPins();
protected:
- ComPtr<IMFTransform> m_spSourceTransform; /*Source Transform*/
-
-private:
+ ComPtr<IMFTransform> 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;
@@ -532,11 +538,6 @@ public:
_In_ IMFSample *pSample,
_In_ CBasePin *inPin
);
- STDMETHODIMP AddSampleInternal(
- _In_ IMFSample *pSample,
- _In_ CBasePin *inPin
- );
-
STDMETHODIMP GetOutputStreamInfo(
_Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo
);
@@ -559,13 +560,17 @@ public:
STDMETHODIMP_(VOID) SetFirstSample(
_In_ BOOL
);
-
+ UINT32 GetMediatypeCount()
+ {
+ return (UINT32)m_listOfMediaTypes.size();
+ }
protected:
CPinQueue * m_queue; /* Queue where the sample will be stored*/
BOOL m_firstSample;
};
+
class CAsyncInPin: public CInPin {
public:
@@ -573,105 +578,69 @@ public:
STDMETHODIMP SendSample(
_In_ IMFSample *
);
- STDMETHODIMP SendSampleInternal(
- _In_ IMFSample *
+ STDMETHODIMP Invoke(
+ _In_ IMFAsyncResult *
);
+ STDMETHODIMP Init();
CAsyncInPin(
_In_opt_ IMFAttributes *pAttributes,
_In_ ULONG ulPinId,
_In_ CMultipinMft *pParent) : CInPin(pAttributes,
ulPinId, pParent)
- , m_dwWorkQueueId(MFASYNC_CALLBACK_QUEUE_UNDEFINED)
, m_dwSamplesInFlight(0)
, m_hHandle(INVALID_HANDLE_VALUE)
, m_bFlushing(FALSE)
+ , m_asyncCallback(nullptr)
{
m_hHandle = CreateEvent(NULL, TRUE, TRUE, L"Async_Pin Event");
+ if (m_hHandle == nullptr)
+ throw bad_alloc();
+ Init();
+
}
~CAsyncInPin()
{
+ FlushQueues();
CloseHandle(m_hHandle);
m_hHandle = INVALID_HANDLE_VALUE;
}
- ////////////////////////////////////////////////////////////////////////////////////////
- // Start of Asynchronous callback definitions :- If we need to use MF work queues
- ////////////////////////////////////////////////////////////////////////////////////////
- class CDMFTAsyncCallback : public IMFAsyncCallback
- {
- public:
- CDMFTAsyncCallback() : m_cRef(1) { }
- virtual ~CDMFTAsyncCallback() { }
- STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
- {
- HRESULT hr = S_OK;
- if (ppv != nullptr)
- {
- *ppv = nullptr;
- if (riid == __uuidof(IMFAsyncCallback) || riid == __uuidof(IUnknown))
- {
- AddRef();
- *ppv = static_cast<IUnknown*>(this);
- }
- else
- {
- hr = E_NOINTERFACE;
- }
- }
- else
- {
- hr = E_POINTER;
- }
- return hr;
- }
-
- STDMETHODIMP_(ULONG) AddRef()
- {
- return InterlockedIncrement(&m_cRef);
- }
- STDMETHODIMP_(ULONG) Release()
- {
- long cRef = InterlockedDecrement(&m_cRef);
- if (cRef == 0)
- {
- delete this;
- }
- return cRef;
- }
- STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
- {
- // Implementation of this method is optional.
- UNREFERENCED_PARAMETER(pdwFlags);
- UNREFERENCED_PARAMETER(pdwQueue);
- return E_NOTIMPL;
- }
-
- STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult);
- // TODO: Implement this method.
-
- // Inside Invoke, IMFAsyncResult::GetStatus to get the status.
- // Then call the EndX method to complete the operation.
- CAsyncInPin* GetParent()
- {
- // The restrictioh that the below expression sets is that
- // we should now have
- return CONTAINING_RECORD(this, CAsyncInPin, m_asyncCallback);
- }
- private:
- long m_cRef;
- };
-
- CDMFTAsyncCallback m_asyncCallback; // Callback object
- DWORD m_dwWorkQueueId; // Work queue Id
+ ComPtr<CDMFTAsyncCallback<CAsyncInPin,&CAsyncInPin::Invoke> > m_asyncCallback; // Callback object
HANDLE m_hHandle; // Handles to keep flush state
DWORD m_dwSamplesInFlight; // Samples in flight i.e. waiting for the callback functions to be called
BOOL m_bFlushing;
-
////////////////////////////////////////////////////////////////////////////////////////
// End of Asynchronous callback definitions
////////////////////////////////////////////////////////////////////////////////////////
};
+class CTranslateOutPin : public COutPin {
+ /*List of GUIDS to be translated*/
+ const GUID tranlateGUIDS[2] = {
+ MFVideoFormat_H264,
+ MFVideoFormat_MJPG
+ };
+ // @@@@README : This is what the compressed media types will be translated into
+ const GUID translatedGUID = MFVideoFormat_NV12; // Translating to NV12
+public:
+ CTranslateOutPin(_In_ ULONG id = 0,
+ _In_opt_ CMultipinMft *pparent = NULL,
+ _In_ IKsControl* iksControl = NULL) : COutPin(id, pparent, iksControl)
+ {
+ SetUINT32(MF_SD_VIDEO_SPHERICAL, TRUE);
+ }
+ STDMETHOD(AddMediaType)(
+ _Inout_ DWORD *pos,
+ _In_ IMFMediaType *pMediatype);
+ STDMETHOD_(BOOL, IsMediaTypeSupported)(
+ _In_ IMFMediaType *pMediaType,
+ _When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_)
+ IMFMediaType **ppIMFMediaTypeFull);
+protected:
+
+ map<IMFMediaType*, IMFMediaType*> m_TranslatedMediaTypes;
+};
+
diff --git a/avstream/sampledevicemft/common.h b/avstream/sampledevicemft/common.h
index d32ec618..72242fa3 100644
--- a/avstream/sampledevicemft/common.h
+++ b/avstream/sampledevicemft/common.h
@@ -97,6 +97,16 @@ DEFINE_GUID(AVSTREAM_CUSTOM_PIN_IMAGE,
#define WPP_CHECKHRGOTO_EXP_LABEL_ENABLED(HR, label) WPP_CHECK_LEVEL_ENABLED( DMFT_INIT, TP_ERROR )
+// Give it checkhr and checknull definitions if some future generations of visual studio remove the wpp processor support
+
+//#if !defined DMFTCHECKHR_GOTO
+//#define DMFTCHECKHR_GOTO(a,b) {hr=(a); if(FAILED(hr)){goto b;}}
+//#endif
+//
+//#if !defined DMFTCHECKNULL_GOTO
+//#define DMFTCHECKNULL_GOTO(a,b,c) {if(!a) {hr = c; goto b;}}
+//#endif
+
#define SAFE_ADDREF(p) if( NULL != p ) { ( p )->AddRef(); }
#define SAFE_DELETE(p) delete p; p = NULL;
#define SAFE_SHUTDELETE(p) if( NULL != p ) { ( p )->Shutdown(); delete p; p = NULL; }
@@ -107,6 +117,7 @@ DEFINE_GUID(AVSTREAM_CUSTOM_PIN_IMAGE,
#define SAFE_SYSFREESTRING(p) SysFreeString( p ); p = NULL;
#define SAFE_ARRAYDELETE(p) delete [] p; p = NULL;
#define SAFE_BYTEARRAYDELETE(p) delete [] (BYTE*) p; p = NULL;
+#define SAFE_CLOSEHANDLE(h) { if(INVALID_HANDLE_VALUE != (h)) { ::CloseHandle(h); (h) = INVALID_HANDLE_VALUE; } }
#define SAFERELEASE(x) \
@@ -212,12 +223,12 @@ public:
-typedef enum _MF_TRANSFORM_XVP_OPERATION{
- DeviceMftTransformXVPDisruptiveIn, //Break the XVP tranform and go to the new Media Type
- DeviceMftTransformXVPDisruptiveOut, //Keep the old transform
- DeviceMftTransformXVPCurrent, //Don't need an XVP
- DeviceMftTransformXVPIllegal //Either of the media types NULL, Major types don't match
-}MF_TRANSFORM_XVP_OPERATION,*PMF_TRANSFORM_XVP_OPERATION;
+typedef enum _DMFT_conversion_type{
+ DeviceMftTransformTypeXVP, // Need an XVP
+ DeviceMftTransformTypeDecoder, // Need a Decoder
+ DeviceMftTransformTypeEqual, // No op.. The media types are equal
+ 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;
@@ -233,13 +244,9 @@ STDMETHODIMP IsOptimizedPlanarVideoInputImageOutputPair(
_Out_ bool *optimizedxvpneeded
);
-STDMETHODIMP CompareMediaTypesForXVP(_In_opt_ IMFMediaType *inMediaType,
+STDMETHODIMP CompareMediaTypesForConverter(_In_opt_ IMFMediaType *inMediaType,
_In_ IMFMediaType *newMediaType,
- _Inout_ MF_TRANSFORM_XVP_OPERATION *operation
- );
-
-STDMETHODIMP RandomnizeMediaTypes(
- _In_ IMFMediaTypeArray &pMediaTypeArray
+ _Inout_ PDMFT_conversion_type operation
);
HRESULT IsInputDxSample(
@@ -533,11 +540,11 @@ class VideoBufferLock
public:
VideoBufferLock(IMFMediaBuffer *pBuffer)
{
- m_pBuffer = pBuffer;
+ m_spBuffer = pBuffer;
// Query for the 2-D buffer interface. OK if this fails.
- if (FAILED(m_pBuffer->QueryInterface(IID_PPV_ARGS(m_p2DBuffer2.GetAddressOf()))))
+ if (FAILED(m_spBuffer->QueryInterface(IID_PPV_ARGS(m_sp2DBuffer2.GetAddressOf()))))
{
- m_pBuffer->QueryInterface(IID_PPV_ARGS(m_p2DBuffer.GetAddressOf()));
+ m_spBuffer->QueryInterface(IID_PPV_ARGS(m_sp2DBuffer.GetAddressOf()));
}
}
~VideoBufferLock()
@@ -562,11 +569,11 @@ public:
{
HRESULT hr = S_OK;
// Use the 2-D version if available.
- if (m_p2DBuffer2)
+ if (m_sp2DBuffer2)
{
BYTE *pbBufferStart = NULL;
MF2DBuffer_LockFlags Flags = (Read == TRUE) ? MF2DBuffer_LockFlags_Read : MF2DBuffer_LockFlags_Write;
- hr = m_p2DBuffer2->Lock2DSize(
+ hr = m_sp2DBuffer2->Lock2DSize(
Flags,
ppbScanLine0,
plStride,
@@ -576,15 +583,15 @@ public:
{
hr = E_FAIL;
}
- } else if (m_p2DBuffer)
+ } else if (m_sp2DBuffer)
{
- hr = m_p2DBuffer->Lock2D(ppbScanLine0, plStride);
+ hr = m_sp2DBuffer->Lock2D(ppbScanLine0, plStride);
}
else
{
// Use non-2D version.
BYTE *pData = NULL;
- hr = m_pBuffer->Lock(&pData, NULL, NULL);
+ hr = m_spBuffer->Lock(&pData, NULL, NULL);
if (SUCCEEDED(hr))
{
*plStride = lDefaultStride;
@@ -606,21 +613,61 @@ public:
}
HRESULT UnlockBuffer()
{
- if (m_p2DBuffer2.Get())
+ if (m_sp2DBuffer2.Get())
{
- return m_p2DBuffer2->Unlock2D();
+ return m_sp2DBuffer2->Unlock2D();
}
- else if (m_p2DBuffer.Get())
+ else if (m_sp2DBuffer.Get())
{
- return m_p2DBuffer->Unlock2D();
+ return m_sp2DBuffer->Unlock2D();
}
else
{
- return m_pBuffer->Unlock();
+ return m_spBuffer->Unlock();
}
}
private:
- ComPtr<IMFMediaBuffer> m_pBuffer;
- ComPtr<IMF2DBuffer> m_p2DBuffer;
- ComPtr<IMF2DBuffer2> m_p2DBuffer2;
+ ComPtr<IMFMediaBuffer> m_spBuffer;
+ ComPtr<IMF2DBuffer> m_sp2DBuffer;
+ ComPtr<IMF2DBuffer2> m_sp2DBuffer2;
};
+
+// Decoding and Allocator specific
+HRESULT CreateDecoderHW( _In_ IMFDXGIDeviceManager* pManager,
+ _In_ IMFMediaType* inType,
+ _In_ IMFMediaType* outType,
+ _Outptr_ IMFTransform** ppTransform,
+ _Inout_ BOOL&);
+
+HRESULT EnumSWDecoder( _Outptr_ IMFTransform** ppTransform,
+ _In_ GUID subType);
+
+HRESULT SetDX11BindFlags( _In_ IUnknown *pUnkManager,
+ _In_ GUID guidPinCategory,
+ _Inout_ DWORD &dwBindFlags);
+
+HRESULT IsDXFormatSupported(
+ _In_ IMFDXGIDeviceManager* pDeviceManager,
+ _In_ GUID subType,
+ _Outptr_opt_ ID3D11Device** ppDevice,
+ _In_opt_ PUINT32 pSupportedFormat);
+
+HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
+ _In_ GUID streamCategory,
+ _In_ IUnknown* pDeviceManagerUnk,
+ _In_ BOOL &isDxAllocator,
+ _Outptr_ IMFVideoSampleAllocatorEx** ppAllocator);
+
+HRESULT GetDXGIAdapterLuid( _In_ IMFDXGIDeviceManager *pDXManager,
+ _Out_ LUID *pAdapterLuid);
+
+HRESULT MergeSampleAttributes(_In_ IMFSample* pInSample, _Inout_ IMFSample* pOutSample);
+
+HRESULT CheckPassthroughMediaType( _In_ IMFMediaType *pMediaType1,
+ _In_ IMFMediaType *pMediaType2,
+ _Out_ BOOL& pfPassThrough);
+//
+// Internal attribute
+//
+EXTERN_GUID(MF_SA_D3D11_SHARED_WITH_NTHANDLE_PRIVATE, 0xb18f1ad, 0xe8c6, 0x4804, 0xb7, 0x70, 0x15, 0x69, 0xdd, 0xc4, 0xbf, 0xe8);
+
diff --git a/avstream/sampledevicemft/multipinmft.cpp b/avstream/sampledevicemft/multipinmft.cpp
index 5a3bb933..3467870b 100644
--- a/avstream/sampledevicemft/multipinmft.cpp
+++ b/avstream/sampledevicemft/multipinmft.cpp
@@ -24,11 +24,15 @@ CMultipinMft::CMultipinMft()
m_lWorkQueuePriority ( 0 ),
m_spAttributes( nullptr ),
m_spSourceTransform( nullptr ),
- m_filterInWarmStart(false)
+ m_SymbolicLink(nullptr)
#if defined (MF_DEVICEMFT_PHTOTOCONFIRMATION)
, m_spPhotoConfirmationCallback(nullptr)
, m_firePhotoConfirmation(FALSE)
#endif
+#if defined (MF_DEVICEMFT_WARMSTART_HANDLING)
+ , m_dwWarmStartMask(0)
+#endif
+
{
HRESULT hr = S_OK;
ComPtr<IMFAttributes> pAttributes = nullptr;
@@ -62,6 +66,7 @@ CMultipinMft::~CMultipinMft( )
SAFERELEASE(m_OutPins[ ulIndex ]);
}
m_OutPins.clear();
+ SAFE_ARRAYDELETE(m_SymbolicLink);
m_spSourceTransform = nullptr;
}
@@ -157,9 +162,10 @@ done:
--*/
-// This Sample will create a grayscale for known media types. Please remove MF_DEVICEMFT_ADD_GRAYSCALER_ to remove the grayscaler
+// This sample will create a grayscale for known media types. Please remove MF_DEVICEMFT_ADD_GRAYSCALER_ to remove the grayscaler
// This sample also has photo confirmation enabled remove DMF_DEVICEMFT_PHTOTOCONFIRMATION to remove photo confirmation
-
+// Please search for the @@@@ README tag for critical sections in code and it's documentation
+//
STDMETHODIMP CMultipinMft::InitializeTransform (
_In_ IMFAttributes *pAttributes
)
@@ -172,7 +178,8 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
GUID* outGuids = NULL;
GUID streamCategory = GUID_NULL;
ULONG ulOutPinIndex = 0;
- CPinCreationFactory* pPinFactory = new CPinCreationFactory(this);
+ UINT32 uiSymLinkLen = 0;
+ CPinCreationFactory* pPinFactory = new (std::nothrow) CPinCreationFactory(this);
DMFTCHECKNULL_GOTO( pAttributes, done, E_INVALIDARG );
//
// The attribute passed with MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL is the source transform. This generally represents a filter
@@ -181,6 +188,13 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
//
DMFTCHECKHR_GOTO( pAttributes->GetUnknown( MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL,IID_PPV_ARGS( &spFilterUnk ) ),done );
+ if (SUCCEEDED(pAttributes->GetStringLength(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &uiSymLinkLen))) // Not available prior to RS5
+ {
+ m_SymbolicLink = new (std::nothrow) WCHAR[++uiSymLinkLen];
+ DMFTCHECKNULL_GOTO(m_SymbolicLink, done, E_OUTOFMEMORY);
+ DMFTCHECKHR_GOTO(pAttributes->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, m_SymbolicLink, uiSymLinkLen, &uiSymLinkLen), done);
+ }
+
DMFTCHECKHR_GOTO( spFilterUnk.As( &m_spSourceTransform ), done );
DMFTCHECKHR_GOTO( m_spSourceTransform.As( &m_spIkscontrol ), done );
@@ -196,10 +210,10 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
if ( inputStreams > 0 || outputStreams > 0 )
{
- pcInputStreams = new DWORD[ inputStreams ];
+ pcInputStreams = new (std::nothrow) DWORD[ inputStreams ];
DMFTCHECKNULL_GOTO( pcInputStreams, done, E_OUTOFMEMORY);
- pcOutputStreams = new DWORD[ outputStreams ];
+ pcOutputStreams = new (std::nothrow) DWORD[ outputStreams ];
DMFTCHECKNULL_GOTO( pcOutputStreams, done, E_OUTOFMEMORY );
DMFTCHECKHR_GOTO( m_spSourceTransform->MFTGetStreamIDs( inputStreams, pcInputStreams,
@@ -214,25 +228,25 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
{
ComPtr<IMFAttributes> pInAttributes = nullptr;
BOOL bCustom = FALSE;
- CInPin *pInPin = nullptr;
+ ComPtr<CInPin> spInPin;
DMFTCHECKHR_GOTO(pPinFactory->CreatePin(
pcOutputStreams[ulIndex], /*Input Pin ID as advertised by the pipeline*/
0, /*This is not needed for Input Pin*/
CPinCreationFactory::DMFT_PIN_INPUT, /*Input Pin*/
- (CBasePin**)&pInPin,
+ (CBasePin**)spInPin.GetAddressOf(),
bCustom), done);
if (bCustom)
{
m_CustomPinCount++;
}
- hr = ExceptionBoundary([this,pInPin]()
+ hr = ExceptionBoundary([&]()
{
- m_InPins.push_back(pInPin);
+ m_InPins.push_back(spInPin.Get());
});
DMFTCHECKHR_GOTO(hr, done);
- DMFTCHECKHR_GOTO( pInPin->Init(m_spSourceTransform.Get() ), done);
- pInPin->AddRef();
+ DMFTCHECKHR_GOTO( spInPin->Init(m_spSourceTransform.Get() ), done);
+ spInPin.Detach();
}
//
@@ -241,14 +255,14 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
for (ULONG ulIndex = 0; ulIndex < m_InPins.size(); ulIndex++)
{
- COutPin *poPin = nullptr;
+ ComPtr<COutPin> spoPin;
BOOL bCustom = FALSE;
- CInPin *piPin = ( CInPin * )m_InPins[ ulIndex ];
+ ComPtr<CInPin> spiPin = ( CInPin * )m_InPins[ ulIndex ];
- if (piPin)
+ if (spiPin.Get())
{
BOOL isCustom = false;
- if ( SUCCEEDED( CheckCustomPin( piPin, &isCustom )) && ( isCustom ) )
+ if (SUCCEEDED(CheckCustomPin(spiPin.Get(), &isCustom)) && (isCustom))
{
//
// In this sample we are not connecting the custom pin to the output
@@ -260,27 +274,36 @@ STDMETHODIMP CMultipinMft::InitializeTransform (
continue;
}
- DMFTCHECKHR_GOTO(pPinFactory->CreatePin(piPin->streamId(), /*Input Pin connected to the Output Pin*/
- ulOutPinIndex, /*Output pin Id*/
- CPinCreationFactory::DMFT_PIN_OUTPUT, /*Output pin */
- (CBasePin**)&poPin,
- bCustom), done);
- DMFTCHECKHR_GOTO(BridgeInputPinOutputPin(piPin, poPin), done);
+ DMFTCHECKHR_GOTO(pPinFactory->CreatePin(spiPin->streamId(), /*Input Pin connected to the Output Pin*/
+ ulOutPinIndex, /*Output pin Id*/
+ CPinCreationFactory::DMFT_PIN_OUTPUT, /*Output pin */
+ (CBasePin**)spoPin.ReleaseAndGetAddressOf(),
+ bCustom), done);
+ hr = BridgeInputPinOutputPin(spiPin.Get(), spoPin.Get());
+ if (SUCCEEDED(hr))
+ {
DMFTCHECKHR_GOTO(ExceptionBoundary([&]()
{
- m_OutPins.push_back(poPin);
- }),done);
- poPin->AddRef();
+ m_OutPins.push_back(spoPin.Get());
+ }), done);
+ spoPin.Detach();
ulOutPinIndex++;
+ hr = S_OK;
}
- }
+ if (hr == MF_E_INVALID_STREAM_DATA)
+ {
+ // Skip the pin which doesn't have any mediatypes exposed
+ hr = S_OK;
+ }
+ DMFTCHECKHR_GOTO(hr, done);
+ }
+ }
}
m_InputPinCount = ULONG ( m_InPins.size() );
m_OutputPinCount = ULONG ( m_OutPins.size() );
-
done:
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!",hr,hr);
@@ -300,24 +323,21 @@ done:
if ( FAILED( hr ) )
{
//Release the pins and the resources acquired
- while ( m_InPins.size() > 0 )
+ for (ULONG ulIndex = 0, ulSize = (ULONG)m_InPins.size(); ulIndex < ulSize; ulIndex++)
{
- CInPin *pInPin = nullptr;
- pInPin = ( CInPin* )m_InPins.back();
- m_InPins.pop_back();
- SAFERELEASE( pInPin );
+ SAFERELEASE(m_InPins[ulIndex]);
}
- while ( m_OutPins.size() > 0 )
+ m_InPins.clear();
+ for (ULONG ulIndex = 0, ulSize = (ULONG)m_OutPins.size(); ulIndex < ulSize; ulIndex++)
{
- COutPin *pin = nullptr;
- pin = ( COutPin* )m_OutPins.back();
- m_OutPins.pop_back();
- SAFERELEASE( pin );
+ SAFERELEASE(m_OutPins[ulIndex]);
}
+ m_OutPins.clear();
//
// Simply clear the custom pins since the input pins must have deleted the pin
//
m_spSourceTransform = nullptr;
+ m_spIkscontrol = nullptr;
}
return hr;
}
@@ -336,10 +356,19 @@ STDMETHODIMP CMultipinMft::SetWorkQueueEx(
{
CAutoLock lock( m_critSec );
//
- // Cache the WorkQueuId and WorkItemBasePriority
+ // Cache the WorkQueuId and WorkItemBasePriority. This is called once soon after the device MFT is initialized
//
m_dwWorkQueueId = dwWorkQueueId;
m_lWorkQueuePriority = lWorkItemBasePriority;
+ // Set it on the pins
+ for (DWORD dwIndex = 0; dwIndex < (DWORD)m_InPins.size(); dwIndex++)
+ {
+ m_InPins[dwIndex]->SetWorkQueue(dwWorkQueueId);
+ }
+ for (DWORD dwIndex = 0; dwIndex < (DWORD)m_OutPins.size(); dwIndex++)
+ {
+ m_OutPins[dwIndex]->SetWorkQueue(dwWorkQueueId);
+ }
return S_OK;
}
@@ -427,13 +456,13 @@ STDMETHODIMP CMultipinMft::GetInputAvailableType(
{
HRESULT hr = S_OK;
- CInPin *piPin = GetInPin( dwInputStreamID );
+ ComPtr<CInPin> spiPin = GetInPin( dwInputStreamID );
DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG);
- DMFTCHECKNULL_GOTO( piPin, done, MF_E_INVALIDSTREAMNUMBER );
+ DMFTCHECKNULL_GOTO( spiPin, done, MF_E_INVALIDSTREAMNUMBER );
*ppMediaType = nullptr;
- hr = piPin->GetOutputAvailableType( dwTypeIndex,ppMediaType );
+ hr = spiPin->GetOutputAvailableType( dwTypeIndex,ppMediaType );
if (FAILED(hr))
{
@@ -462,7 +491,8 @@ STDMETHODIMP CMultipinMft::GetOutputAvailableType(
--*/
{
HRESULT hr = S_OK;
-
+ CAutoLock Lock(m_critSec);
+
ComPtr<COutPin> spoPin = GetOutPin( dwOutputStreamID );
DMFTCHECKNULL_GOTO( spoPin.Get(), done, MF_E_INVALIDSTREAMNUMBER );
@@ -517,17 +547,18 @@ STDMETHODIMP CMultipinMft::GetOutputCurrentType(
--*/
{
HRESULT hr = S_OK;
+ ComPtr<COutPin> spoPin;
CAutoLock lock( m_critSec );
DMFTCHECKNULL_GOTO( ppMediaType, done, E_INVALIDARG );
*ppMediaType = nullptr;
- COutPin *poPin = GetOutPin( dwOutputStreamID );
+ spoPin = GetOutPin( dwOutputStreamID );
- DMFTCHECKNULL_GOTO( poPin, done, MF_E_INVALIDSTREAMNUMBER );
+ DMFTCHECKNULL_GOTO(spoPin, done, MF_E_INVALIDSTREAMNUMBER );
- DMFTCHECKHR_GOTO( poPin->getMediaType( ppMediaType ),done );
+ DMFTCHECKHR_GOTO(spoPin->getMediaType( ppMediaType ),done );
DMFTCHECKNULL_GOTO( *ppMediaType, done, MF_E_TRANSFORM_TYPE_NOT_SET );
@@ -623,6 +654,17 @@ STDMETHODIMP CMultipinMft::ProcessMessage(
hr = S_OK;
DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC!IDirect3DDeviceManager9 was not passed in");
}
+ //
+ // set it on the pins. Can happen anytime
+ //
+ for (DWORD dwIndex = 0; dwIndex < (DWORD)m_InPins.size(); dwIndex++)
+ {
+ m_InPins[dwIndex]->SetD3DManager(m_spDeviceManagerUnk.Get());
+ }
+ for (DWORD dwIndex = 0; dwIndex < (DWORD)m_OutPins.size(); dwIndex++)
+ {
+ m_OutPins[dwIndex]->SetD3DManager(m_spDeviceManagerUnk.Get());
+ }
}
break;
case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
@@ -674,18 +716,22 @@ STDMETHODIMP CMultipinMft::ProcessInput(
HRESULT hr = S_OK;
UNREFERENCED_PARAMETER( dwFlags );
- CInPin *inPin = GetInPin( dwInputStreamID );
- DMFTCHECKNULL_GOTO( inPin, done, MF_E_INVALIDSTREAMNUMBER);
+ ComPtr<CInPin> spInPin = GetInPin( dwInputStreamID );
+ DMFTCHECKNULL_GOTO(spInPin, done, MF_E_INVALIDSTREAMNUMBER);
if ( !IsStreaming() )
{
goto done;
}
- DMFTCHECKHR_GOTO( inPin->SendSample( pSample ), done );
+ DMFTCHECKHR_GOTO(spInPin->SendSample( pSample ), done );
done:
DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr );
- // Workaround A Bug in the pipeline which is incorrectly not releasing the sample
+ //
+ //@@@@ README : There is a bug in the sample that the device transform manager which manages the
+ // device MFT does not release the sample after passing it to Device MFT in processInput like it should. The
+ // Device MFT therefore unfortunately has to make sure that the sample that leaves processoutput has a reference count of 1
+ //
SAFE_RELEASE(pSample);
return hr;
@@ -709,6 +755,7 @@ output pins and populate the corresponding MFT_OUTPUT_DATA_BUFFER with the sampl
{
HRESULT hr = S_OK;
BOOL gotOne = false;
+ ComPtr<COutPin> spOpin;
UNREFERENCED_PARAMETER( dwFlags );
if (cOutputBufferCount > m_OutputPinCount )
@@ -720,26 +767,28 @@ output pins and populate the corresponding MFT_OUTPUT_DATA_BUFFER with the sampl
for ( DWORD i = 0; i < cOutputBufferCount; i++ )
{
DWORD dwStreamID = pOutputSamples[i].dwStreamID;
-
- COutPin *poPin = GetOutPin( dwStreamID );
- GUID pinGuid = GUID_NULL;
- DMFTCHECKNULL_GOTO( poPin, done, E_INVALIDARG );
-
- if ( SUCCEEDED( poPin->ProcessOutput( dwFlags, &pOutputSamples[i],
+ {
+ CAutoLock _lock(m_critSec);
+ spOpin = nullptr;
+ spOpin = GetOutPin(dwStreamID);
+ GUID pinGuid = GUID_NULL;
+ DMFTCHECKNULL_GOTO(spOpin.Get(), done, E_INVALIDARG);
+ }
+ if ( SUCCEEDED(spOpin->ProcessOutput( dwFlags, &pOutputSamples[i],
pdwStatus ) ) )
{
gotOne = true;
- // Do photo confirmation if enabled off the preview stream only
+ // Do photo confirmation if enabled from the preview stream only
#if defined (MF_DEVICEMFT_PHTOTOCONFIRMATION)
BOOL pIsPreviewPin = FALSE;
if (pOutputSamples[i].pSample &&
IsPhotoConfirmationEnabled() &&
- ((SUCCEEDED(CheckPreviewPin(static_cast<IMFAttributes*>(poPin), &pIsPreviewPin)) && pIsPreviewPin) &&
- InterlockedCompareExchange(reinterpret_cast<PLONG>(&m_firePhotoConfirmation),FALSE,TRUE)))
+ ((SUCCEEDED(CheckPreviewPin(static_cast<IMFAttributes*>(spOpin.Get()), &pIsPreviewPin)) && pIsPreviewPin) &&
+ InterlockedCompareExchange(reinterpret_cast<PLONG>(&m_firePhotoConfirmation), FALSE, TRUE)))
{
- // Please note photo confirmation should always be fired off the preview stream.
+ // Please note photo confirmation should always be fired from the preview stream.
ComPtr<IMFMediaType> spMediaType;
- if (SUCCEEDED(poPin->getMediaType(spMediaType.GetAddressOf())))
+ if (SUCCEEDED(spOpin->getMediaType(spMediaType.GetAddressOf())))
{
// Do Photo confirmation
ProcessCapturePhotoConfirmationCallBack(spMediaType.Get(), pOutputSamples[i].pSample);
@@ -772,15 +821,16 @@ STDMETHODIMP CMultipinMft::GetInputStreamAttributes(
--*/
{
HRESULT hr = S_OK;
+ ComPtr<CInPin> spIPin;
DMFTCHECKNULL_GOTO( ppAttributes, done, E_INVALIDARG );
*ppAttributes = nullptr;
- CInPin *piPin = GetInPin( dwInputStreamID );
+ spIPin = GetInPin( dwInputStreamID );
- DMFTCHECKNULL_GOTO( piPin, done, E_INVALIDARG );
+ DMFTCHECKNULL_GOTO(spIPin, done, E_INVALIDARG );
- hr = piPin->getPinAttributes(ppAttributes);
+ hr = spIPin->getPinAttributes(ppAttributes);
done:
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
@@ -800,15 +850,17 @@ STDMETHODIMP CMultipinMft::GetOutputStreamAttributes(
--*/
{
HRESULT hr = S_OK;
-
+ ComPtr<COutPin> spoPin;
+
DMFTCHECKNULL_GOTO(ppAttributes, done, E_INVALIDARG);
+
*ppAttributes = nullptr;
- COutPin *poPin = GetOutPin(dwOutputStreamID);
+ spoPin = GetOutPin(dwOutputStreamID);
- DMFTCHECKNULL_GOTO( poPin, done, E_INVALIDARG );
+ DMFTCHECKNULL_GOTO(spoPin, done, E_INVALIDARG );
- DMFTCHECKHR_GOTO( poPin->getPinAttributes(ppAttributes), done );
+ DMFTCHECKHR_GOTO(spoPin->getPinAttributes(ppAttributes), done );
done:
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
return hr;
@@ -835,10 +887,10 @@ STDMETHODIMP CMultipinMft::SetInputStreamState(
--*/
{
HRESULT hr = S_OK;
- CInPin *piPin = GetInPin(dwStreamID);
- DMFTCHECKNULL_GOTO(piPin, done, MF_E_INVALIDSTREAMNUMBER);
+ ComPtr<CInPin> spiPin = GetInPin(dwStreamID);
+ DMFTCHECKNULL_GOTO(spiPin, done, MF_E_INVALIDSTREAMNUMBER);
- DMFTCHECKHR_GOTO(piPin->SetInputStreamState(pMediaType, value, dwFlags),done);
+ DMFTCHECKHR_GOTO(spiPin->SetInputStreamState(pMediaType, value, dwFlags),done);
done:
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
@@ -911,10 +963,10 @@ STDMETHODIMP CMultipinMft::GetOutputStreamState(
HRESULT hr = S_OK;
CAutoLock lock(m_critSec);
- COutPin *poPin = GetOutPin(dwStreamID);
+ ComPtr<COutPin> spoPin = GetOutPin(dwStreamID);
DMFTCHECKNULL_GOTO(pState, done, E_INVALIDARG);
- DMFTCHECKNULL_GOTO(poPin, done, MF_E_INVALIDSTREAMNUMBER);
- *pState = poPin->GetState();
+ DMFTCHECKNULL_GOTO(spoPin, done, MF_E_INVALIDSTREAMNUMBER);
+ *pState = spoPin->GetState();
done:
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
return hr;
@@ -936,10 +988,10 @@ STDMETHODIMP CMultipinMft::GetInputStreamPreferredState(
--*/
{
HRESULT hr = S_OK;
- CInPin *piPin = GetInPin(dwStreamID);
+ ComPtr<CInPin> spiPin = GetInPin(dwStreamID);
DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG);
- DMFTCHECKNULL_GOTO(piPin, done, MF_E_INVALIDSTREAMNUMBER);
- hr = piPin->GetInputStreamPreferredState(value, ppMediaType);
+ DMFTCHECKNULL_GOTO(spiPin, done, MF_E_INVALIDSTREAMNUMBER);
+ hr = spiPin->GetInputStreamPreferredState(value, ppMediaType);
done:
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
return hr;
@@ -978,11 +1030,11 @@ STDMETHODIMP CMultipinMft::FlushOutputStream(
UNREFERENCED_PARAMETER(dwFlags);
CAutoLock Lock(m_critSec);
- COutPin *poPin = GetOutPin(dwStreamIndex);
- DMFTCHECKNULL_GOTO(poPin, done, E_INVALIDARG);
- DeviceStreamState oldState = poPin->SetState(DeviceStreamState_Disabled);
- DMFTCHECKHR_GOTO(poPin->FlushQueues(),done);
- poPin->SetState(oldState);
+ ComPtr<COutPin> spoPin = GetOutPin(dwStreamIndex);
+ DMFTCHECKNULL_GOTO(spoPin, done, E_INVALIDARG);
+ DeviceStreamState oldState = spoPin->SetState(DeviceStreamState_Disabled);
+ DMFTCHECKHR_GOTO(spoPin->FlushQueues(),done);
+ spoPin->SetState(oldState);
done:
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
return hr;
@@ -1003,13 +1055,13 @@ STDMETHODIMP_(VOID) CMultipinMft::FlushAllStreams(
CAutoLock Lock(m_critSec);
for ( DWORD dwIndex = 0, dwSize = (DWORD)m_OutPins.size(); dwIndex < dwSize; dwIndex++ )
{
- COutPin *poPin = (COutPin *)m_OutPins[dwIndex];
- oldState = poPin->SetState(DeviceStreamState_Disabled);
- poPin->FlushQueues();
+ ComPtr<COutPin> spoPin = (COutPin *)m_OutPins[dwIndex];
+ oldState = spoPin->SetState(DeviceStreamState_Disabled);
+ spoPin->FlushQueues();
//
//Restore state
//
- poPin->SetState(oldState);
+ spoPin->SetState(oldState);
}
}
@@ -1213,6 +1265,7 @@ STDMETHODIMP CMultipinMft::SetPixelFormat(
_In_ GUID subtype
)
{
+ CAutoLock Lock(m_critSec);
m_guidPhotoConfirmationSubtype = subtype;
return S_OK;
}
@@ -1220,6 +1273,7 @@ STDMETHODIMP CMultipinMft::GetPixelFormat(
_Out_ GUID* subtype
)
{
+ CAutoLock Lock(m_critSec);
*subtype = m_guidPhotoConfirmationSubtype;
return S_OK;
}
@@ -1249,7 +1303,7 @@ STDMETHODIMP CMultipinMft::GetAttributes(
)
{
HRESULT hr = S_OK;
-
+ CAutoLock Lock(m_critSec);
DMFTCHECKNULL_GOTO(ppAttributes, done, E_INVALIDARG);
*ppAttributes = nullptr;
@@ -1298,7 +1352,6 @@ COutPin* CMultipinMft::GetOutPin(
)
{
COutPin *outPin = NULL;
- CAutoLock Lock(m_critSec);
for ( DWORD dwIndex = 0, dwSize = (DWORD) m_OutPins.size(); dwIndex < dwSize; dwIndex++ )
{
outPin = ( COutPin * )m_OutPins[ dwIndex ];
@@ -1313,7 +1366,7 @@ COutPin* CMultipinMft::GetOutPin(
return outPin;
}
-
+_Requires_lock_held_(m_Critsec)
HRESULT CMultipinMft::GetConnectedInpin(_In_ ULONG ulOutpin, _Out_ ULONG &ulInPin)
{
HRESULT hr = S_OK;
@@ -1340,19 +1393,21 @@ HRESULT CMultipinMft::ChangeMediaTypeEx(
)
{
HRESULT hr = S_OK;
- COutPin *poPin = GetOutPin(pinId);
+ ComPtr<COutPin> spoPin = GetOutPin(pinId);
+ ComPtr<CInPin> spinPin;
DeviceStreamState oldOutPinState, oldInputStreamState, newOutStreamState, newRequestedInPinState;
ComPtr<IMFMediaType> pFullType, pInputMediaType;
ULONG ulInPinId = 0;
DWORD dwFlags = 0;
- DMFTCHECKNULL_GOTO(poPin, done, E_INVALIDARG);
+
+ DMFTCHECKNULL_GOTO(spoPin, done, E_INVALIDARG);
{
//
// dump the media types to the logs
//
ComPtr<IMFMediaType> spOldMediaType;
- (VOID)poPin->getMediaType(spOldMediaType.GetAddressOf());
+ (VOID)spoPin->getMediaType(spOldMediaType.GetAddressOf());
CMediaTypePrinter newType(pMediaType);
CMediaTypePrinter oldType(spOldMediaType.Get());
if (WPP_LEVEL_ENABLED(DMFT_GENERAL))
@@ -1361,22 +1416,23 @@ HRESULT CMultipinMft::ChangeMediaTypeEx(
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, " Pin:%d new MT:[%s] St:%d", pinId, newType.ToString(), reqState);
}
}
+
if (pMediaType)
{
- if (!poPin->IsMediaTypeSupported(pMediaType, &pFullType))
+ if (!spoPin->IsMediaTypeSupported(pMediaType, &pFullType))
{
DMFTCHECKHR_GOTO(MF_E_INVALIDMEDIATYPE, done);
}
}
DMFTCHECKHR_GOTO(GetConnectedInpin(pinId, ulInPinId), done);
- CInPin *pinPin = GetInPin(ulInPinId); // Get the input pin
+ spinPin = GetInPin(ulInPinId); // Get the input pin
- (VOID)pinPin->getMediaType(&pInputMediaType);
- oldInputStreamState = pinPin->SetState(DeviceStreamState_Disabled); // Disable input pin
- oldOutPinState = poPin->SetState(DeviceStreamState_Disabled); // Disable output pin
- (void)pinPin->FlushQueues(); // Flush the input queues
- (void)poPin->FlushQueues(); // Flush the output queues
+ (VOID)spinPin->getMediaType(&pInputMediaType);
+ oldInputStreamState = spinPin->SetState(DeviceStreamState_Disabled); // Disable input pin
+ oldOutPinState = spoPin->SetState(DeviceStreamState_Disabled); // Disable output pin
+ (void)spoPin->FlushQueues(); // Flush the output queues
+ (void)spinPin->FlushQueues(); // Flush the input queues
newOutStreamState = pinStateTransition[oldOutPinState][reqState]; // New state needed
// The Old input and the output pin states should be the same
@@ -1392,27 +1448,27 @@ HRESULT CMultipinMft::ChangeMediaTypeEx(
// underlying kernel pin
//
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "Changing Mediatype on the input ");
- pinPin->setPreferredMediaType(pFullType.Get());
- pinPin->setPreferredStreamState(newRequestedInPinState);
+ spinPin->setPreferredMediaType(pFullType.Get());
+ spinPin->setPreferredStreamState(newRequestedInPinState);
// Let the pipline know that the input needs to be changed.
- SendEventToManager(METransformInputStreamStateChanged, GUID_NULL, pinPin->streamId());
+ SendEventToManager(METransformInputStreamStateChanged, GUID_NULL, spinPin->streamId());
//
// The media type will be set on the input pin by the time we return from the wait
//
- DMFTCHECKHR_GOTO(pinPin->WaitForSetInputPinMediaChange(), done);
+ DMFTCHECKHR_GOTO(spinPin->WaitForSetInputPinMediaChange(), done);
// Change the media type on the output..
- DMFTCHECKHR_GOTO(poPin->ChangeMediaTypeFromInpin(pFullType.Get(), pFullType.Get(), reqState), done);
+ DMFTCHECKHR_GOTO(spoPin->ChangeMediaTypeFromInpin(pFullType.Get(), pMediaType , reqState), done);
//
// Notify the pipeline that the output stream media type has changed
//
- DMFTCHECKHR_GOTO(SendEventToManager(MEUnknown, MEDeviceStreamCreated, poPin->streamId()), done);
- poPin->SetFirstSample(TRUE);
+ DMFTCHECKHR_GOTO(SendEventToManager(MEUnknown, MEDeviceStreamCreated, spoPin->streamId()), done);
+ spoPin->SetFirstSample(TRUE);
}
else
{
// Restore back old states as we have nothing to do
- pinPin->SetState(oldInputStreamState);
- poPin->SetState(oldOutPinState);
+ spinPin->SetState(oldInputStreamState);
+ spoPin->SetState(oldOutPinState);
}
@@ -1471,11 +1527,12 @@ HRESULT CMultipinMft::BridgeInputPinOutputPin(
{
GUID subType = GUID_NULL;
DMFTCHECKHR_GOTO( pMediaType->GetGUID(MF_MT_SUBTYPE,&subType), done );
-
- if ( IsKnownUncompressedVideoType( subType ) )
{
- DMFTCHECKHR_GOTO( poPin->AddMediaType(NULL, pMediaType.Get() ), done );
- ulAddedMediaTypeCount++;
+ DMFTCHECKHR_GOTO(hr = poPin->AddMediaType(NULL, pMediaType.Get() ), done );
+ if (hr == S_OK)
+ {
+ ulAddedMediaTypeCount++;
+ }
}
pMediaType = nullptr;
@@ -1514,7 +1571,7 @@ done:
//
// Look at the below code only if we need to handle an extended property in Device MFT
//
-
+#if defined (MF_DEVICEMFT_WARMSTART_HANDLING)
HRESULT CMultipinMft::WarmStartHandler(
_In_ PKSPROPERTY Property,
_In_ ULONG ulPropertyLength,
@@ -1547,14 +1604,7 @@ HRESULT CMultipinMft::WarmStartHandler(
//Use the extended value to make changes to the property.. refer documentation
//PKSCAMERA_EXTENDEDPROP_VALUE pExtendedValue = (PKSCAMERA_EXTENDEDPROP_VALUE)(pPayload + sizeof(KSCAMERA_EXTENDEDPROP_HEADER));
//
- if ( pExtendedHeader->Flags & KSCAMERA_EXTENDEDPROP_WARMSTART_MODE_ENABLED )
- {
- m_filterInWarmStart = true;
- }
- else
- {
- m_filterInWarmStart = false;
- }
+ SetWarmStart(pExtendedHeader->PinId, (pExtendedHeader->Flags & KSCAMERA_EXTENDEDPROP_WARMSTART_MODE_ENABLED));
*pulBytesReturned = sizeof( PKSCAMERA_EXTENDEDPROP_HEADER )+sizeof( KSCAMERA_EXTENDEDPROP_VALUE );
m_eventHandler.SetOneShot(KSPROPERTY_CAMERACONTROL_EXTENDED_WARMSTART);
@@ -1586,7 +1636,8 @@ HRESULT CMultipinMft::WarmStartHandler(
pExtendedHeader->Capability = KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL | KSCAMERA_EXTENDEDPROP_WARMSTART_MODE_ENABLED;
pExtendedHeader->Flags = 0;
- if (m_filterInWarmStart)
+ if (GetWarmStart(pExtendedHeader->PinId))
+y
{
pExtendedHeader->Flags |= KSCAMERA_EXTENDEDPROP_WARMSTART_MODE_ENABLED;
}
@@ -1606,7 +1657,7 @@ done:
DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr );
return hr;
}
-
+#endif
//
// IMFShutdown interface functions
@@ -1630,6 +1681,12 @@ STDMETHODIMP CMultipinMft::Shutdown(
// Deref on the connected outpins to break reference loop
pInPin->ReleaseConnectedPins();
}
+#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES)
+ for (ULONG ulIndex = 0, ulSize = (ULONG)m_OutPins.size(); ulIndex < ulSize; ulIndex++)
+ {
+ (VOID) m_OutPins[ulIndex]->DeleteItem(MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT);
+ }
+#endif
return ShutdownEventGenerator();
}
diff --git a/avstream/sampledevicemft/multipinmft.h b/avstream/sampledevicemft/multipinmft.h
index b55a221a..080f4a7a 100644
--- a/avstream/sampledevicemft/multipinmft.h
+++ b/avstream/sampledevicemft/multipinmft.h
@@ -334,7 +334,7 @@ protected:
HRESULT BridgeInputPinOutputPin(
_In_ CInPin* pInPin,
_In_ COutPin* pOutPin);
-
+#if defined (MF_DEVICEMFT_WARMSTART_HANDLING)
HRESULT CMultipinMft::WarmStartHandler(
_In_ PKSPROPERTY Property,
_In_ ULONG ulPropertyLength,
@@ -342,6 +342,7 @@ protected:
_In_ ULONG ulOutputBufferLength,
_Inout_ PULONG pulBytesReturned
);
+#endif
#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES)
STDMETHODIMP CMultipinMft::GetAttributes(
_COM_Outptr_opt_result_maybenull_ IMFAttributes** ppAttributes
@@ -384,7 +385,6 @@ private:
CBasePinArray m_OutPins;
CBasePinArray m_InPins;
BOOL m_PhotoModeIsPhotoSequence; // used to store if the filter is in photo sequence or not
- BOOL m_filterInWarmStart; // Used to store if the filter is in warm start or not!
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
@@ -397,12 +397,24 @@ private:
ComPtr<IMFAttributes> m_spAttributes;
map<int, int> m_outputPinMap; // How output pins are connected to input pins i-><0..outpins>
CDMFTEventHandler m_eventHandler;
+ PWCHAR m_SymbolicLink;
#if defined (MF_DEVICEMFT_PHTOTOCONFIRMATION)
ComPtr<IMFAsyncCallback> m_spPhotoConfirmationCallback; //Photo Confirmation related definitions
GUID m_guidPhotoConfirmationSubtype;
BOOL m_firePhotoConfirmation;
#endif
+#if defined (MF_DEVICEMFT_WARMSTART_HANDLING)
+ VOID SetWarmStart(DWORD dwPinId, BOOL state)
+ {
+ m_dwWarmStartMask ^= (-state ^ m_dwWarmStartMask) & (1UL << dwPinId);
+ }
+ BOOLEAN GetWarmStart(_In_ DWORD dwPinId)
+ {
+ return ((m_dwWarmStartMask >> dwPinId) & 1UL);
+ }
+ DWORD m_dwWarmStartMask;
+#endif
};
diff --git a/avstream/sampledevicemft/multipinmfthelpers.cpp b/avstream/sampledevicemft/multipinmfthelpers.cpp
index 063fafca..904625ad 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.cpp
+++ b/avstream/sampledevicemft/multipinmfthelpers.cpp
@@ -4,26 +4,29 @@
#include "multipinmft.h"
#include "basepin.h"
#include <wincodec.h>
+#include <Codecapi.h>
#ifdef MF_WPP
#include "multipinmfthelpers.tmh" //--REF_ANALYZER_DONT_REMOVE--
#endif
-#define MF_DEVICEMFT_ASYNCPIN_NEEDED 1
-
class CMediaTypePrinter;
//
//Queue implementation
//
-
-CPinQueue::CPinQueue( _In_ DWORD dwPinId )
+CPinQueue::CPinQueue( _In_ DWORD dwPinId ,
+ _In_ IMFDeviceTransform* pParent)
: m_teer(0),
- m_dwInPinId(dwPinId)
+ m_dwInPinId(dwPinId),
+ m_pTransform(pParent),
+ m_cRef(1)
+
/*
Description
dwPinId is the input pin Id to which this queue corresponds
*/
{
+ m_streamCategory = GUID_NULL;
}
CPinQueue::~CPinQueue( )
{
@@ -41,6 +44,11 @@ STDMETHODIMP_(VOID) CPinQueue::InsertInternal( _In_ IMFSample *pSample )
m_sampleList.push_back(pSample);
});
+ if (SUCCEEDED(hr) && m_pTransform)
+ {
+ hr = reinterpret_cast<CMultipinMft*>(m_pTransform)->QueueEvent(METransformHaveOutput, GUID_NULL, S_OK, NULL);
+ }
+
if (FAILED(hr))
{
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
@@ -51,10 +59,10 @@ STDMETHODIMP_(VOID) CPinQueue::InsertInternal( _In_ IMFSample *pSample )
STDMETHODIMP CPinQueue::Insert( _In_ IMFSample *pSample )
//
-//m_teer is the wraptee.. this could be a null tee which is a passthrough, an xvp tee, which inserts an xvp into the queue
+//m_teer is the wraptee.. this could be a null tee which is a passthrough, an xvp tee which inserts an xvp into the queue etc
//
{
- return m_teer->PassThrough( pSample, this );
+ return m_teer->PassThrough( pSample );
}
/*++
@@ -85,7 +93,15 @@ Description:
--*/
VOID CPinQueue::Clear( )
{
-
+ //
+ // Stop the tees
+ // Execute Flush
+ //
+ if (m_teer)
+ {
+ m_teer->Stop();
+ }
+
while ( !Empty() )
{
ComPtr<IMFSample> spSample;
@@ -107,21 +123,32 @@ STDMETHODIMP CPinQueue::RecreateTee( _In_ IMFMediaType *inMediatype,
_In_opt_ IUnknown* punkManager )
{
HRESULT hr = S_OK;
- MF_TRANSFORM_XVP_OPERATION operation = DeviceMftTransformXVPIllegal;
+ DMFT_conversion_type operation = DeviceMftTransformTypeIllegal;
- SAFE_DELETE(m_teer);
+ SAFE_DELETE(m_teer); // Should release the reference
- CNullTee *nulltee = new (std::nothrow) CNullTee();
+ CNullTee *nulltee = new (std::nothrow) CNullTee(this);
DMFTCHECKNULL_GOTO( nulltee, done, E_OUTOFMEMORY);
- DMFTCHECKHR_GOTO( CompareMediaTypesForXVP(inMediatype, outMediatype, &operation), done);
+ DMFTCHECKHR_GOTO(CompareMediaTypesForConverter(inMediatype, outMediatype, &operation), done);
- if ( (operation != DeviceMftTransformXVPCurrent) && (operation!= DeviceMftTransformXVPIllegal) )
+ if (operation == DeviceMftTransformTypeDecoder)
{
- CXvptee* pXvptee = new (std::nothrow) CXvptee(nulltee);
+ // Decoder needed
+ CDecoderTee* pDecTee = new (std::nothrow) CDecoderTee(nulltee,
+ static_cast<CMultipinMft*>(m_pTransform)->GetQueueId(),
+ pinCategory());
+ DMFTCHECKNULL_GOTO(pDecTee, done, E_OUTOFMEMORY);
+ (void)pDecTee->SetD3DManager(punkManager);
+ DMFTCHECKHR_GOTO(pDecTee->SetMediaTypes(inMediatype, outMediatype),done);
+ m_teer = dynamic_cast<Ctee*>(pDecTee);
+ }
+ else if (operation == DeviceMftTransformTypeXVP)
+ {
+ CXvptee* pXvptee = new (std::nothrow) CXvptee(nulltee, pinCategory());
DMFTCHECKNULL_GOTO(pXvptee, done, E_OUTOFMEMORY);
(void)pXvptee->SetD3DManager( punkManager );
- (void)pXvptee->SetMediaTypes( inMediatype, outMediatype );
+ DMFTCHECKHR_GOTO(pXvptee->SetMediaTypes( inMediatype, outMediatype ),done);
m_teer = dynamic_cast< Ctee* >( pXvptee );
}
else
@@ -142,6 +169,7 @@ done:
}
return hr;
}
+
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatype,
_In_ IMFMediaType *outMediatype,
@@ -164,7 +192,7 @@ STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatyp
||IsEqualCLSID(gInputSubType, MFVideoFormat_RGB32))
{
CGrayTee *pTee = NULL;
- pTee = new CGrayTee(m_teer);
+ pTee = new (std::nothrow) CGrayTee(m_teer);
DMFTCHECKHR_GOTO(pTee->SetMediaTypes(inMediatype, outMediatype), done);
m_teer = dynamic_cast< Ctee* >(pTee);
}
@@ -182,12 +210,16 @@ Description:
This is the passthrough Tee in the literal sense i.e. It just dumps the sample
into the queue qupplied as an argument
--*/
-STDMETHODIMP CNullTee::PassThrough( _In_ IMFSample *pSample, _In_ CPinQueue *que )
+STDMETHODIMP CNullTee::PassThrough( _In_ IMFSample *pSample )
{
HRESULT hr = S_OK;
-
DMFTCHECKNULL_GOTO(pSample, done, S_OK); //No OP for a NULL Sample!!!
- (VOID)que->InsertInternal(pSample);
+ DMFTCHECKNULL_GOTO(m_Queue.Get(), done, E_UNEXPECTED); // State not set correctly
+ //
+ // @@@@ README: If there is a deocding operation that happens then the output samples will be here
+ // Any processing work like sticthing etc for 360 can happen here
+ //
+ m_Queue->InsertInternal(pSample);
done:
return hr;
@@ -200,17 +232,9 @@ Description:
--*/
STDMETHODIMP CWrapTee::SetMediaTypes( _In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType )
{
- HRESULT hr = S_OK;
- IMFTransform *pTransform = nullptr;
-
- DMFTCHECKHR_GOTO(Configure( pInMediaType, pOutMediaType, &pTransform ),done);
- m_videoProcessor = pTransform;
- m_pInputMediaType = pInMediaType;
+ m_pInputMediaType = pInMediaType;
m_pOutputMediaType = pOutMediaType;
-
-done:
- SAFE_RELEASE(pTransform);
- return hr;
+ return S_OK;
}
/*++
@@ -219,16 +243,31 @@ This is used when an XVP is present in the Pin. If the path is a passthrough i.e
the media type on the input and the output pins are the same then we will not see
this path traversed. This function feeds the sample to the XVP or the decoding Tee
--*/
-STDMETHODIMP CWrapTee::PassThrough(_In_ IMFSample* pInSample, _In_ CPinQueue *pQue)
+STDMETHODIMP CWrapTee::PassThrough( _In_ IMFSample* pInSample )
{
HRESULT hr = S_OK;
IMFSample* pOutSample = nullptr;
-
- DMFTCHECKHR_GOTO(Do(pInSample, &pOutSample),done);
+ bool newSample = false;
+ DMFTCHECKNULL_GOTO(pInSample, done, S_OK); // pass through for no sample
+ DMFTCHECKHR_GOTO(Do(pInSample, &pOutSample,newSample),done);
if (m_objectWrapped)
{
- hr = m_objectWrapped->PassThrough(pOutSample, pQue);
+ if (SUCCEEDED(hr = m_objectWrapped->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);
+ }
+ }
+
}
done:
@@ -240,138 +279,156 @@ done:
return hr;
}
-
-/*++
-CXvptee::Do
-Description:
-Called to do what an XVP is supposed to do i.e. scaling, resize etc.
-This function is called when the samples are desposited from the input pin to the
-output pin queue during a ProcessInput call on the device transform. Of course the
-outpin should be in Open state for the sample to reach the XVP and consequetively the
-Output Pin.
-
-If the DX manager is set on the Transform and we receieve a DX sample then we will
-undertake the DX transform in the XVP else we will skip it and go the software way
---*/
-STDMETHODIMP CXvptee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** pOutSample)
+STDMETHODIMP CVideoProcTee::StartStreaming()
{
+ return S_OK;
+}
+HRESULT CVideoProcTee::SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType)
+{
+ HRESULT hr = S_OK;
+ ComPtr<IMFTransform> spTransform;
+ DMFTCHECKHR_GOTO(CWrapTee::SetMediaTypes(pInMediaType, pOutMediaType),done);
+ DMFTCHECKHR_GOTO(Configure(pInMediaType, pOutMediaType, spTransform.GetAddressOf()), done);
+ m_videoProcessor = spTransform.Detach();
//
- //Since we are streaming in the software mode we will create a new sample
+ // Start streaming
//
- HRESULT hr = S_OK,pohr = S_OK;
- MFT_OUTPUT_DATA_BUFFER outputSample;
- MFT_OUTPUT_STREAM_INFO StreamInfo;
- ComPtr <IMFSample> spXVPOutputSample;
- ComPtr <IMFMediaType> spOutMediaType;
- ComPtr <IMFMediaBuffer> spIMFMediaBuffer;
- GUID guidOutputSubType = GUID_NULL;
-
- spOutMediaType.Attach(getOutMediaType());
-
- DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG);
-
- DMFTCHECKHR_GOTO(spOutMediaType->GetGUID(MF_MT_SUBTYPE, &guidOutputSubType), done);
-
- BOOL isDx = false;
+ DMFTCHECKHR_GOTO(StartStreaming(), done);
+done:
+ return hr;
+}
- if (SUCCEEDED(IsInputDxSample(pSample, &isDx)) && isDx)
+HRESULT CVideoProcTee::CreateAllocator()
+{
+ HRESULT hr = S_OK;
+ if (m_bProducesSamples)
{
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! DX Sample sent to XVP %p", pSample);
+ // Don't create the Allocator as Samples are created by the Encoder/ Decoder
+ return S_OK;
}
-
- outputSample.dwStreamID = 0;
- outputSample.pSample = NULL;
- if (!(isDx && m_spDeviceManagerUnk!=nullptr))
+ if (m_spAllocator.Get())
{
- //
- //Create a new sample for software encoding
- //
- DMFTCHECKHR_GOTO(MFCreateSample(&spXVPOutputSample), done);
+ // Release what we have currently
+ DMFTCHECKHR_GOTO(m_spAllocator->UninitializeSampleAllocator(), done);
+ m_spAllocator = nullptr;
+ }
- DMFTCHECKHR_GOTO(pSample->CopyAllItems(spXVPOutputSample.Get()), done);
+ DMFTCHECKHR_GOTO(::CreateAllocator(m_pOutputMediaType.Get(),
+ m_streamCategory, m_spDeviceManagerUnk.Get(),
+ m_fSetD3DManager,
+ m_spAllocator.GetAddressOf()), done);
+done:
+ return hr;
+}
- DMFTCHECKHR_GOTO(Transform()->MFTGetOutputStreamInfo(0, &StreamInfo), done);
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
+// @@@@ README: Video Processor functions below
+//
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
- if (!m_isOutPutImage)
- {
- DMFTCHECKHR_GOTO(MFGetAttributeSize(spOutMediaType.Get(), MF_MT_FRAME_SIZE, &m_uWidth, &m_uHeight), done);
- hr = MFCreate2DMediaBuffer(
- m_uWidth,
- m_uHeight,
- guidOutputSubType.Data1,
- FALSE, // top-down buffer (DX compatible)
- spIMFMediaBuffer.GetAddressOf());
- if (FAILED(hr))
- {
- DMFTCHECKHR_GOTO(MFCreateAlignedMemoryBuffer(
- StreamInfo.cbSize,
- StreamInfo.cbAlignment,
- spIMFMediaBuffer.GetAddressOf()), done);
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP Configured without DX, Created a 1D buffer");
+CXvptee::CXvptee(_In_ Ctee *tee, GUID category) :
+ CVideoProcTee(tee, category)
+{
- }
- else
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP Configured with DX, Created a 2D buffer");
- }
- DMFTCHECKHR_GOTO(spXVPOutputSample->AddBuffer(spIMFMediaBuffer.Get()), done);
+}
- outputSample.pSample = spXVPOutputSample.Detach();
- }
- }
- //
- //Start streaming the xvp transform..
- //
+CXvptee::~CXvptee()
+{
+ (VOID)StopStreaming();
+ m_spDeviceManagerUnk = nullptr;
+}
+
+HRESULT CXvptee::StartStreaming()
+{
+ HRESULT hr = S_OK;
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), done); // ulParam set to zero
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), done); // ulParam set to zero
+done:
+ return hr;
+}
+HRESULT CXvptee::StopStreaming()
+{
+ HRESULT hr = S_OK;
+ 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:
+ return hr;
+}
- DMFTCHECKHR_GOTO(Transform()->MFTProcessInput(0, pSample, 0),done);
+/*++
+CXvptee::Do
+Description:
+Called to do what an XVP is supposed to do i.e. scaling, resize etc.
+This function is called when the samples are desposited from the input pin to the
+output pin queue during a ProcessInput call on the device transform. Of course the
+outpin should be in Open state for the sample to reach the XVP and consequetively the
+Output Pin.
+--*/
+STDMETHODIMP CXvptee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample, _Inout_ bool &newSample)
+{
+ HRESULT hr = S_OK;
+ MFT_OUTPUT_DATA_BUFFER outputSample;
+ ComPtr <IMFSample> spXVPOutputSample;
DWORD dwStatus = 0;
- pohr = Transform()->MFTProcessOutput(0, 1, &outputSample, &dwStatus);
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP ProcessOutput Processing Sample =%p", pSample);
+ DMFTCHECKNULL_GOTO(ppOutSample, done, E_INVALIDARG);
- if (FAILED(pohr))
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP ProcessOutput,failure %x sample =%p", pohr, &outputSample);
- }
+ *ppOutSample = nullptr;
- 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
+ DMFTCHECKHR_GOTO(Transform()->MFTProcessInput(0, pSample, 0),done);
- spXVPOutputSample.Attach(outputSample.pSample);
+ outputSample.dwStreamID = 0;
+ outputSample.pSample = NULL;
+ DMFTCHECKHR_GOTO(m_spAllocator->AllocateSample(&outputSample.pSample), done);
+
+ hr = Transform()->MFTProcessOutput(0, 1, &outputSample, &dwStatus);
- if ( SUCCEEDED(pohr) )
+ if ( SUCCEEDED(hr) && pSample)
{
+ spXVPOutputSample.Attach(outputSample.pSample);
//Let us copy the timestamps
LONGLONG hnsSampleDuration = 0;
LONGLONG hnsSampleTime = 0;
+ DMFTCHECKHR_GOTO(MergeSampleAttributes(pSample, spXVPOutputSample.Get()), done);
- pSample->GetSampleDuration(&hnsSampleDuration);
- pSample->GetSampleTime(&hnsSampleTime);
- spXVPOutputSample->SetSampleDuration(hnsSampleDuration);
- spXVPOutputSample->SetSampleTime(hnsSampleTime);
- }
-
- *pOutSample = spXVPOutputSample.Detach();
-
+ if (SUCCEEDED(pSample->GetSampleDuration(&hnsSampleDuration)))
+ {
+ spXVPOutputSample->SetSampleDuration(hnsSampleDuration);
+ }
+ if (SUCCEEDED(pSample->GetSampleTime(&hnsSampleTime)))
+ {
+ spXVPOutputSample->SetSampleTime(hnsSampleTime);
+ }
+ }
+ else
+ {
+ SAFE_RELEASE(outputSample.pSample);
+ }
+
+ if (spXVPOutputSample.Get())
+ {
+ newSample = true;
+ *ppOutSample = spXVPOutputSample.Detach();
+ }
done:
- hr = FAILED(pohr) ? pohr : hr;
+ if (SUCCEEDED(hr))
+ {
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! [hr=0x%x Sample=%p] ", hr, *ppOutSample);
+ }
+ else
+ {
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! [Error hr=0x%x Sample=%p] ", hr, *ppOutSample);
+ }
return hr;
}
-/*++
-Description:
- Set the D3D Manager on the XVP
---*/
-STDMETHODIMP_(VOID) CXvptee::SetD3DManager( _In_opt_ IUnknown* pUnk)
-{
- m_spDeviceManagerUnk = pUnk;
-}
+
/*++
Descrtiption:
Create the XVP Transform with the media types supplied.
@@ -386,20 +443,9 @@ STDMETHODIMP CXvptee::Configure(
)
{
HRESULT hr = S_OK;
- GUID inMajorType = GUID_NULL;
- GUID outMajorType = GUID_NULL;
- bool imageType = false;
- bool optimized = false;
- bool optimizedxvpneeded = false;
- IMFMediaType *pXvpOutputMediaType = nullptr;
- ComPtr<IMFAttributes> pXvpTransformAttributes = nullptr;
- UINT32 width = 0, height = 0;
-
+ ComPtr<IMFAttributes> spXvpTransformAttributes = nullptr;
DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG);
- m_isOutPutImage = false;
- m_isoptimizedPlanarInputOutput = false;
-
//
//Print out the Media type set on the XVP
//
@@ -417,124 +463,609 @@ STDMETHODIMP CXvptee::Configure(
IID_PPV_ARGS(ppTransform)), done);
+ DMFTCHECKHR_GOTO((*ppTransform)->GetAttributes(spXvpTransformAttributes.GetAddressOf()),done);
+ DMFTCHECKHR_GOTO(spXvpTransformAttributes->SetUINT32(MF_XVP_DISABLE_FRC, TRUE),done);
+ // Use caller allocated memory.. We will create the allocator for the XVP
+ DMFTCHECKHR_GOTO(spXvpTransformAttributes->SetUINT32(MF_XVP_CALLER_ALLOCATES_OUTPUT, TRUE), done);
+ m_bProducesSamples = FALSE;
- DMFTCHECKHR_GOTO( inMediaType->GetMajorType( &inMajorType ),done );
- DMFTCHECKHR_GOTO( outMediaType->GetMajorType( &outMajorType ), done );
- //
- //Configuring DX Manager in SW mode.
- //
- if ( !IsEqualGUID(MFMediaType_Video, outMajorType ) )
- {
- imageType = true;
- m_isOutPutImage = true;
- IsOptimizedPlanarVideoInputImageOutputPair(
- inMediaType,
- outMediaType,
- &optimized,
- &optimizedxvpneeded );
- }
-
- //
- //Disable frame rate conversion
- //
- DMFTCHECKHR_GOTO((*ppTransform)->GetAttributes(&pXvpTransformAttributes),done);
- pXvpTransformAttributes->SetUINT32(MF_XVP_DISABLE_FRC, TRUE);
- DMFTCHECKHR_GOTO( (*ppTransform)->MFTProcessMessage( MFT_MESSAGE_SET_D3D_MANAGER, NULL ), done );
DMFTCHECKHR_GOTO((*ppTransform)->MFTSetInputType(0, inMediaType, 0), done);
-
- DMFTCHECKHR_GOTO(MFCreateMediaType(&pXvpOutputMediaType), done);
- DMFTCHECKHR_GOTO(outMediaType->CopyAllItems(pXvpOutputMediaType), done);
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), done); //Video propcessor doesn't understand image types
+ DMFTCHECKHR_GOTO((*ppTransform)->MFTSetOutputType(0, outMediaType, 0), done);
+
+ DMFTCHECKHR_GOTO(CreateAllocator(), done);
+
+ if (m_fSetD3DManager)
+ {
+ DMFTCHECKHR_GOTO((*ppTransform)->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast<UINT_PTR>(m_spDeviceManagerUnk.Get())), done);
+ }
+done:
+ return hr;
+
+}
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
+// @@@@ README: Decoder related functions below
+//
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
- if ( imageType )
+CDecoderTee::~CDecoderTee()
+{
+ (VOID)StopStreaming();
+ if (m_spAllocator)
{
- GUID guidSub;
+ m_spAllocator->UninitializeSampleAllocator();
+ m_spAllocator = nullptr;
+ }
+}
+
+HRESULT CDecoderTee::StartStreaming()
+{
+ HRESULT hr = S_OK;
+ DMFTCHECKNULL_GOTO(Transform(), done, MF_E_UNEXPECTED);
+ DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), done);
+ DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), done);
+ done:
+ return hr;
+}
- if ( !optimized )
+HRESULT CDecoderTee::StopStreaming()
+{
+ HRESULT hr = S_OK;
+ ComPtr<IMFTransform> spTransform = Transform();
+ {
+ CAutoLock Lock(&m_critSec);
+ if (m_hSyncHandle)
{
- DMFTCHECKHR_GOTO( inMediaType->GetGUID(MF_MT_SUBTYPE, &guidSub ), done );
- if ( IsEqualGUID( guidSub, MFVideoFormat_ARGB32 ) )
- {
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_ARGB32), done);
- }
- else
+ ResetEvent(m_hSyncHandle);
+ }
+ }
+ 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);
+ // Shut it down
+ if (SUCCEEDED(spTransform->QueryInterface(IID_PPV_ARGS(&spShutdown))))
+ {
+ (void)spShutdown->Shutdown();
+ }
+ m_critSec.Lock();
+ SetAsyncStatus(MF_E_SHUTDOWN);
+ MFUnlockWorkQueue(m_dwCameraStreamWorkQueueId);
+ if (m_ulProcessOutputsInFlight > 0)
+ {
+ m_critSec.Unlock();
+ WaitForSingleObject(m_hSyncHandle, INFINITE);
+
+ }
+ spTransform = nullptr;
+ }
+done:
+ return hr;
+}
+
+STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
+ _In_opt_ IMFMediaType *outType,
+ _Outptr_ IMFTransform** ppTransform)
+{
+ HRESULT hr = S_OK;
+ ComPtr<IMFTransform> spTransform;
+ GUID gInSubType = GUID_NULL, gOutSubType = GUID_NULL;
+ DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(inType, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(outType, done, E_INVALIDARG);
+ *ppTransform = nullptr;
+
+ SAFE_CLOSEHANDLE(m_hSyncHandle);
+ m_hSyncHandle = CreateEvent(NULL,
+ FALSE,
+ TRUE,
+ TEXT("SyncDecoderWaiter")
+ );
+ if (!(SUCCEEDED(inType->GetGUID(MF_MT_SUBTYPE, &gInSubType))
+ && SUCCEEDED(outType->GetGUID(MF_MT_SUBTYPE, &gOutSubType))))
+ {
+ DMFTCHECKHR_GOTO(E_UNEXPECTED, done);
+ }
+
+ DMFTCHECKHR_GOTO(MFAllocateSerialWorkQueue(m_dwQueueId, &m_dwCameraStreamWorkQueueId), done);
+
+ if (IsEqualCLSID(gInSubType, MFVideoFormat_H264) || (IsEqualCLSID(gInSubType, MFVideoFormat_MJPG)))
+ {
+ MFT_OUTPUT_STREAM_INFO outputStreamInfo;
+ if (SUCCEEDED(hr = CreateDecoderHW(
+ reinterpret_cast<IMFDXGIDeviceManager*>(m_spDeviceManagerUnk.Get()),
+ m_pInputMediaType.Get(),
+ m_pOutputMediaType.Get(),
+ spTransform.ReleaseAndGetAddressOf(), m_hwMFT)))
+ {
+ hr = ConfigDecoder(spTransform.Get(), gInSubType);
+ }
+ if (FAILED(hr))
+ {
+ // Try creating SW deocder
+ hr = S_OK;
+ DMFTCHECKHR_GOTO(EnumSWDecoder(spTransform.ReleaseAndGetAddressOf(), gInSubType), done);
+ DMFTCHECKHR_GOTO(ConfigDecoder(spTransform.Get(), gInSubType), done);
+ }
+ DMFTCHECKNULL_GOTO(spTransform.Get(), done, E_UNEXPECTED);
+
+ if (m_D3daware && SUCCEEDED(IsDXFormatSupported(reinterpret_cast<IMFDXGIDeviceManager*>(m_spDeviceManagerUnk.Get()), gOutSubType, nullptr, nullptr)))
+ {
+ DMFTCHECKHR_GOTO(spTransform->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)m_spDeviceManagerUnk.Get()), done);
+ }
+
+ DMFTCHECKHR_GOTO(spTransform->MFTGetOutputStreamInfo(m_dwMFTOutputId, &outputStreamInfo), done);
+
+ m_bProducesSamples = (outputStreamInfo.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES));
+
+ if (!m_bProducesSamples)
+ {
+ // Create own allocator as the decoder doesn't produce samples
+ DMFTCHECKHR_GOTO(CreateAllocator(), done); // Sets fsetd3dmanager
+ }
+
+ // Create a callback for processoutputs to be called on
+ m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke>(this);
+ DMFTCHECKNULL_GOTO(m_asyncCallback.Get(), done, E_OUTOFMEMORY);
+
+ if (m_fAsyncMFT)
+ {
+ ComPtr<IMFMediaEventGenerator> spGenerator;
+ if (SUCCEEDED(spTransform.As(&spGenerator)) && spGenerator.Get())
{
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), done);
+ // Start listening to decoder events
+ DMFTCHECKHR_GOTO(spGenerator->BeginGetEvent(m_asyncCallback.Get(), spGenerator.Get()), done);
}
- DMFTCHECKHR_GOTO(MFGetAttributeSize(pXvpOutputMediaType, MF_MT_FRAME_SIZE, &width, &height), done);
-
- m_uWidth = width;
- m_uHeight = height;
+ }
+ }
+ else
+ {
+ // We only support the H264 and MJPG decoding
+ DMFTCHECKHR_GOTO(MF_E_NOT_AVAILABLE, done);
+ }
+ *ppTransform = spTransform.Detach();
+done:
+ return hr;
+}
+
+
+STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **ppoutSample, _Inout_ bool &newSample)
+{
+ HRESULT hr = S_OK;
+ ComPtr<IMFSample> spOutputSample;
+ ComPtr<IMFTransform> spTransform = Transform();
+ newSample = false;
+ CAutoLock lock(m_critSec);
+ DMFTCHECKNULL_GOTO(ppoutSample, done, E_INVALIDARG);
+ *ppoutSample = nullptr;
+ DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
+
+ DMFTCHECKNULL_GOTO(spTransform, done, E_UNEXPECTED);
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetUINT32(MF_MT_DEFAULT_STRIDE, width * 4), done); //So we always get a top down buffer
+ if (!m_fAsyncMFT)
+ {
+ // Synchronous MFTs. Feed ProcessInputs till we get MF_E_NOTACCEPTING. Processoutputs on seperate thread
+ DMFTCHECKHR_GOTO(ExceptionBoundary([&]()
+ {
+ m_InputSampleList.push_front(pSample);
+ }),done);
- DMFTCHECKHR_GOTO((*ppTransform)->MFTSetOutputType(0, pXvpOutputMediaType, 0), done);
+ for (UINT32 uiIndex = (UINT32)m_InputSampleList.size(); uiIndex > 0; uiIndex--)
+ {
+ ComPtr<IMFSample> spInputSample;
+ spInputSample.Attach(m_InputSampleList[uiIndex-1].Get());
+ hr = spTransform->MFTProcessInput(m_dwMFTInputId, spInputSample.Get(), 0);
+ if (hr == MF_E_NOTACCEPTING)
+ {
+ spInputSample.Detach();
+ hr = S_OK;
+ // Queue a work item for process output
+ m_ulProcessOutputsInFlight++;
+ DMFTCHECKHR_GOTO(MFPutWorkItem(m_dwCameraStreamWorkQueueId, m_asyncCallback.Get(), nullptr), done);
+ break;
+ }
+ m_InputSampleList[uiIndex - 1].Detach();
+ DMFTCHECKHR_GOTO(hr, done);
+ m_InputSampleList.pop_back();
}
- else
+ DMFTCHECKHR_GOTO(hr, done);
+ }
+ else
+ {
+ // Asynchrnous mode. THE MFT asks for METransformNeedInput and we manage a count of processinputs . We feed it as
+ // much as it asks for.
+ UINT32 uiIndex = 0;
+
+ DMFTCHECKHR_GOTO(ExceptionBoundary([&]()
{
- //*** If we come here we know that the XVP is needed
- //This case should be for non planar and xvp needed cases which we will always assume
- LONG cStride = 0;
- //For now we will just assume that we need the xvp in all cases
- DMFTCHECKHR_GOTO( inMediaType->GetGUID(MF_MT_SUBTYPE, &guidSub ), done );
+ m_InputSampleList.push_front(pSample);
+ }), done);
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetGUID(MF_MT_SUBTYPE, guidSub), done);
+ if (m_lNeedInputRequest > 0)
+ {
+ for(uiIndex = (UINT32)m_InputSampleList.size(); (uiIndex > 0 && m_lNeedInputRequest > 0);uiIndex--)
+ {
+ ComPtr<IMFSample> spInputSample;
+ spInputSample.Attach(m_InputSampleList[uiIndex-1].Detach());
+ hr = spTransform->MFTProcessInput(0, spInputSample.Get(), 0);
+ if (FAILED(hr))
+ break;
+ m_InputSampleList.pop_back();
+ m_lNeedInputRequest--;
+ }
+ }
+ }
+done:
+ if (FAILED(hr))
+ {
+ SetAsyncStatus(hr);
+ }
+ return hr;
+}
- DMFTCHECKHR_GOTO(MFGetAttributeSize(pXvpOutputMediaType, MF_MT_FRAME_SIZE, &width, &height), done);
-
- DMFTCHECKHR_GOTO( MFGetStrideForBitmapInfoHeader( guidSub.Data1, width, &cStride ), done );
+//
+// Asynchronous callback for the decoder, if the decoder runs in asynchronous mode
+// This is serial since we give the eventgenerator a serial thread queue
+//
+HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
+{
+ HRESULT hr = S_OK;
+ HRESULT hrEventStatus = S_OK;
+ MediaEventType met = MEUnknown;
+ ComPtr<IMFMediaEventGenerator> spEventGenerator;
+ ComPtr<IMFMediaEvent> spEvent;
+ ComPtr<IMFTransform> spDecoderTemp;
+ ComPtr<IMFSample> spOutputSample;
+ BOOL bSendSample = FALSE;
+ CAutoLock lock(m_critSec);
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetUINT32(MF_MT_DEFAULT_STRIDE, cStride), done); //So we always get a top down buffer for Nv12/Yv12
+ spDecoderTemp = Transform();
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_0_255), done); //Always set nominal range to 0-255 to feed into a WIC encoder
+ DMFTCHECKNULL_GOTO(pResult, done, E_UNEXPECTED);
+ if (m_fAsyncMFT)
+ {
+
+ DMFTCHECKHR_GOTO(Transform()->QueryInterface(IID_PPV_ARGS(&spEventGenerator)), done);
+ DMFTCHECKHR_GOTO(spEventGenerator->EndGetEvent(pResult, &spEvent), done);
+ DMFTCHECKHR_GOTO(spEvent->GetType(&met), done);
+ DMFTCHECKHR_GOTO(spEvent->GetStatus(&hrEventStatus), done);
+ if (nullptr != spDecoderTemp)
+ {
+ DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
+ switch (met)
+ {
+ case MEError:
+ __fallthrough;
+ case MENonFatalError:
+ SetAsyncStatus(hrEventStatus);
+ break;
+ case METransformNeedInput:
+ m_lNeedInputRequest++;
+ break;
+ case METransformHaveOutput:
+ {
+ ComPtr<IMFSample> spDecodedSample;
+ m_critSec.Unlock();
+ //
+ // The processoutput call blocks for H264 sometimes. This call back is serialized
+ //
+ hr = ProcessOutputSync(spDecodedSample.GetAddressOf());
+ m_critSec.Lock();
+ // Did we error out when we released the lock?
+ DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
+ if (SUCCEEDED(hr))
+ {
+ bSendSample = TRUE;
+ spOutputSample.Attach(spDecodedSample.Detach());
+ }
+ else if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT)
+ {
+ SetAsyncStatus(hr);
+ DMFTCHECKHR_GOTO(hr, done);
+ }
+ hr = S_OK;
+ }
+ break;
+ default:
+ // All other events are simply discarded.
+ break;
+ }
- DMFTCHECKHR_GOTO((*ppTransform)->MFTSetOutputType(0, pXvpOutputMediaType, 0), done);
}
}
else
{
- DMFTCHECKHR_GOTO((*ppTransform)->MFTSetOutputType(0, outMediaType, 0), done);
+ // Synchronous mode. We only need it for processoutputs
+ ComPtr<IMFSample> spDecodedSample;
+ m_ulProcessOutputsInFlight--;
+ DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
+ DMFTCHECKNULL_GOTO(pResult, done, E_UNEXPECTED);
+ DMFTCHECKHR_GOTO(pResult->GetStatus(), done);
+ m_critSec.Unlock();
+ hr = ProcessOutputSync(spDecodedSample.GetAddressOf());
+ m_critSec.Lock();
+ if (SUCCEEDED(hr))
+ {
+ // send the sample on its way
+ bSendSample = TRUE;
+ spOutputSample.Attach(spDecodedSample.Detach());
+ }
+ else if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT)
+ {
+ SetAsyncStatus(hr);
+ }
+ hr = S_OK;
}
- if ((m_spDeviceManagerUnk != nullptr))
+done:
+ if(SUCCEEDED(hr))
{
+ if (bSendSample && spOutputSample.Get())
+ {
+
+ if (m_objectWrapped)
+ {
+ hr = m_objectWrapped->PassThrough(spOutputSample.Get());
+ spOutputSample = nullptr;
+ }
+ }
//
- //Set the D3D Manager on the XVP if present
+ // Keep listening for events
//
- DMFTCHECKHR_GOTO((*ppTransform)->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER,
- reinterpret_cast<ULONG_PTR>(m_spDeviceManagerUnk.Get())), done);
+ if (m_fAsyncMFT)
+ {
+ spEventGenerator->BeginGetEvent(m_asyncCallback.Get(), spEventGenerator.Get());
+ }
+ }
+ if (FAILED(hr))
+ {
+ SetAsyncStatus(hr);
+ }
+ if (m_StoppedAndWaiting)
+ {
+ // Stop is waiting on the threads to run
+ SetEvent(m_hSyncHandle);
}
-done:
- SAFE_RELEASE(pXvpOutputMediaType);
return hr;
+}
+//
+// @@@@README If the Allocator is created for a decoder and the pipeline
+// is holding on to the buffers, could be the xvp then this function will error
+// out the pipeline. you should see the ALLOCATOR_E_EMPTY error pop up
+//
+_Ret_maybenull_ HRESULT CDecoderTee::GetSample( IMFSample** ppSample )
+{
+ if (!m_bProducesSamples && m_spAllocator.Get())
+ {
+ return m_spAllocator->AllocateSample(ppSample);
+ }
+ return S_OK;
}
+HRESULT CDecoderTee::ConfigRealTimeMFT( _In_ IMFTransform* pTransform )
+{
+ DWORD dwTaskID = 0;
+ ComPtr<IMFRealTimeClientEx> spRTClientEx;
-CXvptee::CXvptee( _In_ Ctee *tee) :
-CWrapTee(tee),
- m_isOutPutImage(false),
- m_isoptimizedPlanarInputOutput(true),
- m_spDeviceManagerUnk(nullptr),
- m_uHeight(0),
- m_uWidth(0)
+ (void)MFGetWorkQueueMMCSSTaskId(m_dwQueueId, &dwTaskID);
+ // If MFT supports IMFRealTimeClientEx/IMFRealTimeClient, set workqueue on it.
+ (void)pTransform->QueryInterface(IID_PPV_ARGS(&spRTClientEx));
+ if (spRTClientEx != nullptr)
+ {
+ (void)spRTClientEx->SetWorkQueueEx(m_dwCameraStreamWorkQueueId, 0);
+ (void)spRTClientEx->RegisterThreadsEx(&dwTaskID, L"Capture", 0);
+ }
+ else
+ {
+ ComPtr<IMFRealTimeClient> spRTClient;
+
+ (void)pTransform->QueryInterface(IID_PPV_ARGS(&spRTClient));
+ if (spRTClient != nullptr)
+ {
+ (void)spRTClient->SetWorkQueue(m_dwCameraStreamWorkQueueId);
+ (void)spRTClient->RegisterThreads(dwTaskID, L"Capture");
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT CDecoderTee::ProcessFormatChange()
{
+ HRESULT hr = S_OK;
+ ComPtr<IMFMediaType> spDecoderOutputMediaType;
+ ComPtr<IMFTransform> spTransform = Transform();
+ DMFTCHECKNULL_GOTO(spTransform, done, E_UNEXPECTED);
+
+ if (FAILED(spTransform->MFTSetOutputType(m_dwMFTOutputId, m_pOutputMediaType.Get(), 0)))
+ {
+ GUID guidPreviousSubType = GUID_NULL;
+ //
+ // @@@@ Readme: An XVP will be needed here as the decoder doesn't like the output media type
+ // Also note, The platform doesn't support dynamic media type changes from the stream coming from the
+ // source.
+ //
+ ComPtr<IMFTransform> spXvp;
+ DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidPreviousSubType), done);
+
+ for (DWORD i = 0; ; i++)
+ {
+ GUID guidSubType = GUID_NULL;
+
+ hr = spTransform->MFTGetOutputAvailableType(m_dwMFTOutputId, i, spDecoderOutputMediaType.GetAddressOf());
+ if (MF_E_NO_MORE_TYPES == hr)
+ {
+ hr = S_OK;
+ break;
+ }
+ DMFTCHECKHR_GOTO(hr, done);
+ DMFTCHECKHR_GOTO(spDecoderOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubType), done);
+
+ if (IsEqualGUID(guidSubType, guidPreviousSubType))
+ {
+ break;
+ }
+ spDecoderOutputMediaType = nullptr;
+ }
+ DMFTCHECKNULL_GOTO(spDecoderOutputMediaType.Get(), done, MF_E_INVALIDMEDIATYPE);
+
+ DMFTCHECKHR_GOTO(spTransform->MFTSetOutputType(m_dwMFTOutputId, spDecoderOutputMediaType.Get(), 0), done);
+ //
+ // Create the XVP and insert it into the chain manually. set the output to the mediatype requested by the platform
+ //
+ CXvptee* pXvpTee = new (std::nothrow) CXvptee(m_objectWrapped ,m_streamCategory);
+ DMFTCHECKNULL_GOTO(pXvpTee, done, E_OUTOFMEMORY);
+ (VOID)pXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get());
+ DMFTCHECKHR_GOTO(pXvpTee->SetMediaTypes(spDecoderOutputMediaType.Get(), m_pOutputMediaType.Get()), done);
+ m_objectWrapped = pXvpTee;
+
+ spDecoderOutputMediaType = nullptr;
+
+ DMFTCHECKHR_GOTO(Transform()->MFTGetOutputCurrentType(m_dwMFTOutputId, spDecoderOutputMediaType.GetAddressOf()), done);
+
+ m_pOutputMediaType = spDecoderOutputMediaType;
+
+ //Recreate the Allocator
+ DMFTCHECKHR_GOTO(CreateAllocator(), done);
+ m_bXvpAdded = TRUE;
+ }
+done:
+ return hr;
}
+HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guidSubType )
+{
+ HRESULT hr = S_OK;
+ ComPtr<IMFAttributes> spMFTAttributes;
+ ComPtr<IMFMediaType> spMediaType;
+ GUID guidMajorType;
+ GUID guidSubtype;
+ DWORD dwMediaTypeIndex = 0;
+ UNREFERENCED_PARAMETER(guidSubType);
+ DMFTCHECKNULL_GOTO(pTransform, done, E_INVALIDARG);
-CXvptee::~CXvptee()
+ if (SUCCEEDED(pTransform->GetAttributes(spMFTAttributes.GetAddressOf())) &&
+ (nullptr != spMFTAttributes))
+ {
+ m_fAsyncMFT = (BOOL)MFGetAttributeUINT32(spMFTAttributes.Get(), MF_TRANSFORM_ASYNC, FALSE);
+ if (m_fAsyncMFT)
+ {
+ // if async MFT, unlock the Async MFT functionality
+ DMFTCHECKHR_GOTO(spMFTAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE), done);
+ }
+
+ if ((MFGetAttributeUINT32(spMFTAttributes.Get(), MF_SA_D3D11_AWARE, FALSE) != 0) ||
+ (MFGetAttributeUINT32(spMFTAttributes.Get(), MF_SA_D3D_AWARE, FALSE) != 0))
+ {
+ m_D3daware = TRUE;
+ }
+ }
+ if (IsEqualCLSID(guidSubType, MFVideoFormat_H264))
+ {
+ // H264 specific declarations
+ DMFTCHECKHR_GOTO(spMFTAttributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE), done);
+ }
+ (void)ConfigRealTimeMFT(pTransform);
+ (void)pTransform->MFTGetStreamIDs(1, &m_dwMFTInputId, 1, &m_dwMFTOutputId);
+
+ // Try to set input mediatype on MJPG decoder.
+ DMFTCHECKHR_GOTO(pTransform->MFTSetInputType(m_dwMFTInputId, m_pInputMediaType.Get(), 0), done);
+
+ // Find a matching output mediatype that has the same major/Subtype as pOutputType
+ DMFTCHECKHR_GOTO(m_pOutputMediaType->GetMajorType(&guidMajorType), done);
+ DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done);
+ while (SUCCEEDED(pTransform->MFTGetOutputAvailableType(m_dwMFTOutputId, dwMediaTypeIndex, &spMediaType)))
+ {
+ GUID guidMajorType2;
+ GUID guidSubtype2;
+
+ if (SUCCEEDED(spMediaType->GetMajorType(&guidMajorType2)) &&
+ IsEqualGUID(guidMajorType, guidMajorType2) &&
+ SUCCEEDED(spMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype2)) &&
+ IsEqualGUID(guidSubtype, guidSubtype2))
+ {
+ // Found the same major/subtype
+ break;
+ }
+
+ 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);
+done:
+ if (FAILED(hr))
+ {
+ m_fAsyncMFT = FALSE;
+ m_D3daware = FALSE;
+ }
+ return hr;
+}
+
+
+HRESULT CDecoderTee::ProcessOutputSync(_COM_Outptr_opt_ IMFSample** ppSample)
{
- m_spDeviceManagerUnk = nullptr;
+ HRESULT hr = S_OK;
+ ComPtr<IMFSample> spOutputSample;
+ DWORD dwStatus = 0;
+ MFT_OUTPUT_DATA_BUFFER opDataBuffer = {};
+ ComPtr<IMFTransform> spTransform = Transform();
+
+ DMFTCHECKNULL_GOTO(ppSample, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(spTransform, done, E_UNEXPECTED);
+ *ppSample = nullptr;
+
+ // Setup the output buffer
+ DMFTCHECKHR_GOTO(GetSample(spOutputSample.ReleaseAndGetAddressOf()), done); // Will fail if allocator empty.. keep up
+ opDataBuffer.dwStreamID = m_dwMFTOutputId;
+ opDataBuffer.pSample = spOutputSample.Detach();
+ hr = spTransform->MFTProcessOutput(0, 1, &opDataBuffer, &dwStatus);
+ if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
+ {
+ // Feed it more input, next time
+ SAFE_RELEASE(opDataBuffer.pSample);
+ goto done;
+ } else if ( hr == MF_E_TRANSFORM_STREAM_CHANGE )
+ {
+ SAFE_RELEASE(opDataBuffer.pSample)
+ DMFTCHECKHR_GOTO(ProcessFormatChange(), done);
+ // try feeding it a new sample again
+ DMFTCHECKHR_GOTO(GetSample(spOutputSample.ReleaseAndGetAddressOf()),done);
+ opDataBuffer.dwStreamID = m_dwMFTOutputId;
+ opDataBuffer.dwStatus = 0;
+ opDataBuffer.pSample = spOutputSample.Detach();
+
+ hr = spTransform->MFTProcessOutput(0, 1, &opDataBuffer, &dwStatus);
+ if (FAILED(hr))
+ {
+ // need more input
+ SAFE_RELEASE(opDataBuffer.pSample);
+ goto done;
+ }
+ }
+ if (SUCCEEDED(hr))
+ {
+ spOutputSample.Attach(opDataBuffer.pSample);
+ *ppSample = spOutputSample.Detach();
+ }
+ done:
+ return hr;
}
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
CGrayTee::CGrayTee(_In_ Ctee *tee) : CWrapTee(tee),m_transformfn(nullptr)
{
}
-STDMETHODIMP CGrayTee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample)
+STDMETHODIMP CGrayTee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample, _Inout_ bool &newSample)
{
HRESULT hr = S_OK;
ComPtr<IMFSample> spOutputSample;
@@ -597,7 +1128,11 @@ STDMETHODIMP CGrayTee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSam
DMFTCHECKHR_GOTO(spOutputSample->SetSampleTime(hnsTime), done);
}
}
- *ppOutSample = spOutputSample.Detach();
+ if (spOutputSample.Get())
+ {
+ newSample = true;
+ *ppOutSample = spOutputSample.Detach();
+ }
done:
return hr;
}
@@ -769,7 +1304,7 @@ HRESULT CDMFTEventHandler::KSEvent(
// and KSEVENTDATA with the same address as this call(pEvtdata). Hence store it
// To set the event all we need is the EVENT id.
//
- PDMFTEventEntry pEntry = new DMFTEventEntry(ulEventCommand, pEvtdata, evtHandle);
+ PDMFTEventEntry pEntry = new (std::nothrow) DMFTEventEntry(ulEventCommand, pEvtdata, evtHandle);
DMFTCHECKNULL_GOTO(pEntry, done, E_OUTOFMEMORY);
hr = ExceptionBoundary([&]()
{
@@ -976,49 +1511,60 @@ HRESULT CPinCreationFactory::CreatePin(_In_ ULONG ulInputStreamId, /* The Input
DMFTCHECKHR_GOTO(m_spDeviceTransform->Parent()->GetOutputStreamAttributes(ulInputStreamId, &spAttributes),done);
if (type == DMFT_PIN_INPUT)
{
- CInPin *pInPin = nullptr;
+ ComPtr<CInPin> spInPin;
DMFTCHECKHR_GOTO(spAttributes->GetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, &streamCategory), done);
// Create Cutom Pin
if (IsEqualCLSID(streamCategory, AVSTREAM_CUSTOM_PIN_IMAGE))
{
- pInPin = new CCustomPin(spAttributes.Get(), ulInputStreamId, static_cast<CMultipinMft*> (m_spDeviceTransform.Get()));
+ spInPin = new (std::nothrow) CCustomPin(spAttributes.Get(), ulInputStreamId, static_cast<CMultipinMft*> (m_spDeviceTransform.Get()));
isCustom = TRUE;
}
else
{
#if defined MF_DEVICEMFT_ASYNCPIN_NEEDED
- pInPin = new CAsyncInPin(spAttributes.Get(), ulInputStreamId, m_spDeviceTransform.Get()); // Asynchronous PIn, if you need it
+ spInPin = new (std::nothrow) CAsyncInPin(spAttributes.Get(), ulInputStreamId, m_spDeviceTransform.Get()); // Asynchronous PIn, if you need it
#else
- pInPin = new CInPin(spAttributes.Get(), ulInputStreamId, m_spDeviceTransform.Get());
+ spInPin = new (std::nothrow) CInPin(spAttributes.Get(), ulInputStreamId, m_spDeviceTransform.Get());
#endif
}
- DMFTCHECKNULL_GOTO(pInPin, done, E_OUTOFMEMORY);
- *ppPin = pInPin;
+ DMFTCHECKNULL_GOTO(spInPin.Get(), done, E_OUTOFMEMORY);
+ *ppPin = spInPin.Detach();
}
else if(type == DMFT_PIN_OUTPUT)
{
- COutPin* pOutPin = nullptr;
+ ComPtr<COutPin> spOutPin;
ComPtr<IKsControl> spKscontrol;
- CInPin* pInPin = nullptr;
+ ComPtr<CInPin> spInPin;
GUID pinGuid = GUID_NULL;
UINT32 uiFrameSourceType = 0;
- pInPin = static_cast<CInPin*>(m_spDeviceTransform->GetInPin(ulInputStreamId)); // Get the Input Pin connected to the Output pin
- DMFTCHECKNULL_GOTO(pInPin, done, E_INVALIDARG);
- DMFTCHECKHR_GOTO(pInPin->QueryInterface(IID_PPV_ARGS(spKscontrol.GetAddressOf())), done); // Grab the IKSControl off the input pin
- DMFTCHECKHR_GOTO(pInPin->GetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, &pinGuid), done); // Get the Stream Category. Advertise on the output pin
+ spInPin = static_cast<CInPin*>(m_spDeviceTransform->GetInPin(ulInputStreamId)); // Get the Input Pin connected to the Output pin
+ DMFTCHECKNULL_GOTO(spInPin.Get(), done, E_INVALIDARG);
+ DMFTCHECKHR_GOTO(spInPin.As(&spKscontrol), done); // Grab the IKSControl off the input pin
+ DMFTCHECKHR_GOTO(spInPin->GetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, &pinGuid), done); // Get the Stream Category. Advertise on the output pin
-
- pOutPin = new COutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()); // Create the output pin
- DMFTCHECKNULL_GOTO(pOutPin, done, E_OUTOFMEMORY);
+#if defined MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED
+ spOutPin = new (std::nothrow) CTranslateOutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()); // Create the output pin
+#else
+ spOutPin = new (std::nothrow) COutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()); // Create the output pin
+#endif
+ DMFTCHECKNULL_GOTO(spOutPin.Get(), done, E_OUTOFMEMORY);
- *ppPin = pOutPin;
- DMFTCHECKHR_GOTO(pOutPin->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, pinGuid), done); // Advertise the Stream category to the Pipeline
- DMFTCHECKHR_GOTO(pOutPin->SetUINT32(MF_DEVICESTREAM_STREAM_ID, ulOutStreamId), done); // Advertise the stream Id to the Pipeline
- if (SUCCEEDED(pInPin->GetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, &uiFrameSourceType)))
+ DMFTCHECKHR_GOTO(spOutPin->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, pinGuid), done); // Advertise the Stream category to the Pipeline
+ DMFTCHECKHR_GOTO(spOutPin->SetUINT32(MF_DEVICESTREAM_STREAM_ID, ulOutStreamId), done); // Advertise the stream Id to the Pipeline
+ //
+ // @@@@ README
+ // Note H264 pins are tagged MFFrameSourceTypes_Custom. Since we are decoding H264 if we enable decoding,
+ // lets change it to color, because we are producing an uncompressed format type, hence change it to
+ // MFFrameSourceTypes_Color, MFFrameSourceTypes_Infrared or MFFrameSourceTypes_Depth
+ //
+ if (SUCCEEDED(spInPin->GetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, &uiFrameSourceType)))
{
- DMFTCHECKHR_GOTO(pOutPin->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, uiFrameSourceType),done); // Copy over the Frame Source Type.
+#if defined MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED
+ uiFrameSourceType = (uiFrameSourceType == MFFrameSourceTypes_Custom) ? MFFrameSourceTypes_Color : uiFrameSourceType;
+#endif
+ DMFTCHECKHR_GOTO(spOutPin->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, uiFrameSourceType),done); // Copy over the Frame Source Type.
}
#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES)
@@ -1031,7 +1577,7 @@ HRESULT CPinCreationFactory::CreatePin(_In_ ULONG ulInputStreamId, /* The Input
//
GUID guidMFT0 = GUID_NULL;
- if (SUCCEEDED(pInPin->GetGUID(MF_DEVICESTREAM_EXTENSION_PLUGIN_CLSID, &guidMFT0)))
+ if (SUCCEEDED(spInPin->GetGUID(MF_DEVICESTREAM_EXTENSION_PLUGIN_CLSID, &guidMFT0)))
{
//
// This stream has an MFT0 .. Attach the GUID to the Outpin pin attribute
@@ -1039,13 +1585,14 @@ HRESULT CPinCreationFactory::CreatePin(_In_ ULONG ulInputStreamId, /* The Input
//
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! setting Mft0 guid on pin %d", ulOutStreamId);
- DMFTCHECKHR_GOTO(pOutPin->SetGUID(MF_DEVICESTREAM_EXTENSION_PLUGIN_CLSID, guidMFT0), done);
+ DMFTCHECKHR_GOTO(spOutPin->SetGUID(MF_DEVICESTREAM_EXTENSION_PLUGIN_CLSID, guidMFT0), done);
- DMFTCHECKHR_GOTO(pOutPin->SetUnknown(MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT,
+ DMFTCHECKHR_GOTO(spOutPin->SetUnknown(MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT,
static_cast< IUnknown* >(static_cast < IKsControl * >(m_spDeviceTransform.Get()))), done);
}
#endif
+ *ppPin = spOutPin.Detach();
}
else
{
diff --git a/avstream/sampledevicemft/multipinmfthelpers.h b/avstream/sampledevicemft/multipinmfthelpers.h
index 41472c85..bd3f0876 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.h
+++ b/avstream/sampledevicemft/multipinmfthelpers.h
@@ -8,6 +8,9 @@
#pragma once
#include "stdafx.h"
#include "common.h"
+#include <deque>
+using namespace std;
+#include <functional>
typedef void(*DMFT_IMAGE_TRANSFORM_FN)(
const RECT& rcDest, // Destination rectangle for the transformation.
@@ -25,9 +28,80 @@ class Ctee;
//typedef CMFAttributesTrace CMediaTypeTrace; /* Only used for debug. take this out*/
-class CPinQueue{
+template< typename T , HRESULT ( __stdcall T::*Func) ( IMFAsyncResult* ) >
+class CDMFTAsyncCallback : public IMFAsyncCallback
+{
public:
- CPinQueue(_In_ DWORD _inPinId);
+ CDMFTAsyncCallback( T* parent ) :
+ m_cRef(1),
+ m_Parent(parent)
+ { }
+ virtual ~CDMFTAsyncCallback() { }
+
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
+ {
+ HRESULT hr = S_OK;
+ if (ppv != nullptr)
+ {
+ *ppv = nullptr;
+ if (riid == __uuidof(IMFAsyncCallback) || riid == __uuidof(IUnknown))
+ {
+ AddRef();
+ *ppv = static_cast<IUnknown*>(this);
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ else
+ {
+ hr = E_POINTER;
+ }
+ return hr;
+ }
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+ STDMETHODIMP_(ULONG) Release()
+ {
+ long cRef = InterlockedDecrement(&m_cRef);
+ if (cRef == 0)
+ {
+ delete this;
+ }
+ return cRef;
+ }
+
+ STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
+ {
+ // Implementation of this method is optional.
+ UNREFERENCED_PARAMETER(pdwFlags);
+ UNREFERENCED_PARAMETER(pdwQueue);
+ return E_NOTIMPL;
+ }
+
+ STDMETHODIMP Invoke( IMFAsyncResult* pAsyncResult )
+ {
+ return (m_Parent->*Func)(pAsyncResult);
+ }
+ // TODO: Implement this method.
+
+ T GetParent()
+ {
+ return m_Parent;
+ }
+protected:
+ T* m_Parent; // Weak reference to the parent
+ long m_cRef;
+};
+
+
+class CPinQueue: public IUnknown{
+public:
+ CPinQueue(_In_ DWORD _inPinId, _In_ IMFDeviceTransform* pTransform=nullptr);
~CPinQueue();
STDMETHODIMP_(VOID) InsertInternal ( _In_ IMFSample *pSample = nullptr );
@@ -47,10 +121,63 @@ public:
{
return m_dwInPinId;
}
+ __inline GUID pinCategory()
+ {
+ if (IsEqualCLSID(m_streamCategory, GUID_NULL))
+ {
+ ComPtr<IMFAttributes> spAttributes;
+ if (SUCCEEDED(m_pTransform->GetOutputStreamAttributes(pinStreamId(), spAttributes.ReleaseAndGetAddressOf())))
+ {
+ (VOID)spAttributes->GetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, &m_streamCategory);
+
+ }
+ }
+ return m_streamCategory;
+ }
+
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
+ {
+ HRESULT hr = S_OK;
+ if (ppv != nullptr)
+ {
+ *ppv = nullptr;
+ if (riid == __uuidof(IUnknown))
+ {
+ AddRef();
+ *ppv = static_cast<IUnknown*>(this);
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ else
+ {
+ hr = E_POINTER;
+ }
+ return hr;
+ }
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+ STDMETHODIMP_(ULONG) Release()
+ {
+ long cRef = InterlockedDecrement(&m_cRef);
+ if (cRef == 0)
+ {
+ delete this;
+ }
+ return cRef;
+ }
private:
- DWORD m_dwInPinId; /*This is the input pin */
- IMFSampleList m_sampleList; /*List storing the samples */
+ 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:
Ctee* m_teer; /*Tee that acts as a passthrough or an XVP */
};
@@ -59,7 +186,7 @@ protected:
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
class CPinQueueWithGrayScale:public CPinQueue{
public:
- CPinQueueWithGrayScale(_In_ DWORD dwPinId) :CPinQueue(dwPinId)
+ CPinQueueWithGrayScale(_In_ DWORD dwPinId, _In_ IMFDeviceTransform* pParent) :CPinQueue(dwPinId,pParent)
{
}
STDMETHODIMP RecreateTee(_In_ IMFMediaType *inMediatype, _In_ IMFMediaType *outMediatype, _In_opt_ IUnknown* punkManager);
@@ -68,23 +195,35 @@ public:
//
// Define these in different components
// The below classes are used to add the
-// XVP and the Decoder components
+// XVP and the Decoder components.
//
class Ctee{
public:
- virtual STDMETHODIMP PassThrough( _In_ IMFSample *, _In_ CPinQueue * ) = 0;
+ STDMETHOD(Start)()
+ {
+ return S_OK;
+ }
+ STDMETHOD(Stop)()
+ {
+ return S_OK;
+ }
+ virtual STDMETHODIMP PassThrough( _In_ IMFSample * ) = 0;
};
class CNullTee:public Ctee{
public:
- STDMETHODIMP PassThrough( _In_ IMFSample*, _In_ CPinQueue * );
+ CNullTee(_In_ CPinQueue* q) :m_Queue(q) {}
+ STDMETHODIMP PassThrough( _In_ IMFSample* );
+protected:
+ // Store the queue here for simplicity
+ ComPtr<CPinQueue> m_Queue;
};
class CWrapTee : public Ctee{
public:
- CWrapTee(_In_ Ctee *tee=nullptr)
+ CWrapTee( _In_ Ctee *tee=nullptr )
: m_objectWrapped(tee)
, m_pInputMediaType(nullptr)
, m_pOutputMediaType(nullptr)
@@ -93,26 +232,19 @@ public:
}
virtual ~CWrapTee()=0
{
- m_videoProcessor = nullptr;
if (m_objectWrapped)
{
delete(m_objectWrapped);
}
}
-
- STDMETHODIMP PassThrough ( _In_ IMFSample*, _In_ CPinQueue * );
- virtual STDMETHODIMP Configure ( _In_ IMFMediaType *, _In_ IMFMediaType *, _Inout_ IMFTransform** ) = 0;
- virtual STDMETHODIMP Do ( _In_ IMFSample* pSample, _Out_ IMFSample ** ) = 0;
+ STDMETHODIMP PassThrough ( _In_ IMFSample* );
+ virtual STDMETHODIMP Do ( _In_ IMFSample* pSample, _Out_ IMFSample ** , _Inout_ bool &newSample) = 0;
STDMETHODIMP SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType);
-
//
- //Inline functions
+ // Inline functions
//
protected:
- __inline IMFTransform* Transform()
- {
- return m_videoProcessor.Get();
- }
+
__inline IMFMediaType* getInMediaType()
{
IMFMediaType* pmediaType = nullptr;
@@ -126,29 +258,137 @@ protected:
return pmediaType;
}
-private:
- ComPtr< IMFTransform > m_videoProcessor;
+protected:
+
ComPtr< IMFMediaType > m_pInputMediaType;
ComPtr< IMFMediaType > m_pOutputMediaType;
Ctee *m_objectWrapped;
};
+//
+// wrapper class for encoder and decoder
+//
+class CVideoProcTee: public CWrapTee
+{
+public:
+
+ CVideoProcTee( _In_ Ctee* p, _In_ GUID category = PINNAME_PREVIEW ) :CWrapTee(p)
+ , m_bProducesSamples(FALSE)
+ , m_streamCategory(category)
+ , m_fSetD3DManager(FALSE)
+ {}
+ __inline IMFTransform* Transform()
+ {
+ return m_videoProcessor.Get();
+ }
+
+ VOID SetD3DManager( _In_opt_ IUnknown* pUnk )
+ {
+ m_spDeviceManagerUnk = pUnk;
+ }
+ STDMETHODIMP SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType);
+ virtual STDMETHODIMP Configure(_In_ IMFMediaType *, _In_ IMFMediaType *, _Inout_ IMFTransform**) = 0;
+ STDMETHOD(CreateAllocator)();
+ STDMETHOD(Stop)()
+ {
+ HRESULT hr = S_OK;
+ if (SUCCEEDED(hr = StopStreaming()))
+ {
+ if (m_objectWrapped)
+ {
+ hr = m_objectWrapped->Stop();
+ }
+ }
+ return hr;
+ }
+protected:
+ STDMETHOD(StartStreaming)() = 0;
+ STDMETHOD(StopStreaming)() = 0;
+ ComPtr< IMFTransform > m_videoProcessor;
+ ComPtr<IUnknown> m_spDeviceManagerUnk;
+ ComPtr<IMFVideoSampleAllocatorEx> m_spAllocator;
+ BOOL m_bProducesSamples;
+ GUID m_streamCategory;
+ BOOL m_fSetD3DManager;
+};
-class CXvptee :public CWrapTee{
+class CXvptee :public CVideoProcTee{
public:
- CXvptee( _In_ Ctee * );
+ CXvptee( _In_ Ctee *, _In_ GUID category = PINNAME_PREVIEW );
~CXvptee();
- STDMETHODIMP Do ( _In_ IMFSample* pSample, _Outptr_ IMFSample ** );
+ STDMETHOD(StartStreaming)();
+ STDMETHOD(StopStreaming)();
+ STDMETHODIMP Do ( _In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
STDMETHODIMP Configure ( _In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform** );
- STDMETHODIMP_(VOID) SetD3DManager( _In_opt_ IUnknown* punk );
+};
+
+class CDecoderTee : public CVideoProcTee {
+public:
+
+ CDecoderTee(_In_ Ctee *t,_In_ DWORD dwQueueId,GUID category=PINNAME_PREVIEW) :
+ CVideoProcTee(t)
+ , m_fAsyncMFT(FALSE)
+ , m_D3daware(FALSE)
+ , m_hwMFT(FALSE)
+ , m_asyncCallback(nullptr)
+ , m_asyncHresult(S_OK)
+ , m_lNeedInputRequest(0)
+ , m_streamCategory(category)
+ , m_bXvpAdded(FALSE)
+ , m_dwMFTInputId(0)
+ , m_dwMFTOutputId(0)
+ , m_dwQueueId(dwQueueId)
+ ,m_dwCameraStreamWorkQueueId(0)
+ , m_ulProcessOutputsInFlight(0)
+ , m_hSyncHandle(INVALID_HANDLE_VALUE)
+ , m_StoppedAndWaiting(FALSE)
+ {
+ m_streamCategory = category;
+ }
+ ~CDecoderTee();
+
+ __inline VOID SetAsyncStatus( _In_ HRESULT hrStatus )
+ {
+ InterlockedCompareExchange(&m_asyncHresult, hrStatus, S_OK);
+ }
+ HRESULT GetAsyncStatus()
+ {
+ return InterlockedCompareExchange(&m_asyncHresult, S_OK, S_OK);
+ }
+
+ STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
+ STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
+ STDMETHODIMP Invoke(_In_ IMFAsyncResult*);
+protected:
+ STDMETHODIMP StartStreaming();
+ STDMETHODIMP StopStreaming();
+ _Ret_maybenull_ HRESULT CDecoderTee::GetSample( _Outptr_ IMFSample**);
+ HRESULT ConfigDecoder( _In_ IMFTransform* ,_In_ GUID guidSubType = GUID_NULL);
+ HRESULT ConfigRealTimeMFT(_In_ IMFTransform* );
+ HRESULT ProcessOutputSync( _COM_Outptr_opt_ IMFSample** );
+ HRESULT ProcessFormatChange();
+
+ BOOL m_fAsyncMFT;
+ BOOL m_D3daware;
+ BOOL m_hwMFT;
+ ComPtr<CDMFTAsyncCallback<CDecoderTee,&CDecoderTee::Invoke> > m_asyncCallback;
+ HRESULT m_asyncHresult;
+ DWORD m_lNeedInputRequest;
+ GUID m_streamCategory; // Needed for bind flags
+ BOOL m_bXvpAdded;
+ DWORD m_dwMFTInputId;
+ DWORD m_dwMFTOutputId;
+ ComPtr<IMFSample> m_spUnprocessedSample;
+ DWORD m_dwQueueId;
+ DWORD m_dwCameraStreamWorkQueueId;
+ CCritSec m_critSec;
+ std::deque<ComPtr<IMFSample> > m_InputSampleList;
+ ULONG m_ulProcessOutputsInFlight;
+ HANDLE m_hSyncHandle;
+ BOOL m_StoppedAndWaiting;
-private:
- BOOL m_isoptimizedPlanarInputOutput;
- BOOL m_isOutPutImage;
- UINT32 m_uWidth;
- UINT32 m_uHeight;
- ComPtr<IUnknown> m_spDeviceManagerUnk;
};
+
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
class CGrayTee : public CWrapTee {
public:
@@ -156,7 +396,7 @@ public:
~CGrayTee() {
}
- STDMETHODIMP Do(_In_ IMFSample* pSample, _Out_ IMFSample **);
+ STDMETHODIMP Do(_In_ IMFSample* pSample, _Out_ IMFSample **, , _Inout_ bool &newSample);
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/multipinmftutils.cpp b/avstream/sampledevicemft/multipinmftutils.cpp
index 737eb13f..d056b364 100644
--- a/avstream/sampledevicemft/multipinmftutils.cpp
+++ b/avstream/sampledevicemft/multipinmftutils.cpp
@@ -136,118 +136,43 @@ Description:
DeviceMftTransformXVPDisruptiveIn -> If the mediatype at the output pin is greater than the input pin. This will result in change of the media type on the input
DeviceMftTransformXVPDisruptiveOut -> This is a reconfiguration or addition of the XVP in the Output pin queue
DeviceMftTransformXVPCurrent -> No XVP needed at all
- Note: This iteration doesn't support decoder. The next one will and this function will accordingly change
*/
-STDMETHODIMP CompareMediaTypesForXVP(
+STDMETHODIMP CompareMediaTypesForConverter(
_In_opt_ IMFMediaType *inMediaType,
- _In_ IMFMediaType *newMediaType,
- _Inout_ MF_TRANSFORM_XVP_OPERATION *operation
+ _In_ IMFMediaType *newMediaType,
+ _Inout_ PDMFT_conversion_type operation
)
{
- UINT32 unWidthin, unHeightin, unWidthNew, unHeightNew = 0;
HRESULT hr = S_OK;
GUID guidTypeA = GUID_NULL;
GUID guidTypeB = GUID_NULL;
- *operation = DeviceMftTransformXVPIllegal;
+ *operation = DeviceMftTransformTypeIllegal;
if ((!inMediaType) || (!newMediaType))
{
goto done;
}
- DMFTCHECKHR_GOTO( MFGetAttributeSize( inMediaType, MF_MT_FRAME_SIZE, &unWidthin, &unHeightin ), done );
- DMFTCHECKHR_GOTO( MFGetAttributeSize( newMediaType, MF_MT_FRAME_SIZE, &unWidthNew, &unHeightNew ), done );
-
-
- if ( SUCCEEDED( inMediaType->GetGUID( MF_MT_MAJOR_TYPE, &guidTypeA ) ) &&
+ if ( SUCCEEDED( inMediaType->GetGUID( MF_MT_MAJOR_TYPE, &guidTypeA ) ) &&
SUCCEEDED( newMediaType->GetGUID( MF_MT_MAJOR_TYPE, &guidTypeB ) ) &&
IsEqualGUID( guidTypeA, guidTypeB ) )
{
- if ( SUCCEEDED( inMediaType->GetGUID ( MF_MT_SUBTYPE, &guidTypeA ) ) &&
- SUCCEEDED( newMediaType->GetGUID( MF_MT_SUBTYPE, &guidTypeB ) ) &&
- IsEqualGUID( guidTypeA, guidTypeB ) )
- {
- //Comparing the MF_MT_AM_FORMAT_TYPE for the directshow format guid
-#if 0
- if (SUCCEEDED(inMediaType->GetGUID(MF_MT_AM_FORMAT_TYPE, &guidTypeA)) &&
- SUCCEEDED(newMediaType->GetGUID(MF_MT_AM_FORMAT_TYPE, &guidTypeB)) &&
- IsEqualGUID(guidTypeA, guidTypeB))
-#endif
- {
-
- if (!(( unWidthin == unWidthNew ) &&
- ( unHeightin == unHeightNew ) ) )
- {
- if ( ( unWidthNew > unWidthin ) || ( unHeightNew > unHeightin ) )
- {
- *operation = DeviceMftTransformXVPDisruptiveIn; //Media type needs to change at input
- }
- else
- {
- *operation = DeviceMftTransformXVPDisruptiveOut; //Media type needs to change at output
- }
- goto done;
- }
-
- if ( MFGetAttributeUINT32( inMediaType, MF_MT_SAMPLE_SIZE, 0 ) !=
- MFGetAttributeUINT32( newMediaType, MF_MT_SAMPLE_SIZE, 0 ) )
- {
- hr = S_FALSE; //Sample sizes differ.
- goto done;
- }
- else
- {
- //Same media type.. No XVP needed or the current XVP is fine!
- *operation = DeviceMftTransformXVPCurrent;
- }
- }
- }
- else
- {
- //This is a disruptive operation. Actually a decoder operation!
- *operation = DeviceMftTransformXVPDisruptiveIn;
- }
- }
- done:
- return hr;
-}
-
-/*++
-Description:
- A Simple function to randomnize the media types supplied in an array
---*/
-STDMETHODIMP RandomnizeMediaTypes(_In_ IMFMediaTypeArray &pMediaTypeArray)
-{
- HRESULT hr = S_OK;
- IMFMediaType *pTempMediaType = nullptr;
- UNREFERENCED_PARAMETER(pTempMediaType);
- if (pMediaTypeArray.empty())
- {
- goto done;
- }
-
- srand(static_cast<unsigned long>(GetTickCount64()));
-
- for (DWORD dwIndex = (DWORD)pMediaTypeArray.size() - 1; dwIndex > 0; dwIndex--)
- {
- DWORD fromIndex = rand() % ( dwIndex + 1 );
- pTempMediaType = pMediaTypeArray[dwIndex];
- pMediaTypeArray [ dwIndex ] = pMediaTypeArray[fromIndex] ;
- pMediaTypeArray [ fromIndex ] = pTempMediaType;
- }
- //
- //Just reverse the array
- //
- for (DWORD dwIndex = (DWORD)pMediaTypeArray.size() - 1, fromIndex = 0; dwIndex > 0; dwIndex--, fromIndex++)
- {
-
- pTempMediaType = pMediaTypeArray[dwIndex];
- pMediaTypeArray [ dwIndex ] = pMediaTypeArray[fromIndex];
- pMediaTypeArray [ fromIndex ] = pTempMediaType;
- }
- done:
+ if ( SUCCEEDED( inMediaType->GetGUID ( MF_MT_SUBTYPE, &guidTypeA ) ) &&
+ SUCCEEDED( newMediaType->GetGUID( MF_MT_SUBTYPE, &guidTypeB ) ) &&
+ IsEqualGUID( guidTypeA, guidTypeB ) )
+ {
+ BOOL passThrough = TRUE;
+ DMFTCHECKHR_GOTO(CheckPassthroughMediaType(inMediaType, newMediaType, passThrough), done);
+ *operation = passThrough?DeviceMftTransformTypeEqual: DeviceMftTransformTypeXVP;
+ }
+ else
+ {
+ //This is a disruptive operation. Actually a decoder operation!
+ *operation = DeviceMftTransformTypeDecoder;
+ }
+ }
+ done:
return hr;
-
}
/*++
@@ -348,7 +273,7 @@ STDMETHODIMP_(BOOL) IsKnownUncompressedVideoType(_In_ GUID guidSubType)
if (a && strlen(a) > ((len * 7) / 10)){\
tStore = a; \
len *= 2; \
- a = new char[len]; \
+ a = new (std::nothrow) char[len]; \
if (!a){\
goto done;}\
a[0] = 0; \
@@ -372,10 +297,13 @@ LPSTR DumpGUIDA(_In_ REFGUID guid)
if (mbGuidLen > 0)
{
mf_assert(mbGuidLen == (int)wcslen(lpszGuidString));
- ansiguidStr = new char[mbGuidLen];
- WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpszGuidString, -1, ansiguidStr, mbGuidLen, NULL, NULL);
- CoTaskMemFree(lpszGuidString);
- ansiguidStr[mbGuidLen - 1] = 0;
+ ansiguidStr = new (std::nothrow) char[mbGuidLen];
+ if (ansiguidStr)
+ {
+ WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpszGuidString, -1, ansiguidStr, mbGuidLen, NULL, NULL);
+ CoTaskMemFree(lpszGuidString);
+ ansiguidStr[mbGuidLen - 1] = 0;
+ }
}
}
return ansiguidStr;
@@ -539,7 +467,7 @@ LPSTR DumpAttribute( _In_ const MF_ATTRIBUTE_TYPE& type,
_In_ REFPROPVARIANT var)
{
CHAR *tempStr = NULL;
- tempStr = new CHAR[256];
+ tempStr = new (std::nothrow) CHAR[256];
switch (type)
{
case MF_ATTRIBUTE_UINT32:
@@ -615,6 +543,7 @@ PCHAR CMediaTypePrinter::ToCompleteString( )
DMFTCHECKHR_GOTO(pMediaType->GetCount(&attrCount), done);
buffLen = MEDIAPRINTER_STARTLEN;
m_pBuffer = new char[buffLen];
+ DMFTCHECKNULL_GOTO(m_pBuffer, done, E_OUTOFMEMORY);
m_pBuffer[0] = 0;
for ( UINT32 ulIndex = 0; ulIndex < attrCount; ulIndex++ )
{
@@ -668,7 +597,8 @@ PCHAR CMediaTypePrinter::ToString()
if (pMediaType && !m_pBuffer)
{
buffLen = MEDIAPRINTER_STARTLEN;
- m_pBuffer = new char[buffLen];
+ m_pBuffer = new (std::nothrow) char[buffLen];
+ DMFTCHECKNULL_GOTO(m_pBuffer, done, E_OUTOFMEMORY);
m_pBuffer[0] = 0;
for (UINT32 ulIndex = 0; ulIndex < ARRAYSIZE(impGuids); ulIndex++)
{
@@ -1006,4 +936,586 @@ void TransformImage_RGB32(
}
}
-#endif \ No newline at end of file
+#endif
+
+HRESULT GetDXGIAdapterLuid(_In_ IMFDXGIDeviceManager *pDXManager, _Out_ LUID &AdapterLuid)
+{
+ HRESULT hr = S_OK;
+ ComPtr<ID3D11Device> spDevice;
+ ComPtr<IDXGIDevice> spDXGIDevice;
+ ComPtr<IDXGIAdapter> spDXGIAdapter;
+ DXGI_ADAPTER_DESC adapterDesc = { 0 };
+ HANDLE hDevice = NULL;
+
+ DMFTCHECKNULL_GOTO(pDXManager, done, E_INVALIDARG);
+
+ DMFTCHECKHR_GOTO(pDXManager->OpenDeviceHandle(&hDevice), done);
+ DMFTCHECKHR_GOTO(pDXManager->GetVideoService(hDevice, IID_PPV_ARGS(&spDevice)), done);
+ DMFTCHECKHR_GOTO(spDevice->QueryInterface(IID_PPV_ARGS(&spDXGIDevice)), done);
+ DMFTCHECKHR_GOTO(spDXGIDevice->GetAdapter(&spDXGIAdapter), done);
+ DMFTCHECKHR_GOTO(spDXGIAdapter->GetDesc(&adapterDesc), done);
+
+ CopyMemory(&AdapterLuid, &adapterDesc.AdapterLuid, sizeof(LUID));
+
+done:
+ if (NULL != hDevice)
+ {
+ pDXManager->CloseDeviceHandle(hDevice);
+ }
+
+ return hr;
+}
+
+HRESULT EnumSWDecoder(_Outptr_ IMFTransform** ppTransform, _In_ GUID subType)
+{
+ HRESULT hr = S_OK;
+ IMFActivate** ppActivate = nullptr;
+ UINT32 count = 0;
+ ComPtr<IMFTransform> spTransform;
+ LPWSTR pszFriendlyName = nullptr;
+
+ MFT_REGISTER_TYPE_INFO info = { MFMediaType_Video, subType };
+ UINT32 unFlags = MFT_ENUM_FLAG_SYNCMFT |
+ MFT_ENUM_FLAG_LOCALMFT |
+ MFT_ENUM_FLAG_SORTANDFILTER;
+
+ DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG);
+ *ppTransform = nullptr;
+
+ DMFTCHECKHR_GOTO(MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER, unFlags,
+ &info, // Input type
+ NULL, // Output type
+ &ppActivate,
+ &count
+ ), done);
+
+
+ if (count == 0)
+ {
+ DMFTCHECKHR_GOTO(MF_E_TOPO_CODEC_NOT_FOUND, done);
+ }
+
+ if (SUCCEEDED(MFGetAttributeString(ppActivate[0], MFT_FRIENDLY_NAME_Attribute, &pszFriendlyName)))
+ {
+ //
+ // Log the friendly name of the decoder
+ //
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! decoder name: %S ", (pszFriendlyName ? pszFriendlyName : L"UnknownCodec"));
+ SAFE_COTASKMEMFREE(pszFriendlyName);
+ }
+
+ DMFTCHECKHR_GOTO(ppActivate[0]->ActivateObject(IID_PPV_ARGS(spTransform.GetAddressOf())), done);
+
+ *ppTransform = spTransform.Detach();
+
+done:
+ if (ppActivate)
+ {
+ for (UINT32 uiIndex = 0; uiIndex < count; uiIndex++)
+ {
+ ppActivate[uiIndex]->Release();
+ }
+ CoTaskMemFree(ppActivate);
+ }
+ return hr;
+}
+//
+// @@@@ README Create the decoder
+//
+HRESULT CreateDecoderFromLuid( _In_ LUID ullAdapterLuidRunningOn,
+ _In_ IMFMediaType* pInputType,
+ _In_ IMFMediaType* pOutputType,
+ _Inout_ BOOL fHwMft,
+ _Outptr_ IMFTransform** ppDecoder)
+{
+ HRESULT hr = S_OK;
+ ComPtr<IMFAttributes> spAttribs;
+ ComPtr<IMFTransform> spMJPGDecoder;
+ IMFActivate **ppActivates = nullptr;
+ DWORD dwFlags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_SORTANDFILTER | MFT_ENUM_FLAG_HARDWARE | 0x10000000 /*Internal attribute*/;
+ UINT32 cMFTActivate = 0;
+ MFT_REGISTER_TYPE_INFO InputType;
+ MFT_REGISTER_TYPE_INFO OutputType;
+ GUID compressedGUID;
+ ComPtr<ID3D11Device> spD3D11Device;
+
+ fHwMft = FALSE;
+
+
+ DMFTCHECKNULL_GOTO(pInputType, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(pOutputType, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(ppDecoder, done, E_INVALIDARG);
+ *ppDecoder = nullptr;
+ DMFTCHECKHR_GOTO(pInputType->GetGUID(MF_MT_SUBTYPE, &compressedGUID), done);
+
+ InputType.guidMajorType = MFMediaType_Video;
+ InputType.guidSubtype = compressedGUID;
+
+ DMFTCHECKHR_GOTO(pOutputType->GetMajorType(&OutputType.guidMajorType), done);
+ DMFTCHECKHR_GOTO(pOutputType->GetGUID(MF_MT_SUBTYPE, &OutputType.guidSubtype), done);
+
+ DMFTCHECKHR_GOTO(MFCreateAttributes(&spAttribs, 1), done);
+ DMFTCHECKHR_GOTO(spAttribs->SetBlob(MFT_ENUM_ADAPTER_LUID, (byte*)&ullAdapterLuidRunningOn, sizeof(ullAdapterLuidRunningOn)), done);
+ DMFTCHECKHR_GOTO(MFTEnum2(MFT_CATEGORY_VIDEO_DECODER, dwFlags, &InputType, &OutputType, spAttribs.Get(), &ppActivates, &cMFTActivate), done);
+
+ for (DWORD i = 0; i < cMFTActivate; i++)
+ {
+ HRESULT hrTemp = ppActivates[i]->ActivateObject(IID_PPV_ARGS(spMJPGDecoder.GetAddressOf()));
+ fHwMft = (MFT_ENUM_FLAG_HARDWARE & MFGetAttributeUINT32(ppActivates[i], MF_TRANSFORM_FLAGS_Attribute, 0));
+ // Pickup the first MFT enumerated. Normally, it should be a HW MFT, if HWMFT is available.
+ if (SUCCEEDED(hrTemp))
+ {
+ break;
+ }
+ else
+ {
+ spMJPGDecoder = nullptr;
+ }
+ }
+ if (spMJPGDecoder == nullptr)
+ {
+ hr = MF_E_NOT_FOUND;
+ }
+ *ppDecoder = spMJPGDecoder.Detach();
+done:
+
+ for (UINT32 i = 0; i < cMFTActivate; i++)
+ {
+ if (nullptr != ppActivates[i])
+ {
+ ppActivates[i]->Release();
+ }
+ }
+ SAFE_COTASKMEMFREE(ppActivates);
+ return hr;
+}
+
+HRESULT SetDX11BindFlags( _In_ IUnknown *pUnkManager,
+ _In_ GUID guidPinCategory,
+ _Inout_ DWORD &dwBindFlags)
+{
+ HRESULT hr = S_OK;
+ ComPtr<IUnknown> spDeviceManager;
+ BOOL fFL10 = FALSE;
+
+ auto
+ IsFeatureLevel10OrBetter = [&]() -> BOOL
+ {
+ ComPtr<IMFDXGIDeviceManager> spDXGIManager;
+ ComPtr<ID3D11Device> spDevice;
+ HANDLE hDevice = 0;
+ BOOL fRet = FALSE;
+ UINT level = 0, result = 0;
+
+ if (SUCCEEDED(pUnkManager->QueryInterface(IID_PPV_ARGS(&spDXGIManager))) &&
+ SUCCEEDED(spDXGIManager->OpenDeviceHandle(&hDevice)) &&
+ SUCCEEDED(spDXGIManager->LockDevice(hDevice, IID_PPV_ARGS(&spDevice), FALSE)))
+ {
+
+ level = (UINT)spDevice->GetFeatureLevel();
+ fRet = (level >= D3D_FEATURE_LEVEL_10_0);
+ if (!fRet)
+ {
+ if (SUCCEEDED(spDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &result)))
+ {
+ fRet = (result & D3D11_FORMAT_SUPPORT_TEXTURE2D) && (result & D3D11_FORMAT_SUPPORT_RENDER_TARGET);
+ }
+ }
+ (void)spDXGIManager->UnlockDevice(hDevice, FALSE);
+ (void)spDXGIManager->CloseDeviceHandle(hDevice);
+ }
+ return fRet;
+ };
+
+ DMFTCHECKNULL_GOTO(pUnkManager, done, E_INVALIDARG);
+ fFL10 = IsFeatureLevel10OrBetter();
+
+ dwBindFlags |= fFL10 ? D3D11_BIND_SHADER_RESOURCE : 0;
+ dwBindFlags |= (guidPinCategory != PINNAME_VIDEO_PREVIEW) ? D3D11_BIND_VIDEO_ENCODER : 0;
+ if ((dwBindFlags != 0) && ((dwBindFlags & ~(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_VIDEO_ENCODER)) == 0))
+ {
+ dwBindFlags |= D3D11_BIND_RENDER_TARGET;
+ }
+done:
+ return hr;
+}
+
+// @@@@ README: Create the Decoder
+HRESULT CreateDecoderHW(_In_ IMFDXGIDeviceManager* pManager,
+ _In_ IMFMediaType* inType,
+ _In_ IMFMediaType* outType,
+ _Outptr_ IMFTransform** ppTransform,
+ _Inout_ BOOL& fHwMft)
+{
+ HRESULT hr = S_OK;
+ LUID luid;
+ ComPtr<IMFTransform> spTransform;
+ DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG);
+ *ppTransform = nullptr;
+
+ if (pManager)
+ {
+ if (SUCCEEDED(hr = GetDXGIAdapterLuid(pManager, luid)))
+ {
+ hr = CreateDecoderFromLuid(luid, inType, outType, fHwMft, spTransform.GetAddressOf());
+ if (FAILED(hr))
+ {
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Error creating HW Decoder with LUID %d-%d", luid.HighPart, luid.LowPart);
+ DMFTCHECKHR_GOTO(hr, done);
+ }
+ }
+ }
+ *ppTransform = spTransform.Detach();
+done:
+ return hr;
+}
+
+HRESULT
+SubtypeToDXGIFormat(
+ _In_ GUID subType,
+ _Inout_ DXGI_FORMAT &format
+)
+{
+ HRESULT hr = S_OK;
+ typedef struct {
+ GUID subType;
+ DXGI_FORMAT format;
+ }DXGIFormatMap;
+ DXGIFormatMap formatMap[]
+ {
+ { MFVideoFormat_NV12, DXGI_FORMAT_NV12 },
+ { MFVideoFormat_YUY2, DXGI_FORMAT_YUY2 },
+ { MFVideoFormat_RGB32, DXGI_FORMAT_B8G8R8X8_UNORM },
+ { MFVideoFormat_ARGB32, DXGI_FORMAT_B8G8R8A8_UNORM },
+ { MFVideoFormat_AYUV, DXGI_FORMAT_AYUV },
+ { MFVideoFormat_NV11, DXGI_FORMAT_NV11 },
+ { MFVideoFormat_AI44, DXGI_FORMAT_AI44 },
+ { MFVideoFormat_P010, DXGI_FORMAT_P010 },
+ { MFVideoFormat_P016, DXGI_FORMAT_P016 },
+ { MFVideoFormat_Y210, DXGI_FORMAT_Y210 },
+ { MFVideoFormat_Y216, DXGI_FORMAT_Y216 },
+ { MFVideoFormat_Y410, DXGI_FORMAT_Y410 },
+ { MFVideoFormat_Y416, DXGI_FORMAT_Y416 },
+ };
+ format = DXGI_FORMAT_UNKNOWN;
+ for (UINT32 uiIndex = 0; uiIndex < _countof(formatMap); uiIndex++)
+ {
+ if (formatMap[uiIndex].subType == subType)
+ {
+ format = formatMap[uiIndex].format;
+ break;
+ }
+ }
+ // compressed media type or unsupported of the range
+ hr = (format == DXGI_FORMAT_UNKNOWN) ? E_NOTIMPL : S_OK;
+ return hr;
+}
+
+HRESULT IsDXFormatSupported(
+ _In_ IMFDXGIDeviceManager* pDeviceManager ,
+ _In_ GUID subType,
+ _Outptr_opt_ ID3D11Device** ppDevice,
+ _In_opt_ PUINT32 pSupportedFormat)
+{
+ HRESULT hr = S_OK;
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+ UINT32 supportedFormat = 0;
+ HANDLE hDevice = NULL;
+ ComPtr<ID3D11Device> spDevice;
+ DMFTCHECKNULL_GOTO(pDeviceManager, done, E_INVALIDARG);
+ DMFTCHECKHR_GOTO(pDeviceManager->OpenDeviceHandle(&hDevice), done);
+ DMFTCHECKHR_GOTO(pDeviceManager->GetVideoService(hDevice, IID_PPV_ARGS(&spDevice)), done);
+ DMFTCHECKHR_GOTO(SubtypeToDXGIFormat(subType, format), done);
+ DMFTCHECKHR_GOTO(spDevice->CheckFormatSupport(format, &supportedFormat), done);
+ if (pSupportedFormat)
+ {
+ *pSupportedFormat = supportedFormat;
+ }
+ if (ppDevice)
+ {
+ *ppDevice = spDevice.Detach();
+ }
+done:
+ if (hDevice != NULL)
+ {
+ pDeviceManager->CloseDeviceHandle(hDevice);
+ }
+ return hr;
+}
+
+HRESULT
+UpdateAllocatorAttributes(
+ _In_ IMFAttributes *pAttributes,
+ _In_ REFGUID guidStreamCategory,
+ _In_ GUID subType,
+ _In_ IMFDXGIDeviceManager *pDeviceManager
+)
+{
+ HRESULT hr = S_OK;
+ UINT32 supportedFormat = 0;
+ ComPtr<ID3D11Device> spDevice;
+ DWORD dwBindFlags = 0;
+
+ DMFTCHECKHR_GOTO(IsDXFormatSupported(pDeviceManager,subType,
+ spDevice.GetAddressOf(),&supportedFormat),done);
+
+ // MF_SA_D3D11_USAGE should be D3D11_USAGE_DEFAULT, same as previous release.
+ DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_USAGE, D3D11_USAGE_DEFAULT), done);
+
+ DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_SHARED_WITHOUT_MUTEX, TRUE), done);
+ DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_SHARED_WITH_NTHANDLE_PRIVATE, TRUE), done);
+
+ // Bind Flags
+ dwBindFlags |= ((supportedFormat & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0 ? D3D11_BIND_RENDER_TARGET : 0);
+
+ if (((supportedFormat & D3D11_FORMAT_SUPPORT_VIDEO_ENCODER) != 0) &&
+ (!IsEqualGUID(guidStreamCategory, PINNAME_VIDEO_PREVIEW)) &&
+ IsEqualGUID(subType, MFVideoFormat_NV12))
+ {
+ D3D11_FEATURE_DATA_D3D11_OPTIONS4 Options = { 0 };
+
+ // "D3D11_BIND_VIDEO_ENCODER + sharing" is only supported on those devices that
+ // advertise ExtendedNV12SharedTextureSupported.
+ DMFTCHECKHR_GOTO(spDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS4, &Options, sizeof(Options)), done);
+ if (Options.ExtendedNV12SharedTextureSupported)
+ {
+ dwBindFlags |= D3D11_BIND_VIDEO_ENCODER;
+ }
+ }
+
+ // D3D requires one of the flags (D3D11_BIND_RENDER_TARGET, D3D11_PRIVATE_BIND_CAPTURE, or D3D11_BIND_VIDEO_ENCODER) to be set for non-zero bind flags.
+ if (dwBindFlags != 0)
+ {
+ D3D_FEATURE_LEVEL level;
+
+ // D3D11_BIND_SHADER_RESOURCE
+ level = spDevice->GetFeatureLevel();
+ dwBindFlags |= ((level >= D3D_FEATURE_LEVEL_10_0) ? D3D11_BIND_SHADER_RESOURCE : 0);
+ }
+
+ DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_BINDFLAGS, dwBindFlags), done);
+
+done:
+ return hr;
+}
+
+const UINT32 ALLOCATOR_MIN_SAMPLES = 10;
+const UINT32 ALLOCATOR_MAX_SAMPLES = 50;
+//
+//@@@@ README: Creating an Allocator.. Please don't allocate samples individually using MFCreateSample as that can lead to fragmentation and is
+// extremely inefficent. Instead create an Allocator which will create a fixed number of samples which are recycled when the pipeline returns back
+// the buffers. The above has defines will enable to create a circular allocator which will have maximum 20 samples flowing in the pipeline
+// This way we can also catch samples leaks if any.
+//
+HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
+ _In_ GUID streamCategory,
+ _In_ IUnknown* pDeviceManagerUnk,
+ _In_ BOOL &bDxAllocator,
+ _Outptr_ IMFVideoSampleAllocatorEx** ppAllocator )
+{
+ HRESULT hr = S_OK;
+ ComPtr<IMFVideoSampleAllocatorEx> spVideoSampleAllocator;
+ ComPtr<IMFAttributes> spAllocatorAttributes;
+ GUID guidMajorType = GUID_NULL;
+ GUID guidSubtype = GUID_NULL;
+ BOOL fDXAllocator = FALSE;
+
+ DMFTCHECKNULL_GOTO(ppAllocator, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(pOutputMediaType, done, E_INVALIDARG);
+ DMFTCHECKHR_GOTO(pOutputMediaType->GetMajorType(&guidMajorType), done);
+
+ *ppAllocator = nullptr;
+ if (!IsEqualGUID(guidMajorType, MFMediaType_Video))
+ {
+ DMFTCHECKHR_GOTO(MF_E_INVALIDMEDIATYPE, done);
+ }
+
+ DMFTCHECKHR_GOTO(pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done);
+ //
+ // Set Attributes on the allocator we need. First get the Bind Flags.
+ //
+ DMFTCHECKHR_GOTO(MFCreateAttributes(&spAllocatorAttributes, 8), done);
+ DMFTCHECKHR_GOTO(spAllocatorAttributes->SetUINT32(MF_SA_BUFFERS_PER_SAMPLE, 1), done);
+
+ if (pDeviceManagerUnk != nullptr)
+ {
+ if (SUCCEEDED(UpdateAllocatorAttributes(spAllocatorAttributes.Get(), streamCategory,guidSubtype, (IMFDXGIDeviceManager*)pDeviceManagerUnk)))
+ {
+ fDXAllocator = TRUE;
+ }
+ }
+ DMFTCHECKHR_GOTO(MFCreateVideoSampleAllocatorEx(IID_PPV_ARGS(spVideoSampleAllocator.ReleaseAndGetAddressOf())), done);
+ if (fDXAllocator)
+ {
+ DMFTCHECKHR_GOTO(spVideoSampleAllocator->SetDirectXManager(pDeviceManagerUnk), done);
+ }
+ DMFTCHECKHR_GOTO(spVideoSampleAllocator->InitializeSampleAllocatorEx(ALLOCATOR_MIN_SAMPLES, ALLOCATOR_MAX_SAMPLES, spAllocatorAttributes.Get(), pOutputMediaType), done);
+
+ *ppAllocator = spVideoSampleAllocator.Detach();
+ bDxAllocator = fDXAllocator;
+done:
+ return hr;
+}
+
+HRESULT CheckPassthroughMediaType(_In_ IMFMediaType *pMediaType1,
+ _In_ IMFMediaType *pMediaType2,
+ _Out_ BOOL& pfPassThrough)
+{
+ HRESULT hr = S_OK;
+ BOOL fPassThrough = FALSE;
+ UINT32 uWidth, uHeight;
+ UINT32 uWidth2, uHeight2;
+
+ // Compare Width/Height.
+ DMFTCHECKHR_GOTO(MFGetAttributeSize(pMediaType1, MF_MT_FRAME_SIZE, &uWidth, &uHeight), done);
+ DMFTCHECKHR_GOTO(MFGetAttributeSize(pMediaType2, MF_MT_FRAME_SIZE, &uWidth2, &uHeight2), done);
+ if ((uWidth != uWidth2) || (uHeight != uHeight2))
+ {
+ goto done;
+ }
+
+ // Compare rotation
+ {
+ UINT32 uRotation;
+ UINT32 uRotation2;
+
+ uRotation = MFGetAttributeUINT32(pMediaType1, MF_MT_VIDEO_ROTATION, 0);
+ uRotation2 = MFGetAttributeUINT32(pMediaType2, MF_MT_VIDEO_ROTATION, 0);
+ if (uRotation != uRotation2)
+ {
+ goto done;
+ }
+ }
+
+ // Compare Aspect Ratio
+ {
+ UINT32 uNumerator = 1, uDenominator = 1;
+ UINT32 uNumerator2 = 1, uDenominator2 = 1;
+
+ (void)MFGetAttributeRatio(pMediaType1, MF_MT_FRAME_RATE, &uNumerator, &uDenominator);
+ (void)MFGetAttributeRatio(pMediaType2, MF_MT_FRAME_RATE, &uNumerator2, &uDenominator2);
+ if ((uNumerator * uDenominator2) != (uNumerator2 * uDenominator))
+ {
+ goto done;
+ }
+ }
+
+ // Compare Nominal Range
+ {
+ UINT32 uNorminalRange;
+ UINT32 uNorminalRange2;
+
+ uNorminalRange = MFGetAttributeUINT32(pMediaType1, MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_Unknown);
+ uNorminalRange2 = MFGetAttributeUINT32(pMediaType2, MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_Unknown);
+ if (uNorminalRange != uNorminalRange2)
+ {
+ goto done;
+ }
+ }
+
+ // Compare color primaries
+ {
+ UINT32 uPrimaries;
+ UINT32 uPrimaries2;
+
+ uPrimaries = MFGetAttributeUINT32(pMediaType1, MF_MT_VIDEO_PRIMARIES, MFVideoPrimaries_Unknown);
+ uPrimaries2 = MFGetAttributeUINT32(pMediaType2, MF_MT_VIDEO_PRIMARIES, MFVideoPrimaries_Unknown);
+ if (uPrimaries != uPrimaries2)
+ {
+ goto done;
+ }
+ }
+
+
+ // Compare InterlaceMode
+ {
+ UINT32 uInterlaceMode;
+ UINT32 uInterlaceMode2;
+
+ uInterlaceMode = MFGetAttributeUINT32(pMediaType1, MF_MT_INTERLACE_MODE, MFVideoInterlace_Unknown);
+ uInterlaceMode2 = MFGetAttributeUINT32(pMediaType2, MF_MT_INTERLACE_MODE, MFVideoInterlace_Unknown);
+ if (uInterlaceMode != uInterlaceMode2)
+ {
+ goto done;
+ }
+ }
+
+ // Compare display aperture
+ {
+ MFVideoArea VideoArea = { 0 };
+ MFVideoArea VideoArea2 = { 0 };
+ UINT32 cbBlobSize = 0;
+
+ if (SUCCEEDED(pMediaType1->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)&VideoArea, sizeof(MFVideoArea), &cbBlobSize)))
+ {
+ if ((VideoArea.OffsetX.value == 0 && VideoArea.OffsetX.fract == 0) &&
+ (VideoArea.OffsetY.value == 0 && VideoArea.OffsetY.fract == 0) &&
+ (VideoArea.Area.cx == (LONG)uWidth) &&
+ (VideoArea.Area.cy == (LONG)uHeight))
+ {
+ // If the display aperture is the whole frame size, ignore it.
+ ZeroMemory(&VideoArea, sizeof(VideoArea));
+ }
+ }
+
+ if (SUCCEEDED(pMediaType2->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)&VideoArea2, sizeof(MFVideoArea), &cbBlobSize)))
+ {
+ if ((VideoArea2.OffsetX.value == 0 && VideoArea2.OffsetX.fract == 0) &&
+ (VideoArea2.OffsetY.value == 0 && VideoArea2.OffsetY.fract == 0) &&
+ (VideoArea2.Area.cx == (LONG)uWidth) &&
+ (VideoArea2.Area.cy == (LONG)uHeight))
+ {
+ // If the display aperture is the whole frame size, ignore it.
+ ZeroMemory(&VideoArea, sizeof(VideoArea));
+ }
+ }
+
+ if (memcmp(&VideoArea, &VideoArea2, sizeof(MFVideoArea)) != 0)
+ {
+ goto done;
+ }
+ }
+
+ fPassThrough = TRUE;
+
+done:
+ pfPassThrough = fPassThrough;
+ return hr;
+}
+
+
+HRESULT MergeSampleAttributes( _In_ IMFSample* pInSample, _Inout_ IMFSample* pOutSample)
+{
+ HRESULT hr = S_OK;
+ DMFTCHECKNULL_GOTO(pInSample, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG);
+ UINT32 cAttributes = 0;
+ GUID guidAttribute;
+ PROPVARIANT varAttribute;
+ PROPVARIANT varAttributeExists;
+
+ PropVariantInit(&varAttribute);
+ PropVariantInit(&varAttributeExists);
+
+ DMFTCHECKHR_GOTO(pInSample->GetCount(&cAttributes), done);
+ for (UINT32 i = 0; i < cAttributes; i++)
+ {
+ PropVariantClear(&varAttribute);
+ PropVariantClear(&varAttributeExists);
+
+ DMFTCHECKHR_GOTO(pInSample->GetItemByIndex(i, &guidAttribute, &varAttribute), done);
+
+ if (S_OK == pOutSample->GetItem(guidAttribute, &varAttributeExists))
+ {
+ // Exists.. dont clobber
+ continue;
+ }
+
+ DMFTCHECKHR_GOTO(pOutSample->SetItem(guidAttribute, varAttribute), done);
+ }
+
+done:
+ PropVariantClear(&varAttribute);
+ PropVariantClear(&varAttributeExists);
+ return hr;
+}
diff --git a/avstream/sampledevicemft/stdafx.h b/avstream/sampledevicemft/stdafx.h
index 6c5550a3..a3cd5354 100644
--- a/avstream/sampledevicemft/stdafx.h
+++ b/avstream/sampledevicemft/stdafx.h
@@ -29,7 +29,9 @@
#include <dxva2api.h>
#include <d3d11.h>
#include <mfcaptureengine.h>
+#include <algorithm>
#include <new>
+#include <d3d11_4.h>
#include <vector>
#include <map>
using namespace std;
@@ -38,4 +40,24 @@ using namespace std;
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
-#define MF_DEVICEMFT_ADD_GRAYSCALER_ 1 // remore this to remove the grayscaler
+// @@@@ README Please check / uncheck various hash defines to enable/ disable features
+// MF_DEVICEMFT_ASYNCPIN_NEEDED will show how to use Asynchronous queues
+// MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED will show how to decode a compressed mediatype.. it supports H264 and MJPG
+// MF_DEVICEMFT_SET_SPHERICAL_ATTRIBUTES will set the spherical attributes
+// MF_DEVICEMFT_ENUM_HW_DECODERS will make the device MFT enumerate hardware decoders
+//
+//#define MF_DEVICEMFT_ADD_GRAYSCALER_ 1
+#define MF_DEVICEMFT_ASYNCPIN_NEEDED 1
+#define MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED 1
+#define MF_DEVICEMFT_SET_SPHERICAL_ATTRIBUTES 1
+//#define MF_DEVICEMFT_ENUM_HW_DECODERS 1
+
+
+/*Some important notes regarding Device MFT
+Device MFT is an asynchronous transform that is loaded in the device source
+There are a few key operations that need a special mention
+1) InitializeTransform: This is where the device MFT should be initialized
+2) ProcessInput is where the samples are supplied to the Device MFT
+3) METransformHaveOutput is how deviceMFT notifies the Device Transform Manager (DTM) in the OS to pick up samples in its queues
+4) SetOutPutStreamState is where the state transition on a Device MFT will come in
+*/
diff --git a/network/wlan/WDI/COMMON/HashTable.c b/network/wlan/WDI/COMMON/HashTable.c
index fe8724e1..c2a54b9b 100644
--- a/network/wlan/WDI/COMMON/HashTable.c
+++ b/network/wlan/WDI/COMMON/HashTable.c
@@ -378,7 +378,7 @@ RtFreeHashTable(
// Remove value object of specified key from hash table.
//
void
-RtRemvoeKeyFromVaHashTable(
+RtRemoveKeyFromVaHashTable(
IN RT_HASH_TABLE_HANDLE hHashTable,
IN RT_HASH_KEY Key
)
diff --git a/network/wlan/WDI/COMMON/QosGen.c b/network/wlan/WDI/COMMON/QosGen.c
index dba375ef..652dd442 100644
--- a/network/wlan/WDI/COMMON/QosGen.c
+++ b/network/wlan/WDI/COMMON/QosGen.c
@@ -1280,7 +1280,7 @@ QosRemoveTs(
u1Byte Key[QOS_TSTREAM_KEY_SIZE];
PlatformMoveMemory(Key, pTs->__HashEntry.Key, QOS_TSTREAM_KEY_SIZE);
- RtRemvoeKeyFromVaHashTable(pStaQos->hApTsTable, Key);
+ RtRemoveKeyFromVaHashTable(pStaQos->hApTsTable, Key);
}
}
diff --git a/network/wlan/WDI/HEADER/HashTable.h b/network/wlan/WDI/HEADER/HashTable.h
index 7806b10b..67fcceda 100644
--- a/network/wlan/WDI/HEADER/HashTable.h
+++ b/network/wlan/WDI/HEADER/HashTable.h
@@ -111,7 +111,7 @@ RtPutKeyToHashTable(
);
void
-RtRemvoeKeyFromVaHashTable(
+RtRemoveKeyFromVaHashTable(
IN RT_HASH_TABLE_HANDLE hHashTable,
IN RT_HASH_KEY Key
);
diff --git a/setup/devcon/devcon.sln b/setup/devcon/devcon.sln
index 584555f8..5cd951c6 100644
--- a/setup/devcon/devcon.sln
+++ b/setup/devcon/devcon.sln
@@ -7,18 +7,24 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "devcon", "devcon.vcxproj",
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM64 = Debug|ARM64
Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
Debug|x64 = Debug|x64
+ Release|ARM64 = Release|ARM64
+ Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Debug|ARM64.Build.0 = Debug|ARM64
{14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Debug|Win32.ActiveCfg = Debug|Win32
{14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Debug|Win32.Build.0 = Debug|Win32
- {14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Release|Win32.ActiveCfg = Release|Win32
- {14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Release|Win32.Build.0 = Release|Win32
{14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Debug|x64.ActiveCfg = Debug|x64
{14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Debug|x64.Build.0 = Debug|x64
+ {14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Release|ARM64.ActiveCfg = Release|ARM64
+ {14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Release|ARM64.Build.0 = Release|ARM64
+ {14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Release|Win32.ActiveCfg = Release|Win32
+ {14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Release|Win32.Build.0 = Release|Win32
{14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Release|x64.ActiveCfg = Release|x64
{14EDBD07-E4CD-4BD8-82CC-F2840C160570}.Release|x64.Build.0 = Release|x64
EndGlobalSection
diff --git a/setup/devcon/devcon.vcxproj b/setup/devcon/devcon.vcxproj
index a5728918..b7b15302 100644
--- a/setup/devcon/devcon.vcxproj
+++ b/setup/devcon/devcon.vcxproj
@@ -1,10 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
@@ -50,6 +58,14 @@
<PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>True</UseDebugLibraries>
@@ -58,6 +74,14 @@
<PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<OutDir>$(IntDir)</OutDir>
@@ -71,9 +95,15 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
<ItemGroup Label="WrappedTaskItems" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<TargetName>devcon</TargetName>
@@ -84,9 +114,15 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetName>devcon</TargetName>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <TargetName>devcon</TargetName>
+ </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>devcon</TargetName>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <TargetName>devcon</TargetName>
+ </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
@@ -141,6 +177,24 @@
<AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;kernel32.lib;ntdll.lib;ole32.lib;setupapi.lib;shell32.lib;user32.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;kernel32.lib;ntdll.lib;ole32.lib;setupapi.lib;shell32.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
@@ -159,6 +213,24 @@
<AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;kernel32.lib;ntdll.lib;ole32.lib;setupapi.lib;shell32.lib;user32.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;kernel32.lib;ntdll.lib;ole32.lib;setupapi.lib;shell32.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="cmds.cpp" />
<ClCompile Include="devcon.cpp" />