Insert CHWMFT sample and try ot run

This commit is contained in:
Linnea May 2022-02-03 14:39:46 -08:00
Родитель 53f147b3a6
Коммит 5463991b65
26 изменённых файлов: 4469 добавлений и 100 удалений

Просмотреть файл

@ -149,6 +149,12 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="Capture.h" />
<ClInclude Include="CHWMFT\CAutoLock.h" />
<ClInclude Include="CHWMFT\CHWMFT.h" />
<ClInclude Include="CHWMFT\CHWMFT_DebugLogger.h" />
<ClInclude Include="CHWMFT\CHWMFT_DecodeTask.h" />
<ClInclude Include="CHWMFT\CSampleQueue.h" />
<ClInclude Include="CHWMFT\IMYMFT.h" />
<ClInclude Include="common.h" />
<ClInclude Include="common\CAutoLock.h" />
<ClInclude Include="common\CHWMFT_DebugLogger.h" />
@ -160,20 +166,25 @@
<ClInclude Include="Resource.h" />
<ClInclude Include="SegmentModel.h" />
<ClInclude Include="StreamModel.h" />
<ClInclude Include="TransformAsync.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Capture.cpp" />
<ClCompile Include="CHWMFT\CAutoLock.cpp" />
<ClCompile Include="CHWMFT\CHWMFT.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_DebugLogger.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_DecodeTask.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IMFAsyncCallback_Impl.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IMFMediaEventGenerator_Impl.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IMFShutdown_Impl.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IMFTransform_Impl.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IUnknown_Impl.cpp" />
<ClCompile Include="CHWMFT\CSampleQueue.cpp" />
<ClCompile Include="CHWMFT\dllmain.cpp" />
<ClCompile Include="common\CAutoLock.cpp" />
<ClCompile Include="common\CHWMFT_DebugLogger.cpp" />
<ClCompile Include="common\CSampleQueue.cpp" />
<ClCompile Include="PreviewWnd.cpp" />
<ClCompile Include="SegmentModel.cpp" />
<ClCompile Include="TransformAsync.cpp" />
<ClCompile Include="TransformAsync_IMFAsyncCallback.cpp" />
<ClCompile Include="TransformAsync_IMFMediaEventGenerator.cpp" />
<ClCompile Include="TransformAsync_IMFShutdown.cpp" />
<ClCompile Include="TransformAsync_IMFTransform.cpp" />
<ClCompile Include="utils.cpp" />
<ClCompile Include="winmain.cpp" />
</ItemGroup>

Просмотреть файл

@ -6,14 +6,20 @@
<ClCompile Include="PreviewWnd.cpp" />
<ClCompile Include="utils.cpp" />
<ClCompile Include="winmain.cpp" />
<ClCompile Include="TransformAsync_IMFMediaEventGenerator.cpp" />
<ClCompile Include="TransformAsync_IMFTransform.cpp" />
<ClCompile Include="TransformAsync.cpp" />
<ClCompile Include="TransformAsync_IMFAsyncCallback.cpp" />
<ClCompile Include="TransformAsync_IMFShutdown.cpp" />
<ClCompile Include="common\CSampleQueue.cpp" />
<ClCompile Include="common\CHWMFT_DebugLogger.cpp" />
<ClCompile Include="common\CAutoLock.cpp" />
<ClCompile Include="CHWMFT\CAutoLock.cpp" />
<ClCompile Include="CHWMFT\CHWMFT.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_DebugLogger.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_DecodeTask.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IMFAsyncCallback_Impl.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IMFMediaEventGenerator_Impl.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IMFShutdown_Impl.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IMFTransform_Impl.cpp" />
<ClCompile Include="CHWMFT\CHWMFT_IUnknown_Impl.cpp" />
<ClCompile Include="CHWMFT\CSampleQueue.cpp" />
<ClCompile Include="CHWMFT\dllmain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="SegmentModel.h" />
@ -21,12 +27,17 @@
<ClInclude Include="Resource.h" />
<ClInclude Include="common.h" />
<ClInclude Include="StreamModel.h" />
<ClInclude Include="TransformAsync.h" />
<ClInclude Include="common\CHWMFT_DebugLogger.h" />
<ClInclude Include="common\CAutoLock.h" />
<ClInclude Include="common\CSampleQueue.h" />
<ClInclude Include="common\GrowArray.h" />
<ClInclude Include="common\critsec.h" />
<ClInclude Include="CHWMFT\CAutoLock.h" />
<ClInclude Include="CHWMFT\CHWMFT.h" />
<ClInclude Include="CHWMFT\CHWMFT_DebugLogger.h" />
<ClInclude Include="CHWMFT\CHWMFT_DecodeTask.h" />
<ClInclude Include="CHWMFT\CSampleQueue.h" />
<ClInclude Include="CHWMFT\IMYMFT.h" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

Просмотреть файл

@ -0,0 +1,23 @@
#include "CAutoLock.h"
_When_(pcs != NULL, _Acquires_lock_(*this->m_pcs) _Post_same_lock_(*pcs, *this->m_pcs)) _Post_satisfies_(this->m_pcs == pcs)
CAutoLock::CAutoLock(CRITICAL_SECTION* pcs)
{
m_pcs = pcs;
if(m_pcs != NULL)
{
EnterCriticalSection(m_pcs);
}
}
_When_(this->m_pcs != NULL, _Releases_lock_(*this->m_pcs))
CAutoLock::~CAutoLock(void)
{
if(m_pcs != NULL)
{
LeaveCriticalSection(m_pcs);
m_pcs = NULL;
}
}

Просмотреть файл

@ -0,0 +1,15 @@
#pragma once
#include <windows.h>
class CAutoLock
{
public:
_When_(pcs != NULL, _Acquires_lock_(*this->m_pcs) _Post_same_lock_(*pcs, *this->m_pcs)) _Post_satisfies_(this->m_pcs == pcs)
CAutoLock(CRITICAL_SECTION* pcs);
_When_(this->m_pcs != NULL, _Releases_lock_(*this->m_pcs))
~CAutoLock(void);
protected:
CRITICAL_SECTION* m_pcs;
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,267 @@
#pragma once
#include "IMYMFT.h"
#include "CSampleQueue.h"
#include <Mfidl.h>
#define MFT_MAX_STREAMS 1
#define MFT_OUTPUT_WIDTH 1280
#define MFT_OUTPUT_HEIGHT 720
#define MFT_FRAMERATE_NUMERATOR 30
#define MFT_FRAMERATE_DENOMINATOR 1
#define MFT_DEFAULT_SAMPLE_DURATION 300000 // 1/30th of a second in hundred nanoseconds
#define _HMFTLOGGING_
enum eMFTStatus
{
MYMFT_STATUS_INPUT_ACCEPT_DATA = 0x00000001, /* The MFT can accept input data */
MYMFT_STATUS_OUTPUT_SAMPLE_READY = 0x00000002,
MYMFT_STATUS_STREAM_STARTED = 0x00000004,
MYMFT_STATUS_DRAINING = 0x00000008, /* See http://msdn.microsoft.com/en-us/library/dd940418(v=VS.85).aspx
** While the MFT is is in this state, it must not send
** any more METransformNeedInput events. It should continue
** to send METransformHaveOutput events until it is out of
** output. At that time, it should send METransformDrainComplete */
};
extern const GUID* g_ppguidInputTypes[];
extern const DWORD g_dwNumInputTypes;
extern const GUID* g_ppguidOutputTypes[];
extern const DWORD g_dwNumOutputTypes;
extern const GUID MYMFT_MFSampleExtension_Marker;
class CHWMFT:
public IMFTransform,
public IMFShutdown,
public IMFMediaEventGenerator,
public IMFAsyncCallback,
public IMYMFT
/*****************************
** Todo: if you add interfaces
** ensure that you add them
** to QueryInterface
*****************************/
{
public:
static volatile ULONG m_ulNumObjects; // Total object count
// Initializer
static HRESULT CreateInstance(IMFTransform** ppHWMFT);
#pragma region IUnknown
// IUnknown Implementations
ULONG __stdcall AddRef(void);
HRESULT __stdcall QueryInterface(
REFIID riid,
void** ppvObject
);
ULONG __stdcall Release(void);
#pragma endregion IUnknown
#pragma region IMFTransform
// IMFTransform Implementations
HRESULT __stdcall AddInputStreams(
DWORD dwStreams,
DWORD* pdwStreamIDs
);
HRESULT __stdcall DeleteInputStream(
DWORD dwStreamID
);
HRESULT __stdcall GetAttributes(
IMFAttributes** ppAttributes
);
HRESULT __stdcall GetInputAvailableType(
DWORD dwInputStreamID,
DWORD dwTypeIndex,
IMFMediaType** ppType
);
HRESULT __stdcall GetInputCurrentType(
DWORD dwInputStreamID,
IMFMediaType** ppType
);
HRESULT __stdcall GetInputStatus(
DWORD dwInputStreamID,
DWORD* pdwFlags
);
HRESULT __stdcall GetInputStreamAttributes(
DWORD dwInputStreamID,
IMFAttributes** ppAttributes
);
HRESULT __stdcall GetInputStreamInfo(
DWORD dwInputStreamID,
MFT_INPUT_STREAM_INFO* pStreamInfo
);
HRESULT __stdcall GetOutputAvailableType(
DWORD dwOutputStreamID,
DWORD dwTypeIndex,
IMFMediaType** ppType
);
HRESULT __stdcall GetOutputCurrentType(
DWORD dwOutputStreamID,
IMFMediaType** ppType
);
HRESULT __stdcall GetOutputStatus(
DWORD* pdwFlags
);
HRESULT __stdcall GetOutputStreamAttributes(
DWORD dwOutputStreamID,
IMFAttributes** ppAttributes
);
HRESULT __stdcall GetOutputStreamInfo(
DWORD dwOutputStreamID,
MFT_OUTPUT_STREAM_INFO* pStreamInfo
);
HRESULT __stdcall GetStreamCount(
DWORD* pdwInputStreams,
DWORD* pdwOutputStreams
);
HRESULT __stdcall GetStreamIDs(
DWORD dwInputIDArraySize,
DWORD* pdwInputIDs,
DWORD dwOutputIDArraySize,
DWORD* pdwOutputIDs
);
HRESULT __stdcall GetStreamLimits(
DWORD* pdwInputMinimum,
DWORD* pdwInputMaximum,
DWORD* pdwOutputMinimum,
DWORD* pdwOutputMaximum
);
HRESULT __stdcall ProcessEvent(
DWORD dwInputStreamID,
IMFMediaEvent* pEvent
);
HRESULT __stdcall ProcessInput(
DWORD dwInputStreamID,
IMFSample* pSample,
DWORD dwFlags
);
HRESULT __stdcall ProcessMessage(
MFT_MESSAGE_TYPE eMessage,
ULONG_PTR ulParam
);
HRESULT __stdcall ProcessOutput(
DWORD dwFlags,
DWORD dwOutputBufferCount,
MFT_OUTPUT_DATA_BUFFER* pOutputSamples,
DWORD* pdwStatus
);
HRESULT __stdcall SetInputType(
DWORD dwInputStreamID,
IMFMediaType* pType,
DWORD dwFlags
);
HRESULT __stdcall SetOutputBounds(
LONGLONG hnsLowerBound,
LONGLONG hnsUpperBound
);
HRESULT __stdcall SetOutputType(
DWORD dwOutputStreamID,
IMFMediaType* pType,
DWORD dwFlags
);
#pragma endregion IMFTransform
#pragma region IMFShutdown
// IMFShutdown Implementations
HRESULT __stdcall GetShutdownStatus(
MFSHUTDOWN_STATUS* pStatus
);
HRESULT __stdcall Shutdown(void);
#pragma endregion IMFShutdown
#pragma region IMFMediaEventGenerator
// IMFMediaEventGenerator Implementations
HRESULT __stdcall BeginGetEvent(
IMFAsyncCallback* pCallback,
IUnknown* punkState
);
HRESULT __stdcall EndGetEvent(
IMFAsyncResult* pResult,
IMFMediaEvent** ppEvent
);
HRESULT __stdcall GetEvent(
DWORD dwFlags,
IMFMediaEvent** ppEvent
);
HRESULT __stdcall QueueEvent(
MediaEventType met,
REFGUID guidExtendedType,
HRESULT hrStatus,
const PROPVARIANT* pvValue
);
#pragma endregion IMFMediaEventGenerator
#pragma region IMFAsyncCallback
// IMFAsyncCallback Implementations
HRESULT __stdcall GetParameters(
DWORD* pdwFlags,
DWORD* pdwQueue
);
HRESULT __stdcall Invoke(
IMFAsyncResult *pAsyncResult
);
#pragma endregion IMFAsyncCallback
// IMYMFT Implementations
HRESULT __stdcall DecodeInputFrame(
IMFSample* pInputSample
);
protected:
CHWMFT(void);
~CHWMFT(void);
HRESULT InitializeTransform(void);
HRESULT CheckInputType(
IMFMediaType* pMT
);
HRESULT CheckOutputType(
IMFMediaType* pMT
);
HRESULT ShutdownEventQueue(void);
/******* MFT Media Event Handlers**********/
HRESULT OnStartOfStream(void);
HRESULT OnEndOfStream(void);
HRESULT OnDrain(
const UINT32 un32StreamID
);
HRESULT OnFlush(void);
HRESULT OnMarker(
const ULONG_PTR pulID
);
/***********End Event Handlers************/
HRESULT RequestSample(
const UINT32 un32StreamID
);
HRESULT FlushSamples(void);
HRESULT ScheduleFrameDecode(void);
HRESULT SendEvent(void);
BOOL IsLocked(void);
BOOL IsMFTReady(void);
// Member variables
volatile ULONG m_ulRef;
volatile ULONG m_ulSampleCounter;
IMFMediaType* m_pInputMT;
IMFMediaType* m_pOutputMT;
IMFAttributes* m_pAttributes;
IMFMediaEventQueue* m_pEventQueue;
DWORD m_dwStatus;
DWORD m_dwNeedInputCount;
DWORD m_dwHaveOutputCount;
DWORD m_dwDecodeWorkQueueID;
LONGLONG m_llCurrentSampleTime;
BOOL m_bFirstSample;
BOOL m_bShutdown;
BOOL m_bDXVA;
CSampleQueue* m_pInputSampleQueue;
CSampleQueue* m_pOutputSampleQueue;
CRITICAL_SECTION m_csLock;
};
HRESULT DuplicateAttributes(
IMFAttributes* pDest,
IMFAttributes* pSource
);

Просмотреть файл

@ -0,0 +1,109 @@
#include "CHWMFT_DebugLogger.h"
#ifdef _HMFTLOGGING_
#include <evntrace.h>
#include <strsafe.h>
REGHANDLE g_ETWHandle = NULL;
BOOL g_bEnabled = FALSE;
UCHAR g_ucLevel = 0;
void NTAPI EventRegisterCallback(
LPCGUID lpcguidSourceId,
ULONG ulIsEnabled,
UCHAR ucLevel,
ULONGLONG ullMatchAnyKeyword,
ULONGLONG ullMatchAllKeywords,
PEVENT_FILTER_DESCRIPTOR pefdFilterData,
PVOID pvCallbackContext)
{
switch(ulIsEnabled)
{
case EVENT_CONTROL_CODE_ENABLE_PROVIDER:
g_bEnabled = TRUE;
g_ucLevel = ucLevel;
break;
case EVENT_CONTROL_CODE_DISABLE_PROVIDER:
g_bEnabled = FALSE;
g_ucLevel = 0;
break;
default:
// Nothing to do
break;
};
}
#endif
void TraceInitialize(void)
{
#ifdef _HMFTLOGGING_
if(g_bEnabled == FALSE)
{
// Provider ID: {54E23341-C608-4161-97F1-653A9B6FFFF1}
// TODO: Generate a new unique provider ID. Do not reuse this GUID.
static const GUID guidTrace =
{ 0x54e23341, 0xc608, 0x4161, { 0x97, 0xf1, 0x65, 0x3a, 0x9b, 0x6f, 0xff, 0xf1 } };
EventRegister(
&guidTrace,
&EventRegisterCallback,
NULL,
&g_ETWHandle
);
}
#endif
}
void TraceUninitialize(void)
{
#ifdef _HMFTLOGGING_
if(g_ETWHandle != NULL)
{
EventUnregister(g_ETWHandle);
}
g_ETWHandle = NULL;
g_bEnabled = FALSE;
g_ucLevel = 0;
#endif
}
void TraceString(
const UCHAR ucLevel,
const WCHAR* pwszFormat,
...)
{
#ifdef _HMFTLOGGING_
do
{
if(g_bEnabled == FALSE)
{
// Do not trace
break;
}
if( (ucLevel > g_ucLevel) &&
(g_ucLevel != 0) )
{
// Do not trace
break;
}
WCHAR pwszTrace[1024] = {0};
va_list args;
va_start(args, pwszFormat);
StringCchVPrintfW(
pwszTrace,
ARRAYSIZE(pwszTrace),
pwszFormat,
args
);
va_end(args);
EventWriteString(g_ETWHandle, ucLevel, 0, pwszTrace);
}while(false);
#endif
}

Просмотреть файл

@ -0,0 +1,27 @@
#pragma once
#include <windows.h>
#ifdef _HMFTLOGGING_
#include <Evntprov.h>
extern UCHAR g_ucLevel;
#endif
namespace CHMFTTracing
{
enum eTraceLeve
{
TRACE_INFORMATION = 4,
TRACE_ERROR = 2
};
}
void TraceInitialize(void);
void TraceUninitialize(void);
void TraceString(
const UCHAR ucLevel,
const WCHAR* pwszFormat,
...
);

Просмотреть файл

@ -0,0 +1,228 @@
#include "CHWMFT_DecodeTask.h"
#include <Mfapi.h>
#include <initguid.h>
#include "IMYMFT.h"
// Helper Macros
#define SAFERELEASE(x) \
if((x) != NULL) \
{ \
(x)->Release(); \
(x) = NULL; \
} \
HRESULT CDecodeTask::Create(
const DWORD dwDecodeWorkQueueID,
IMFSample* pInputSample,
IMFAsyncCallback** ppTask)
{
HRESULT hr = S_OK;
CDecodeTask* pNewDecodeTask = NULL;
do
{
if(pInputSample == NULL)
{
hr = E_POINTER;
break;
}
pNewDecodeTask = new CDecodeTask();
if(pNewDecodeTask == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
pNewDecodeTask->m_dwDecodeWorkQueueID = dwDecodeWorkQueueID;
pNewDecodeTask->m_pInputSample = pInputSample;
pNewDecodeTask->m_pInputSample->AddRef();
hr = pNewDecodeTask->QueryInterface(IID_IMFAsyncCallback, (void**)ppTask);
if(FAILED(hr))
{
break;
}
}while(false);
SAFERELEASE(pNewDecodeTask);
return hr;
}
HRESULT CDecodeTask::Begin(
IMYMFT* pMYMFT)
{
HRESULT hr = S_OK;
IMFAsyncCallback* pDecodeTask = NULL;
IMFAsyncResult* pResult = NULL;
do
{
if(pMYMFT == NULL)
{
hr = E_POINTER;
break;
}
hr = MFCreateAsyncResult(NULL, this, pMYMFT, &pResult);
if(FAILED(hr))
{
break;
}
hr = MFPutWorkItemEx(m_dwDecodeWorkQueueID, pResult);
if(FAILED(hr))
{
break;
}
}while(false);
SAFERELEASE(pDecodeTask);
SAFERELEASE(pResult);
return hr;
}
HRESULT CDecodeTask::End(void)
{
// Nothing to do
return S_OK;
}
HRESULT CDecodeTask::GetParameters(
DWORD* pdwFlags,
DWORD* pdwQueue)
{
HRESULT hr = S_OK;
do
{
if((pdwFlags == NULL) || (pdwQueue == NULL))
{
hr = E_POINTER;
break;
}
(*pdwFlags) = 0;
(*pdwQueue) = m_dwDecodeWorkQueueID;
}while(false);
return hr;
}
HRESULT CDecodeTask::Invoke(
IMFAsyncResult* pAsyncResult)
{
HRESULT hr = S_OK;
IUnknown* pStateUnk = NULL;
IMYMFT* pMYMFT = NULL;
do
{
if(pAsyncResult == NULL)
{
hr = E_POINTER;
break;
}
hr = pAsyncResult->GetState(&pStateUnk);
if(FAILED(hr))
{
break;
}
hr = pStateUnk->QueryInterface(IID_IMYMFT, (void**)&pMYMFT);
if(FAILED(hr))
{
break;
}
hr = pMYMFT->DecodeInputFrame(m_pInputSample);
// Save the status
hr = pAsyncResult->SetStatus(hr);
if(FAILED(hr))
{
break;
}
}while(false);
SAFERELEASE(pStateUnk);
SAFERELEASE(pMYMFT);
End();
return hr;
}
ULONG CDecodeTask::AddRef(void)
{
return InterlockedIncrement(&m_ulRef);
}
HRESULT CDecodeTask::QueryInterface(
REFIID riid,
void** ppvObject)
{
HRESULT hr = S_OK;
do
{
if(ppvObject == NULL)
{
hr = E_POINTER;
break;
}
if(riid == IID_IMFAsyncCallback)
{
*ppvObject = (IMFAsyncCallback*)this;
}
else if(riid == IID_IUnknown)
{
*ppvObject = this;
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
break;
}
AddRef();
}while(false);
return hr;
}
ULONG CDecodeTask::Release(void)
{
ULONG ulRef = 0;
if(m_ulRef > 0)
{
ulRef = InterlockedDecrement(&m_ulRef);
}
if(ulRef == 0)
{
delete this;
}
return ulRef;
}
CDecodeTask::CDecodeTask(void)
{
m_ulRef = 1;
m_pInputSample = NULL;
m_dwDecodeWorkQueueID = 0;
}
CDecodeTask::~CDecodeTask(void)
{
SAFERELEASE(m_pInputSample);
}

Просмотреть файл

@ -0,0 +1,46 @@
#pragma once
#include <Mfidl.h>
class IMYMFT; // Defined in IMYMFT.h, included in the cpp for this class
class CDecodeTask:
public IMFAsyncCallback
{
public:
// Creation Function
static HRESULT Create(
const DWORD dwDecodeWorkQueueID,
IMFSample* pInputSample,
IMFAsyncCallback** ppTask
);
HRESULT Begin(
IMYMFT* pMYMFT
);
HRESULT End(void);
// IMFAsyncCallback Implementations
HRESULT __stdcall GetParameters(
DWORD* pdwFlags,
DWORD* pdwQueue
);
HRESULT __stdcall Invoke(
IMFAsyncResult *pAsyncResult
);
// IUnknown Implementations
ULONG __stdcall AddRef(void);
HRESULT __stdcall QueryInterface(
REFIID riid,
void** ppvObject
);
ULONG __stdcall Release(void);
protected:
CDecodeTask(void);
~CDecodeTask(void);
volatile ULONG m_ulRef;
IMFSample* m_pInputSample;
DWORD m_dwDecodeWorkQueueID;
};

Просмотреть файл

@ -0,0 +1,55 @@
#include "CHWMFT.h"
// Helper Macros
#define SAFERELEASE(x) \
if((x) != NULL) \
{ \
(x)->Release(); \
(x) = NULL; \
} \
HRESULT CHWMFT::GetParameters(
DWORD* pdwFlags,
DWORD* pdwQueue)
{
HRESULT hr = S_OK;
do
{
if((pdwFlags == NULL) || (pdwQueue == NULL))
{
hr = E_POINTER;
break;
}
(*pdwFlags) = 0;
(*pdwQueue) = m_dwDecodeWorkQueueID;
}while(false);
return hr;
}
HRESULT CHWMFT::Invoke(
IMFAsyncResult *pAsyncResult)
{
/*********************************
** Todo: This function is called
** when you schedule an async event
** Determine the event type from
** the result and take appropriate
** action
*********************************/
HRESULT hr = S_OK;
do
{
if(pAsyncResult == NULL)
{
hr = E_POINTER;
break;
}
}while(false);
return hr;
}

Просмотреть файл

@ -0,0 +1,64 @@
#include "CHWMFT.h"
#include <Mfapi.h>
// Helper Macros
#define SAFERELEASE(x) \
if((x) != NULL) \
{ \
(x)->Release(); \
(x) = NULL; \
} \
HRESULT CHWMFT::BeginGetEvent(
IMFAsyncCallback* pCallback,
IUnknown* punkState)
{
/***************************************
** Since this in an internal function
** we know m_pEventQueue can never be
** NULL due to InitializeTransform()
***************************************/
return m_pEventQueue->BeginGetEvent(pCallback, punkState);
}
HRESULT CHWMFT::EndGetEvent(
IMFAsyncResult* pResult,
IMFMediaEvent** ppEvent)
{
/***************************************
** Since this in an internal function
** we know m_pEventQueue can never be
** NULL due to InitializeTransform()
***************************************/
return m_pEventQueue->EndGetEvent(pResult, ppEvent);
}
HRESULT CHWMFT::GetEvent(
DWORD dwFlags,
IMFMediaEvent** ppEvent)
{
/***************************************
** Since this in an internal function
** we know m_pEventQueue can never be
** NULL due to InitializeTransform()
***************************************/
return m_pEventQueue->GetEvent(dwFlags, ppEvent);
}
HRESULT CHWMFT::QueueEvent(
MediaEventType met,
REFGUID guidExtendedType,
HRESULT hrStatus,
const PROPVARIANT* pvValue)
{
/***************************************
** Since this in an internal function
** we know m_pEventQueue can never be
** NULL due to InitializeTransform()
***************************************/
return m_pEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue);
}

Просмотреть файл

@ -0,0 +1,59 @@
#include "CHWMFT.h"
#include "CAutoLock.h"
#include <mferror.h>
#include <mfapi.h>
HRESULT CHWMFT::GetShutdownStatus(
MFSHUTDOWN_STATUS* pStatus)
{
HRESULT hr = S_OK;
do
{
if(pStatus == NULL)
{
hr = E_POINTER;
break;
}
{
CAutoLock lock(&m_csLock);
if(m_bShutdown == FALSE)
{
hr = MF_E_INVALIDREQUEST;
break;
}
*pStatus = MFSHUTDOWN_COMPLETED;
}
}while(false);
return hr;
}
HRESULT CHWMFT::Shutdown(void)
{
HRESULT hr = S_OK;
do
{
CAutoLock lock(&m_csLock);
hr = ShutdownEventQueue();
if(FAILED(hr))
{
break;
}
hr = MFUnlockWorkQueue(m_dwDecodeWorkQueueID);
if(FAILED(hr))
{
break;
}
m_bShutdown = TRUE;
}while(false);
return hr;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,82 @@
#include "CHWMFT.h"
#include "IMYMFT.h"
ULONG CHWMFT::AddRef(void)
{
return InterlockedIncrement(&m_ulRef);
}
HRESULT CHWMFT::QueryInterface(
REFIID riid,
void** ppvObject)
{
HRESULT hr = S_OK;
do
{
if(ppvObject == NULL)
{
hr = E_POINTER;
break;
}
/****************************************************
** Todo: add all supported interfaces by your MFT
****************************************************/
if(riid == IID_IMFTransform)
{
*ppvObject = (IMFTransform*)this;
}
else if(riid == IID_IMFAttributes)
{
*ppvObject = (IMFAttributes*)this;
}
else if(riid == IID_IMFShutdown)
{
*ppvObject = (IMFShutdown*)this;
}
else if(riid == IID_IMFMediaEventGenerator)
{
*ppvObject = (IMFMediaEventGenerator*)this;
}
else if(riid == IID_IMFAsyncCallback)
{
*ppvObject = (IMFAsyncCallback*)this;
}
else if(riid == IID_IMYMFT)
{
*ppvObject = (IMYMFT*)this;
}
else if(riid == IID_IUnknown)
{
*ppvObject = this;
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
break;
}
AddRef();
}while(false);
return hr;
}
ULONG CHWMFT::Release(void)
{
ULONG ulRef = 0;
if(m_ulRef > 0)
{
ulRef = InterlockedDecrement(&m_ulRef);
}
if(ulRef == 0)
{
delete this;
}
return ulRef;
}

Просмотреть файл

@ -0,0 +1,307 @@
#include "CSampleQueue.h"
#include "CAutoLock.h"
#include "CHWMFT.h"
#include "CHWMFT_DebugLogger.h"
// Helper Macros
#define SAFERELEASE(x) \
if((x) != NULL) \
{ \
(x)->Release(); \
(x) = NULL; \
} \
#define SAFEDELETE(x) \
if((x) != NULL) \
{ \
delete (x); \
(x) = NULL; \
} \
class CSampleQueue::CNode
{
public:
IMFSample* pSample;
CNode* pNext;
CNode(void)
{
pSample = NULL;
pNext = NULL;
}
~CNode(void)
{
SAFERELEASE(pSample);
pNext = NULL;
}
};
HRESULT CSampleQueue::Create(
CSampleQueue** ppQueue)
{
HRESULT hr = S_OK;
CSampleQueue* pNewQueue = NULL;
do
{
if(ppQueue == NULL)
{
hr = E_POINTER;
break;
}
pNewQueue = new CSampleQueue();
if(pNewQueue == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
(*ppQueue) = pNewQueue;
(*ppQueue)->AddRef();
}while(false);
SAFERELEASE(pNewQueue);
return hr;
}
ULONG CSampleQueue::AddRef(void)
{
return InterlockedIncrement(&m_ulRef);
}
HRESULT CSampleQueue::QueryInterface(
REFIID riid,
void** ppvObject)
{
HRESULT hr = S_OK;
do
{
if(ppvObject == NULL)
{
hr = E_POINTER;
break;
}
if(riid == IID_IUnknown)
{
*ppvObject = (IUnknown*)this;
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
break;
}
AddRef();
}while(false);
return hr;
}
ULONG CSampleQueue::Release(void)
{
ULONG ulRef = 0;
if(m_ulRef > 0)
{
ulRef = InterlockedDecrement(&m_ulRef);
}
if(ulRef == 0)
{
delete this;
}
return ulRef;
}
HRESULT CSampleQueue::AddSample(
IMFSample* pSample)
{
HRESULT hr = S_OK;
CNode* pNewNode = NULL;
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Enter", __FUNCTION__);
do
{
if(pSample == NULL)
{
hr = E_POINTER;
break;
}
pNewNode = new CNode();
if(pNewNode == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
pNewNode->pSample = pSample;
pNewNode->pSample->AddRef();
pNewNode->pNext = NULL;
{
CAutoLock lock(&m_csLock);
if(m_bAddMarker != FALSE)
{
hr = pSample->SetUINT64(MYMFT_MFSampleExtension_Marker, m_pulMarkerID);
if(FAILED(hr))
{
break;
}
m_pulMarkerID = 0;
m_bAddMarker = FALSE;
}
if(IsQueueEmpty() != FALSE)
{
// This is the first sample in the queue
m_pHead = pNewNode;
m_pTail = pNewNode;
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Sample @%p is first sample in Queue @%p", __FUNCTION__, pSample, this);
}
else
{
m_pTail->pNext = pNewNode;
m_pTail = pNewNode;
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Sample @%p added to back of Queue @%p", __FUNCTION__, pSample, this);
}
}
}while(false);
if(FAILED(hr))
{
SAFEDELETE(pNewNode);
}
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Exit (hr=0x%x)", __FUNCTION__, hr);
return hr;
}
HRESULT CSampleQueue::GetNextSample(
IMFSample** ppSample)
{
HRESULT hr = S_OK;
CNode* pCurrentNode = NULL;
do
{
if(ppSample == NULL)
{
hr = E_POINTER;
break;
}
*ppSample = NULL;
{
CAutoLock lock(&m_csLock);
if(IsQueueEmpty() != FALSE)
{
// The queue is empty
hr = S_FALSE;
break;
}
pCurrentNode = m_pHead;
(*ppSample) = pCurrentNode->pSample;
(*ppSample)->AddRef();
// Now remove the node from the list
m_pHead = m_pHead->pNext;
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Sample @%p removed from queue Queue @%p", __FUNCTION__, (*ppSample), this);
if(m_pHead == NULL)
{
// This was the last sample in the queue
m_pTail = NULL;
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Queue @%p is not empty", __FUNCTION__, this);
}
}
}while(false);
SAFEDELETE(pCurrentNode);
return hr;
}
HRESULT CSampleQueue::RemoveAllSamples(void)
{
HRESULT hr = S_OK;
CNode* pCurrNode = NULL;
do
{
CAutoLock lock(&m_csLock);
while(IsQueueEmpty() == FALSE)
{
pCurrNode = m_pHead;
m_pHead = m_pHead->pNext;
delete pCurrNode;
}
m_pTail = NULL;
}while(false);
return hr;
}
HRESULT CSampleQueue::MarkerNextSample(
const ULONG_PTR pulID)
{
HRESULT hr = S_OK;
do
{
CAutoLock lock(&m_csLock);
m_pulMarkerID = pulID;
m_bAddMarker = TRUE;
}while(false);
return hr;
}
BOOL CSampleQueue::IsQueueEmpty(void)
{
CAutoLock lock(&m_csLock);
return (m_pHead == NULL) ? TRUE : FALSE;
}
CSampleQueue::CSampleQueue(void)
{
m_ulRef = 1;
m_pHead = NULL;
m_pTail = NULL;
m_bAddMarker = FALSE;
m_pulMarkerID = 0;
InitializeCriticalSection(&m_csLock);
}
CSampleQueue::~CSampleQueue(void)
{
RemoveAllSamples();
DeleteCriticalSection(&m_csLock);
}

Просмотреть файл

@ -0,0 +1,60 @@
#pragma once
#include <windows.h>
#include <Mfidl.h>
class CSampleQueue: public IUnknown
{
public:
class ILockedSample;
static HRESULT Create(
CSampleQueue** ppQueue
);
#pragma region IUnknown
// IUnknown Implementations
ULONG __stdcall AddRef(void);
HRESULT __stdcall QueryInterface(
REFIID riid,
void** ppvObject
);
ULONG __stdcall Release(void);
#pragma endregion IUnknown
// ILockedSampleCallback Implementation
HRESULT AddSample( // Add a sample to the back of the queue
IMFSample* pSample
);
HRESULT GetNextSample( // Remove a sample from the front of the queue
IMFSample** pSample
);
HRESULT RemoveAllSamples(void);
HRESULT MarkerNextSample(
const ULONG_PTR pulID
);
BOOL IsQueueEmpty(void);
protected:
class CNode;
CSampleQueue(void);
~CSampleQueue(void);
volatile ULONG m_ulRef;
CNode* m_pHead;
CNode* m_pTail;
BOOL m_bAddMarker;
ULONG_PTR m_pulMarkerID;
CRITICAL_SECTION m_csLock;
};
class CSampleQueue::ILockedSample
{
public:
virtual HRESULT GetSample(
IMFSample** ppSample
) = 0;
virtual HRESULT Unlock(void) = 0;
};

Просмотреть файл

@ -0,0 +1,16 @@
#pragma once
#include <Mfidl.h>
// {BC36CB81-C1FA-4B92-B12D-FCBB8DB3FDF6}
DEFINE_GUID(IID_IMYMFT,
0xbc36cb81, 0xc1fa, 0x4b92, 0xb1, 0x2d, 0xfc, 0xbb, 0x8d, 0xb3, 0xfd, 0xf6);
class IMYMFT:
public IUnknown
{
public:
virtual HRESULT __stdcall DecodeInputFrame(
IMFSample* pInputSample
) = 0;
};

Просмотреть файл

@ -0,0 +1,582 @@
#include "CHWMFT.h"
#include <strsafe.h>
#include <mfapi.h>
#include <initguid.h>
#pragma region HelperMacros
// Helper Macros
#define SAFERELEASE(x) \
if((x) != NULL) \
{ \
(x)->Release(); \
(x) = NULL; \
} \
#define SAFEREGCLOSEKEY(x) \
if((x) != NULL) \
{ \
RegCloseKey(x); \
(x) = NULL; \
} \
#define SAFEARRAYDELETE(x) \
if((x) != NULL) \
{ \
delete[] (x); \
(x) = NULL; \
} \
#pragma endregion HelperMacros
#pragma region GlobalDefines
// {C637E2D2-01A0-4ACE-9C43-D2AF07E00B8C}
DEFINE_GUID(CLSID_MYMFT,
0xc637e2d2, 0x1a0, 0x4ace, 0x9c, 0x43, 0xd2, 0xaf, 0x7, 0xe0, 0xb, 0x8c);
#define MY_MFT_NAME L"Win8 SDK HW MFT Sample"
#define MFT_CODEC_MERIT 8 /*Todo: Replace this with the actual codec Merit*/
#pragma endregion GlobalDefines
#pragma region ClassFactory
// Implements the class factory for the MFT
class ClassFactory : public IClassFactory
{
protected:
volatile ULONG m_ulRefCount; // Reference count.
static volatile ULONG m_ulServerLocks; // Number of server locks
public:
ClassFactory(void)
{
m_ulRefCount = 1;
}
static bool IsLocked(void)
{
return (m_ulServerLocks != 0);
}
// IUnknown methods
ULONG __stdcall AddRef(void)
{
return InterlockedIncrement(&m_ulRefCount);
}
ULONG __stdcall Release(void)
{
ULONG ulRef = 0;
if(m_ulRefCount > 0)
{
ulRef = InterlockedDecrement(&m_ulRefCount);
}
if(ulRef == 0)
{
delete this;
}
return ulRef;
}
HRESULT __stdcall QueryInterface(
REFIID riid,
void** ppvObject)
{
HRESULT hr = S_OK;
do
{
if(ppvObject == NULL)
{
hr = E_POINTER;
break;
}
if(riid == IID_IUnknown)
{
*ppvObject = (IUnknown*)this;
}
else if(riid == IID_IClassFactory)
{
*ppvObject = (IClassFactory*)this;
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
break;
}
AddRef();
}while(false);
return hr;
}
HRESULT __stdcall CreateInstance(
IUnknown *pUnkOuter,
REFIID riid, void**
ppv)
{
HRESULT hr = S_OK;
IMFTransform* pHWMFT = NULL;
do
{
if (pUnkOuter != NULL)
{
// This MFT not support aggregation.
hr = CLASS_E_NOAGGREGATION;
break;
}
hr = CHWMFT::CreateInstance(&pHWMFT);
if(FAILED(hr))
{
break;
}
hr = pHWMFT->QueryInterface(riid,
ppv
);
if(FAILED(hr))
{
break;
}
}while(false);
SAFERELEASE(pHWMFT);
return hr;
}
HRESULT __stdcall LockServer(
BOOL bLock)
{
HRESULT hr = S_OK;
do
{
if(bLock != FALSE)
{
InterlockedIncrement(&m_ulServerLocks);
}
else
{
InterlockedDecrement(&m_ulServerLocks);
}
}while(false);
return hr;
}
};
#pragma endregion ClassFactory
#pragma region GlobalVariables
HMODULE g_hModule = NULL; // DLL module handle
volatile ULONG CHWMFT::m_ulNumObjects = 0; // Number of active COM objects
volatile ULONG ClassFactory::m_ulServerLocks = 0; // Number of server locks
#pragma endregion GlobalVariables
#pragma region HelperFunctions
HRESULT CreateObjectKeyName(
_In_ const GUID& guid,
_Out_writes_(dwMax) WCHAR* pwszName,
_In_ const DWORD dwMax)
{
HRESULT hr = S_OK;
do
{
if(pwszName == NULL)
{
hr = E_POINTER;
break;
}
if(StringCchPrintf(pwszName,
dwMax,
L"CLSID\\{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
guid.Data1,
guid.Data2,
guid.Data3,
guid.Data4[0],
guid.Data4[1],
guid.Data4[2],
guid.Data4[3],
guid.Data4[4],
guid.Data4[5],
guid.Data4[6],
guid.Data4[7]
) < 0)
{
hr = E_FAIL;
break;
}
}while(false);
return hr;
}
HRESULT SetKeyValue(
HKEY hKey,
const WCHAR* pwszName,
const WCHAR* pwszValue)
{
HRESULT hr = S_OK;
do
{
hr = HRESULT_FROM_WIN32(
RegSetValueEx(hKey,
pwszName,
0,
REG_SZ,
(BYTE*)pwszValue,
(DWORD)((wcslen(pwszValue) + 1) * sizeof(WCHAR))
)
);
if(FAILED(hr))
{
break;
}
}while(false);
return hr;
}
HRESULT RegisterObject(
const GUID& guid,
const WCHAR* pwszDescription,
const WCHAR* pwszThreadingModel)
{
HRESULT hr = S_OK;
HKEY hKey = NULL;
HKEY hSubkey = NULL;
DWORD dwFileNameLen = 0;
WCHAR pwszBuffer[MAX_PATH] = {0};
do
{
if(g_hModule == NULL)
{
hr = E_UNEXPECTED;
break;
}
// Create the name of the key from the object's CLSID
hr = CreateObjectKeyName(guid,
pwszBuffer,
sizeof(pwszBuffer) / sizeof(pwszBuffer[0])
);
if(FAILED(hr))
{
break;
}
// Create the new key.
hr = HRESULT_FROM_WIN32(
RegCreateKeyEx(
HKEY_CLASSES_ROOT,
pwszBuffer,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
)
);
if(FAILED(hr))
{
break;
}
hr = SetKeyValue(hKey,
NULL,
pwszDescription);
if(FAILED(hr))
{
break;
}
// Create the "InprocServer32" subkey
hr = HRESULT_FROM_WIN32(
RegCreateKeyEx(
hKey,
L"InprocServer32",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hSubkey,
NULL
)
);
// The default value for this subkey is the path to the DLL.
// Get the name of the module ...
dwFileNameLen = GetModuleFileName(g_hModule,
pwszBuffer,
MAX_PATH);
if (dwFileNameLen == 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else if (dwFileNameLen == MAX_PATH)
{
hr = E_FAIL; // buffer too small
}
if(FAILED(hr))
{
break;
}
// ... and set the default key value.
hr = SetKeyValue(hSubkey,
NULL,
pwszBuffer
);
if(FAILED(hr))
{
break;
}
// Add a new value to the subkey, for "ThreadingModel" = <threading model>
hr = SetKeyValue(hSubkey,
L"ThreadingModel",
pwszThreadingModel
);
if(FAILED(hr))
{
break;
}
}while(false);
SAFEREGCLOSEKEY(hSubkey);
SAFEREGCLOSEKEY(hKey);
return hr;
}
HRESULT UnregisterObject(
const GUID& guid)
{
HRESULT hr = S_OK;
WCHAR pwszBuffer[MAX_PATH] = {0};
do
{
hr = CreateObjectKeyName(guid,
pwszBuffer,
sizeof(pwszBuffer) / sizeof(pwszBuffer[0])
);
if(FAILED(hr))
{
break;
}
hr = HRESULT_FROM_WIN32(
RegDeleteTree(HKEY_CLASSES_ROOT,
pwszBuffer
)
);
if(FAILED(hr))
{
break;
}
}while(false);
return hr;
}
#pragma endregion HelperFunctions
#pragma region DLLFunctions
BOOL APIENTRY DllMain(
HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
g_hModule = (HMODULE)hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
// Nothing to do
break;
case DLL_PROCESS_DETACH:
break;
};
return TRUE;
}
HRESULT __stdcall DllCanUnloadNow(void)
{
HRESULT hr = S_FALSE;
do
{
if ((ClassFactory::IsLocked() != FALSE) || (CHWMFT::m_ulNumObjects != 0))
{
break;
}
hr = S_OK;
}while(false);
return hr;
}
HRESULT __stdcall DllRegisterServer(void)
{
HRESULT hr = S_OK;
MFT_REGISTER_TYPE_INFO* pmftrtiInput = NULL;
MFT_REGISTER_TYPE_INFO* pmftrtiOutput = NULL;
IMFAttributes* pMFTAttributes = NULL;
do
{
pmftrtiInput = new MFT_REGISTER_TYPE_INFO[g_dwNumInputTypes];
if(pmftrtiInput == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
pmftrtiOutput = new MFT_REGISTER_TYPE_INFO[g_dwNumOutputTypes];
if(pmftrtiOutput == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
for(DWORD i = 0; i < g_dwNumInputTypes; i++)
{
pmftrtiInput[i].guidMajorType = MFMediaType_Video;
pmftrtiInput[i].guidSubtype = *(g_ppguidInputTypes[i]);
}
for(DWORD i = 0; i < g_dwNumOutputTypes; i++)
{
pmftrtiOutput[i].guidMajorType = MFMediaType_Video;
pmftrtiOutput[i].guidSubtype = *(g_ppguidOutputTypes[i]);
}
/****************************************
** !!MSFT_TODO: Report as HW MFT
****************************************
// Since this is a HW MFT, we have to set MFT_CODEC_MERIT_Attribute
hr = MFCreateAttributes(&pMFTAttributes, 1);
if(FAILED(hr))
{
break;
}
hr = pMFTAttributes->SetUINT32(MFT_CODEC_MERIT_Attribute, MFT_CODEC_MERIT);
if(FAILED(hr))
{
break;
}
*/
// Register the object with COM
hr = RegisterObject(CLSID_MYMFT,
MY_MFT_NAME,
L"Both");
if(FAILED(hr))
{
break;
}
// Register the MFT with MF
hr = MFTRegister(
CLSID_MYMFT,
MFT_CATEGORY_VIDEO_DECODER, // This MFT acts as a video decoder
MY_MFT_NAME,
/****************************************
** !!MSFT_TODO: Report as HW MFT
****************************************
MFT_ENUM_FLAG_HARDWARE,*/ MFT_ENUM_FLAG_ASYNCMFT,
g_dwNumInputTypes,
pmftrtiInput,
g_dwNumOutputTypes,
pmftrtiOutput,
pMFTAttributes
);
if(FAILED(hr))
{
break;
}
}while(false);
SAFEARRAYDELETE(pmftrtiInput);
SAFEARRAYDELETE(pmftrtiOutput);
SAFERELEASE(pMFTAttributes);
return hr;
}
HRESULT __stdcall DllUnregisterServer(void)
{
UnregisterObject(CLSID_MYMFT);
return S_OK;
}
HRESULT __stdcall DllGetClassObject(
_In_ REFCLSID clsid,
_In_ REFIID riid,
_Outptr_ void** ppv)
{
HRESULT hr = S_OK;
ClassFactory* pFactory = NULL;
do
{
if (clsid != CLSID_MYMFT)
{
hr = CLASS_E_CLASSNOTAVAILABLE;
break;
}
pFactory = new ClassFactory();
if (pFactory == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
hr = pFactory->QueryInterface(riid, ppv);
if(FAILED(hr))
{
break;
}
}while(false);
SAFERELEASE(pFactory);
return hr;
}
#pragma endregion DLLFunctions

Просмотреть файл

@ -7,7 +7,9 @@
#include "Capture.h"
#include "resource.h"
#include "TransformAsync.h"
#include "CHWMFT/CHWMFT.h"
#include <winrt/Windows.Foundation.h>
#include <winrt/base.h>
IMFDXGIDeviceManager* g_pDXGIMan = NULL;
ID3D11Device* g_pDX11Device = NULL;
@ -396,8 +398,9 @@ HRESULT CaptureManager::StartPreview()
hr = TransformBlur::CreateInstance(NULL, __uuidof(IMFTransform), (void**)(&blur));
hr = blur->QueryInterface(__uuidof(IMFTransform), (void**)(&pMFT));*/
winrt::com_ptr<IMFTransform> pMFT;
hr = TransformAsync::CreateInstance(pMFT.put());
//winrt::com_ptr<CHWMFT> pMFT;
winrt::com_ptr<IMFTransform>pMFT;
hr = CHWMFT::CreateInstance(pMFT.put());
// IMFCaptureSource
hr = pSource->AddEffect(0, pMFT.get());

Просмотреть файл

@ -21,6 +21,7 @@ const FOURCC FOURCC_RGB32 = 22;
// static array of media types (preferred and accepted).
const GUID* g_MediaSubtypes[] =
{
&MFVideoFormat_YUY2,
&MFVideoFormat_RGB32
};
@ -101,10 +102,6 @@ HRESULT TransformAsync::QueryInterface(REFIID iid, void** ppv)
return E_POINTER;
}
if (iid == IID_IUnknown)
{
*ppv = static_cast<IUnknown*>(this);
}
else if (iid == __uuidof(IMFTransform))
{
*ppv = static_cast<IMFTransform*>(this);
@ -120,12 +117,18 @@ HRESULT TransformAsync::QueryInterface(REFIID iid, void** ppv)
}
else if (iid == IID_IMFMediaEventGenerator)
{
*ppv = static_cast<IMFMediaEventGenerator*>(this);
*ppv = (IMFMediaEventGenerator*)this;
// TODO: QI Correctly?
//*ppv = static_cast<IMFMediaEventGenerator*>(this);
}
else if (iid == IID_IMFAsyncCallback)
{
*ppv = static_cast<IMFAsyncCallback*>(this);
}
else if (iid == IID_IUnknown)
{
*ppv = static_cast<IUnknown*>(this);
}
else
{
*ppv = NULL;
@ -695,71 +698,40 @@ HRESULT TransformAsync::InitializeTransform(void)
HRESULT hr = S_OK;
do
{
hr = MFCreateAttributes(m_spAttributes.put(), MFT_NUM_DEFAULT_ATTRIBUTES);
if (FAILED(hr))
{
break;
}
CHECK_HR(hr = MFCreateAttributes(m_spAttributes.put(), MFT_NUM_DEFAULT_ATTRIBUTES));
CHECK_HR(hr = m_spAttributes->SetUINT32(MF_TRANSFORM_ASYNC, TRUE));
CHECK_HR(hr = m_spAttributes->SetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, TRUE));
/*CHECK_HR(hr = m_spAttributes->SetUINT32(MF_SA_D3D_AWARE, TRUE));
CHECK_HR(hr = m_spAttributes->SetUINT32(MF_SA_D3D11_AWARE, TRUE));*/
hr = m_spAttributes->SetUINT32(MF_TRANSFORM_ASYNC, TRUE);
if (FAILED(hr))
{
break;
}
// Initialize attributes for output sample allocator
CHECK_HR(hr = MFCreateAttributes(m_spOutputAttributes.put(), 3));
hr = m_spAttributes->SetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, TRUE);
if (FAILED(hr))
{
break;
}
hr = m_spAttributes->SetUINT32(MF_SA_D3D_AWARE, TRUE);
hr = m_spAttributes->SetUINT32(MF_SA_D3D11_AWARE, TRUE);
/**********************************
** Since this is an Async MFT, an
** event queue is required
** MF Provides a standard implementation
**********************************/
CHECK_HR(hr = MFCreateEventQueue(m_pEventQueue.put()));
/**********************************
** Since this is an Async MFT, an
** event queue is required
** MF Provides a standard implementation
**********************************/
hr = MFCreateEventQueue(m_pEventQueue.put());
if (FAILED(hr))
{
break;
}
CHECK_HR(hr = CSampleQueue::Create(&m_pInputSampleQueue));
hr = CSampleQueue::Create(&m_pInputSampleQueue);
if (FAILED(hr))
{
break;
}
CHECK_HR(hr = CSampleQueue::Create(&m_pOutputSampleQueue));
hr = CSampleQueue::Create(&m_pOutputSampleQueue);
if (FAILED(hr))
{
break;
}
/**********************************
** Since this is an Async MFT, all
** work will be done using standard
** MF Work Queues
**********************************/
hr = MFAllocateWorkQueueEx(MF_STANDARD_WORKQUEUE, &m_dwDecodeWorkQueueID);
if (FAILED(hr))
{
break;
}
// Set up circular queue of IStreamModels
for (int i = 0; i < m_numThreads; i++) {
// TODO: maybe styletransfer is the default model but have this change w/user input
m_models.push_back(std::make_unique<StyleTransfer>());
}
} while (false);
/**********************************
** Since this is an Async MFT, all
** work will be done using standard
** MF Work Queues
**********************************/
hr = MFAllocateWorkQueueEx(MF_STANDARD_WORKQUEUE, &m_dwDecodeWorkQueueID);
// Set up circular queue of IStreamModels
for (int i = 0; i < m_numThreads; i++) {
// TODO: maybe styletransfer is the default model but have this change w/user input
m_models.push_back(std::make_unique<StyleTransfer>());
}
done:
return hr;
}
@ -886,7 +858,6 @@ done:
HRESULT TransformAsync::ShutdownEventQueue(void)
{
HRESULT hr = S_OK;
do
{
/***************************************
@ -901,7 +872,7 @@ HRESULT TransformAsync::ShutdownEventQueue(void)
break;
}
} while (false);
LOG_HRESULT(hr);
return hr;
}
@ -931,7 +902,7 @@ HRESULT TransformAsync::OnStartOfStream(void)
}
} while (false);
LOG_HRESULT(hr);
return hr;
}
@ -954,7 +925,7 @@ HRESULT TransformAsync::OnEndOfStream(void)
m_dwNeedInputCount = 0;
} while (false);
LOG_HRESULT(hr);
return hr;
}
@ -1054,6 +1025,10 @@ HRESULT TransformAsync::RequestSample(
{
break;
}
if (pEvent == NULL)
{
TRACE((L"RequestSample: pEvent null not queueing anything!"));
}
hr = pEvent->SetUINT32(MF_EVENT_MFT_INPUT_STREAM_ID, un32StreamID);
if (FAILED(hr))
@ -1200,8 +1175,5 @@ HRESULT DuplicateAttributes(
} while (false);
PropVariantClear(&pv);
//TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Exit(hr=0x%x)", __FUNCTION__, hr);
return hr;
}

Просмотреть файл

@ -219,14 +219,7 @@ public:
);
#pragma endregion IMFAsyncCallback
// Frame transform function
// TODO: This will actually be in segmentmodel
HRESULT DoProcessSample(
DWORD dwFlags,
IMFSample** ppOutputSample,
DWORD* pdwSampleStatus,
DWORD* pdwOutputStatus
);
HRESULT SubmitEval(IMFSample* pInputSample);
protected:
TransformAsync(HRESULT& hr);
@ -234,6 +227,7 @@ protected:
// Destructor is private. The object deletes itself when the reference count is zero.
~TransformAsync();
HRESULT InitializeTransform(void);
HRESULT ShutdownEventQueue(void);
/******* MFT Helpers **********/
HRESULT OnGetPartialType(DWORD dwTypeIndex, IMFMediaType** ppmt);
@ -250,7 +244,7 @@ protected:
HRESULT UpdateDX11Device();
void InvalidateDX11Resources();
IDirect3DSurface SampleToD3Dsurface(IMFSample* sample);
HRESULT ShutdownEventQueue(void);
/******* MFT Media Event Handlers **********/
HRESULT OnStartOfStream(void);
@ -269,7 +263,6 @@ protected:
);
HRESULT FlushSamples(void);
HRESULT ScheduleFrameInference(void);
HRESULT SubmitEval(IMFSample* pInputSample);
HRESULT SendEvent(void);
BOOL IsLocked(void);
BOOL IsMFTReady(void); // TODO: Add calls in ProcessOutput, SetInput/OutputType

Просмотреть файл

@ -64,7 +64,7 @@ HRESULT TransformAsync::Invoke(
// Now that scheduler has told us to process this sample, call SubmitEval with next
// Available set of bindings, session.
// hr = pMFT->SubmitEval(m_p);
hr = pMFT->SubmitEval(pInputSample.get());
// hr = pAsyncResult->SetStatus(hr)
// TOOD: finish

Просмотреть файл

@ -178,7 +178,7 @@ HRESULT TransformAsync::GetAttributes(IMFAttributes** ppAttributes)
AutoLock lock(m_critSec);
*ppAttributes = m_spAttributes.detach();
*ppAttributes = m_spAttributes.get();
if ((*ppAttributes) == NULL)
{
return E_UNEXPECTED;
@ -846,7 +846,6 @@ HRESULT TransformAsync::ProcessInput(
CHECK_HR(hr = m_pInputSampleQueue->AddSample(pSample));
// Now schedule the work to decode the sample
// TODO: WHAT DO
CHECK_HR(hr = ScheduleFrameInference());
done:

Просмотреть файл

@ -1,10 +1,11 @@
#include "CHWMFT_DebugLogger.h"
#ifdef _HMFTLOGGING_
#include <evntrace.h>
#include <strsafe.h>
REGHANDLE g_ETWHandle = NULL;
BOOL g_bEnabled = FALSE;
BOOL g_bEnabled = TRUE;
UCHAR g_ucLevel = 0;
void NTAPI EventRegisterCallback(

Просмотреть файл

@ -1,5 +1,5 @@
#pragma once
#define _HMFTLOGGING_
#include <windows.h>
#ifdef _HMFTLOGGING_
#include <Evntprov.h>