Insert CHWMFT sample and try ot run
This commit is contained in:
Родитель
53f147b3a6
Коммит
5463991b65
|
@ -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>
|
||||
|
|
Загрузка…
Ссылка в новой задаче