├── AudioSourceReaderSeek ├── AudioSourceReaderSeek.sln ├── AudioSourceReaderSeek.vcxproj ├── AudioSourceReaderSeek.vcxproj.filters ├── AudioSourceReaderSeek.vcxproj.user └── Main.cpp ├── CustomVideoMixer ├── Common │ ├── MFClassFactory.h │ ├── MFCriticSection.h │ ├── MFGuid.h │ ├── MFLogCommon.h │ ├── MFLogMediaType.h │ ├── MFLogging.h │ ├── MFMacro.h │ ├── MFRegistry.h │ ├── MFTExternTrace.h │ └── MFTrace.h ├── CustomVideoMixer.sln ├── CustomVideoMixer │ ├── CustomVideoMixer.cpp │ ├── CustomVideoMixer.def │ ├── CustomVideoMixer.h │ ├── CustomVideoMixer.vcxproj │ ├── CustomVideoMixer.vcxproj.filters │ ├── CustomVideoMixer.vcxproj.user │ ├── CustomVideoMixer_Attributes.cpp │ ├── CustomVideoMixer_Bitmap.cpp │ ├── CustomVideoMixer_Mixer.cpp │ ├── CustomVideoMixer_Transform.cpp │ ├── CustomVideoMixer_Type.cpp │ ├── DllMain.cpp │ ├── Dxva2Manager.cpp │ ├── Dxva2Manager.h │ ├── StdAfx.cpp │ └── StdAfx.h └── TestCustomVideoMixer │ ├── Main.cpp │ ├── TestCustomVideoMixer.vcxproj │ ├── TestCustomVideoMixer.vcxproj.filters │ └── TestCustomVideoMixer.vcxproj.user ├── EncodeWithSourceReaderSinkWriter ├── EncodeWithSourceReaderSinkWriter.sln ├── EncodeWithSourceReaderSinkWriter.vcxproj ├── EncodeWithSourceReaderSinkWriter.vcxproj.filters ├── EncodeWithSourceReaderSinkWriter.vcxproj.user ├── MFGuid.h ├── MFLogCommon.h ├── MFLogMediaType.h ├── MFLogging.h ├── MFMacro.h ├── MFTExternTrace.h ├── MFTime.h ├── MFTrace.h ├── Main.cpp ├── StdAfx.cpp └── StdAfx.h ├── FrameRateConverterDSP ├── FrameRateConverterDSP.sln ├── FrameRateConverterDSP.vcxproj └── Main.cpp ├── IMFSinkWriterCallback ├── IMFSinkWriterCallback.sln ├── IMFSinkWriterCallback.vcxproj └── Main.cpp ├── LICENSE ├── MFMultiVideo ├── Common │ ├── MFLogging.h │ ├── MFMacro.h │ ├── MFTExternTrace.h │ └── MFTrace.h ├── MFMultiVideo.sln ├── MFMultiVideo.vcxproj ├── MFMultiVideo.vcxproj.filters ├── MFMultiVideo.vcxproj.user ├── Player.cpp ├── Player.h ├── StdAfx.cpp ├── StdAfx.h └── WinMain.cpp ├── MFVideoCaptureEVR ├── MFVideoCaptureEVR.sln ├── MFVideoCaptureEVR.vcxproj ├── MFVideoCaptureEVR.vcxproj.filters ├── MFVideoCaptureEVR.vcxproj.user └── Main.cpp ├── MFVideoEVR ├── MFVideoEVR.sln ├── MFVideoEVR.vcxproj ├── MFVideoEVR.vcxproj.user └── Main.cpp ├── Media ├── CustomVideoMixer.jpg ├── IMFSinkWriterCallback.jpg ├── MFMultiVideo.jpg └── ScreenCaptureEncode.jpg ├── MinimalSinkRenderer ├── Common │ ├── MFClassFactory.h │ ├── MFCriticSection.h │ ├── MFGuid.h │ ├── MFLogCommon.h │ ├── MFLogMediaType.h │ ├── MFLogging.h │ ├── MFMacro.h │ ├── MFRegistry.h │ ├── MFState.h │ ├── MFTExternTrace.h │ ├── MFTime.h │ └── MFTrace.h ├── MinimalSinkRenderer.sln ├── MinimalSinkRenderer │ ├── DllMain.cpp │ ├── MinimalSinkRenderer.vcxproj │ ├── MinimalSinkRenderer.vcxproj.filters │ ├── MinimalSinkRenderer.vcxproj.user │ ├── MinimalSkinkRenderer.cpp │ ├── MinimalSkinkRenderer.def │ ├── MinimalSkinkRenderer.h │ ├── MinimalSkinkRenderer_Clock.cpp │ ├── MinimalSkinkRenderer_Sink.cpp │ ├── StdAfx.cpp │ ├── StdAfx.h │ ├── StreamSkinkRenderer.cpp │ ├── StreamSkinkRenderer.h │ ├── StreamSkinkRenderer_Event.cpp │ ├── StreamSkinkRenderer_Sink.cpp │ └── StreamSkinkRenderer_Type.cpp └── TestMinimalSinkRenderer │ ├── Main.cpp │ ├── TestMinimalSinkRenderer.vcxproj │ ├── TestMinimalSinkRenderer.vcxproj.filters │ └── TestMinimalSinkRenderer.vcxproj.user ├── README.md ├── ScreenCaptureEncode ├── Main.cpp ├── ScreenCaptureEncode.sln └── ScreenCaptureEncode.vcxproj ├── TranscodeMp4ToMp4 ├── Main.cpp ├── TranscodeMp4ToMp4.sln └── TranscodeMp4ToMp4.vcxproj ├── VideoStabilizationMFT ├── MFGuid.h ├── MFLogCommon.h ├── MFLogMediaType.h ├── MFLogging.h ├── MFMacro.h ├── MFTExternTrace.h ├── MFTime.h ├── MFTrace.h ├── Main.cpp ├── StdAfx.cpp ├── StdAfx.h ├── VideoStabilizationMFT.sln ├── VideoStabilizationMFT.vcxproj ├── VideoStabilizationMFT.vcxproj.filters └── VideoStabilizationMFT.vcxproj.user └── WasapiCapture ├── MFLogging.h ├── MFMacro.h ├── MFTExternTrace.h ├── MFTrace.h ├── MFWaveWriter.cpp ├── MFWaveWriter.h ├── Main.cpp ├── StdAfx.cpp ├── StdAfx.h ├── WasapiCapture.sln ├── WasapiCapture.vcxproj ├── WasapiCapture.vcxproj.filters └── WasapiCapture.vcxproj.user /AudioSourceReaderSeek/AudioSourceReaderSeek.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AudioSourceReaderSeek", "AudioSourceReaderSeek.vcxproj", "{943C81EA-088B-4969-A03C-A990C9BD3E91}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {943C81EA-088B-4969-A03C-A990C9BD3E91}.Debug|x64.ActiveCfg = Debug|x64 17 | {943C81EA-088B-4969-A03C-A990C9BD3E91}.Debug|x64.Build.0 = Debug|x64 18 | {943C81EA-088B-4969-A03C-A990C9BD3E91}.Debug|x86.ActiveCfg = Debug|Win32 19 | {943C81EA-088B-4969-A03C-A990C9BD3E91}.Debug|x86.Build.0 = Debug|Win32 20 | {943C81EA-088B-4969-A03C-A990C9BD3E91}.Release|x64.ActiveCfg = Release|x64 21 | {943C81EA-088B-4969-A03C-A990C9BD3E91}.Release|x64.Build.0 = Release|x64 22 | {943C81EA-088B-4969-A03C-A990C9BD3E91}.Release|x86.ActiveCfg = Release|Win32 23 | {943C81EA-088B-4969-A03C-A990C9BD3E91}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {75EFBF0E-754D-4692-92FF-397497359B12} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /AudioSourceReaderSeek/AudioSourceReaderSeek.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Fichiers sources 20 | 21 | 22 | -------------------------------------------------------------------------------- /AudioSourceReaderSeek/AudioSourceReaderSeek.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /CustomVideoMixer/Common/MFClassFactory.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFClassFactory.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFCLASSFACTORY_H 5 | #define MFCLASSFACTORY_H 6 | 7 | typedef HRESULT (*CreateInstanceFn)(IUnknown*, REFIID, void**); 8 | 9 | struct ClassFactoryData{ 10 | 11 | const GUID* pclsid; 12 | CreateInstanceFn pfnCreate; 13 | }; 14 | 15 | class ClassFactory : public IClassFactory{ 16 | 17 | private: 18 | 19 | volatile long m_refCount; // Reference count. 20 | static volatile long m_serverLocks; // Number of server locks 21 | 22 | CreateInstanceFn m_pfnCreation; // Function to create an instance of the object. 23 | 24 | public: 25 | 26 | ClassFactory(CreateInstanceFn pfnCreation) : m_pfnCreation(pfnCreation), m_refCount(1){} 27 | 28 | static bool IsLocked(){ return (m_serverLocks != 0); } 29 | 30 | STDMETHODIMP_(ULONG) AddRef(){ return InterlockedIncrement(&m_refCount); } 31 | STDMETHODIMP_(ULONG) Release(){ 32 | 33 | assert(m_refCount >= 0); 34 | ULONG uCount = InterlockedDecrement(&m_refCount); 35 | 36 | if(uCount == 0){ 37 | delete this; 38 | } 39 | 40 | return uCount; 41 | } 42 | 43 | STDMETHODIMP QueryInterface(REFIID riid, void** ppv){ 44 | 45 | if(NULL == ppv){ 46 | return E_POINTER; 47 | } 48 | else if(riid == __uuidof(IUnknown)){ 49 | *ppv = static_cast(this); 50 | } 51 | else if(riid == __uuidof(IClassFactory)){ 52 | *ppv = static_cast(this); 53 | } 54 | else{ 55 | *ppv = NULL; 56 | return E_NOINTERFACE; 57 | } 58 | 59 | AddRef(); 60 | return S_OK; 61 | } 62 | 63 | STDMETHODIMP CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppv){ 64 | 65 | if(pUnkOuter != NULL){ 66 | 67 | if(riid != __uuidof(IUnknown)){ 68 | return E_NOINTERFACE; 69 | } 70 | } 71 | 72 | return m_pfnCreation(pUnkOuter, riid, ppv); 73 | } 74 | 75 | STDMETHODIMP LockServer(BOOL lock){ 76 | 77 | if(lock){ 78 | LockServer(); 79 | } 80 | else{ 81 | UnlockServer(); 82 | } 83 | return S_OK; 84 | } 85 | 86 | static void LockServer(){ InterlockedIncrement(&m_serverLocks); } 87 | static void UnlockServer(){ InterlockedDecrement(&m_serverLocks); } 88 | }; 89 | 90 | class BaseObject{ 91 | 92 | public: 93 | 94 | BaseObject(){ ClassFactory::LockServer(); } 95 | virtual ~BaseObject(){ ClassFactory::UnlockServer(); } 96 | }; 97 | 98 | #define DEFINE_CLASSFACTORY_SERVER_LOCK volatile long ClassFactory::m_serverLocks = 0; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /CustomVideoMixer/Common/MFCriticSection.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFCriticSection.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFCRITICSECTION_H 5 | #define MFCRITICSECTION_H 6 | 7 | class CriticSection{ 8 | 9 | private: 10 | 11 | CRITICAL_SECTION m_Section; 12 | 13 | public: 14 | 15 | CriticSection(){ InitializeCriticalSection(&m_Section); } 16 | ~CriticSection(){ DeleteCriticalSection(&m_Section); } 17 | 18 | void Lock(){ EnterCriticalSection(&m_Section); } 19 | void Unlock(){ LeaveCriticalSection(&m_Section); } 20 | }; 21 | 22 | class AutoLock{ 23 | 24 | private: 25 | 26 | CriticSection* m_pSection; 27 | 28 | public: 29 | 30 | AutoLock(CriticSection& critic){ m_pSection = &critic; m_pSection->Lock(); } 31 | ~AutoLock(){ m_pSection->Unlock(); } 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /CustomVideoMixer/Common/MFGuid.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFGuid.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFGUID_H 5 | #define MFGUID_H 6 | 7 | // {B2F74C92-79DF-45DE-9C55-A99DE8276679} 8 | DEFINE_GUID(CLSID_CustomVideoMixer, 0xb2f74c92, 0x79df, 0x45de, 0x9c, 0x55, 0xa9, 0x9d, 0xe8, 0x27, 0x66, 0x79); 9 | 10 | //---------------------------------------------------------------------------------------------- 11 | // Media subType guid 12 | 13 | // {7634706D-0000-0010-8000-00AA00389B71} 14 | DEFINE_GUID(MEDIASUBTYPE_mp4v, 0x7634706d, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 15 | 16 | // 56564D41-0000-0010-8000-00AA00389B71 17 | DEFINE_GUID(MEDIASUBTYPE_XVID, 0x44495658, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 18 | 19 | // {64697678-0000-0010-8000-00AA00389B71} 20 | DEFINE_GUID(MEDIASUBTYPE_xvid, 0x64697678, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 21 | 22 | // {58564944-0000-0010-8000-00AA00389B71} 23 | DEFINE_GUID(MEDIASUBTYPE_DIVX, 0x58564944, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 24 | 25 | // {78766964-0000-0010-8000-00AA00389B71} 26 | DEFINE_GUID(MEDIASUBTYPE_divx, 0x78766964, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 27 | 28 | // {30355844-0000-0010-8000-00aa00389b71} 29 | DEFINE_GUID(MEDIASUBTYPE_DX50, 0x30355844, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 30 | 31 | // {30357864-0000-0010-8000-00AA00389B71} 32 | DEFINE_GUID(MEDIASUBTYPE_dx50, 0x30357864, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 33 | 34 | // {1D4A45F2-E5F6-4B44-8388-F0AE5C0E0C37} 35 | DEFINE_GUID(MEDIASUBTYPE_VIDEOIMAGE, 0x1D4A45F2, 0xE5F6, 0x4B44, 0x83, 0x88, 0xF0, 0xAE, 0x5C, 0x0E, 0x0C, 0x37); 36 | 37 | // {00000031-0000-0010-8000-00AA00389B71} 38 | DEFINE_GUID(MEDIASUBTYPE_GSM, 0x00000031, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 39 | 40 | // {00000011-0000-0010-8000-00AA00389B71} 41 | DEFINE_GUID(MEDIASUBTYPE_IMAADPCMACM, 0x00000011, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 42 | 43 | #endif -------------------------------------------------------------------------------- /CustomVideoMixer/Common/MFLogCommon.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogCommon.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGCOMMON_H 5 | #define MFLOGCOMMON_H 6 | 7 | #if (_DEBUG && MF_USE_LOGGING) 8 | 9 | typedef LPCWSTR(*GetGUIDStringName)(const GUID&); 10 | 11 | inline void LogGuidHexa(const GUID& guid, const BOOL bFirst){ 12 | 13 | HRESULT hr; 14 | WCHAR pBuffer[39] = {0}; 15 | 16 | hr = StringCchPrintf(pBuffer, 39, L"{%.8lX-%.4hX-%.4hX-%.2hhX%.2hhX-%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX}", 17 | guid.Data1, 18 | guid.Data2, 19 | guid.Data3, 20 | guid.Data4[0], 21 | guid.Data4[1], 22 | guid.Data4[2], 23 | guid.Data4[3], 24 | guid.Data4[4], 25 | guid.Data4[5], 26 | guid.Data4[6], 27 | guid.Data4[7] 28 | ); 29 | 30 | if(SUCCEEDED(hr)){ 31 | 32 | if(bFirst) 33 | TRACE_NO_END_LINE((L"\t%s\t", pBuffer)); 34 | else 35 | TRACE((L"%s", pBuffer)); 36 | } 37 | else{ 38 | 39 | TRACE((L"Guid problem")); 40 | } 41 | } 42 | 43 | inline void LogUINT32AsUINT64(const PROPVARIANT& var){ 44 | 45 | UINT32 uHigh = 0, uLow = 0; 46 | 47 | Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &uHigh, &uLow); 48 | 49 | TRACE((L"%u x %u", uHigh, uLow)); 50 | } 51 | 52 | inline HRESULT SpecialCaseAttributeValue(GUID guid, const PROPVARIANT& var){ 53 | 54 | if(guid == MF_MT_FRAME_RATE){ 55 | LogUINT32AsUINT64(var); 56 | } 57 | else if(guid == MF_MT_FRAME_SIZE){ 58 | LogUINT32AsUINT64(var); 59 | } 60 | else if(guid == MF_MT_PIXEL_ASPECT_RATIO){ 61 | LogUINT32AsUINT64(var); 62 | } 63 | else{ 64 | return S_FALSE; 65 | } 66 | 67 | return S_OK; 68 | } 69 | 70 | inline void LogPropertyVariant(const GUID* pGuid, const PROPVARIANT& var, GetGUIDStringName pGetGUIDString){ 71 | 72 | HRESULT hr = S_FALSE; 73 | 74 | if(pGuid != NULL) 75 | hr = SpecialCaseAttributeValue(*pGuid, var); 76 | 77 | if(hr == S_FALSE){ 78 | 79 | switch(var.vt){ 80 | 81 | case VT_UI4: 82 | TRACE((L"%lu", var.ulVal)); 83 | break; 84 | 85 | case VT_I4: 86 | TRACE((L"%ld", var.lVal)); 87 | break; 88 | 89 | case VT_UI8: 90 | TRACE((L"%I64u", var.uhVal)); 91 | break; 92 | 93 | case VT_BOOL: 94 | TRACE((L"%s", var.boolVal == -1 ? "true" : "false")); 95 | break; 96 | 97 | case VT_R8: 98 | TRACE((L"%f", var.dblVal)); 99 | break; 100 | 101 | case VT_CLSID: 102 | { 103 | LPCWSTR pwszGuidName = pGetGUIDString(*var.puuid); 104 | 105 | if(pwszGuidName != NULL){ 106 | TRACE((L"%s", pwszGuidName)); 107 | } 108 | else{ 109 | LogGuidHexa(*var.puuid, FALSE); 110 | } 111 | } 112 | break; 113 | 114 | case VT_LPWSTR: 115 | // Log : var.pwszVal 116 | TRACE((L"VT_LPWSTR = todo")); 117 | break; 118 | 119 | case VT_VECTOR | VT_UI1: 120 | TRACE((L"(VT_VECTOR|VT_UI1) = <>")); 121 | break; 122 | 123 | case VT_UNKNOWN: 124 | TRACE((L"VT_UNKNOWN = IUnknown")); 125 | break; 126 | 127 | case VT_EMPTY: 128 | TRACE((L"VT_EMPTY")); 129 | break; 130 | 131 | case VT_R4: 132 | TRACE((L"VT_R4 = %f", var.fltVal)); 133 | break; 134 | 135 | // 8195 = VT_ARRAY | VT_I4 136 | 137 | default: 138 | TRACE((L"Unexpected attribute type (vt = %hu)", var.vt)); 139 | break; 140 | } 141 | } 142 | } 143 | 144 | inline void LogAttributeValueByIndex(IMFAttributes* pAttributes, UINT32 uiIndex, GetGUIDStringName pGetGUIDString){ 145 | 146 | HRESULT hr; 147 | PROPVARIANT var; 148 | GUID guid = GUID_NULL; 149 | 150 | PropVariantInit(&var); 151 | 152 | hr = pAttributes->GetItemByIndex(uiIndex, &guid, &var); 153 | 154 | if(SUCCEEDED(hr)){ 155 | 156 | LPCWSTR pwszGUIDNameAttributes = pGetGUIDString(guid); 157 | 158 | if(pwszGUIDNameAttributes != NULL){ 159 | TRACE_NO_END_LINE((L"\t%s\t", pwszGUIDNameAttributes)); 160 | } 161 | else{ 162 | 163 | LogGuidHexa(guid, TRUE); 164 | } 165 | 166 | LogPropertyVariant(&guid, var, pGetGUIDString); 167 | } 168 | else{ 169 | TRACE((L"\tGetItemByIndex (Index = %u) hr = %s", uiIndex, MFErrorString(hr))); 170 | } 171 | 172 | PropVariantClear(&var); 173 | } 174 | 175 | #endif 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /CustomVideoMixer/Common/MFLogging.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogging.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGGING_H 5 | #define MFLOGGING_H 6 | 7 | #ifdef _DEBUG 8 | 9 | class DebugLog{ 10 | 11 | public: 12 | 13 | static void Initialize(){ 14 | _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); 15 | //_CrtSetBreakAlloc(155); 16 | } 17 | 18 | static void Trace(const WCHAR* sFormatString, ...){ 19 | 20 | HRESULT hr = S_OK; 21 | va_list va; 22 | 23 | const DWORD TRACE_STRING_LEN = 512; 24 | 25 | WCHAR message[TRACE_STRING_LEN]; 26 | 27 | va_start(va, sFormatString); 28 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 29 | va_end(va); 30 | 31 | if(SUCCEEDED(hr)){ 32 | 33 | size_t size = _tcslen(message); 34 | 35 | if(size != 0 && size < TRACE_STRING_LEN){ 36 | message[size] = '\n'; 37 | message[size + 1] = '\0'; 38 | } 39 | 40 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 41 | } 42 | } 43 | 44 | static void TraceNoEndLine(const WCHAR* sFormatString, ...){ 45 | 46 | HRESULT hr = S_OK; 47 | va_list va; 48 | 49 | const DWORD TRACE_STRING_LEN = 512; 50 | 51 | WCHAR message[TRACE_STRING_LEN]; 52 | 53 | va_start(va, sFormatString); 54 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 55 | va_end(va); 56 | 57 | if(SUCCEEDED(hr)){ 58 | 59 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 60 | } 61 | } 62 | 63 | static void Close(){ 64 | int bLeak = _CrtDumpMemoryLeaks(); 65 | assert(bLeak == FALSE); 66 | } 67 | }; 68 | 69 | #define TRACE_INIT() DebugLog::Initialize() 70 | #define TRACE(x) DebugLog::Trace x 71 | #define TRACE_NO_END_LINE(x) DebugLog::TraceNoEndLine x 72 | #define TRACE_CLOSE() DebugLog::Close() 73 | 74 | inline HRESULT _LOG_HRESULT(HRESULT hr, const char* sFileName, long lLineNo){ 75 | 76 | if(FAILED(hr)){ 77 | TRACE((L"\n%S - Line: %d hr = %s\n", sFileName, lLineNo, MFErrorString(hr))); 78 | } 79 | 80 | return hr; 81 | } 82 | 83 | #define LOG_HRESULT(hr) _LOG_HRESULT(hr, __FILE__, __LINE__) 84 | #define LOG_LAST_ERROR() _LOG_HRESULT(HRESULT_FROM_WIN32(GetLastError()), __FILE__, __LINE__) 85 | 86 | #ifdef MF_USE_LOGREFCOUNT 87 | #define TRACE_REFCOUNT(x) DebugLog::Trace x 88 | #else 89 | #define TRACE_REFCOUNT(x) 90 | #endif 91 | 92 | #ifdef MF_TRACE_TRANSFORM 93 | #define TRACE_TRANSFORM(x) DebugLog::Trace x 94 | #else 95 | #define TRACE_TRANSFORM(x) 96 | #endif 97 | 98 | #else 99 | #define TRACE_INIT() 100 | #define TRACE(x) 101 | #define TRACE_NO_END_LINE(x) 102 | #define TRACE_CLOSE() 103 | #define LOG_HRESULT(hr) hr 104 | #define LOG_LAST_ERROR() 105 | #define TRACE_REFCOUNT(x) 106 | #define TRACE_TRANSFORM(x) 107 | #endif 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /CustomVideoMixer/Common/MFMacro.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFMacro.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFMACRO_H 5 | #define MFMACRO_H 6 | 7 | #ifndef MF_SAFE_RELEASE 8 | #define MF_SAFE_RELEASE 9 | template inline void SAFE_RELEASE(T*& p){ 10 | 11 | if(p){ 12 | p->Release(); 13 | p = NULL; 14 | } 15 | } 16 | #endif 17 | 18 | #ifndef MF_SAFE_DELETE 19 | #define MF_SAFE_DELETE 20 | template inline void SAFE_DELETE(T*& p){ 21 | 22 | if(p){ 23 | delete p; 24 | p = NULL; 25 | } 26 | } 27 | #endif 28 | 29 | #ifndef MF_SAFE_DELETE_ARRAY 30 | #define MF_SAFE_DELETE_ARRAY 31 | template inline void SAFE_DELETE_ARRAY(T*& p){ 32 | 33 | if(p){ 34 | delete[] p; 35 | p = NULL; 36 | } 37 | } 38 | #endif 39 | 40 | // Need to use other macro. When error, multiple call. 41 | #ifndef IF_FAILED_RETURN 42 | #if(_DEBUG && MF_USE_LOGGING) 43 | #define IF_FAILED_RETURN(hr) if(FAILED(hr)){ LOG_HRESULT(hr); return hr; } 44 | #else 45 | #define IF_FAILED_RETURN(hr) if(FAILED(hr)){ return hr; } 46 | #endif 47 | #endif 48 | 49 | #ifndef IF_FAILED_THROW 50 | #if(_DEBUG && MF_USE_LOGGING) 51 | #define IF_FAILED_THROW(hr) if(FAILED(hr)){ LOG_HRESULT(hr); throw hr; } 52 | #else 53 | #define IF_FAILED_THROW(hr) if(FAILED(hr)){ throw hr; } 54 | #endif 55 | #endif 56 | 57 | #ifndef ARRAY_SIZE 58 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]) ) 59 | #endif 60 | 61 | #ifndef RETURN_STRING 62 | #define RETURN_STRING(x) case x: return L#x 63 | #endif 64 | 65 | #ifndef IF_EQUAL_RETURN 66 | #define IF_EQUAL_RETURN(param, val) if(val == param) return L#val 67 | #endif 68 | 69 | #ifndef VALUE_NOT_FOUND 70 | #define VALUE_NOT_FOUND(val) return L#val 71 | #endif 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /CustomVideoMixer/Common/MFTExternTrace.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFTExternTrace.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFTEXTERNTRACE_H 5 | #define MFTEXTERNTRACE_H 6 | 7 | // CExternTrace initializes the memory leaks detection (see "crtdbg.h"). 8 | // CExternTrace ensures that no object is allocated before TRACE_INIT is called. 9 | // Because DllMain.cpp contains external objects, you will see "FAKE" memory leaks. 10 | #ifdef _DEBUG 11 | 12 | class CExternTrace{ 13 | 14 | public: 15 | 16 | CExternTrace(){ TRACE_INIT(); }; 17 | ~CExternTrace(){ TRACE_CLOSE(); }; 18 | }; 19 | 20 | CExternTrace cExternTrace; 21 | 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CustomVideoMixer", "CustomVideoMixer\CustomVideoMixer.vcxproj", "{465730C8-22A8-4E4C-A3B6-B7D1F8F6D359}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{97ADAD4A-E363-42CE-95D8-AFE2939F1DE5}" 9 | ProjectSection(SolutionItems) = preProject 10 | Common\MFClassFactory.h = Common\MFClassFactory.h 11 | Common\MFCriticSection.h = Common\MFCriticSection.h 12 | Common\MFGuid.h = Common\MFGuid.h 13 | Common\MFLogCommon.h = Common\MFLogCommon.h 14 | Common\MFLogging.h = Common\MFLogging.h 15 | Common\MFLogMediaType.h = Common\MFLogMediaType.h 16 | Common\MFMacro.h = Common\MFMacro.h 17 | Common\MFRegistry.h = Common\MFRegistry.h 18 | Common\MFTExternTrace.h = Common\MFTExternTrace.h 19 | Common\MFTrace.h = Common\MFTrace.h 20 | EndProjectSection 21 | EndProject 22 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCustomVideoMixer", "TestCustomVideoMixer\TestCustomVideoMixer.vcxproj", "{DC45D0F4-780B-4B9E-A449-A9B27E176029}" 23 | EndProject 24 | Global 25 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 26 | Debug|x64 = Debug|x64 27 | Debug|x86 = Debug|x86 28 | Release|x64 = Release|x64 29 | Release|x86 = Release|x86 30 | EndGlobalSection 31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 32 | {465730C8-22A8-4E4C-A3B6-B7D1F8F6D359}.Debug|x64.ActiveCfg = Debug|x64 33 | {465730C8-22A8-4E4C-A3B6-B7D1F8F6D359}.Debug|x64.Build.0 = Debug|x64 34 | {465730C8-22A8-4E4C-A3B6-B7D1F8F6D359}.Debug|x86.ActiveCfg = Debug|Win32 35 | {465730C8-22A8-4E4C-A3B6-B7D1F8F6D359}.Debug|x86.Build.0 = Debug|Win32 36 | {465730C8-22A8-4E4C-A3B6-B7D1F8F6D359}.Release|x64.ActiveCfg = Release|x64 37 | {465730C8-22A8-4E4C-A3B6-B7D1F8F6D359}.Release|x64.Build.0 = Release|x64 38 | {465730C8-22A8-4E4C-A3B6-B7D1F8F6D359}.Release|x86.ActiveCfg = Release|Win32 39 | {465730C8-22A8-4E4C-A3B6-B7D1F8F6D359}.Release|x86.Build.0 = Release|Win32 40 | {DC45D0F4-780B-4B9E-A449-A9B27E176029}.Debug|x64.ActiveCfg = Debug|x64 41 | {DC45D0F4-780B-4B9E-A449-A9B27E176029}.Debug|x64.Build.0 = Debug|x64 42 | {DC45D0F4-780B-4B9E-A449-A9B27E176029}.Debug|x86.ActiveCfg = Debug|Win32 43 | {DC45D0F4-780B-4B9E-A449-A9B27E176029}.Debug|x86.Build.0 = Debug|Win32 44 | {DC45D0F4-780B-4B9E-A449-A9B27E176029}.Release|x64.ActiveCfg = Release|x64 45 | {DC45D0F4-780B-4B9E-A449-A9B27E176029}.Release|x64.Build.0 = Release|x64 46 | {DC45D0F4-780B-4B9E-A449-A9B27E176029}.Release|x86.ActiveCfg = Release|Win32 47 | {DC45D0F4-780B-4B9E-A449-A9B27E176029}.Release|x86.Build.0 = Release|Win32 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | GlobalSection(ExtensibilityGlobals) = postSolution 53 | SolutionGuid = {836B91E2-F32C-4E61-9DCD-53B3BF5BD9D8} 54 | EndGlobalSection 55 | EndGlobal 56 | -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/CustomVideoMixer.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllCanUnloadNow PRIVATE 3 | DllRegisterServer PRIVATE 4 | DllUnregisterServer PRIVATE 5 | DllGetClassObject PRIVATE -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/CustomVideoMixer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Fichiers sources 20 | 21 | 22 | Fichiers sources 23 | 24 | 25 | Fichiers sources 26 | 27 | 28 | Fichiers sources 29 | 30 | 31 | Fichiers sources 32 | 33 | 34 | Fichiers sources 35 | 36 | 37 | Fichiers sources 38 | 39 | 40 | Fichiers sources 41 | 42 | 43 | Fichiers sources 44 | 45 | 46 | 47 | 48 | Fichiers d%27en-tête 49 | 50 | 51 | Fichiers d%27en-tête 52 | 53 | 54 | Fichiers d%27en-tête 55 | 56 | 57 | 58 | 59 | Fichiers de ressources 60 | 61 | 62 | -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/CustomVideoMixer.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/CustomVideoMixer_Bitmap.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // CustomVideoMixer_Bitmap.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | HRESULT CCustomVideoMixer::ClearAlphaBitmap() { 7 | 8 | TRACE_TRANSFORM((L"CustomVideoMixer::ClearAlphaBitmap")); 9 | 10 | return E_NOTIMPL; 11 | } 12 | 13 | HRESULT CCustomVideoMixer::GetAlphaBitmapParameters(MFVideoAlphaBitmapParams* /*pBmpParms*/) { 14 | 15 | TRACE_TRANSFORM((L"CustomVideoMixer::GetAlphaBitmapParameters")); 16 | 17 | return E_NOTIMPL; 18 | } 19 | 20 | HRESULT CCustomVideoMixer::SetAlphaBitmap(const MFVideoAlphaBitmap* /*pBmpParms*/) { 21 | 22 | TRACE_TRANSFORM((L"CustomVideoMixer::SetAlphaBitmap")); 23 | 24 | return E_NOTIMPL; 25 | } 26 | 27 | HRESULT CCustomVideoMixer::UpdateAlphaBitmapParameters(const MFVideoAlphaBitmapParams* /*pBmpParms*/) { 28 | 29 | TRACE_TRANSFORM((L"CustomVideoMixer::UpdateAlphaBitmapParameters")); 30 | 31 | return E_NOTIMPL; 32 | } 33 | 34 | HRESULT CCustomVideoMixer::MapOutputCoordinateToInputStream(float /*xOut*/, float /*yOut*/, DWORD /*dwOutputStreamIndex*/, DWORD /*dwInputStreamIndex*/, float* /*pxIn*/, float* /*pyIn*/) { 35 | 36 | TRACE_TRANSFORM((L"CustomVideoMixer::MapOutputCoordinateToInputStream")); 37 | 38 | return E_NOTIMPL; 39 | } -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/CustomVideoMixer_Mixer.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // CustomVideoMixer_Transform.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | HRESULT CCustomVideoMixer::GetStreamOutputRect(DWORD, MFVideoNormalizedRect*) { 7 | 8 | TRACE_TRANSFORM((L"CustomVideoMixer::GetStreamOutputRect")); 9 | 10 | return S_OK; 11 | } 12 | 13 | HRESULT CCustomVideoMixer::GetStreamZOrder(DWORD, DWORD*) { 14 | 15 | TRACE_TRANSFORM((L"CustomVideoMixer::GetStreamZOrder")); 16 | 17 | return S_OK; 18 | } 19 | 20 | HRESULT CCustomVideoMixer::SetStreamOutputRect(DWORD, const MFVideoNormalizedRect*) { 21 | 22 | TRACE_TRANSFORM((L"CustomVideoMixer::SetStreamOutputRect")); 23 | 24 | return S_OK; 25 | } 26 | 27 | HRESULT CCustomVideoMixer::SetStreamZOrder(DWORD, DWORD) { 28 | 29 | TRACE_TRANSFORM((L"CustomVideoMixer::SetStreamZOrder")); 30 | 31 | return S_OK; 32 | } 33 | 34 | HRESULT CCustomVideoMixer::GetAvailableVideoProcessorModes(UINT*, GUID**) { 35 | 36 | TRACE_TRANSFORM((L"CustomVideoMixer::GetAvailableVideoProcessorModes")); 37 | 38 | return S_OK; 39 | } 40 | 41 | HRESULT CCustomVideoMixer::GetBackgroundColor(COLORREF*) { 42 | 43 | TRACE_TRANSFORM((L"CustomVideoMixer::GetBackgroundColor")); 44 | 45 | return S_OK; 46 | } 47 | 48 | HRESULT CCustomVideoMixer::GetFilteringRange(DWORD, DXVA2_ValueRange*) { 49 | 50 | TRACE_TRANSFORM((L"CustomVideoMixer::GetFilteringRange")); 51 | 52 | return S_OK; 53 | } 54 | 55 | HRESULT CCustomVideoMixer::GetFilteringValue(DWORD, DXVA2_Fixed32*) { 56 | 57 | TRACE_TRANSFORM((L"CustomVideoMixer::GetFilteringValue")); 58 | 59 | return S_OK; 60 | } 61 | 62 | HRESULT CCustomVideoMixer::GetProcAmpRange(DWORD, DXVA2_ValueRange*) { 63 | 64 | TRACE_TRANSFORM((L"CustomVideoMixer::GetProcAmpRange")); 65 | 66 | return S_OK; 67 | } 68 | 69 | HRESULT CCustomVideoMixer::GetProcAmpValues(DWORD, DXVA2_ProcAmpValues*) { 70 | 71 | TRACE_TRANSFORM((L"CustomVideoMixer::GetProcAmpValues")); 72 | 73 | return S_OK; 74 | } 75 | 76 | HRESULT CCustomVideoMixer::GetVideoProcessorCaps(LPGUID, DXVA2_VideoProcessorCaps*) { 77 | 78 | TRACE_TRANSFORM((L"CustomVideoMixer::GetVideoProcessorCaps")); 79 | 80 | return S_OK; 81 | } 82 | 83 | HRESULT CCustomVideoMixer::GetVideoProcessorMode(LPGUID) { 84 | 85 | TRACE_TRANSFORM((L"CustomVideoMixer::GetVideoProcessorMode")); 86 | 87 | return S_OK; 88 | } 89 | 90 | HRESULT CCustomVideoMixer::SetBackgroundColor(COLORREF) { 91 | 92 | TRACE_TRANSFORM((L"CustomVideoMixer::SetBackgroundColor")); 93 | 94 | return S_OK; 95 | } 96 | 97 | HRESULT CCustomVideoMixer::SetFilteringValue(DWORD, DXVA2_Fixed32*) { 98 | 99 | TRACE_TRANSFORM((L"CustomVideoMixer::SetFilteringValue")); 100 | 101 | return S_OK; 102 | } 103 | 104 | HRESULT CCustomVideoMixer::SetProcAmpValues(DWORD, DXVA2_ProcAmpValues*) { 105 | 106 | TRACE_TRANSFORM((L"CustomVideoMixer::SetProcAmpValues")); 107 | 108 | return S_OK; 109 | } 110 | 111 | HRESULT CCustomVideoMixer::SetVideoProcessorMode(LPGUID) { 112 | 113 | TRACE_TRANSFORM((L"CustomVideoMixer::SetVideoProcessorMode")); 114 | 115 | return S_OK; 116 | } -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/CustomVideoMixer_Type.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // CustomVideoMixer_Type.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | HRESULT CCustomVideoMixer::GetOutputType(IMFMediaType** ppType) { 7 | 8 | TRACE_TRANSFORM((L"CustomVideoMixer::GetOutputType")); 9 | 10 | HRESULT hr = S_OK; 11 | IMFMediaType* pOutputType = NULL; 12 | 13 | try { 14 | 15 | IF_FAILED_THROW(hr = MFCreateMediaType(&pOutputType)); 16 | 17 | IF_FAILED_THROW(hr = pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); 18 | // MFVideoFormat_ARGB32 MFVideoFormat_RGB32 19 | IF_FAILED_THROW(hr = pOutputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32)); 20 | IF_FAILED_THROW(hr = pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE)); 21 | IF_FAILED_THROW(hr = pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)); 22 | IF_FAILED_THROW(hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)); 23 | IF_FAILED_THROW(hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1)); 24 | 25 | *ppType = pOutputType; 26 | (*ppType)->AddRef(); 27 | } 28 | catch (HRESULT) {} 29 | 30 | SAFE_RELEASE(pOutputType); 31 | return hr; 32 | } 33 | 34 | HRESULT CCustomVideoMixer::OnCheckInputType(IMFMediaType** ppInptuType, IMFMediaType* pmt, const GUID gFormatSubType) { 35 | 36 | TRACE_TRANSFORM((L"CustomVideoMixer::OnCheckInputType")); 37 | 38 | HRESULT hr = S_OK; 39 | 40 | if (ppInptuType && *ppInptuType) { 41 | 42 | DWORD dwFlags = 0; 43 | 44 | if ((*ppInptuType)->IsEqual(pmt, &dwFlags) == S_OK) { 45 | return hr; 46 | } 47 | else { 48 | IF_FAILED_RETURN(hr = MF_E_INVALIDTYPE); 49 | // Todo 50 | //SAFE_RELEASE(pInptuType); 51 | //SAFE_RELEASE(m_pOutputType); 52 | //Flush(); 53 | } 54 | } 55 | 56 | GUID majortype = { 0 }; 57 | GUID subtype = { 0 }; 58 | UINT32 width = 0; 59 | UINT32 height = 0; 60 | 61 | IF_FAILED_RETURN(hr = pmt->GetMajorType(&majortype)); 62 | IF_FAILED_RETURN(hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype)); 63 | IF_FAILED_RETURN(hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &width, &height)); 64 | 65 | IF_FAILED_RETURN(hr = (majortype != MFMediaType_Video ? MF_E_INVALIDTYPE : S_OK)); 66 | IF_FAILED_RETURN(hr = (subtype != gFormatSubType ? MF_E_INVALIDTYPE : S_OK)); 67 | 68 | // Todo : check width = 0/height = 0 69 | IF_FAILED_RETURN(hr = ((width > MAX_VIDEO_WIDTH_HEIGHT || height > MAX_VIDEO_WIDTH_HEIGHT) ? MF_E_INVALIDTYPE : S_OK)); 70 | 71 | return hr; 72 | } 73 | 74 | HRESULT CCustomVideoMixer::OnSetInputType(IMFMediaType** ppInptuType, IMFMediaType* pType) { 75 | 76 | TRACE_TRANSFORM((L"CustomVideoMixer::OnSetInputType")); 77 | 78 | HRESULT hr = S_OK; 79 | GUID subtype = { 0 }; 80 | 81 | SAFE_RELEASE(*ppInptuType); 82 | 83 | IF_FAILED_RETURN(hr = pType->GetGUID(MF_MT_SUBTYPE, &subtype)); 84 | 85 | *ppInptuType = pType; 86 | (*ppInptuType)->AddRef(); 87 | 88 | return hr; 89 | } 90 | 91 | HRESULT CCustomVideoMixer::OnCheckOutputType(IMFMediaType* pType) { 92 | 93 | TRACE_TRANSFORM((L"CustomVideoMixer::OnCheckOutputType")); 94 | 95 | LogMediaType(pType); 96 | 97 | HRESULT hr = S_OK; 98 | 99 | if (m_pOutputType) { 100 | 101 | DWORD dwFlags = 0; 102 | 103 | if (m_pOutputType->IsEqual(pType, &dwFlags) == S_OK) { 104 | return hr; 105 | } 106 | else { 107 | IF_FAILED_RETURN(hr = MF_E_INVALIDTYPE); 108 | // Todo 109 | //SAFE_RELEASE(m_pInputType); 110 | //Flush(); 111 | } 112 | } 113 | 114 | // Todo : not here, but before call to OnCheckOutputType 115 | if (m_pRefInputType == NULL) { 116 | return MF_E_TRANSFORM_TYPE_NOT_SET; 117 | } 118 | 119 | IMFMediaType* pOurType = NULL; 120 | BOOL bMatch = FALSE; 121 | 122 | try { 123 | 124 | IF_FAILED_THROW(hr = GetOutputType(&pOurType)); 125 | 126 | IF_FAILED_THROW(hr = pOurType->Compare(pType, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &bMatch)); 127 | 128 | IF_FAILED_THROW(hr = (!bMatch ? MF_E_INVALIDTYPE : S_OK)); 129 | } 130 | catch (HRESULT) {} 131 | 132 | SAFE_RELEASE(pOurType); 133 | return hr; 134 | } 135 | -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/DllMain.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // DllMain.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | HMODULE g_hModule; 7 | 8 | DEFINE_CLASSFACTORY_SERVER_LOCK 9 | 10 | const WCHAR SZ_DECODER_NAME[] = L"Custom Video Mixer"; 11 | 12 | BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID /*lpReserved*/){ 13 | 14 | switch(ul_reason_for_call){ 15 | 16 | case DLL_PROCESS_ATTACH: 17 | DisableThreadLibraryCalls((HMODULE)hModule); 18 | g_hModule = (HMODULE)hModule; 19 | break; 20 | 21 | case DLL_PROCESS_DETACH: 22 | case DLL_THREAD_ATTACH: 23 | case DLL_THREAD_DETACH: 24 | break; 25 | } 26 | 27 | return TRUE; 28 | } 29 | 30 | STDAPI DllCanUnloadNow(){ 31 | 32 | if(!ClassFactory::IsLocked()){ 33 | return S_OK; 34 | } 35 | else{ 36 | return S_FALSE; 37 | } 38 | } 39 | 40 | STDAPI DllRegisterServer(){ 41 | 42 | HRESULT hr = S_OK; 43 | 44 | if(SUCCEEDED(hr = RegisterObject(g_hModule, CLSID_CustomVideoMixer, SZ_DECODER_NAME, TEXT("Both")))){ 45 | 46 | MFT_REGISTER_TYPE_INFO InputTypesInfo[] = { { MFMediaType_Video, MFVideoFormat_NV12 }, { MFMediaType_Video, MFVideoFormat_AYUV } }; 47 | MFT_REGISTER_TYPE_INFO OutputTypesInfo[] = { { MFMediaType_Video, MFVideoFormat_RGB32 } }; 48 | 49 | hr = MFTRegister(CLSID_CustomVideoMixer, MFT_CATEGORY_VIDEO_DECODER, const_cast(SZ_DECODER_NAME), 0, ARRAY_SIZE(InputTypesInfo), 50 | InputTypesInfo, ARRAY_SIZE(OutputTypesInfo), OutputTypesInfo, NULL); 51 | } 52 | 53 | return hr; 54 | } 55 | 56 | STDAPI DllUnregisterServer(){ 57 | 58 | UnregisterObject(CLSID_CustomVideoMixer); 59 | MFTUnregister(CLSID_CustomVideoMixer); 60 | 61 | return S_OK; 62 | } 63 | 64 | STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void** ppv){ 65 | 66 | HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; 67 | 68 | if(clsid == CLSID_CustomVideoMixer){ 69 | 70 | ClassFactory* pFactory = NULL; 71 | 72 | pFactory = new (std::nothrow)ClassFactory(CCustomVideoMixer::CreateInstance); 73 | 74 | if(pFactory){ 75 | 76 | hr = pFactory->QueryInterface(riid, ppv); 77 | 78 | SAFE_RELEASE(pFactory); 79 | } 80 | else{ 81 | 82 | hr = E_OUTOFMEMORY; 83 | } 84 | } 85 | 86 | return hr; 87 | } -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/Dxva2Manager.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // Dxva2Manager.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef DXVA2MANAGER_H 5 | #define DXVA2MANAGER_H 6 | 7 | class CDxva2Manager { 8 | 9 | public: 10 | 11 | CDxva2Manager(); 12 | ~CDxva2Manager() { ReleaseDxva2(); } 13 | 14 | HRESULT InitDxva2(IDirect3DDeviceManager9*, IMFMediaType*, IMFMediaType*, IMFMediaType*); 15 | void ReleaseDxva2(); 16 | HRESULT ProcessInput(IMFSample*, const DWORD); 17 | HRESULT ProcessOutput(IMFSample*); 18 | 19 | private: 20 | 21 | IDirectXVideoProcessor* m_pVideoProcessor; 22 | IDirect3DSurface9* m_pRefSurface9; 23 | IDirect3DSurface9* m_pSubSurface9; 24 | 25 | LONGLONG m_llDuration; 26 | LONGLONG m_llTime; 27 | 28 | UINT32 m_uiRefWidth; 29 | UINT32 m_uiRefHeight; 30 | UINT32 m_uiRefLine; 31 | UINT32 m_uiSubWidth; 32 | UINT32 m_uiSubHeight; 33 | UINT32 m_uiSubLine; 34 | 35 | HRESULT GetDxva2VideoDesc(DXVA2_VideoDesc*, IMFMediaType*); 36 | 37 | void LogVideoProcessBltParams(DXVA2_VideoProcessBltParams&); 38 | void LogVideoSample(DXVA2_VideoSample&); 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "Stdafx.h" -------------------------------------------------------------------------------- /CustomVideoMixer/CustomVideoMixer/StdAfx.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef STDAFX_H 5 | #define STDAFX_H 6 | 7 | #pragma once 8 | #define WIN32_LEAN_AND_MEAN 9 | #define STRICT 10 | 11 | #pragma comment(lib, "mf") 12 | #pragma comment(lib, "mfplat") 13 | #pragma comment(lib, "mfuuid") 14 | #pragma comment(lib, "shlwapi") 15 | #pragma comment(lib, "strmiids") 16 | 17 | //---------------------------------------------------------------------------------------------- 18 | // Microsoft Windows SDK for Windows 7 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #ifdef _DEBUG 26 | #include 27 | #endif 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | //---------------------------------------------------------------------------------------------- 44 | // Common Project Files 45 | #ifdef _DEBUG 46 | #define MF_USE_LOGGING 1 47 | //#define MF_USE_LOGREFCOUNT 48 | //#define MF_TRACE_TRANSFORM 49 | #else 50 | #define MF_USE_LOGGING 0 51 | #endif 52 | 53 | #include "..\Common\MFMacro.h" 54 | #include "..\Common\MFTrace.h" 55 | #include "..\Common\MFLogging.h" 56 | #include "..\Common\MFTExternTrace.h" 57 | #include "..\Common\MFGuid.h" 58 | #include "..\Common\MFClassFactory.h" 59 | #include "..\Common\MFCriticSection.h" 60 | #include "..\Common\MFRegistry.h" 61 | #include "..\Common\MFLogCommon.h" 62 | #include "..\Common\MFLogMediaType.h" 63 | 64 | //---------------------------------------------------------------------------------------------- 65 | // Project Files 66 | #include "Dxva2Manager.h" 67 | #include "CustomVideoMixer.h" 68 | 69 | #define MAX_VIDEO_WIDTH_HEIGHT 4095 70 | 71 | const DWORD D3DFMT_NV12 = MAKEFOURCC('N', 'V', '1', '2'); 72 | 73 | #endif -------------------------------------------------------------------------------- /CustomVideoMixer/TestCustomVideoMixer/TestCustomVideoMixer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Fichiers sources 20 | 21 | 22 | -------------------------------------------------------------------------------- /CustomVideoMixer/TestCustomVideoMixer/TestCustomVideoMixer.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/EncodeWithSourceReaderSinkWriter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EncodeWithSourceReaderSinkWriter", "EncodeWithSourceReaderSinkWriter.vcxproj", "{20CF3858-CBE6-4AFE-8FD0-934D8B1DCFF9}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {20CF3858-CBE6-4AFE-8FD0-934D8B1DCFF9}.Debug|x64.ActiveCfg = Debug|x64 17 | {20CF3858-CBE6-4AFE-8FD0-934D8B1DCFF9}.Debug|x64.Build.0 = Debug|x64 18 | {20CF3858-CBE6-4AFE-8FD0-934D8B1DCFF9}.Debug|x86.ActiveCfg = Debug|Win32 19 | {20CF3858-CBE6-4AFE-8FD0-934D8B1DCFF9}.Debug|x86.Build.0 = Debug|Win32 20 | {20CF3858-CBE6-4AFE-8FD0-934D8B1DCFF9}.Release|x64.ActiveCfg = Release|x64 21 | {20CF3858-CBE6-4AFE-8FD0-934D8B1DCFF9}.Release|x64.Build.0 = Release|x64 22 | {20CF3858-CBE6-4AFE-8FD0-934D8B1DCFF9}.Release|x86.ActiveCfg = Release|Win32 23 | {20CF3858-CBE6-4AFE-8FD0-934D8B1DCFF9}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {930C5FFD-60CD-4FC2-98AD-258D6B62DBF3} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/EncodeWithSourceReaderSinkWriter.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Fichiers d%27en-tête 20 | 21 | 22 | Fichiers d%27en-tête 23 | 24 | 25 | Fichiers d%27en-tête 26 | 27 | 28 | Fichiers d%27en-tête 29 | 30 | 31 | Fichiers d%27en-tête 32 | 33 | 34 | Fichiers d%27en-tête 35 | 36 | 37 | Fichiers d%27en-tête 38 | 39 | 40 | Fichiers d%27en-tête 41 | 42 | 43 | Fichiers d%27en-tête 44 | 45 | 46 | 47 | 48 | Fichiers sources 49 | 50 | 51 | Fichiers sources 52 | 53 | 54 | -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/EncodeWithSourceReaderSinkWriter.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/MFGuid.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFGuid.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFGUID_H 5 | #define MFGUID_H 6 | 7 | // {B2F74C92-79DF-45DE-9C55-A99DE8276679} 8 | DEFINE_GUID(CLSID_CustomVideoMixer, 0xb2f74c92, 0x79df, 0x45de, 0x9c, 0x55, 0xa9, 0x9d, 0xe8, 0x27, 0x66, 0x79); 9 | 10 | //---------------------------------------------------------------------------------------------- 11 | // Media subType guid 12 | 13 | // {7634706D-0000-0010-8000-00AA00389B71} 14 | DEFINE_GUID(MEDIASUBTYPE_mp4v, 0x7634706d, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 15 | 16 | // 56564D41-0000-0010-8000-00AA00389B71 17 | DEFINE_GUID(MEDIASUBTYPE_XVID, 0x44495658, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 18 | 19 | // {64697678-0000-0010-8000-00AA00389B71} 20 | DEFINE_GUID(MEDIASUBTYPE_xvid, 0x64697678, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 21 | 22 | // {58564944-0000-0010-8000-00AA00389B71} 23 | DEFINE_GUID(MEDIASUBTYPE_DIVX, 0x58564944, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 24 | 25 | // {78766964-0000-0010-8000-00AA00389B71} 26 | DEFINE_GUID(MEDIASUBTYPE_divx, 0x78766964, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 27 | 28 | // {30355844-0000-0010-8000-00aa00389b71} 29 | DEFINE_GUID(MEDIASUBTYPE_DX50, 0x30355844, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 30 | 31 | // {30357864-0000-0010-8000-00AA00389B71} 32 | DEFINE_GUID(MEDIASUBTYPE_dx50, 0x30357864, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 33 | 34 | // {1D4A45F2-E5F6-4B44-8388-F0AE5C0E0C37} 35 | DEFINE_GUID(MEDIASUBTYPE_VIDEOIMAGE, 0x1D4A45F2, 0xE5F6, 0x4B44, 0x83, 0x88, 0xF0, 0xAE, 0x5C, 0x0E, 0x0C, 0x37); 36 | 37 | // {00000031-0000-0010-8000-00AA00389B71} 38 | DEFINE_GUID(MEDIASUBTYPE_GSM, 0x00000031, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 39 | 40 | // {00000011-0000-0010-8000-00AA00389B71} 41 | DEFINE_GUID(MEDIASUBTYPE_IMAADPCMACM, 0x00000011, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 42 | 43 | #endif -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/MFLogCommon.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogCommon.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGCOMMON_H 5 | #define MFLOGCOMMON_H 6 | 7 | #if (_DEBUG && MF_USE_LOGGING) 8 | 9 | typedef LPCWSTR(*GetGUIDStringName)(const GUID&); 10 | 11 | inline void LogGuidHexa(const GUID& guid, const BOOL bFirst){ 12 | 13 | HRESULT hr; 14 | WCHAR pBuffer[39] = {0}; 15 | 16 | hr = StringCchPrintf(pBuffer, 39, L"{%.8lX-%.4hX-%.4hX-%.2hhX%.2hhX-%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX}", 17 | guid.Data1, 18 | guid.Data2, 19 | guid.Data3, 20 | guid.Data4[0], 21 | guid.Data4[1], 22 | guid.Data4[2], 23 | guid.Data4[3], 24 | guid.Data4[4], 25 | guid.Data4[5], 26 | guid.Data4[6], 27 | guid.Data4[7] 28 | ); 29 | 30 | if(SUCCEEDED(hr)){ 31 | 32 | if(bFirst) 33 | TRACE_NO_END_LINE((L"\t%s\t", pBuffer)); 34 | else 35 | TRACE((L"%s", pBuffer)); 36 | } 37 | else{ 38 | 39 | TRACE((L"Guid problem")); 40 | } 41 | } 42 | 43 | inline void LogUINT32AsUINT64(const PROPVARIANT& var){ 44 | 45 | UINT32 uHigh = 0, uLow = 0; 46 | 47 | Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &uHigh, &uLow); 48 | 49 | TRACE((L"%u x %u", uHigh, uLow)); 50 | } 51 | 52 | inline HRESULT SpecialCaseAttributeValue(GUID guid, const PROPVARIANT& var){ 53 | 54 | if(guid == MF_MT_FRAME_RATE){ 55 | LogUINT32AsUINT64(var); 56 | } 57 | else if(guid == MF_MT_FRAME_SIZE){ 58 | LogUINT32AsUINT64(var); 59 | } 60 | else if(guid == MF_MT_PIXEL_ASPECT_RATIO){ 61 | LogUINT32AsUINT64(var); 62 | } 63 | else{ 64 | return S_FALSE; 65 | } 66 | 67 | return S_OK; 68 | } 69 | 70 | inline void LogPropertyVariant(const GUID* pGuid, const PROPVARIANT& var, GetGUIDStringName pGetGUIDString){ 71 | 72 | HRESULT hr = S_FALSE; 73 | 74 | if(pGuid != NULL) 75 | hr = SpecialCaseAttributeValue(*pGuid, var); 76 | 77 | if(hr == S_FALSE){ 78 | 79 | switch(var.vt){ 80 | 81 | case VT_UI4: 82 | TRACE((L"%lu", var.ulVal)); 83 | break; 84 | 85 | case VT_I4: 86 | TRACE((L"%ld", var.lVal)); 87 | break; 88 | 89 | case VT_UI8: 90 | TRACE((L"%I64u", var.uhVal)); 91 | break; 92 | 93 | case VT_BOOL: 94 | TRACE((L"%s", var.boolVal == -1 ? "true" : "false")); 95 | break; 96 | 97 | case VT_R8: 98 | TRACE((L"%f", var.dblVal)); 99 | break; 100 | 101 | case VT_CLSID: 102 | { 103 | LPCWSTR pwszGuidName = pGetGUIDString(*var.puuid); 104 | 105 | if(pwszGuidName != NULL){ 106 | TRACE((L"%s", pwszGuidName)); 107 | } 108 | else{ 109 | LogGuidHexa(*var.puuid, FALSE); 110 | } 111 | } 112 | break; 113 | 114 | case VT_LPWSTR: 115 | // Log : var.pwszVal 116 | TRACE((L"VT_LPWSTR = todo")); 117 | break; 118 | 119 | case VT_VECTOR | VT_UI1: 120 | TRACE((L"(VT_VECTOR|VT_UI1) = <>")); 121 | break; 122 | 123 | case VT_UNKNOWN: 124 | TRACE((L"VT_UNKNOWN = IUnknown")); 125 | break; 126 | 127 | case VT_EMPTY: 128 | TRACE((L"VT_EMPTY")); 129 | break; 130 | 131 | case VT_R4: 132 | TRACE((L"VT_R4 = %f", var.fltVal)); 133 | break; 134 | 135 | // 8195 = VT_ARRAY | VT_I4 136 | 137 | default: 138 | TRACE((L"Unexpected attribute type (vt = %hu)", var.vt)); 139 | break; 140 | } 141 | } 142 | } 143 | 144 | inline void LogAttributeValueByIndex(IMFAttributes* pAttributes, UINT32 uiIndex, GetGUIDStringName pGetGUIDString){ 145 | 146 | HRESULT hr; 147 | PROPVARIANT var; 148 | GUID guid = GUID_NULL; 149 | 150 | PropVariantInit(&var); 151 | 152 | hr = pAttributes->GetItemByIndex(uiIndex, &guid, &var); 153 | 154 | if(SUCCEEDED(hr)){ 155 | 156 | LPCWSTR pwszGUIDNameAttributes = pGetGUIDString(guid); 157 | 158 | if(pwszGUIDNameAttributes != NULL){ 159 | TRACE_NO_END_LINE((L"\t%s\t", pwszGUIDNameAttributes)); 160 | } 161 | else{ 162 | 163 | LogGuidHexa(guid, TRUE); 164 | } 165 | 166 | LogPropertyVariant(&guid, var, pGetGUIDString); 167 | } 168 | else{ 169 | TRACE((L"\tGetItemByIndex (Index = %u) hr = %s", uiIndex, MFErrorString(hr))); 170 | } 171 | 172 | PropVariantClear(&var); 173 | } 174 | 175 | #endif 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/MFLogging.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogging.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGGING_H 5 | #define MFLOGGING_H 6 | 7 | #ifdef _DEBUG 8 | 9 | class DebugLog{ 10 | 11 | public: 12 | 13 | static void Initialize(){ 14 | _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); 15 | //_CrtSetBreakAlloc(171); 16 | } 17 | 18 | static void Trace(const WCHAR* sFormatString, ...){ 19 | 20 | HRESULT hr = S_OK; 21 | va_list va; 22 | 23 | const DWORD TRACE_STRING_LEN = 512; 24 | 25 | WCHAR message[TRACE_STRING_LEN]; 26 | 27 | va_start(va, sFormatString); 28 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 29 | va_end(va); 30 | 31 | if(SUCCEEDED(hr)){ 32 | 33 | size_t size = _tcslen(message); 34 | 35 | if(size != 0 && size < TRACE_STRING_LEN){ 36 | message[size] = '\n'; 37 | message[size + 1] = '\0'; 38 | } 39 | 40 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 41 | } 42 | } 43 | 44 | static void TraceNoEndLine(const WCHAR* sFormatString, ...){ 45 | 46 | HRESULT hr = S_OK; 47 | va_list va; 48 | 49 | const DWORD TRACE_STRING_LEN = 512; 50 | 51 | WCHAR message[TRACE_STRING_LEN]; 52 | 53 | va_start(va, sFormatString); 54 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 55 | va_end(va); 56 | 57 | if(SUCCEEDED(hr)){ 58 | 59 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 60 | } 61 | } 62 | 63 | static void Close(){ 64 | int bLeak = _CrtDumpMemoryLeaks(); 65 | assert(bLeak == FALSE); 66 | } 67 | }; 68 | 69 | #define TRACE_INIT() DebugLog::Initialize() 70 | #define TRACE(x) DebugLog::Trace x 71 | #define TRACE_NO_END_LINE(x) DebugLog::TraceNoEndLine x 72 | #define TRACE_CLOSE() DebugLog::Close() 73 | 74 | inline HRESULT _LOG_HRESULT(HRESULT hr, const char* sFileName, long lLineNo){ 75 | 76 | if(FAILED(hr)){ 77 | TRACE((L"\n%S - Line: %d hr = %s\n", sFileName, lLineNo, MFErrorString(hr))); 78 | } 79 | 80 | return hr; 81 | } 82 | 83 | #define LOG_HRESULT(hr) _LOG_HRESULT(hr, __FILE__, __LINE__) 84 | #define LOG_LAST_ERROR() _LOG_HRESULT(HRESULT_FROM_WIN32(GetLastError()), __FILE__, __LINE__) 85 | 86 | #else 87 | #define TRACE_INIT() 88 | #define TRACE(x) 89 | #define TRACE_NO_END_LINE(x) 90 | #define TRACE_CLOSE() 91 | #define LOG_HRESULT(hr) hr 92 | #define LOG_LAST_ERROR() 93 | #endif 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/MFMacro.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFMacro.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFMACRO_H 5 | #define MFMACRO_H 6 | 7 | #ifndef MF_SAFE_RELEASE 8 | #define MF_SAFE_RELEASE 9 | template inline void SAFE_RELEASE(T*& p){ 10 | 11 | if(p){ 12 | p->Release(); 13 | p = NULL; 14 | } 15 | } 16 | #endif 17 | 18 | #ifndef MF_SAFE_DELETE 19 | #define MF_SAFE_DELETE 20 | template inline void SAFE_DELETE(T*& p){ 21 | 22 | if(p){ 23 | delete p; 24 | p = NULL; 25 | } 26 | } 27 | #endif 28 | 29 | #ifndef MF_SAFE_DELETE_ARRAY 30 | #define MF_SAFE_DELETE_ARRAY 31 | template inline void SAFE_DELETE_ARRAY(T*& p){ 32 | 33 | if(p){ 34 | delete[] p; 35 | p = NULL; 36 | } 37 | } 38 | #endif 39 | 40 | #ifndef IF_FAILED_RETURN 41 | #if(_DEBUG && MF_USE_LOGGING) 42 | #define IF_FAILED_RETURN(X) if(FAILED(hr = (X))){ LOG_HRESULT(hr); return hr; } 43 | #else 44 | #define IF_FAILED_RETURN(X) if(FAILED(hr = (X))){ return hr; } 45 | #endif 46 | #endif 47 | 48 | #ifndef IF_FAILED_THROW 49 | #if(_DEBUG && MF_USE_LOGGING) 50 | #define IF_FAILED_THROW(X) if(FAILED(hr = (X))){ LOG_HRESULT(hr); throw hr; } 51 | #else 52 | #define IF_FAILED_THROW(X) if(FAILED(hr = (X))){ throw hr; } 53 | #endif 54 | #endif 55 | 56 | #ifndef IF_ERROR_RETURN 57 | #if (_DEBUG && MF_USE_LOGGING) 58 | #define IF_ERROR_RETURN(b) if(b == FALSE){ LOG_LAST_ERROR(); return b; } 59 | #else 60 | #define IF_ERROR_RETURN(b) if(b == FALSE){ return b; } 61 | #endif 62 | #endif 63 | 64 | #ifndef CLOSE_HANDLE_IF 65 | #if (_DEBUG && MF_USE_LOGGING) 66 | #define CLOSE_HANDLE_IF(h) if(h != INVALID_HANDLE_VALUE){ if(CloseHandle(h) == FALSE){ LOG_LAST_ERROR(); } h = INVALID_HANDLE_VALUE; } 67 | #else 68 | #define CLOSE_HANDLE_IF(h) if(h != INVALID_HANDLE_VALUE){ CloseHandle(h); h = INVALID_HANDLE_VALUE; } 69 | #endif 70 | #endif 71 | 72 | #ifndef RETURN_STRING 73 | #define RETURN_STRING(x) case x: return L#x 74 | #endif 75 | 76 | #ifndef IF_EQUAL_RETURN 77 | #define IF_EQUAL_RETURN(param, val) if(val == param) return L#val 78 | #endif 79 | 80 | #ifndef VALUE_NOT_FOUND 81 | #define VALUE_NOT_FOUND(val) return L#val 82 | #endif 83 | 84 | #ifndef MIN 85 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 86 | #endif 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/MFTExternTrace.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFTExternTrace.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFTEXTERNTRACE_H 5 | #define MFTEXTERNTRACE_H 6 | 7 | // CExternTrace initializes the memory leaks detection (see "crtdbg.h"). 8 | // CExternTrace ensures that no object is allocated before TRACE_INIT is called. 9 | // Because DllMain.cpp contains external objects, you will see "FAKE" memory leaks. 10 | #ifdef _DEBUG 11 | 12 | class CExternTrace{ 13 | 14 | public: 15 | 16 | CExternTrace(){ TRACE_INIT(); }; 17 | ~CExternTrace(){ TRACE_CLOSE(); }; 18 | }; 19 | 20 | CExternTrace cExternTrace; 21 | 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/MFTime.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFTime.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFTIME_H 5 | #define MFTIME_H 6 | 7 | // One second in hns 8 | const MFTIME ONE_SECOND = 10000000; 9 | 10 | // One msec in hns 11 | const LONG ONE_MSEC = 1000; 12 | 13 | inline LONG MFTimeToMilliSec(const LONGLONG& time){ 14 | 15 | return (LONG)(time / (ONE_SECOND / ONE_MSEC)); 16 | } 17 | 18 | inline LONG MFTimeToSec(const LONGLONG& time){ 19 | 20 | return (LONG)(time / ONE_SECOND); 21 | } 22 | 23 | #if (_DEBUG && MF_USE_LOGGING) 24 | 25 | inline void MFTimeString(const MFTIME& Duration){ 26 | 27 | MFTIME DurationInMilliSec = 0; 28 | MFTIME DurationInSec = 0; 29 | MFTIME Hours = 0; 30 | MFTIME Minutes = 0; 31 | MFTIME Seconds = 0; 32 | 33 | DurationInSec = MFTimeToSec(Duration); 34 | DurationInMilliSec = MFTimeToMilliSec(Duration); 35 | 36 | if(DurationInSec > 60){ 37 | 38 | Minutes = DurationInSec / 60; 39 | 40 | if(Minutes > 60){ 41 | 42 | Hours = Minutes / 60; 43 | Minutes = Minutes % 60; 44 | } 45 | 46 | Seconds = (DurationInSec % 60); 47 | } 48 | else{ 49 | 50 | Seconds = DurationInSec; 51 | } 52 | 53 | if(Seconds){ 54 | DurationInMilliSec = DurationInMilliSec % (Seconds * ONE_MSEC); 55 | } 56 | 57 | TRACE((L"%02dh:%02dmn:%02ds:%03dms", (int)Hours, (int)Minutes, (int)Seconds, DurationInMilliSec)); 58 | } 59 | 60 | #else 61 | #define MFTimeString(x) 62 | #endif 63 | 64 | #endif -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" -------------------------------------------------------------------------------- /EncodeWithSourceReaderSinkWriter/StdAfx.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef STDAFX_H 5 | #define STDAFX_H 6 | 7 | #pragma once 8 | #define WIN32_LEAN_AND_MEAN 9 | #define STRICT 10 | 11 | #pragma comment(lib, "mf") 12 | #pragma comment(lib, "mfplat") 13 | #pragma comment(lib, "mfuuid") 14 | #pragma comment(lib, "mfreadwrite") 15 | #pragma comment(lib, "strmiids") 16 | 17 | //---------------------------------------------------------------------------------------------- 18 | // Microsoft Windows SDK for Windows 7 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #ifdef _DEBUG 26 | #include 27 | #endif 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | //---------------------------------------------------------------------------------------------- 45 | // Common Project Files 46 | #ifdef _DEBUG 47 | #define MF_USE_LOGGING 1 48 | #else 49 | #define MF_USE_LOGGING 0 50 | #endif 51 | 52 | #include "MFMacro.h" 53 | #include "MFTrace.h" 54 | #include "MFLogging.h" 55 | #include "MFTExternTrace.h" 56 | #include "MFGuid.h" 57 | #include "MFLogCommon.h" 58 | #include "MFLogMediaType.h" 59 | #include "MFTime.h" 60 | 61 | #endif -------------------------------------------------------------------------------- /FrameRateConverterDSP/FrameRateConverterDSP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrameRateConverterDSP", "FrameRateConverterDSP.vcxproj", "{832CA548-40B4-45C7-BFF5-B68F6C85ED82}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {832CA548-40B4-45C7-BFF5-B68F6C85ED82}.Debug|x64.ActiveCfg = Debug|x64 17 | {832CA548-40B4-45C7-BFF5-B68F6C85ED82}.Debug|x64.Build.0 = Debug|x64 18 | {832CA548-40B4-45C7-BFF5-B68F6C85ED82}.Debug|x86.ActiveCfg = Debug|Win32 19 | {832CA548-40B4-45C7-BFF5-B68F6C85ED82}.Debug|x86.Build.0 = Debug|Win32 20 | {832CA548-40B4-45C7-BFF5-B68F6C85ED82}.Release|x64.ActiveCfg = Release|x64 21 | {832CA548-40B4-45C7-BFF5-B68F6C85ED82}.Release|x64.Build.0 = Release|x64 22 | {832CA548-40B4-45C7-BFF5-B68F6C85ED82}.Release|x86.ActiveCfg = Release|Win32 23 | {832CA548-40B4-45C7-BFF5-B68F6C85ED82}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {C35FB983-8745-44D3-BE78-579D379694C1} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /IMFSinkWriterCallback/IMFSinkWriterCallback.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IMFSinkWriterCallback", "IMFSinkWriterCallback.vcxproj", "{4F362AC8-B517-4382-A943-33CEC77CBC95}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4F362AC8-B517-4382-A943-33CEC77CBC95}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {4F362AC8-B517-4382-A943-33CEC77CBC95}.Debug|Win32.Build.0 = Debug|Win32 16 | {4F362AC8-B517-4382-A943-33CEC77CBC95}.Release|Win32.ActiveCfg = Release|Win32 17 | {4F362AC8-B517-4382-A943-33CEC77CBC95}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /IMFSinkWriterCallback/IMFSinkWriterCallback.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {4F362AC8-B517-4382-A943-33CEC77CBC95} 15 | Win32Proj 16 | IMFSinkWriterCallback 17 | 10.0.15063.0 18 | 19 | 20 | 21 | Application 22 | true 23 | v141 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v141 30 | true 31 | Unicode 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level4 54 | Disabled 55 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 56 | ProgramDatabase 57 | 58 | 59 | Console 60 | true 61 | 62 | 63 | 64 | 65 | Level3 66 | 67 | 68 | MaxSpeed 69 | true 70 | true 71 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 72 | 73 | 74 | Console 75 | false 76 | true 77 | true 78 | UseLinkTimeCodeGeneration 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /MFMultiVideo/Common/MFLogging.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogging.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGGING_H 5 | #define MFLOGGING_H 6 | 7 | #ifdef _DEBUG 8 | 9 | class DebugLog{ 10 | 11 | public: 12 | 13 | static void Initialize(){ 14 | _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); 15 | //_CrtSetBreakAlloc(223); 16 | } 17 | 18 | static void Trace(const WCHAR* sFormatString, ...){ 19 | 20 | HRESULT hr = S_OK; 21 | va_list va; 22 | 23 | const DWORD TRACE_STRING_LEN = 512; 24 | 25 | WCHAR message[TRACE_STRING_LEN]; 26 | 27 | va_start(va, sFormatString); 28 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 29 | va_end(va); 30 | 31 | if(SUCCEEDED(hr)){ 32 | 33 | size_t size = _tcslen(message); 34 | 35 | if(size != 0 && size < TRACE_STRING_LEN){ 36 | message[size] = '\n'; 37 | message[size + 1] = '\0'; 38 | } 39 | 40 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 41 | } 42 | } 43 | 44 | static void TraceNoEndLine(const WCHAR* sFormatString, ...){ 45 | 46 | HRESULT hr = S_OK; 47 | va_list va; 48 | 49 | const DWORD TRACE_STRING_LEN = 512; 50 | 51 | WCHAR message[TRACE_STRING_LEN]; 52 | 53 | va_start(va, sFormatString); 54 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 55 | va_end(va); 56 | 57 | if(SUCCEEDED(hr)){ 58 | 59 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 60 | } 61 | } 62 | 63 | static void Close(){ 64 | int bLeak = _CrtDumpMemoryLeaks(); 65 | assert(bLeak == FALSE); 66 | } 67 | }; 68 | 69 | #define TRACE_INIT() DebugLog::Initialize() 70 | #define TRACE(x) DebugLog::Trace x 71 | #define TRACE_NO_END_LINE(x) DebugLog::TraceNoEndLine x 72 | #define TRACE_CLOSE() DebugLog::Close() 73 | 74 | inline HRESULT _LOG_HRESULT(HRESULT hr, const char* sFileName, long lLineNo){ 75 | 76 | if(FAILED(hr)){ 77 | TRACE((L"\n%S - Line: %d hr = %s\n", sFileName, lLineNo, MFErrorString(hr))); 78 | } 79 | 80 | return hr; 81 | } 82 | 83 | #define LOG_HRESULT(hr) _LOG_HRESULT(hr, __FILE__, __LINE__) 84 | #define LOG_LAST_ERROR() _LOG_HRESULT(HRESULT_FROM_WIN32(GetLastError()), __FILE__, __LINE__) 85 | 86 | #ifdef MF_USE_LOGREFCOUNT 87 | #define TRACE_REFCOUNT(x) DebugLog::Trace x 88 | #else 89 | #define TRACE_REFCOUNT(x) 90 | #endif 91 | 92 | #ifdef MF_TRACE_PLAYER 93 | #define TRACE_PLAYER(x) DebugLog::Trace x 94 | #else 95 | #define TRACE_PLAYER(x) 96 | #endif 97 | 98 | #else 99 | #define TRACE_INIT() 100 | #define TRACE(x) 101 | #define TRACE_NO_END_LINE(x) 102 | #define TRACE_CLOSE() 103 | #define LOG_HRESULT(hr) hr 104 | #define LOG_LAST_ERROR() 105 | #define TRACE_REFCOUNT(x) 106 | #define TRACE_PLAYER(x) 107 | #endif 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /MFMultiVideo/Common/MFMacro.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFMacro.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFMACRO_H 5 | #define MFMACRO_H 6 | 7 | #ifndef MF_SAFE_RELEASE 8 | #define MF_SAFE_RELEASE 9 | template inline void SAFE_RELEASE(T*& p){ 10 | 11 | if(p){ 12 | p->Release(); 13 | p = NULL; 14 | } 15 | } 16 | #endif 17 | 18 | #ifndef MF_SAFE_DELETE 19 | #define MF_SAFE_DELETE 20 | template inline void SAFE_DELETE(T*& p){ 21 | 22 | if(p){ 23 | delete p; 24 | p = NULL; 25 | } 26 | } 27 | #endif 28 | 29 | #ifndef MF_SAFE_DELETE_ARRAY 30 | #define MF_SAFE_DELETE_ARRAY 31 | template inline void SAFE_DELETE_ARRAY(T*& p){ 32 | 33 | if(p){ 34 | delete[] p; 35 | p = NULL; 36 | } 37 | } 38 | #endif 39 | 40 | #ifndef IF_FAILED_RETURN 41 | #if(_DEBUG && MF_USE_LOGGING) 42 | #define IF_FAILED_RETURN(X) if(FAILED(hr = (X))){ LOG_HRESULT(hr); return hr; } 43 | #else 44 | #define IF_FAILED_RETURN(X) if(FAILED(hr = (X))){ return hr; } 45 | #endif 46 | #endif 47 | 48 | #ifndef IF_FAILED_THROW 49 | #if(_DEBUG && MF_USE_LOGGING) 50 | #define IF_FAILED_THROW(X) if(FAILED(hr = (X))){ LOG_HRESULT(hr); throw hr; } 51 | #else 52 | #define IF_FAILED_THROW(X) if(FAILED(hr = (X))){ throw hr; } 53 | #endif 54 | #endif 55 | 56 | #ifndef IF_ERROR_RETURN 57 | #if (_DEBUG && MF_USE_LOGGING) 58 | #define IF_ERROR_RETURN(b) if(b == FALSE){ LOG_LAST_ERROR(); return b; } 59 | #else 60 | #define IF_ERROR_RETURN(b) if(b == FALSE){ return b; } 61 | #endif 62 | #endif 63 | 64 | #ifndef CLOSE_HANDLE_IF 65 | #if (_DEBUG && MF_USE_LOGGING) 66 | #define CLOSE_HANDLE_IF(h) if(h != INVALID_HANDLE_VALUE){ if(CloseHandle(h) == FALSE){ LOG_LAST_ERROR(); } h = INVALID_HANDLE_VALUE; } 67 | #else 68 | #define CLOSE_HANDLE_IF(h) if(h != INVALID_HANDLE_VALUE){ CloseHandle(h); h = INVALID_HANDLE_VALUE; } 69 | #endif 70 | #endif 71 | 72 | #ifndef CLOSE_HANDLE_NULL_IF 73 | #if (_DEBUG && MF_USE_LOGGING) 74 | #define CLOSE_HANDLE_NULL_IF(h) if(h != NULL){ if(CloseHandle(h) == FALSE){ LOG_LAST_ERROR(); } h = NULL; } 75 | #else 76 | #define CLOSE_HANDLE_NULL_IF(h) if(h != NULL){ CloseHandle(h); h = NULL; } 77 | #endif 78 | #endif 79 | 80 | #ifndef RETURN_STRING 81 | #define RETURN_STRING(x) case x: return L#x 82 | #endif 83 | 84 | #ifndef IF_EQUAL_RETURN 85 | #define IF_EQUAL_RETURN(param, val) if(val == param) return L#val 86 | #endif 87 | 88 | #ifndef VALUE_NOT_FOUND 89 | #define VALUE_NOT_FOUND(val) return L#val 90 | #endif 91 | 92 | #ifndef MIN 93 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 94 | #endif 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /MFMultiVideo/Common/MFTExternTrace.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFTExternTrace.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFTEXTERNTRACE_H 5 | #define MFTEXTERNTRACE_H 6 | 7 | // CExternTrace initializes the memory leaks detection (see "crtdbg.h"). 8 | // CExternTrace ensures that no object is allocated before TRACE_INIT is called. 9 | // Because DllMain.cpp contains external objects, you will see "FAKE" memory leaks. 10 | #ifdef _DEBUG 11 | 12 | class CExternTrace{ 13 | 14 | public: 15 | 16 | CExternTrace(){ TRACE_INIT(); }; 17 | ~CExternTrace(){ TRACE_CLOSE(); }; 18 | }; 19 | 20 | CExternTrace cExternTrace; 21 | 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /MFMultiVideo/MFMultiVideo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MFMultiVideo", "MFMultiVideo.vcxproj", "{8817B8D0-718A-4E5E-A216-AC08A9A8F679}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {8817B8D0-718A-4E5E-A216-AC08A9A8F679}.Debug|x64.ActiveCfg = Debug|x64 17 | {8817B8D0-718A-4E5E-A216-AC08A9A8F679}.Debug|x64.Build.0 = Debug|x64 18 | {8817B8D0-718A-4E5E-A216-AC08A9A8F679}.Debug|x86.ActiveCfg = Debug|Win32 19 | {8817B8D0-718A-4E5E-A216-AC08A9A8F679}.Debug|x86.Build.0 = Debug|Win32 20 | {8817B8D0-718A-4E5E-A216-AC08A9A8F679}.Release|x64.ActiveCfg = Release|x64 21 | {8817B8D0-718A-4E5E-A216-AC08A9A8F679}.Release|x64.Build.0 = Release|x64 22 | {8817B8D0-718A-4E5E-A216-AC08A9A8F679}.Release|x86.ActiveCfg = Release|Win32 23 | {8817B8D0-718A-4E5E-A216-AC08A9A8F679}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {367D630C-FC0C-4155-9CBF-89DA4CC9DE76} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /MFMultiVideo/MFMultiVideo.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {39dccb02-dd0a-4587-9597-98feb56c17a9} 18 | 19 | 20 | 21 | 22 | Fichiers sources 23 | 24 | 25 | Fichiers sources 26 | 27 | 28 | Fichiers sources 29 | 30 | 31 | 32 | 33 | Fichiers d%27en-tête 34 | 35 | 36 | Fichiers d%27en-tête 37 | 38 | 39 | Common 40 | 41 | 42 | Common 43 | 44 | 45 | Common 46 | 47 | 48 | Common 49 | 50 | 51 | -------------------------------------------------------------------------------- /MFMultiVideo/MFMultiVideo.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /MFMultiVideo/Player.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // Player.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef PLAYER_H 5 | #define PLAYER_H 6 | 7 | enum PlayerState 8 | { 9 | Closed = 0, // No session. 10 | Ready, // Session was created, ready to open a file. 11 | OpenPending, // Session is opening a file. 12 | Started, // Session is playing a file. 13 | Paused, // Session is paused. 14 | Stopped, // Session is stopped (ready to play). 15 | Closing // Application has closed the session, but is waiting for MESessionClosed. 16 | }; 17 | 18 | class CPlayer : public IMFAsyncCallback{ 19 | 20 | public: 21 | 22 | static HRESULT CreateInstance(const HWND, const int, CPlayer**); 23 | 24 | // IUnknown - Player.cpp 25 | STDMETHODIMP QueryInterface(REFIID, void**); 26 | STDMETHODIMP_(ULONG) AddRef(); 27 | STDMETHODIMP_(ULONG) Release(); 28 | 29 | // IMFAsyncCallback - Player.cpp 30 | STDMETHODIMP GetParameters(DWORD*, DWORD*); 31 | STDMETHODIMP Invoke(IMFAsyncResult*); 32 | 33 | HRESULT OpenUrl(LPCWSTR); 34 | HRESULT Shutdown(); 35 | 36 | private: 37 | 38 | CPlayer(HRESULT&, const HWND, const int); 39 | virtual ~CPlayer(); 40 | 41 | volatile long m_lRefCount; 42 | HWND m_hwndVideo = NULL; 43 | int m_iIndex = 0; 44 | PlayerState m_state = Closed; 45 | std::mutex m_mtx; 46 | std::condition_variable m_cv_open; 47 | std::condition_variable m_cv_close; 48 | CComPtr m_pSource = NULL; 49 | CComPtr m_pDecoder = NULL; 50 | IMFMediaSession* m_pSession = NULL; 51 | DWORD m_dwQueue = MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION; 52 | 53 | HRESULT HandleEvent(IMFMediaEvent*); 54 | HRESULT OnTopologyStatus(IMFMediaEvent*); 55 | HRESULT OnPresentationEnded(IMFMediaEvent*); 56 | HRESULT StartPlayback(); 57 | HRESULT CreateSession(); 58 | HRESULT CreateMediaSource(LPCWSTR, IMFMediaSource**); 59 | HRESULT CreatePlaybackTopology(IMFMediaSource*, IMFPresentationDescriptor*, const HWND, IMFTopology**, IMFTransform**); 60 | HRESULT AddBranchToPartialTopology(IMFTopology*, IMFMediaSource*, IMFPresentationDescriptor*, const DWORD, const HWND, IMFTransform**, const bool withOverlay = false); 61 | HRESULT AddOutputNode(IMFTopology*, IMFActivate*, const DWORD, IMFTopologyNode**); 62 | HRESULT AddSourceNode(IMFTopology*, IMFMediaSource*, IMFPresentationDescriptor*, IMFStreamDescriptor*, IMFTopologyNode**); 63 | HRESULT CreateVideoDecoderTopology(IMFTopology*, IMFTopologyNode*, IMFTopologyNode*, IMFTransform**); 64 | HRESULT AddTransformNode(IMFTopology*, const CLSID&, IMFTopologyNode**, IMFTransform**); 65 | }; 66 | 67 | #endif -------------------------------------------------------------------------------- /MFMultiVideo/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" -------------------------------------------------------------------------------- /MFMultiVideo/StdAfx.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef STDAFX_H 5 | #define STDAFX_H 6 | 7 | #pragma once 8 | #define WIN32_LEAN_AND_MEAN 9 | #define STRICT 10 | 11 | //---------------------------------------------------------------------------------------------- 12 | // Pragma 13 | #pragma comment(lib, "mfplat") 14 | #pragma comment(lib, "shlwapi") 15 | #pragma comment(lib, "dxva2") 16 | #pragma comment(lib, "d3d9") 17 | #pragma comment(lib, "Mf") 18 | #pragma comment(lib, "strmiids") 19 | #pragma comment(lib, "mfuuid") 20 | 21 | //---------------------------------------------------------------------------------------------- 22 | // Microsoft Windows SDK for Windows 7 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #ifdef _DEBUG 30 | #include 31 | #endif 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | //---------------------------------------------------------------------------------------------- 52 | // Common Project Files 53 | #ifdef _DEBUG 54 | #define MF_USE_LOGGING 1 55 | //#define MF_USE_LOGREFCOUNT 56 | //#define TRACE_PLAYER 57 | #else 58 | #define MF_USE_LOGGING 0 59 | #endif 60 | 61 | #include ".\Common\MFMacro.h" 62 | #include ".\Common\MFTrace.h" 63 | #include ".\Common\MFLogging.h" 64 | #include ".\Common\MFTExternTrace.h" 65 | 66 | //---------------------------------------------------------------------------------------------- 67 | // Project Files 68 | #include "Player.h" 69 | 70 | #endif -------------------------------------------------------------------------------- /MFMultiVideo/WinMain.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | #define WINDOWSFORM_CLASS L"MFMultiVideo" 7 | #define PLAYER_COUNT 16 8 | #define PLAYER_PER_LINE 4 9 | #define MAX_PLAYER_PLAY 4 10 | #define VIDEO_INPUT_FILE L"big_buck_bunny_240p_5mb.mp4" 11 | #define VIDEO_INPUT_TIME 60000 12 | 13 | HWND g_hWnd = NULL; 14 | HWND g_hWndPlayers[PLAYER_COUNT] = {0}; 15 | CPlayer* g_pPlayer[PLAYER_COUNT] = {0}; 16 | 17 | BOOL InitInstance(HINSTANCE, int); 18 | void AutoStartPlayback(); 19 | LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 20 | 21 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow) 22 | { 23 | if(!InitInstance(hInstance, nCmdShow)) 24 | { 25 | return -1; 26 | } 27 | 28 | MSG msg; 29 | ZeroMemory(&msg, sizeof(msg)); 30 | 31 | while(GetMessage(&msg, NULL, 0, 0) > 0) 32 | { 33 | TranslateMessage(&msg); 34 | DispatchMessage(&msg); 35 | } 36 | 37 | if(IsWindow(g_hWnd)){ 38 | DestroyWindow(g_hWnd); 39 | } 40 | 41 | UnregisterClass(WINDOWSFORM_CLASS, hInstance); 42 | 43 | MFShutdown(); 44 | CoUninitialize(); 45 | 46 | return 0; 47 | } 48 | 49 | BOOL InitInstance(HINSTANCE hInst, int nCmdShow) 50 | { 51 | WNDCLASSEX wcex; 52 | 53 | ZeroMemory(&wcex, sizeof(WNDCLASSEX)); 54 | wcex.cbSize = sizeof(WNDCLASSEX); 55 | wcex.style = CS_HREDRAW | CS_VREDRAW; 56 | wcex.lpfnWndProc = WndProc; 57 | wcex.hInstance = hInst; 58 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 59 | wcex.lpszClassName = WINDOWSFORM_CLASS; 60 | 61 | if(RegisterClassEx(&wcex) == 0) 62 | { 63 | return FALSE; 64 | } 65 | 66 | // Create the application window. 67 | g_hWnd = CreateWindow(WINDOWSFORM_CLASS, WINDOWSFORM_CLASS, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL); 68 | 69 | if(g_hWnd == 0) 70 | { 71 | return FALSE; 72 | } 73 | 74 | ShowWindow(g_hWnd, nCmdShow); 75 | UpdateWindow(g_hWnd); 76 | 77 | CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); 78 | MFStartup(MF_VERSION, MFSTARTUP_LITE); 79 | 80 | for(int i = 0; i < PLAYER_COUNT; i++) 81 | { 82 | g_hWndPlayers[i] = CreateWindowEx(0, WINDOWSFORM_CLASS, L"Player Window", WS_VISIBLE | WS_CHILD, (i % PLAYER_PER_LINE) * 164, int((i / PLAYER_PER_LINE)) * 117, 164, 117, g_hWnd, (HMENU)1, hInst, NULL); 83 | 84 | assert(g_hWndPlayers[i] != NULL); 85 | 86 | HRESULT hr = CPlayer::CreateInstance(g_hWndPlayers[i], i, &g_pPlayer[i]); 87 | 88 | assert(hr == S_OK && g_pPlayer[i] != NULL); 89 | } 90 | 91 | std::thread t(AutoStartPlayback); 92 | t.detach(); 93 | 94 | return TRUE; 95 | } 96 | 97 | void AutoStartPlayback() 98 | { 99 | int iCount = 0; 100 | 101 | do 102 | { 103 | for(int i = 0; i < PLAYER_COUNT; i++) 104 | { 105 | LOG_HRESULT(g_pPlayer[i]->OpenUrl(VIDEO_INPUT_FILE)); 106 | } 107 | 108 | Sleep(VIDEO_INPUT_TIME); 109 | 110 | for(int i = 0; i < PLAYER_COUNT; i++) 111 | { 112 | LOG_HRESULT(g_pPlayer[i]->Shutdown()); 113 | } 114 | 115 | iCount++; 116 | } 117 | while(iCount < MAX_PLAYER_PLAY); 118 | 119 | for(int i = 0; i < PLAYER_COUNT; i++) 120 | { 121 | LOG_HRESULT(g_pPlayer[i]->Shutdown()); 122 | SAFE_RELEASE(g_pPlayer[i]); 123 | } 124 | 125 | for(int i = 0; i < PLAYER_COUNT; i++) 126 | { 127 | DestroyWindow(g_hWndPlayers[i]); 128 | } 129 | } 130 | 131 | LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 132 | { 133 | switch(message) 134 | { 135 | case WM_ERASEBKGND: 136 | return 1L; 137 | 138 | case WM_DESTROY: 139 | PostQuitMessage(0); 140 | break; 141 | 142 | default: 143 | return DefWindowProc(hwnd, message, wParam, lParam); 144 | } 145 | 146 | return 0L; 147 | } -------------------------------------------------------------------------------- /MFVideoCaptureEVR/MFVideoCaptureEVR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MFVideoCaptureEVR", "MFVideoCaptureEVR.vcxproj", "{91E6311D-6613-4E32-B635-0719DA39446A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {91E6311D-6613-4E32-B635-0719DA39446A}.Debug|x64.ActiveCfg = Debug|x64 17 | {91E6311D-6613-4E32-B635-0719DA39446A}.Debug|x64.Build.0 = Debug|x64 18 | {91E6311D-6613-4E32-B635-0719DA39446A}.Debug|x86.ActiveCfg = Debug|Win32 19 | {91E6311D-6613-4E32-B635-0719DA39446A}.Debug|x86.Build.0 = Debug|Win32 20 | {91E6311D-6613-4E32-B635-0719DA39446A}.Release|x64.ActiveCfg = Release|x64 21 | {91E6311D-6613-4E32-B635-0719DA39446A}.Release|x64.Build.0 = Release|x64 22 | {91E6311D-6613-4E32-B635-0719DA39446A}.Release|x86.ActiveCfg = Release|Win32 23 | {91E6311D-6613-4E32-B635-0719DA39446A}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {28A88B0D-F66C-40FE-BF9A-A688A3344B77} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /MFVideoCaptureEVR/MFVideoCaptureEVR.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Fichiers sources 20 | 21 | 22 | -------------------------------------------------------------------------------- /MFVideoCaptureEVR/MFVideoCaptureEVR.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /MFVideoEVR/MFVideoEVR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MFVideoEVR", "MFVideoEVR.vcxproj", "{005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}.Debug|Win32.Build.0 = Debug|Win32 16 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}.Release|Win32.ActiveCfg = Release|Win32 17 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /MFVideoEVR/MFVideoEVR.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08} 15 | Win32Proj 16 | MFVideoEVR 17 | 10.0.15063.0 18 | 19 | 20 | 21 | Application 22 | true 23 | v141 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v141 30 | true 31 | Unicode 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level4 54 | Disabled 55 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 71 | 72 | 73 | Console 74 | false 75 | true 76 | true 77 | UseLinkTimeCodeGeneration 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /MFVideoEVR/MFVideoEVR.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Media/CustomVideoMixer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mofo7777/Stackoverflow/20aeebb815f6b9c1492abd54127dfe6b9be65b77/Media/CustomVideoMixer.jpg -------------------------------------------------------------------------------- /Media/IMFSinkWriterCallback.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mofo7777/Stackoverflow/20aeebb815f6b9c1492abd54127dfe6b9be65b77/Media/IMFSinkWriterCallback.jpg -------------------------------------------------------------------------------- /Media/MFMultiVideo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mofo7777/Stackoverflow/20aeebb815f6b9c1492abd54127dfe6b9be65b77/Media/MFMultiVideo.jpg -------------------------------------------------------------------------------- /Media/ScreenCaptureEncode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mofo7777/Stackoverflow/20aeebb815f6b9c1492abd54127dfe6b9be65b77/Media/ScreenCaptureEncode.jpg -------------------------------------------------------------------------------- /MinimalSinkRenderer/Common/MFClassFactory.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFClassFactory.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFCLASSFACTORY_H 5 | #define MFCLASSFACTORY_H 6 | 7 | typedef HRESULT (*CreateInstanceFn)(IUnknown*, REFIID, void**); 8 | 9 | struct ClassFactoryData{ 10 | 11 | const GUID* pclsid; 12 | CreateInstanceFn pfnCreate; 13 | }; 14 | 15 | class ClassFactory : public IClassFactory{ 16 | 17 | private: 18 | 19 | volatile long m_refCount; // Reference count. 20 | static volatile long m_serverLocks; // Number of server locks 21 | 22 | CreateInstanceFn m_pfnCreation; // Function to create an instance of the object. 23 | 24 | public: 25 | 26 | ClassFactory(CreateInstanceFn pfnCreation) : m_pfnCreation(pfnCreation), m_refCount(1){} 27 | 28 | static bool IsLocked(){ return (m_serverLocks != 0); } 29 | 30 | STDMETHODIMP_(ULONG) AddRef(){ return InterlockedIncrement(&m_refCount); } 31 | STDMETHODIMP_(ULONG) Release(){ 32 | 33 | assert(m_refCount >= 0); 34 | ULONG uCount = InterlockedDecrement(&m_refCount); 35 | 36 | if(uCount == 0){ 37 | delete this; 38 | } 39 | 40 | return uCount; 41 | } 42 | 43 | STDMETHODIMP QueryInterface(REFIID riid, void** ppv){ 44 | 45 | if(NULL == ppv){ 46 | return E_POINTER; 47 | } 48 | else if(riid == __uuidof(IUnknown)){ 49 | *ppv = static_cast(this); 50 | } 51 | else if(riid == __uuidof(IClassFactory)){ 52 | *ppv = static_cast(this); 53 | } 54 | else{ 55 | *ppv = NULL; 56 | return E_NOINTERFACE; 57 | } 58 | 59 | AddRef(); 60 | return S_OK; 61 | } 62 | 63 | STDMETHODIMP CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppv){ 64 | 65 | if(pUnkOuter != NULL){ 66 | 67 | if(riid != __uuidof(IUnknown)){ 68 | return E_NOINTERFACE; 69 | } 70 | } 71 | 72 | return m_pfnCreation(pUnkOuter, riid, ppv); 73 | } 74 | 75 | STDMETHODIMP LockServer(BOOL lock){ 76 | 77 | if(lock){ 78 | LockServer(); 79 | } 80 | else{ 81 | UnlockServer(); 82 | } 83 | return S_OK; 84 | } 85 | 86 | static void LockServer(){ InterlockedIncrement(&m_serverLocks); } 87 | static void UnlockServer(){ InterlockedDecrement(&m_serverLocks); } 88 | }; 89 | 90 | class BaseObject{ 91 | 92 | public: 93 | 94 | BaseObject(){ ClassFactory::LockServer(); } 95 | virtual ~BaseObject(){ ClassFactory::UnlockServer(); } 96 | }; 97 | 98 | #define DEFINE_CLASSFACTORY_SERVER_LOCK volatile long ClassFactory::m_serverLocks = 0; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/Common/MFCriticSection.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFCriticSection.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFCRITICSECTION_H 5 | #define MFCRITICSECTION_H 6 | 7 | class CriticSection{ 8 | 9 | private: 10 | 11 | CRITICAL_SECTION m_Section; 12 | 13 | public: 14 | 15 | CriticSection(){ InitializeCriticalSection(&m_Section); } 16 | ~CriticSection(){ DeleteCriticalSection(&m_Section); } 17 | 18 | void Lock(){ EnterCriticalSection(&m_Section); } 19 | void Unlock(){ LeaveCriticalSection(&m_Section); } 20 | }; 21 | 22 | class AutoLock{ 23 | 24 | private: 25 | 26 | CriticSection* m_pSection; 27 | 28 | public: 29 | 30 | AutoLock(CriticSection& critic){ m_pSection = &critic; m_pSection->Lock(); } 31 | ~AutoLock(){ m_pSection->Unlock(); } 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/Common/MFGuid.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFGuid.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFGUID_H 5 | #define MFGUID_H 6 | 7 | // {2F181C36-36CC-4527-AAA5-4F46720194EE} 8 | DEFINE_GUID(CLSID_MinimalSinkRenderer, 0x2f181c36, 0x36cc, 0x4527, 0xaa, 0xa5, 0x4f, 0x46, 0x72, 0x1, 0x94, 0xee); 9 | 10 | //---------------------------------------------------------------------------------------------- 11 | // Media subType guid 12 | 13 | // {7634706D-0000-0010-8000-00AA00389B71} 14 | DEFINE_GUID(MEDIASUBTYPE_mp4v, 0x7634706d, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 15 | 16 | // 56564D41-0000-0010-8000-00AA00389B71 17 | DEFINE_GUID(MEDIASUBTYPE_XVID, 0x44495658, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 18 | 19 | // {64697678-0000-0010-8000-00AA00389B71} 20 | DEFINE_GUID(MEDIASUBTYPE_xvid, 0x64697678, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 21 | 22 | // {58564944-0000-0010-8000-00AA00389B71} 23 | DEFINE_GUID(MEDIASUBTYPE_DIVX, 0x58564944, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 24 | 25 | // {78766964-0000-0010-8000-00AA00389B71} 26 | DEFINE_GUID(MEDIASUBTYPE_divx, 0x78766964, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 27 | 28 | // {30355844-0000-0010-8000-00aa00389b71} 29 | DEFINE_GUID(MEDIASUBTYPE_DX50, 0x30355844, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 30 | 31 | // {30357864-0000-0010-8000-00AA00389B71} 32 | DEFINE_GUID(MEDIASUBTYPE_dx50, 0x30357864, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 33 | 34 | // {1D4A45F2-E5F6-4B44-8388-F0AE5C0E0C37} 35 | DEFINE_GUID(MEDIASUBTYPE_VIDEOIMAGE, 0x1D4A45F2, 0xE5F6, 0x4B44, 0x83, 0x88, 0xF0, 0xAE, 0x5C, 0x0E, 0x0C, 0x37); 36 | 37 | // {00000031-0000-0010-8000-00AA00389B71} 38 | DEFINE_GUID(MEDIASUBTYPE_GSM, 0x00000031, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 39 | 40 | // {00000011-0000-0010-8000-00AA00389B71} 41 | DEFINE_GUID(MEDIASUBTYPE_IMAADPCMACM, 0x00000011, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 42 | 43 | #endif -------------------------------------------------------------------------------- /MinimalSinkRenderer/Common/MFLogCommon.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogCommon.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGCOMMON_H 5 | #define MFLOGCOMMON_H 6 | 7 | #if (_DEBUG && MF_USE_LOGGING) 8 | 9 | typedef LPCWSTR(*GetGUIDStringName)(const GUID&); 10 | 11 | inline void LogGuidHexa(const GUID& guid, const BOOL bFirst){ 12 | 13 | HRESULT hr; 14 | WCHAR pBuffer[39] = {0}; 15 | 16 | hr = StringCchPrintf(pBuffer, 39, L"{%.8lX-%.4hX-%.4hX-%.2hhX%.2hhX-%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX}", 17 | guid.Data1, 18 | guid.Data2, 19 | guid.Data3, 20 | guid.Data4[0], 21 | guid.Data4[1], 22 | guid.Data4[2], 23 | guid.Data4[3], 24 | guid.Data4[4], 25 | guid.Data4[5], 26 | guid.Data4[6], 27 | guid.Data4[7] 28 | ); 29 | 30 | if(SUCCEEDED(hr)){ 31 | 32 | if(bFirst) 33 | TRACE_NO_END_LINE((L"\t%s\t", pBuffer)); 34 | else 35 | TRACE((L"%s", pBuffer)); 36 | } 37 | else{ 38 | 39 | TRACE((L"Guid problem")); 40 | } 41 | } 42 | 43 | inline void LogUINT32AsUINT64(const PROPVARIANT& var){ 44 | 45 | UINT32 uHigh = 0, uLow = 0; 46 | 47 | Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &uHigh, &uLow); 48 | 49 | TRACE((L"%u x %u", uHigh, uLow)); 50 | } 51 | 52 | inline HRESULT SpecialCaseAttributeValue(GUID guid, const PROPVARIANT& var){ 53 | 54 | if(guid == MF_MT_FRAME_RATE){ 55 | LogUINT32AsUINT64(var); 56 | } 57 | else if(guid == MF_MT_FRAME_SIZE){ 58 | LogUINT32AsUINT64(var); 59 | } 60 | else if(guid == MF_MT_PIXEL_ASPECT_RATIO){ 61 | LogUINT32AsUINT64(var); 62 | } 63 | else{ 64 | return S_FALSE; 65 | } 66 | 67 | return S_OK; 68 | } 69 | 70 | inline void LogPropertyVariant(const GUID* pGuid, const PROPVARIANT& var, GetGUIDStringName pGetGUIDString){ 71 | 72 | HRESULT hr = S_FALSE; 73 | 74 | if(pGuid != NULL) 75 | hr = SpecialCaseAttributeValue(*pGuid, var); 76 | 77 | if(hr == S_FALSE){ 78 | 79 | switch(var.vt){ 80 | 81 | case VT_UI4: 82 | TRACE((L"%lu", var.ulVal)); 83 | break; 84 | 85 | case VT_I4: 86 | TRACE((L"%ld", var.lVal)); 87 | break; 88 | 89 | case VT_UI8: 90 | TRACE((L"%I64u", var.uhVal)); 91 | break; 92 | 93 | case VT_BOOL: 94 | TRACE((L"%s", var.boolVal == -1 ? "true" : "false")); 95 | break; 96 | 97 | case VT_R8: 98 | TRACE((L"%f", var.dblVal)); 99 | break; 100 | 101 | case VT_CLSID: 102 | { 103 | LPCWSTR pwszGuidName = pGetGUIDString(*var.puuid); 104 | 105 | if(pwszGuidName != NULL){ 106 | TRACE((L"%s", pwszGuidName)); 107 | } 108 | else{ 109 | LogGuidHexa(*var.puuid, FALSE); 110 | } 111 | } 112 | break; 113 | 114 | case VT_LPWSTR: 115 | // Log : var.pwszVal 116 | TRACE((L"VT_LPWSTR = todo")); 117 | break; 118 | 119 | case VT_VECTOR | VT_UI1: 120 | TRACE((L"(VT_VECTOR|VT_UI1) = <>")); 121 | break; 122 | 123 | case VT_UNKNOWN: 124 | TRACE((L"VT_UNKNOWN = IUnknown")); 125 | break; 126 | 127 | case VT_EMPTY: 128 | TRACE((L"VT_EMPTY")); 129 | break; 130 | 131 | case VT_R4: 132 | TRACE((L"VT_R4 = %f", var.fltVal)); 133 | break; 134 | 135 | // 8195 = VT_ARRAY | VT_I4 136 | 137 | default: 138 | TRACE((L"Unexpected attribute type (vt = %hu)", var.vt)); 139 | break; 140 | } 141 | } 142 | } 143 | 144 | inline void LogAttributeValueByIndex(IMFAttributes* pAttributes, UINT32 uiIndex, GetGUIDStringName pGetGUIDString){ 145 | 146 | HRESULT hr; 147 | PROPVARIANT var; 148 | GUID guid = GUID_NULL; 149 | 150 | PropVariantInit(&var); 151 | 152 | hr = pAttributes->GetItemByIndex(uiIndex, &guid, &var); 153 | 154 | if(SUCCEEDED(hr)){ 155 | 156 | LPCWSTR pwszGUIDNameAttributes = pGetGUIDString(guid); 157 | 158 | if(pwszGUIDNameAttributes != NULL){ 159 | TRACE_NO_END_LINE((L"\t%s\t", pwszGUIDNameAttributes)); 160 | } 161 | else{ 162 | 163 | LogGuidHexa(guid, TRUE); 164 | } 165 | 166 | LogPropertyVariant(&guid, var, pGetGUIDString); 167 | } 168 | else{ 169 | TRACE((L"\tGetItemByIndex (Index = %u) hr = %s", uiIndex, MFErrorString(hr))); 170 | } 171 | 172 | PropVariantClear(&var); 173 | } 174 | 175 | #endif 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/Common/MFLogging.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogging.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGGING_H 5 | #define MFLOGGING_H 6 | 7 | #ifdef _DEBUG 8 | 9 | class DebugLog{ 10 | 11 | public: 12 | 13 | static void Initialize(){ 14 | _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); 15 | //_CrtSetBreakAlloc(155); 16 | } 17 | 18 | static void Trace(const WCHAR* sFormatString, ...){ 19 | 20 | HRESULT hr = S_OK; 21 | va_list va; 22 | 23 | const DWORD TRACE_STRING_LEN = 512; 24 | 25 | WCHAR message[TRACE_STRING_LEN]; 26 | 27 | va_start(va, sFormatString); 28 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 29 | va_end(va); 30 | 31 | if(SUCCEEDED(hr)){ 32 | 33 | size_t size = _tcslen(message); 34 | 35 | if(size != 0 && size < TRACE_STRING_LEN){ 36 | message[size] = '\n'; 37 | message[size + 1] = '\0'; 38 | } 39 | 40 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 41 | } 42 | } 43 | 44 | static void TraceNoEndLine(const WCHAR* sFormatString, ...){ 45 | 46 | HRESULT hr = S_OK; 47 | va_list va; 48 | 49 | const DWORD TRACE_STRING_LEN = 512; 50 | 51 | WCHAR message[TRACE_STRING_LEN]; 52 | 53 | va_start(va, sFormatString); 54 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 55 | va_end(va); 56 | 57 | if(SUCCEEDED(hr)){ 58 | 59 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 60 | } 61 | } 62 | 63 | static void Close(){ 64 | int bLeak = _CrtDumpMemoryLeaks(); 65 | assert(bLeak == FALSE); 66 | } 67 | }; 68 | 69 | #define TRACE_INIT() DebugLog::Initialize() 70 | #define TRACE(x) DebugLog::Trace x 71 | #define TRACE_NO_END_LINE(x) DebugLog::TraceNoEndLine x 72 | #define TRACE_CLOSE() DebugLog::Close() 73 | 74 | inline HRESULT _LOG_HRESULT(HRESULT hr, const char* sFileName, long lLineNo){ 75 | 76 | if(FAILED(hr)){ 77 | TRACE((L"\n%S - Line: %d hr = %s\n", sFileName, lLineNo, MFErrorString(hr))); 78 | } 79 | 80 | return hr; 81 | } 82 | 83 | #define LOG_HRESULT(hr) _LOG_HRESULT(hr, __FILE__, __LINE__) 84 | #define LOG_LAST_ERROR() _LOG_HRESULT(HRESULT_FROM_WIN32(GetLastError()), __FILE__, __LINE__) 85 | 86 | #ifdef MF_USE_LOGREFCOUNT 87 | #define TRACE_REFCOUNT(x) DebugLog::Trace x 88 | #else 89 | #define TRACE_REFCOUNT(x) 90 | #endif 91 | 92 | #ifdef MF_TRACE_SINK 93 | #define TRACE_SINK(x) DebugLog::Trace x 94 | #else 95 | #define TRACE_SINK(x) 96 | #endif 97 | 98 | #ifdef MF_TRACE_STREAM 99 | #define TRACE_STREAM(x) DebugLog::Trace x 100 | #else 101 | #define TRACE_STREAM(x) 102 | #endif 103 | 104 | #else 105 | #define TRACE_INIT() 106 | #define TRACE(x) 107 | #define TRACE_NO_END_LINE(x) 108 | #define TRACE_CLOSE() 109 | #define LOG_HRESULT(hr) hr 110 | #define LOG_LAST_ERROR() 111 | #define TRACE_REFCOUNT(x) 112 | #define TRACE_SINK(x) 113 | #define TRACE_STREAM(x) 114 | #endif 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/Common/MFMacro.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFMacro.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFMACRO_H 5 | #define MFMACRO_H 6 | 7 | #ifndef MF_SAFE_RELEASE 8 | #define MF_SAFE_RELEASE 9 | template inline void SAFE_RELEASE(T*& p){ 10 | 11 | if(p){ 12 | p->Release(); 13 | p = NULL; 14 | } 15 | } 16 | #endif 17 | 18 | #ifndef MF_SAFE_DELETE 19 | #define MF_SAFE_DELETE 20 | template inline void SAFE_DELETE(T*& p){ 21 | 22 | if(p){ 23 | delete p; 24 | p = NULL; 25 | } 26 | } 27 | #endif 28 | 29 | #ifndef MF_SAFE_DELETE_ARRAY 30 | #define MF_SAFE_DELETE_ARRAY 31 | template inline void SAFE_DELETE_ARRAY(T*& p){ 32 | 33 | if(p){ 34 | delete[] p; 35 | p = NULL; 36 | } 37 | } 38 | #endif 39 | 40 | // Need to use other macro. When error, multiple call. 41 | #ifndef IF_FAILED_RETURN 42 | #if(_DEBUG && MF_USE_LOGGING) 43 | #define IF_FAILED_RETURN(hr) if(FAILED(hr)){ LOG_HRESULT(hr); return hr; } 44 | #else 45 | #define IF_FAILED_RETURN(hr) if(FAILED(hr)){ return hr; } 46 | #endif 47 | #endif 48 | 49 | #ifndef IF_FAILED_THROW 50 | #if(_DEBUG && MF_USE_LOGGING) 51 | #define IF_FAILED_THROW(hr) if(FAILED(hr)){ LOG_HRESULT(hr); throw hr; } 52 | #else 53 | #define IF_FAILED_THROW(hr) if(FAILED(hr)){ throw hr; } 54 | #endif 55 | #endif 56 | 57 | #ifndef ARRAY_SIZE 58 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]) ) 59 | #endif 60 | 61 | #ifndef RETURN_STRING 62 | #define RETURN_STRING(x) case x: return L#x 63 | #endif 64 | 65 | #ifndef IF_EQUAL_RETURN 66 | #define IF_EQUAL_RETURN(param, val) if(val == param) return L#val 67 | #endif 68 | 69 | #ifndef VALUE_NOT_FOUND 70 | #define VALUE_NOT_FOUND(val) return L#val 71 | #endif 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/Common/MFState.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFState.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFSTATE_H 5 | #define MFSTATE_H 6 | 7 | enum SessionState{ 8 | 9 | SessionClosed = 0, 10 | SessionReady, 11 | SessionOpenPending, 12 | SessionStarted, 13 | SessionPaused, 14 | SessionStopped, 15 | SessionClosing, 16 | SessionAbort 17 | }; 18 | 19 | enum StreamState{ 20 | 21 | StreamTypeNotSet = 0, 22 | StreamReady, 23 | StreamStarted, 24 | StreamStopped, 25 | StreamPaused, 26 | StreamFinalized, 27 | 28 | StreamCount = StreamFinalized + 1 29 | }; 30 | 31 | enum StreamRequest{ 32 | 33 | RequestSetMediaType = 0, 34 | RequestStart, 35 | RequestRestart, 36 | RequestPause, 37 | RequestStop, 38 | RequestProcessSample, 39 | RequestPlaceMarker, 40 | RequestFinalize, 41 | 42 | RequestCount = RequestFinalize + 1 43 | }; 44 | 45 | enum SourceState{ 46 | 47 | SourceInvalid, 48 | SourceOpening, 49 | SourceStopped, 50 | SourcePaused, 51 | SourceStarted, 52 | SourceShutdown 53 | }; 54 | 55 | enum RendererState{ 56 | 57 | RendererStarted, 58 | RendererStopped, 59 | RendererPaused, 60 | RendererShutdown 61 | }; 62 | 63 | #if (_DEBUG && MF_USE_LOGGING) 64 | 65 | inline LPCWSTR ClockStateString(MFCLOCK_STATE State){ 66 | 67 | switch(State){ 68 | 69 | RETURN_STRING(MFCLOCK_STATE_INVALID); 70 | RETURN_STRING(MFCLOCK_STATE_RUNNING); 71 | RETURN_STRING(MFCLOCK_STATE_STOPPED); 72 | RETURN_STRING(MFCLOCK_STATE_PAUSED); 73 | 74 | default: 75 | return L"Unknown Clock State"; 76 | } 77 | } 78 | 79 | inline LPCWSTR SessionStateString(SessionState State){ 80 | 81 | switch(State){ 82 | 83 | RETURN_STRING(SessionClosed); 84 | RETURN_STRING(SessionReady); 85 | RETURN_STRING(SessionOpenPending); 86 | RETURN_STRING(SessionStarted); 87 | RETURN_STRING(SessionPaused); 88 | RETURN_STRING(SessionStopped); 89 | RETURN_STRING(SessionClosing); 90 | 91 | default: 92 | return L"Unknown Session State"; 93 | } 94 | } 95 | 96 | inline LPCWSTR StreamStateString(StreamState State){ 97 | 98 | switch(State){ 99 | 100 | RETURN_STRING(StreamTypeNotSet); 101 | RETURN_STRING(StreamReady); 102 | RETURN_STRING(StreamStarted); 103 | RETURN_STRING(StreamStopped); 104 | RETURN_STRING(StreamPaused); 105 | RETURN_STRING(StreamFinalized); 106 | RETURN_STRING(StreamCount); 107 | 108 | default: 109 | return L"Unknown Stream State"; 110 | } 111 | } 112 | 113 | inline LPCWSTR StreamRequestStateString(StreamRequest State){ 114 | 115 | switch(State){ 116 | 117 | RETURN_STRING(RequestSetMediaType); 118 | RETURN_STRING(RequestStart); 119 | RETURN_STRING(RequestRestart); 120 | RETURN_STRING(RequestPause); 121 | RETURN_STRING(RequestStop); 122 | RETURN_STRING(RequestProcessSample); 123 | RETURN_STRING(RequestPlaceMarker); 124 | RETURN_STRING(RequestFinalize); 125 | RETURN_STRING(RequestCount); 126 | 127 | default: 128 | return L"Unknown StreamRequest State"; 129 | } 130 | } 131 | 132 | inline LPCWSTR SourceStateString(SourceState State){ 133 | 134 | switch(State){ 135 | 136 | RETURN_STRING(SourceInvalid); 137 | RETURN_STRING(SourceOpening); 138 | RETURN_STRING(SourceStopped); 139 | RETURN_STRING(SourcePaused); 140 | RETURN_STRING(SourceStarted); 141 | RETURN_STRING(SourceShutdown); 142 | 143 | default: 144 | return L"Unknown Source State"; 145 | } 146 | } 147 | 148 | inline LPCWSTR RendererStateString(RendererState State){ 149 | 150 | switch(State){ 151 | 152 | RETURN_STRING(RendererStarted); 153 | RETURN_STRING(RendererStopped); 154 | RETURN_STRING(RendererPaused); 155 | RETURN_STRING(RendererShutdown); 156 | 157 | default: 158 | return L"Unknown Renderer State"; 159 | } 160 | } 161 | 162 | #else 163 | 164 | #define ClockStateString(x) L"" 165 | #define SessionStateString(x) L"" 166 | #define StreamStateString(x) L"" 167 | #define StreamRequestStateString(x) L"" 168 | #define SourceStateString(x) L"" 169 | #define RendererStateString(x) L"" 170 | 171 | #endif 172 | 173 | #endif -------------------------------------------------------------------------------- /MinimalSinkRenderer/Common/MFTExternTrace.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFTExternTrace.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFTEXTERNTRACE_H 5 | #define MFTEXTERNTRACE_H 6 | 7 | // CExternTrace initializes the memory leaks detection (see "crtdbg.h"). 8 | // CExternTrace ensures that no object is allocated before TRACE_INIT is called. 9 | // Because DllMain.cpp contains external objects, you will see "FAKE" memory leaks. 10 | #ifdef _DEBUG 11 | 12 | class CExternTrace{ 13 | 14 | public: 15 | 16 | CExternTrace(){ TRACE_INIT(); }; 17 | ~CExternTrace(){ TRACE_CLOSE(); }; 18 | }; 19 | 20 | CExternTrace cExternTrace; 21 | 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/Common/MFTime.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFTime.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFTIME_H 5 | #define MFTIME_H 6 | 7 | // One second in hns 8 | const MFTIME ONE_SECOND = 10000000; 9 | 10 | // One msec in hns 11 | const LONG ONE_MSEC = 1000; 12 | 13 | inline LONG MFTimeToMilliSec(const LONGLONG& time){ 14 | 15 | return (LONG)(time / (ONE_SECOND / ONE_MSEC)); 16 | } 17 | 18 | inline LONG MFTimeToSec(const LONGLONG& time){ 19 | 20 | return (LONG)(time / ONE_SECOND); 21 | } 22 | 23 | #if (_DEBUG && MF_USE_LOGGING) 24 | 25 | inline void MFTimeString(const MFTIME& Duration){ 26 | 27 | MFTIME DurationInMilliSec = 0; 28 | MFTIME DurationInSec = 0; 29 | MFTIME Hours = 0; 30 | MFTIME Minutes = 0; 31 | MFTIME Seconds = 0; 32 | 33 | DurationInSec = MFTimeToSec(Duration); 34 | DurationInMilliSec = MFTimeToMilliSec(Duration); 35 | 36 | if(DurationInSec > 60){ 37 | 38 | Minutes = DurationInSec / 60; 39 | 40 | if(Minutes > 60){ 41 | 42 | Hours = Minutes / 60; 43 | Minutes = Minutes % 60; 44 | } 45 | 46 | Seconds = (DurationInSec % 60); 47 | } 48 | else{ 49 | 50 | Seconds = DurationInSec; 51 | } 52 | 53 | if(Seconds){ 54 | DurationInMilliSec = DurationInMilliSec % (Seconds * ONE_MSEC); 55 | } 56 | 57 | TRACE((L"%02dh:%02dmn:%02ds:%03dms", (int)Hours, (int)Minutes, (int)Seconds, DurationInMilliSec)); 58 | } 59 | 60 | #else 61 | #define MFTimeString(x) 62 | #endif 63 | 64 | #endif -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinimalSinkRenderer", "MinimalSinkRenderer\MinimalSinkRenderer.vcxproj", "{78024A78-8995-47A3-821A-FDDA40B0D8A5}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{050C0987-83ED-4019-9CC7-C08B71091EF7}" 9 | ProjectSection(SolutionItems) = preProject 10 | Common\MFClassFactory.h = Common\MFClassFactory.h 11 | Common\MFCriticSection.h = Common\MFCriticSection.h 12 | Common\MFGuid.h = Common\MFGuid.h 13 | Common\MFLogCommon.h = Common\MFLogCommon.h 14 | Common\MFLogging.h = Common\MFLogging.h 15 | Common\MFLogMediaType.h = Common\MFLogMediaType.h 16 | Common\MFMacro.h = Common\MFMacro.h 17 | Common\MFRegistry.h = Common\MFRegistry.h 18 | Common\MFState.h = Common\MFState.h 19 | Common\MFTExternTrace.h = Common\MFTExternTrace.h 20 | Common\MFTime.h = Common\MFTime.h 21 | Common\MFTrace.h = Common\MFTrace.h 22 | EndProjectSection 23 | EndProject 24 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestMinimalSinkRenderer", "TestMinimalSinkRenderer\TestMinimalSinkRenderer.vcxproj", "{C404D8DA-ACC9-454C-AE54-E83235C475F9}" 25 | EndProject 26 | Global 27 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 28 | Debug|x64 = Debug|x64 29 | Debug|x86 = Debug|x86 30 | Release|x64 = Release|x64 31 | Release|x86 = Release|x86 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {78024A78-8995-47A3-821A-FDDA40B0D8A5}.Debug|x64.ActiveCfg = Debug|x64 35 | {78024A78-8995-47A3-821A-FDDA40B0D8A5}.Debug|x64.Build.0 = Debug|x64 36 | {78024A78-8995-47A3-821A-FDDA40B0D8A5}.Debug|x86.ActiveCfg = Debug|Win32 37 | {78024A78-8995-47A3-821A-FDDA40B0D8A5}.Debug|x86.Build.0 = Debug|Win32 38 | {78024A78-8995-47A3-821A-FDDA40B0D8A5}.Release|x64.ActiveCfg = Release|x64 39 | {78024A78-8995-47A3-821A-FDDA40B0D8A5}.Release|x64.Build.0 = Release|x64 40 | {78024A78-8995-47A3-821A-FDDA40B0D8A5}.Release|x86.ActiveCfg = Release|Win32 41 | {78024A78-8995-47A3-821A-FDDA40B0D8A5}.Release|x86.Build.0 = Release|Win32 42 | {C404D8DA-ACC9-454C-AE54-E83235C475F9}.Debug|x64.ActiveCfg = Debug|x64 43 | {C404D8DA-ACC9-454C-AE54-E83235C475F9}.Debug|x64.Build.0 = Debug|x64 44 | {C404D8DA-ACC9-454C-AE54-E83235C475F9}.Debug|x86.ActiveCfg = Debug|Win32 45 | {C404D8DA-ACC9-454C-AE54-E83235C475F9}.Debug|x86.Build.0 = Debug|Win32 46 | {C404D8DA-ACC9-454C-AE54-E83235C475F9}.Release|x64.ActiveCfg = Release|x64 47 | {C404D8DA-ACC9-454C-AE54-E83235C475F9}.Release|x64.Build.0 = Release|x64 48 | {C404D8DA-ACC9-454C-AE54-E83235C475F9}.Release|x86.ActiveCfg = Release|Win32 49 | {C404D8DA-ACC9-454C-AE54-E83235C475F9}.Release|x86.Build.0 = Release|Win32 50 | EndGlobalSection 51 | GlobalSection(SolutionProperties) = preSolution 52 | HideSolutionNode = FALSE 53 | EndGlobalSection 54 | GlobalSection(ExtensibilityGlobals) = postSolution 55 | SolutionGuid = {D190FCBF-ABCD-4253-9682-D32ADF6F7FEB} 56 | EndGlobalSection 57 | EndGlobal 58 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/DllMain.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // DllMain.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | HMODULE g_hModule; 7 | 8 | DEFINE_CLASSFACTORY_SERVER_LOCK 9 | 10 | WCHAR SZ_RENDERER_NAME[] = L"Minimal Sink Renderer"; 11 | 12 | BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID /*lpReserved*/){ 13 | 14 | switch(ul_reason_for_call){ 15 | 16 | case DLL_PROCESS_ATTACH: 17 | DisableThreadLibraryCalls((HMODULE)hModule); 18 | g_hModule = (HMODULE)hModule; 19 | break; 20 | 21 | case DLL_PROCESS_DETACH: 22 | case DLL_THREAD_ATTACH: 23 | case DLL_THREAD_DETACH: 24 | break; 25 | } 26 | return TRUE; 27 | } 28 | 29 | STDAPI DllCanUnloadNow(){ 30 | 31 | if(!ClassFactory::IsLocked()){ 32 | return S_OK; 33 | } 34 | else{ 35 | return S_FALSE; 36 | } 37 | } 38 | 39 | STDAPI DllRegisterServer(){ 40 | 41 | HRESULT hr; 42 | 43 | hr = RegisterObject(g_hModule, CLSID_MinimalSinkRenderer, SZ_RENDERER_NAME, TEXT("Both")); 44 | 45 | if(SUCCEEDED(hr)){ 46 | 47 | MFT_REGISTER_TYPE_INFO tInInfo [] = { { MFMediaType_Video, MFVideoFormat_RGB32 } }; 48 | 49 | hr = MFTRegister(CLSID_MinimalSinkRenderer, MFT_CATEGORY_OTHER, SZ_RENDERER_NAME, 0, ARRAY_SIZE(tInInfo), tInInfo, 0, NULL, NULL); 50 | } 51 | 52 | return hr; 53 | } 54 | 55 | STDAPI DllUnregisterServer(){ 56 | 57 | UnregisterObject(CLSID_MinimalSinkRenderer); 58 | MFTUnregister(CLSID_MinimalSinkRenderer); 59 | return S_OK; 60 | } 61 | 62 | STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void** ppv){ 63 | 64 | HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; 65 | 66 | if(clsid == CLSID_MinimalSinkRenderer){ 67 | 68 | ClassFactory* pFactory = NULL; 69 | 70 | pFactory = new (std::nothrow)ClassFactory(CMinimalSkinkRenderer::CreateInstance); 71 | 72 | if(pFactory){ 73 | 74 | hr = pFactory->QueryInterface(riid, ppv); 75 | 76 | SAFE_RELEASE(pFactory); 77 | } 78 | else{ 79 | 80 | hr = E_OUTOFMEMORY; 81 | } 82 | } 83 | 84 | return hr; 85 | } -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/MinimalSinkRenderer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Fichiers sources 6 | 7 | 8 | Fichiers sources 9 | 10 | 11 | Fichiers sources 12 | 13 | 14 | Fichiers sources 15 | 16 | 17 | Fichiers sources 18 | 19 | 20 | Fichiers sources 21 | 22 | 23 | Fichiers sources 24 | 25 | 26 | Fichiers sources 27 | 28 | 29 | Fichiers sources 30 | 31 | 32 | 33 | 34 | Fichiers d%27en-tête 35 | 36 | 37 | Fichiers d%27en-tête 38 | 39 | 40 | Fichiers d%27en-tête 41 | 42 | 43 | 44 | 45 | {5134eb78-c9fc-440d-89b1-0cf8df0e5c8d} 46 | 47 | 48 | {5508b7ae-2491-4e6a-a0a6-87861da137f3} 49 | 50 | 51 | {95f1c72f-5685-4a20-bfc3-972744c68e54} 52 | 53 | 54 | 55 | 56 | Fichiers de ressources 57 | 58 | 59 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/MinimalSinkRenderer.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/MinimalSkinkRenderer.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllCanUnloadNow PRIVATE 3 | DllRegisterServer PRIVATE 4 | DllUnregisterServer PRIVATE 5 | DllGetClassObject PRIVATE 6 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/MinimalSkinkRenderer.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MinimalSkinkRenderer.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MINIMALSINKRENDERER_H 5 | #define MINIMALSINKRENDERER_H 6 | 7 | class CMinimalSkinkRenderer : BaseObject, public IMFMediaSink, public IMFClockStateSink{ 8 | 9 | public: 10 | 11 | // MinimalSkinkRenderer.cpp 12 | static HRESULT CreateInstance(IUnknown*, REFIID, void**); 13 | 14 | // IUnknown - MinimalSkinkRenderer.cpp 15 | STDMETHODIMP QueryInterface(REFIID, void**); 16 | STDMETHODIMP_(ULONG) AddRef(); 17 | STDMETHODIMP_(ULONG) Release(); 18 | 19 | // IMFMediaSink - MinimalSkinkRenderer_Sink.cpp 20 | STDMETHODIMP GetCharacteristics(DWORD*); 21 | STDMETHODIMP AddStreamSink(DWORD, IMFMediaType*, IMFStreamSink**); 22 | STDMETHODIMP RemoveStreamSink(DWORD); 23 | STDMETHODIMP GetStreamSinkCount(DWORD*); 24 | STDMETHODIMP GetStreamSinkByIndex(DWORD, IMFStreamSink**); 25 | STDMETHODIMP GetStreamSinkById(DWORD, IMFStreamSink**); 26 | STDMETHODIMP SetPresentationClock(IMFPresentationClock*); 27 | STDMETHODIMP GetPresentationClock(IMFPresentationClock**); 28 | STDMETHODIMP Shutdown(); 29 | 30 | // IMFClockStateSink - MinimalSkinkRenderer_Clock.cpp 31 | STDMETHODIMP OnClockStart(MFTIME, LONGLONG); 32 | STDMETHODIMP OnClockStop(MFTIME); 33 | STDMETHODIMP OnClockPause(MFTIME); 34 | STDMETHODIMP OnClockRestart(MFTIME); 35 | STDMETHODIMP OnClockSetRate(MFTIME, float); 36 | 37 | // MinimalSkinkRenderer.cpp 38 | HRESULT ProcessSample(IMFSample*); 39 | 40 | private: 41 | 42 | // MinimalSkinkRenderer.cpp 43 | CMinimalSkinkRenderer(HRESULT&); 44 | virtual ~CMinimalSkinkRenderer(); 45 | 46 | CriticSection m_CriticSection; 47 | volatile long m_nRefCount; 48 | BOOL m_bShutdown; 49 | DWORD m_dwCurrentFrame; 50 | 51 | CStreamSkinkRenderer* m_pStreamSkinkRenderer; 52 | IMFPresentationClock* m_pClock; 53 | 54 | // MinimalSkinkRenderer.cpp 55 | void SaveSampleToBmpFile(IMFSample*); 56 | void CreateBmpFile(LPCWSTR, BYTE*, const UINT32, const UINT32, const UINT32, const UINT32); 57 | 58 | // Inline 59 | HRESULT CheckShutdown() const{ return (m_bShutdown ? MF_E_SHUTDOWN : S_OK); } 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/MinimalSkinkRenderer_Clock.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MinimalSkinkRenderer_Clock.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "Stdafx.h" 5 | 6 | HRESULT CMinimalSkinkRenderer::OnClockStart(MFTIME /*hnsSystemTime*/, LONGLONG llClockStartOffset){ 7 | 8 | TRACE_SINK((L"SinkRenderer::OnClockStart")); 9 | 10 | AutoLock lock(m_CriticSection); 11 | 12 | HRESULT hr; 13 | IF_FAILED_RETURN(hr = CheckShutdown()); 14 | 15 | IF_FAILED_RETURN(hr = m_pStreamSkinkRenderer->Start(llClockStartOffset)); 16 | 17 | m_dwCurrentFrame = 0; 18 | 19 | return hr; 20 | } 21 | 22 | HRESULT CMinimalSkinkRenderer::OnClockStop(MFTIME /*hnsSystemTime*/){ 23 | 24 | TRACE_SINK((L"SinkRenderer::OnClockStop")); 25 | 26 | AutoLock lock(m_CriticSection); 27 | 28 | HRESULT hr; 29 | IF_FAILED_RETURN(hr = CheckShutdown()); 30 | 31 | IF_FAILED_RETURN(hr = m_pStreamSkinkRenderer->Stop()); 32 | 33 | return hr; 34 | } 35 | 36 | HRESULT CMinimalSkinkRenderer::OnClockPause(MFTIME /*hnsSystemTime*/){ 37 | 38 | TRACE_SINK((L"SinkRenderer::OnClockPause")); 39 | 40 | AutoLock lock(m_CriticSection); 41 | 42 | HRESULT hr; 43 | IF_FAILED_RETURN(hr = CheckShutdown()); 44 | 45 | IF_FAILED_RETURN(hr = m_pStreamSkinkRenderer->Pause()); 46 | 47 | return hr; 48 | } 49 | 50 | HRESULT CMinimalSkinkRenderer::OnClockRestart(MFTIME /*hnsSystemTime*/){ 51 | 52 | TRACE_SINK((L"SinkRenderer::OnClockRestart")); 53 | 54 | AutoLock lock(m_CriticSection); 55 | 56 | HRESULT hr; 57 | IF_FAILED_RETURN(hr = CheckShutdown()); 58 | 59 | IF_FAILED_RETURN(hr = m_pStreamSkinkRenderer->Restart()); 60 | 61 | return hr; 62 | } 63 | 64 | HRESULT CMinimalSkinkRenderer::OnClockSetRate(MFTIME /*hnsSystemTime*/, float /*flRate*/){ 65 | 66 | TRACE_SINK((L"SinkRenderer::OnClockSetRate")); 67 | 68 | HRESULT hr; 69 | IF_FAILED_RETURN(hr = CheckShutdown()); 70 | 71 | return hr; 72 | } -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/MinimalSkinkRenderer_Sink.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MinimalSkinkRenderer_Sink.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "Stdafx.h" 5 | 6 | HRESULT CMinimalSkinkRenderer::GetCharacteristics(DWORD* pdwCharacteristics){ 7 | 8 | TRACE_SINK((L"SinkRenderer::GetCharacteristics")); 9 | 10 | HRESULT hr; 11 | IF_FAILED_RETURN(hr = (pdwCharacteristics == NULL ? E_INVALIDARG : S_OK)); 12 | 13 | AutoLock lock(m_CriticSection); 14 | 15 | IF_FAILED_RETURN(hr = CheckShutdown()); 16 | 17 | *pdwCharacteristics = MEDIASINK_FIXED_STREAMS; 18 | 19 | return hr; 20 | } 21 | 22 | HRESULT CMinimalSkinkRenderer::AddStreamSink(DWORD /*dwStreamSinkIdentifier*/, IMFMediaType* /*pMediaType*/, IMFStreamSink** /*ppStreamSink*/){ 23 | 24 | TRACE_SINK((L"SinkRenderer::AddStreamSink")); 25 | return MF_E_STREAMSINKS_FIXED; 26 | } 27 | 28 | HRESULT CMinimalSkinkRenderer::RemoveStreamSink(DWORD /*dwStreamSinkIdentifier*/){ 29 | 30 | TRACE_SINK((L"SinkRenderer::RemoveStreamSink")); 31 | return MF_E_STREAMSINKS_FIXED; 32 | } 33 | 34 | HRESULT CMinimalSkinkRenderer::GetStreamSinkCount(DWORD* pcStreamSinkCount){ 35 | 36 | TRACE_SINK((L"SinkRenderer::GetStreamSinkCount")); 37 | 38 | HRESULT hr; 39 | IF_FAILED_RETURN(hr = (pcStreamSinkCount == NULL ? E_INVALIDARG : S_OK)); 40 | 41 | AutoLock lock(m_CriticSection); 42 | 43 | IF_FAILED_RETURN(hr = CheckShutdown()); 44 | 45 | *pcStreamSinkCount = 1; 46 | 47 | return hr; 48 | } 49 | 50 | HRESULT CMinimalSkinkRenderer::GetStreamSinkByIndex(DWORD dwIndex, IMFStreamSink** ppStreamSink){ 51 | 52 | TRACE_SINK((L"SinkRenderer::GetStreamSinkByIndex")); 53 | 54 | HRESULT hr; 55 | IF_FAILED_RETURN(hr = (ppStreamSink == NULL ? E_INVALIDARG : S_OK)); 56 | IF_FAILED_RETURN(hr = (dwIndex != 0 ? MF_E_INVALIDINDEX : S_OK)); 57 | 58 | AutoLock lock(m_CriticSection); 59 | 60 | IF_FAILED_RETURN(hr = CheckShutdown()); 61 | 62 | *ppStreamSink = m_pStreamSkinkRenderer; 63 | (*ppStreamSink)->AddRef(); 64 | 65 | return hr; 66 | } 67 | 68 | HRESULT CMinimalSkinkRenderer::GetStreamSinkById(DWORD dwStreamSinkIdentifier, IMFStreamSink** ppStreamSink){ 69 | 70 | TRACE_SINK((L"SinkRenderer::GetStreamSinkById")); 71 | 72 | HRESULT hr; 73 | IF_FAILED_RETURN(hr = (ppStreamSink == NULL ? E_INVALIDARG : S_OK)); 74 | IF_FAILED_RETURN(hr = (dwStreamSinkIdentifier != 0 ? MF_E_INVALIDSTREAMNUMBER : S_OK)); 75 | 76 | AutoLock lock(m_CriticSection); 77 | 78 | IF_FAILED_RETURN(hr = CheckShutdown()); 79 | 80 | *ppStreamSink = m_pStreamSkinkRenderer; 81 | (*ppStreamSink)->AddRef(); 82 | 83 | return hr; 84 | } 85 | 86 | HRESULT CMinimalSkinkRenderer::SetPresentationClock(IMFPresentationClock* pPresentationClock){ 87 | 88 | TRACE_SINK((L"SinkRenderer::SetPresentationClock")); 89 | 90 | HRESULT hr; 91 | 92 | AutoLock lock(m_CriticSection); 93 | 94 | IF_FAILED_RETURN(hr = CheckShutdown()); 95 | 96 | if(m_pClock){ 97 | IF_FAILED_RETURN(hr = m_pClock->RemoveClockStateSink(this)); 98 | } 99 | 100 | if(pPresentationClock){ 101 | IF_FAILED_RETURN(hr = pPresentationClock->AddClockStateSink(this)); 102 | } 103 | 104 | SAFE_RELEASE(m_pClock); 105 | 106 | if(pPresentationClock){ 107 | 108 | m_pClock = pPresentationClock; 109 | m_pClock->AddRef(); 110 | } 111 | 112 | return hr; 113 | } 114 | 115 | HRESULT CMinimalSkinkRenderer::GetPresentationClock(IMFPresentationClock** ppPresentationClock){ 116 | 117 | TRACE_SINK((L"SinkRenderer::GetPresentationClock")); 118 | 119 | HRESULT hr; 120 | IF_FAILED_RETURN(hr = (ppPresentationClock == NULL ? E_INVALIDARG : S_OK)); 121 | 122 | AutoLock lock(m_CriticSection); 123 | 124 | IF_FAILED_RETURN(hr = CheckShutdown()); 125 | 126 | if(m_pClock == NULL){ 127 | 128 | hr = MF_E_NO_CLOCK; 129 | } 130 | else{ 131 | 132 | *ppPresentationClock = m_pClock; 133 | (*ppPresentationClock)->AddRef(); 134 | } 135 | 136 | return hr; 137 | } 138 | 139 | HRESULT CMinimalSkinkRenderer::Shutdown(){ 140 | 141 | TRACE_SINK((L"SinkRenderer::Shutdown")); 142 | 143 | AutoLock lock(m_CriticSection); 144 | 145 | HRESULT hr; 146 | IF_FAILED_RETURN(hr = CheckShutdown()); 147 | 148 | if(m_pStreamSkinkRenderer){ 149 | IF_FAILED_RETURN(hr = m_pStreamSkinkRenderer->Shutdown()); 150 | SAFE_RELEASE(m_pStreamSkinkRenderer); 151 | } 152 | 153 | SAFE_RELEASE(m_pClock); 154 | 155 | m_bShutdown = TRUE; 156 | m_dwCurrentFrame = 0; 157 | 158 | return hr; 159 | } -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "Stdafx.h" -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/StdAfx.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef STDAFX_H 5 | #define STDAFX_H 6 | 7 | #pragma once 8 | #define WIN32_LEAN_AND_MEAN 9 | #define STRICT 10 | 11 | #pragma comment(lib, "mfplat") 12 | #pragma comment(lib, "shlwapi") 13 | #pragma comment(lib, "mfuuid") 14 | #pragma comment(lib, "strmiids") 15 | 16 | //---------------------------------------------------------------------------------------------- 17 | // Microsoft Windows SDK for Windows 7 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #ifdef _DEBUG 25 | #include 26 | #endif 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | //---------------------------------------------------------------------------------------------- 43 | // Common Project Files 44 | #ifdef _DEBUG 45 | #define MF_USE_LOGGING 1 46 | //#define MF_USE_LOGREFCOUNT 47 | //#define MF_TRACE_SINK 48 | //#define MF_TRACE_STREAM 49 | #else 50 | #define MF_USE_LOGGING 0 51 | #endif 52 | 53 | #include "..\Common\MFMacro.h" 54 | #include "..\Common\MFTrace.h" 55 | #include "..\Common\MFLogging.h" 56 | #include "..\Common\MFTExternTrace.h" 57 | #include "..\Common\MFClassFactory.h" 58 | #include "..\Common\MFGuid.h" 59 | #include "..\Common\MFRegistry.h" 60 | #include "..\Common\MFLogCommon.h" 61 | #include "..\Common\MFLogMediaType.h" 62 | #include "..\Common\MFCriticSection.h" 63 | #include "..\Common\MFState.h" 64 | #include "..\Common\MFTime.h" 65 | 66 | //---------------------------------------------------------------------------------------------- 67 | // Project Files 68 | class CMinimalSkinkRenderer; 69 | 70 | #define TRACE_FRAME_NUMBER 1 71 | #define BMP_IMAGE_FILE L"Image.bmp" 72 | 73 | #include "StreamSkinkRenderer.h" 74 | #include "MinimalSkinkRenderer.h" 75 | 76 | #endif -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/StreamSkinkRenderer.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StreamSkinkRenderer.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | CStreamSkinkRenderer::CStreamSkinkRenderer(CMinimalSkinkRenderer* pMinimalSkinkRenderer, HRESULT& hr) 7 | : m_nRefCount(1), 8 | m_State(StreamTypeNotSet), 9 | m_pEventQueue(NULL), 10 | m_pMediaType(NULL), 11 | m_pMinimalSkinkRenderer(NULL) 12 | { 13 | TRACE_STREAM((L"StreamRenderer::CTOR")); 14 | 15 | LOG_HRESULT(hr = MFCreateEventQueue(&m_pEventQueue)); 16 | 17 | m_pMinimalSkinkRenderer = pMinimalSkinkRenderer; 18 | m_pMinimalSkinkRenderer->AddRef(); 19 | } 20 | 21 | CStreamSkinkRenderer::~CStreamSkinkRenderer(){ 22 | 23 | TRACE_STREAM((L"StreamRenderer::DTOR")); 24 | 25 | Shutdown(); 26 | } 27 | 28 | HRESULT CStreamSkinkRenderer::CreateInstance(CMinimalSkinkRenderer* pSink, CStreamSkinkRenderer** ppStream, HRESULT& hr){ 29 | 30 | TRACE_SINK((L"StreamRenderer::CreateInstance")); 31 | 32 | IF_FAILED_RETURN(hr = (ppStream == NULL ? E_INVALIDARG : S_OK)); 33 | 34 | CStreamSkinkRenderer* pStream = new (std::nothrow)CStreamSkinkRenderer(pSink, hr); 35 | 36 | IF_FAILED_RETURN(pStream == NULL ? E_OUTOFMEMORY : S_OK); 37 | 38 | *ppStream = pStream; 39 | (*ppStream)->AddRef(); 40 | 41 | SAFE_RELEASE(pStream); 42 | 43 | return hr; 44 | } 45 | 46 | HRESULT CStreamSkinkRenderer::QueryInterface(REFIID riid, void** ppv){ 47 | 48 | TRACE_STREAM((L"StreamRenderer::QI : riid = %s", GetIIDString(riid))); 49 | 50 | static const QITAB qit[] = { 51 | QITABENT(CStreamSkinkRenderer, IMFStreamSink), 52 | QITABENT(CStreamSkinkRenderer, IMFMediaEventGenerator), 53 | QITABENT(CStreamSkinkRenderer, IMFMediaTypeHandler), 54 | {0} 55 | }; 56 | 57 | return QISearch(this, qit, riid, ppv); 58 | } 59 | 60 | ULONG CStreamSkinkRenderer::AddRef(){ 61 | 62 | LONG lRef = InterlockedIncrement(&m_nRefCount); 63 | 64 | TRACE_REFCOUNT((L"StreamRenderer::AddRef m_nRefCount = %d", lRef)); 65 | 66 | return lRef; 67 | } 68 | 69 | ULONG CStreamSkinkRenderer::Release(){ 70 | 71 | ULONG uCount = InterlockedDecrement(&m_nRefCount); 72 | 73 | TRACE_REFCOUNT((L"StreamRenderer::Release m_nRefCount = %d", uCount)); 74 | 75 | if(uCount == 0){ 76 | delete this; 77 | } 78 | 79 | return uCount; 80 | } 81 | 82 | HRESULT CStreamSkinkRenderer::Shutdown(){ 83 | 84 | TRACE_STREAM((L"StreamRenderer::Shutdown")); 85 | 86 | AutoLock lock(m_CriticSection); 87 | 88 | HRESULT hr; 89 | IF_FAILED_RETURN(hr = CheckShutdown()); 90 | 91 | if(m_pEventQueue){ 92 | LOG_HRESULT(m_pEventQueue->Shutdown()); 93 | } 94 | 95 | SAFE_RELEASE(m_pMediaType); 96 | SAFE_RELEASE(m_pMinimalSkinkRenderer); 97 | SAFE_RELEASE(m_pEventQueue); 98 | 99 | m_State = StreamFinalized; 100 | 101 | return S_OK; 102 | } 103 | 104 | HRESULT CStreamSkinkRenderer::Start(MFTIME){ 105 | 106 | TRACE_STREAM((L"StreamRenderer::Start")); 107 | 108 | AutoLock lock(m_CriticSection); 109 | 110 | HRESULT hr; 111 | IF_FAILED_RETURN(hr = CheckShutdown()); 112 | 113 | IF_FAILED_RETURN(hr = (m_State == StreamTypeNotSet || m_State == StreamFinalized ? MF_E_INVALIDREQUEST : S_OK)); 114 | 115 | IF_FAILED_RETURN(hr = QueueEvent(MEStreamSinkStarted, GUID_NULL, hr, NULL)); 116 | 117 | if(m_State != StreamStarted){ 118 | 119 | IF_FAILED_RETURN(hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, hr, NULL)); 120 | m_State = StreamStarted; 121 | } 122 | 123 | return hr; 124 | } 125 | 126 | HRESULT CStreamSkinkRenderer::Stop(){ 127 | 128 | TRACE_STREAM((L"StreamRenderer::Stop")); 129 | 130 | AutoLock lock(m_CriticSection); 131 | 132 | HRESULT hr; 133 | IF_FAILED_RETURN(hr = CheckShutdown()); 134 | 135 | IF_FAILED_RETURN(hr = (m_State == StreamTypeNotSet || m_State == StreamFinalized ? MF_E_INVALIDREQUEST : S_OK)); 136 | 137 | IF_FAILED_RETURN(hr = QueueEvent(MEStreamSinkStopped, GUID_NULL, hr, NULL)); 138 | 139 | m_State = StreamStopped; 140 | 141 | return hr; 142 | } 143 | 144 | HRESULT CStreamSkinkRenderer::Pause(){ 145 | 146 | TRACE_STREAM((L"StreamRenderer::Pause")); 147 | 148 | AutoLock lock(m_CriticSection); 149 | 150 | HRESULT hr; 151 | IF_FAILED_RETURN(hr = CheckShutdown()); 152 | 153 | IF_FAILED_RETURN(hr = (m_State == StreamTypeNotSet || m_State == StreamFinalized || m_State == StreamStopped ? MF_E_INVALIDREQUEST : S_OK)); 154 | 155 | IF_FAILED_RETURN(hr = QueueEvent(MEStreamSinkPaused, GUID_NULL, hr, NULL)); 156 | 157 | m_State = StreamPaused; 158 | 159 | return hr; 160 | } 161 | 162 | HRESULT CStreamSkinkRenderer::Restart(){ 163 | 164 | TRACE_STREAM((L"StreamRenderer::Restart")); 165 | 166 | AutoLock lock(m_CriticSection); 167 | 168 | HRESULT hr; 169 | IF_FAILED_RETURN(hr = CheckShutdown()); 170 | 171 | IF_FAILED_RETURN(hr = (m_State != StreamPaused ? MF_E_INVALIDREQUEST : S_OK)); 172 | 173 | IF_FAILED_RETURN(hr = QueueEvent(MEStreamSinkStarted, GUID_NULL, hr, NULL)); 174 | IF_FAILED_RETURN(hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, hr, NULL)); 175 | 176 | m_State = StreamStarted; 177 | 178 | return hr; 179 | } -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/StreamSkinkRenderer.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StreamSkinkRenderer.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef STREAMSINKRENDERER_H 5 | #define STREAMSINKRENDERER_H 6 | 7 | class CStreamSkinkRenderer : BaseObject, public IMFStreamSink, public IMFMediaTypeHandler{ 8 | 9 | public: 10 | 11 | // StreamSkinkRenderer.cpp 12 | static HRESULT CreateInstance(CMinimalSkinkRenderer*, CStreamSkinkRenderer**, HRESULT&); 13 | 14 | // IUnknown - StreamSkinkRenderer.cpp 15 | STDMETHODIMP QueryInterface(REFIID, void**); 16 | STDMETHODIMP_(ULONG) AddRef(); 17 | STDMETHODIMP_(ULONG) Release(); 18 | 19 | // IMFStreamSink - StreamSkinkRenderer_Sink.cpp 20 | STDMETHODIMP GetMediaSink(IMFMediaSink**); 21 | STDMETHODIMP GetIdentifier(DWORD*); 22 | STDMETHODIMP GetMediaTypeHandler(IMFMediaTypeHandler**); 23 | STDMETHODIMP ProcessSample(IMFSample*); 24 | STDMETHODIMP PlaceMarker(MFSTREAMSINK_MARKER_TYPE, const PROPVARIANT*, const PROPVARIANT*); 25 | STDMETHODIMP Flush(); 26 | 27 | // IMFMediaEventGenerator - StreamSkinkRenderer_Event.cpp 28 | STDMETHODIMP GetEvent(DWORD, IMFMediaEvent**); 29 | STDMETHODIMP BeginGetEvent(IMFAsyncCallback*, IUnknown*); 30 | STDMETHODIMP EndGetEvent(IMFAsyncResult*, IMFMediaEvent**); 31 | STDMETHODIMP QueueEvent(MediaEventType, REFGUID, HRESULT, const PROPVARIANT*); 32 | 33 | // IMFMediaTypeHandler - StreamSkinkRenderer_Type.cpp 34 | STDMETHODIMP IsMediaTypeSupported(IMFMediaType*, IMFMediaType**); 35 | STDMETHODIMP GetMediaTypeCount(DWORD*); 36 | STDMETHODIMP GetMediaTypeByIndex(DWORD, IMFMediaType**); 37 | STDMETHODIMP SetCurrentMediaType(IMFMediaType*); 38 | STDMETHODIMP GetCurrentMediaType(IMFMediaType**); 39 | STDMETHODIMP GetMajorType(GUID*); 40 | 41 | // StreamSkinkRenderer.cpp 42 | HRESULT Start(MFTIME); 43 | HRESULT Stop(); 44 | HRESULT Pause(); 45 | HRESULT Restart(); 46 | HRESULT Shutdown(); 47 | 48 | private: 49 | 50 | // StreamSkinkRenderer.cpp 51 | CStreamSkinkRenderer(CMinimalSkinkRenderer*, HRESULT&); 52 | virtual ~CStreamSkinkRenderer(); 53 | 54 | CriticSection m_CriticSection; 55 | volatile long m_nRefCount; 56 | StreamState m_State; 57 | 58 | IMFMediaEventQueue* m_pEventQueue; 59 | IMFMediaType* m_pMediaType; 60 | CMinimalSkinkRenderer* m_pMinimalSkinkRenderer; 61 | 62 | // Inline 63 | HRESULT CheckShutdown() const{ return (m_State == StreamFinalized ? MF_E_SHUTDOWN : S_OK); } 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/StreamSkinkRenderer_Event.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StreamSkinkRenderer_Event.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | HRESULT CStreamSkinkRenderer::GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent){ 7 | 8 | TRACE_STREAM((L"StreamRenderer::GetEvent")); 9 | 10 | HRESULT hr; 11 | 12 | IMFMediaEventQueue* pQueue = NULL; 13 | 14 | { 15 | AutoLock lock(m_CriticSection); 16 | 17 | LOG_HRESULT(hr = CheckShutdown()); 18 | 19 | if(SUCCEEDED(hr)){ 20 | pQueue = m_pEventQueue; 21 | pQueue->AddRef(); 22 | } 23 | } 24 | 25 | if(SUCCEEDED(hr)){ 26 | LOG_HRESULT(hr = pQueue->GetEvent(dwFlags, ppEvent)); 27 | } 28 | 29 | SAFE_RELEASE(pQueue); 30 | 31 | return hr; 32 | } 33 | 34 | HRESULT CStreamSkinkRenderer::BeginGetEvent(IMFAsyncCallback* pCallback, IUnknown* punkState){ 35 | 36 | TRACE_STREAM((L"StreamRenderer::BeginGetEvent")); 37 | 38 | HRESULT hr; 39 | 40 | AutoLock lock(m_CriticSection); 41 | 42 | IF_FAILED_RETURN(hr = CheckShutdown()); 43 | 44 | LOG_HRESULT(hr = m_pEventQueue->BeginGetEvent(pCallback, punkState)); 45 | 46 | return hr; 47 | } 48 | 49 | HRESULT CStreamSkinkRenderer::EndGetEvent(IMFAsyncResult* pResult, IMFMediaEvent** ppEvent){ 50 | 51 | TRACE_STREAM((L"StreamRenderer::EndGetEvent")); 52 | 53 | HRESULT hr; 54 | 55 | AutoLock lock(m_CriticSection); 56 | 57 | IF_FAILED_RETURN(hr = CheckShutdown()); 58 | 59 | LOG_HRESULT(hr = m_pEventQueue->EndGetEvent(pResult, ppEvent)); 60 | 61 | return hr; 62 | } 63 | 64 | HRESULT CStreamSkinkRenderer::QueueEvent(MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, const PROPVARIANT* pvValue){ 65 | 66 | TRACE_STREAM((L"StreamRenderer::QueueEvent : %s", MFEventString(met))); 67 | 68 | HRESULT hr; 69 | 70 | AutoLock lock(m_CriticSection); 71 | 72 | IF_FAILED_RETURN(hr = CheckShutdown()); 73 | 74 | LOG_HRESULT(hr = m_pEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue)); 75 | 76 | return hr; 77 | } -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/StreamSkinkRenderer_Sink.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StreamSkinkRenderer_Sink.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | HRESULT CStreamSkinkRenderer::GetMediaSink(IMFMediaSink** ppMediaSink){ 7 | 8 | TRACE_STREAM((L"StreamRenderer::GetMediaSink")); 9 | 10 | HRESULT hr; 11 | IF_FAILED_RETURN(hr = (ppMediaSink == NULL ? E_INVALIDARG : S_OK)); 12 | 13 | AutoLock lock(m_CriticSection); 14 | 15 | IF_FAILED_RETURN(hr = CheckShutdown()); 16 | 17 | *ppMediaSink = m_pMinimalSkinkRenderer; 18 | (*ppMediaSink)->AddRef(); 19 | 20 | return hr; 21 | } 22 | 23 | HRESULT CStreamSkinkRenderer::GetIdentifier(DWORD* pdwIdentifier){ 24 | 25 | TRACE_STREAM((L"StreamRenderer::GetIdentifier")); 26 | 27 | HRESULT hr; 28 | IF_FAILED_RETURN(hr = (pdwIdentifier == NULL ? E_INVALIDARG : S_OK)); 29 | 30 | AutoLock lock(m_CriticSection); 31 | 32 | IF_FAILED_RETURN(hr = CheckShutdown()); 33 | 34 | *pdwIdentifier = 0; 35 | 36 | return hr; 37 | } 38 | 39 | HRESULT CStreamSkinkRenderer::GetMediaTypeHandler(IMFMediaTypeHandler** ppHandler){ 40 | 41 | TRACE_STREAM((L"StreamRenderer::GetMediaTypeHandler")); 42 | 43 | HRESULT hr; 44 | IF_FAILED_RETURN(hr = (ppHandler == NULL ? E_INVALIDARG : S_OK)); 45 | 46 | AutoLock lock(m_CriticSection); 47 | 48 | IF_FAILED_RETURN(hr = CheckShutdown()); 49 | 50 | IF_FAILED_RETURN(hr = this->QueryInterface(IID_IMFMediaTypeHandler, reinterpret_cast(ppHandler))); 51 | 52 | return hr; 53 | } 54 | 55 | HRESULT CStreamSkinkRenderer::ProcessSample(IMFSample* pSample){ 56 | 57 | TRACE_STREAM((L"StreamRenderer::ProcessSample")); 58 | 59 | HRESULT hr; 60 | IF_FAILED_RETURN(hr = (pSample == NULL ? E_INVALIDARG : S_OK)); 61 | 62 | AutoLock lock(m_CriticSection); 63 | 64 | IF_FAILED_RETURN(hr = CheckShutdown()); 65 | 66 | IF_FAILED_RETURN(hr = m_pMinimalSkinkRenderer->ProcessSample(pSample)); 67 | 68 | IF_FAILED_RETURN(hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, hr, NULL)); 69 | 70 | return hr; 71 | } 72 | 73 | HRESULT CStreamSkinkRenderer::PlaceMarker(MFSTREAMSINK_MARKER_TYPE /*eMarkerType*/, const PROPVARIANT* /*pvarMarkerValue*/, const PROPVARIANT* /*pvarContextValue*/){ 74 | 75 | TRACE_STREAM((L"StreamRenderer::PlaceMarker")); 76 | 77 | // Todo check marker. 78 | return E_NOTIMPL; 79 | } 80 | 81 | HRESULT CStreamSkinkRenderer::Flush(){ 82 | 83 | TRACE_STREAM((L"StreamRenderer::Flush")); 84 | 85 | // if CStreamSkinkRenderer::PlaceMarker is implemented, see : 86 | // http://msdn.microsoft.com/en-us/library/windows/desktop/ms701626(v=vs.85).aspx 87 | 88 | return S_OK; 89 | } -------------------------------------------------------------------------------- /MinimalSinkRenderer/MinimalSinkRenderer/StreamSkinkRenderer_Type.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StreamSkinkRenderer_Type.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" 5 | 6 | HRESULT CStreamSkinkRenderer::IsMediaTypeSupported(IMFMediaType* pMediaType, IMFMediaType** ppMediaType){ 7 | 8 | TRACE_STREAM((L"StreamRenderer::IsMediaTypeSupported")); 9 | 10 | HRESULT hr; 11 | IF_FAILED_RETURN(hr = (pMediaType == NULL ? E_INVALIDARG : S_OK)); 12 | 13 | AutoLock lock(m_CriticSection); 14 | 15 | IF_FAILED_RETURN(hr = CheckShutdown()); 16 | 17 | GUID MajorType = GUID_NULL; 18 | GUID SubType = GUID_NULL; 19 | 20 | //LogMediaType(pMediaType); 21 | 22 | IF_FAILED_RETURN(hr = pMediaType->GetGUID(MF_MT_MAJOR_TYPE, &MajorType)); 23 | IF_FAILED_RETURN(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &SubType)); 24 | 25 | IF_FAILED_RETURN(hr = (MajorType != MFMediaType_Video ? MF_E_INVALIDTYPE : S_OK)); 26 | IF_FAILED_RETURN(hr = (SubType != MFVideoFormat_RGB32 ? MF_E_INVALIDTYPE : S_OK)); 27 | 28 | if(ppMediaType){ 29 | *ppMediaType = NULL; 30 | } 31 | 32 | return hr; 33 | } 34 | 35 | HRESULT CStreamSkinkRenderer::GetMediaTypeCount(DWORD* pdwTypeCount){ 36 | 37 | TRACE_STREAM((L"StreamRenderer::GetMediaTypeCount")); 38 | 39 | HRESULT hr; 40 | IF_FAILED_RETURN(hr = (pdwTypeCount == NULL ? E_INVALIDARG : S_OK)); 41 | 42 | AutoLock lock(m_CriticSection); 43 | 44 | IF_FAILED_RETURN(hr = CheckShutdown()); 45 | 46 | *pdwTypeCount = 1; 47 | 48 | return hr; 49 | } 50 | 51 | HRESULT CStreamSkinkRenderer::GetMediaTypeByIndex(DWORD dwIndex, IMFMediaType** ppType){ 52 | 53 | TRACE_STREAM((L"StreamRenderer::GetMediaTypeByIndex")); 54 | 55 | HRESULT hr; 56 | IF_FAILED_RETURN(hr = (ppType == NULL ? E_INVALIDARG : S_OK)); 57 | IF_FAILED_RETURN(hr = (dwIndex != 0 ? MF_E_NO_MORE_TYPES : S_OK)); 58 | 59 | AutoLock lock(m_CriticSection); 60 | 61 | IF_FAILED_RETURN(hr = CheckShutdown()); 62 | 63 | IMFMediaType* pType = NULL; 64 | 65 | try{ 66 | 67 | IF_FAILED_THROW(hr = MFCreateMediaType(&pType)); 68 | IF_FAILED_THROW(hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); 69 | IF_FAILED_THROW(hr = pType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32)); 70 | 71 | *ppType = pType; 72 | (*ppType)->AddRef(); 73 | } 74 | catch(HRESULT){} 75 | 76 | SAFE_RELEASE(pType); 77 | 78 | return hr; 79 | } 80 | 81 | HRESULT CStreamSkinkRenderer::SetCurrentMediaType(IMFMediaType* pMediaType){ 82 | 83 | TRACE_STREAM((L"StreamRenderer::SetCurrentMediaType")); 84 | 85 | HRESULT hr; 86 | IF_FAILED_RETURN(hr = (pMediaType == NULL ? E_INVALIDARG : S_OK)); 87 | 88 | AutoLock lock(m_CriticSection); 89 | 90 | IF_FAILED_RETURN(hr = CheckShutdown()); 91 | 92 | IF_FAILED_RETURN(hr = IsMediaTypeSupported(pMediaType, NULL)); 93 | 94 | // Todo check valid size... 95 | 96 | SAFE_RELEASE(m_pMediaType); 97 | m_pMediaType = pMediaType; 98 | m_pMediaType->AddRef(); 99 | 100 | if(m_State != StreamPaused) 101 | m_State = StreamReady; 102 | 103 | return hr; 104 | } 105 | 106 | HRESULT CStreamSkinkRenderer::GetCurrentMediaType(IMFMediaType** ppMediaType){ 107 | 108 | TRACE_STREAM((L"StreamRenderer::GetCurrentMediaType")); 109 | 110 | HRESULT hr; 111 | IF_FAILED_RETURN(hr = (ppMediaType == NULL ? E_INVALIDARG : S_OK)); 112 | 113 | AutoLock lock(m_CriticSection); 114 | 115 | IF_FAILED_RETURN(hr = CheckShutdown()); 116 | 117 | IF_FAILED_RETURN(hr = (m_pMediaType == NULL ? MF_E_NOT_INITIALIZED : S_OK)); 118 | 119 | *ppMediaType = m_pMediaType; 120 | (*ppMediaType)->AddRef(); 121 | 122 | return hr; 123 | } 124 | 125 | HRESULT CStreamSkinkRenderer::GetMajorType(GUID* pguidMajorType){ 126 | 127 | TRACE_STREAM((L"StreamRenderer::GetMajorType")); 128 | 129 | HRESULT hr; 130 | IF_FAILED_RETURN(hr = (pguidMajorType == NULL ? E_INVALIDARG : S_OK)); 131 | 132 | *pguidMajorType = MFMediaType_Video; 133 | 134 | return hr; 135 | } -------------------------------------------------------------------------------- /MinimalSinkRenderer/TestMinimalSinkRenderer/TestMinimalSinkRenderer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {c62268e7-bd22-459b-8754-378766040134} 6 | 7 | 8 | {bd5646bc-a4af-491d-b809-ecf3c5d0610e} 9 | 10 | 11 | {54d2df31-6844-4485-9a7c-5f6e3385d4bf} 12 | 13 | 14 | 15 | 16 | Fichiers sources 17 | 18 | 19 | -------------------------------------------------------------------------------- /MinimalSinkRenderer/TestMinimalSinkRenderer/TestMinimalSinkRenderer.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stackoverflow 2 | All source codes I've provided on stackoverflow as an answer, usually under tags ms-media-foundation. Most of the source codes here are quick fixes to source code from people asking for help. So be careful, it's not necessarily the most appropriate way to do it. That just answers the question. It' s up to the user to improve the code. 3 | 4 | In the programs below, some values are harcoded, like video file path for example : 5 | 6 | #define VIDEO_FILE L"C:\\\\Users\\\\Public\\\\Videos\\\\Sample Videos\\\\Wildlife.wmv" 7 | 8 | Dont't forget to change them, if you use a different video file, in a different path. 9 | 10 | 11 | ## AudioSourceReaderSeek 12 | This program uses SourceReader to check seek position with audio file. 13 | 14 | stackoverflow question : https://stackoverflow.com/questions/49739170/imfsourcereader-m4a-audio-accurate-frame-seek 15 | 16 | ## CustomVideoMixer 17 | This program shows the basic essentials for implementing a custom video mixer, to be used by a media session. 18 | 19 | You must register the CustomVideoMixer.dll with this command, and with the administrator rights : regsrv32 CustomVideoMixer.dll. 20 | 21 | Be careful, the width and height of both videos are hardcoded (320x240). See VIDEO_WIDTH_1 and VIDEO_HEIGHT_1, change it if necessary. 22 | 23 | In this example, I use two identical mp4 files, big_buck_bunny_240p_5mb.mp4 and a copy of itself. the two videos use NV12 video format as input. therefore, there is no real alpha mix, but both videos can be displayed next to each other, as the picture below. 24 | 25 | stackoverflow question : https://stackoverflow.com/questions/42946608/media-foundation-custom-mixer-mft-getting-error-mf-e-cannot-create-sink 26 | 27 | ![Custom Video Mixer](./Media/CustomVideoMixer.jpg) 28 | 29 | ## EncodeWithSourceReaderSinkWriter 30 | 31 | Encode a video file using SourceReader and SinkWriter manually. 32 | 33 | stackoverflow question : https://stackoverflow.com/questions/55054531/media-foundation-video-re-encoding-producing-audio-stream-sync-offset 34 | 35 | ## FrameRateConverterDSP 36 | 37 | This program shows how to use the Frame Rate Converter DSP (CLSID_CFrameRateConvertDmo), using a Source Reader. You can change the frame rate of a video stream. For example, if the video has 30 fps, you can get 60 fps. 38 | 39 | stackoverflow question : https://stackoverflow.com/questions/8412343/how-to-use-frame-rate-convertor-dmo-in-mf-app 40 | 41 | ## IMFSinkWriterCallback 42 | 43 | This program shows how to use an IMFSinkWriterCallback and event to wait for the Finalize method on the Sink Writer. The program simply create a wmv video file with blue frames, using the Sink Writer. 44 | 45 | stackoverflow question : https://stackoverflow.com/questions/34189440/imfsinkwritercallback-never-happens 46 | 47 | ![IMFSinkWriterCallback](./Media/IMFSinkWriterCallback.jpg) 48 | 49 | ## MFVideoCaptureEVR 50 | 51 | This program shows how to setup EVR (enhanced video renderer), and how to provide video capture samples to it, using a Source Reader. 52 | Same as MFVideoEVR, but with video capture card source. 53 | 54 | stackoverflow question : https://stackoverflow.com/questions/59616228/webcam-source-to-evr-sink 55 | 56 | ## MFVideoEVR 57 | 58 | This program shows how to setup EVR (enhanced video renderer), and how to provide video samples to it, using a Source Reader. 59 | Same as MFVideoCaptureEVR, but with video file source. 60 | 61 | stackoverflow question : https://stackoverflow.com/questions/32739558/media-foundation-evr-no-video-displaying 62 | 63 | ## MFMultiVideo 64 | 65 | A program to see if there are memory leaks using 1 to 16 MediaSession. 66 | 67 | stackoverflow question : https://stackoverflow.com/questions/58912803/media-foundation-multiple-videos-playback-results-in-memory-leak-crash-after-u 68 | 69 | ![MFMultiVideo](./Media/MFMultiVideo.jpg) 70 | 71 | ## MinimalSinkRenderer 72 | 73 | This program shows the basic essentials for implementing a custom sink renderer, to be used by a Media Session. The stream sink format is MFVideoFormat_RGB32. 74 | 75 | You must register the MinimalSinkRenderer.dll with this command, and with the administrator rights : regsrv32 MinimalSinkRenderer.dll. 76 | 77 | stackoverflow question : https://stackoverflow.com/questions/52198300/how-to-have-custom-video-media-stream-sink-request-rgb32-frames-in-media-foundat 78 | 79 | ## ScreenCaptureEncode 80 | 81 | This program takes screenshots using Directx9, and create a mp4 video file with Mediafoundation API. In this example, the video duration is 5 seconds, see VIDEO_FRAME_COUNT to change it. 82 | 83 | stackoverflow question : https://stackoverflow.com/questions/33753912/directx-screen-capture-and-output-as-video 84 | 85 | ![Screen Capture Encode](./Media/ScreenCaptureEncode.jpg) 86 | 87 | ## TranscodeMp4ToMp4 88 | This program transcode a mp4 video file into a new mp4 file, using mp4 Sink Writer and a Media Session with topology. There is no real encoding process, because output file has the same format as input file. 89 | The concept was to show how to setup IMFTopologyNode for both audio and video. 90 | 91 | stackoverflow question : https://stackoverflow.com/questions/52025546/configuring-the-mpeg4mediasink 92 | 93 | ## VideoStabilizationMFT 94 | 95 | Using the Video Stabilization MFT with Source Reader and Sink Writer. 96 | 97 | stackoverflow question : https://stackoverflow.com/questions/59471641/trying-to-use-a-mft-in-media-foundation-encoding 98 | 99 | ## WasapiCapture 100 | 101 | A program to capture sound with Wasapi, and record the captured audio in a wav file. Handle PCM format and Extensible Format. 102 | 103 | stackoverflow question : https://stackoverflow.com/questions/59483071/trying-to-create-a-wav-file-with-capturing-a-stream-from-win32-wasapi-c 104 | -------------------------------------------------------------------------------- /ScreenCaptureEncode/ScreenCaptureEncode.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScreenCaptureEncode", "ScreenCaptureEncode.vcxproj", "{005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}.Debug|Win32.Build.0 = Debug|Win32 16 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}.Release|Win32.ActiveCfg = Release|Win32 17 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /ScreenCaptureEncode/ScreenCaptureEncode.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {005DA1A0-9F56-4F1D-980F-4EAB2AECFC08} 15 | Win32Proj 16 | ScreenCaptureEncode 17 | 10.0.15063.0 18 | 19 | 20 | 21 | Application 22 | true 23 | v141 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v141 30 | true 31 | Unicode 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 71 | 72 | 73 | Console 74 | false 75 | true 76 | true 77 | UseLinkTimeCodeGeneration 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /TranscodeMp4ToMp4/TranscodeMp4ToMp4.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TranscodeMp4ToMp4", "TranscodeMp4ToMp4.vcxproj", "{77A8C6AD-2FE2-4ADE-AEA9-EF76F8BBFF08}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {77A8C6AD-2FE2-4ADE-AEA9-EF76F8BBFF08}.Debug|x64.ActiveCfg = Debug|x64 17 | {77A8C6AD-2FE2-4ADE-AEA9-EF76F8BBFF08}.Debug|x64.Build.0 = Debug|x64 18 | {77A8C6AD-2FE2-4ADE-AEA9-EF76F8BBFF08}.Debug|x86.ActiveCfg = Debug|Win32 19 | {77A8C6AD-2FE2-4ADE-AEA9-EF76F8BBFF08}.Debug|x86.Build.0 = Debug|Win32 20 | {77A8C6AD-2FE2-4ADE-AEA9-EF76F8BBFF08}.Release|x64.ActiveCfg = Release|x64 21 | {77A8C6AD-2FE2-4ADE-AEA9-EF76F8BBFF08}.Release|x64.Build.0 = Release|x64 22 | {77A8C6AD-2FE2-4ADE-AEA9-EF76F8BBFF08}.Release|x86.ActiveCfg = Release|Win32 23 | {77A8C6AD-2FE2-4ADE-AEA9-EF76F8BBFF08}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {BB5E2610-EE74-40AD-852E-E315115C6537} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /VideoStabilizationMFT/MFGuid.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFGuid.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFGUID_H 5 | #define MFGUID_H 6 | 7 | // {B2F74C92-79DF-45DE-9C55-A99DE8276679} 8 | DEFINE_GUID(CLSID_CustomVideoMixer, 0xb2f74c92, 0x79df, 0x45de, 0x9c, 0x55, 0xa9, 0x9d, 0xe8, 0x27, 0x66, 0x79); 9 | 10 | //---------------------------------------------------------------------------------------------- 11 | // Media subType guid 12 | 13 | // {7634706D-0000-0010-8000-00AA00389B71} 14 | DEFINE_GUID(MEDIASUBTYPE_mp4v, 0x7634706d, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 15 | 16 | // 56564D41-0000-0010-8000-00AA00389B71 17 | DEFINE_GUID(MEDIASUBTYPE_XVID, 0x44495658, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 18 | 19 | // {64697678-0000-0010-8000-00AA00389B71} 20 | DEFINE_GUID(MEDIASUBTYPE_xvid, 0x64697678, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 21 | 22 | // {58564944-0000-0010-8000-00AA00389B71} 23 | DEFINE_GUID(MEDIASUBTYPE_DIVX, 0x58564944, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 24 | 25 | // {78766964-0000-0010-8000-00AA00389B71} 26 | DEFINE_GUID(MEDIASUBTYPE_divx, 0x78766964, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 27 | 28 | // {30355844-0000-0010-8000-00aa00389b71} 29 | DEFINE_GUID(MEDIASUBTYPE_DX50, 0x30355844, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 30 | 31 | // {30357864-0000-0010-8000-00AA00389B71} 32 | DEFINE_GUID(MEDIASUBTYPE_dx50, 0x30357864, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 33 | 34 | // {1D4A45F2-E5F6-4B44-8388-F0AE5C0E0C37} 35 | DEFINE_GUID(MEDIASUBTYPE_VIDEOIMAGE, 0x1D4A45F2, 0xE5F6, 0x4B44, 0x83, 0x88, 0xF0, 0xAE, 0x5C, 0x0E, 0x0C, 0x37); 36 | 37 | // {00000031-0000-0010-8000-00AA00389B71} 38 | DEFINE_GUID(MEDIASUBTYPE_GSM, 0x00000031, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 39 | 40 | // {00000011-0000-0010-8000-00AA00389B71} 41 | DEFINE_GUID(MEDIASUBTYPE_IMAADPCMACM, 0x00000011, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); 42 | 43 | #endif -------------------------------------------------------------------------------- /VideoStabilizationMFT/MFLogCommon.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogCommon.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGCOMMON_H 5 | #define MFLOGCOMMON_H 6 | 7 | #if (_DEBUG && MF_USE_LOGGING) 8 | 9 | typedef LPCWSTR(*GetGUIDStringName)(const GUID&); 10 | 11 | inline void LogGuidHexa(const GUID& guid, const BOOL bFirst){ 12 | 13 | HRESULT hr; 14 | WCHAR pBuffer[39] = {0}; 15 | 16 | hr = StringCchPrintf(pBuffer, 39, L"{%.8lX-%.4hX-%.4hX-%.2hhX%.2hhX-%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX}", 17 | guid.Data1, 18 | guid.Data2, 19 | guid.Data3, 20 | guid.Data4[0], 21 | guid.Data4[1], 22 | guid.Data4[2], 23 | guid.Data4[3], 24 | guid.Data4[4], 25 | guid.Data4[5], 26 | guid.Data4[6], 27 | guid.Data4[7] 28 | ); 29 | 30 | if(SUCCEEDED(hr)){ 31 | 32 | if(bFirst) 33 | TRACE_NO_END_LINE((L"\t%s\t", pBuffer)); 34 | else 35 | TRACE((L"%s", pBuffer)); 36 | } 37 | else{ 38 | 39 | TRACE((L"Guid problem")); 40 | } 41 | } 42 | 43 | inline void LogUINT32AsUINT64(const PROPVARIANT& var){ 44 | 45 | UINT32 uHigh = 0, uLow = 0; 46 | 47 | Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &uHigh, &uLow); 48 | 49 | TRACE((L"%u x %u", uHigh, uLow)); 50 | } 51 | 52 | inline HRESULT SpecialCaseAttributeValue(GUID guid, const PROPVARIANT& var){ 53 | 54 | if(guid == MF_MT_FRAME_RATE){ 55 | LogUINT32AsUINT64(var); 56 | } 57 | else if(guid == MF_MT_FRAME_SIZE){ 58 | LogUINT32AsUINT64(var); 59 | } 60 | else if(guid == MF_MT_PIXEL_ASPECT_RATIO){ 61 | LogUINT32AsUINT64(var); 62 | } 63 | else{ 64 | return S_FALSE; 65 | } 66 | 67 | return S_OK; 68 | } 69 | 70 | inline void LogPropertyVariant(const GUID* pGuid, const PROPVARIANT& var, GetGUIDStringName pGetGUIDString){ 71 | 72 | HRESULT hr = S_FALSE; 73 | 74 | if(pGuid != NULL) 75 | hr = SpecialCaseAttributeValue(*pGuid, var); 76 | 77 | if(hr == S_FALSE){ 78 | 79 | switch(var.vt){ 80 | 81 | case VT_UI4: 82 | TRACE((L"%lu", var.ulVal)); 83 | break; 84 | 85 | case VT_I4: 86 | TRACE((L"%ld", var.lVal)); 87 | break; 88 | 89 | case VT_UI8: 90 | TRACE((L"%I64u", var.uhVal)); 91 | break; 92 | 93 | case VT_BOOL: 94 | TRACE((L"%s", var.boolVal == -1 ? "true" : "false")); 95 | break; 96 | 97 | case VT_R8: 98 | TRACE((L"%f", var.dblVal)); 99 | break; 100 | 101 | case VT_CLSID: 102 | { 103 | LPCWSTR pwszGuidName = pGetGUIDString(*var.puuid); 104 | 105 | if(pwszGuidName != NULL){ 106 | TRACE((L"%s", pwszGuidName)); 107 | } 108 | else{ 109 | LogGuidHexa(*var.puuid, FALSE); 110 | } 111 | } 112 | break; 113 | 114 | case VT_LPWSTR: 115 | // Log : var.pwszVal 116 | TRACE((L"VT_LPWSTR = todo")); 117 | break; 118 | 119 | case VT_VECTOR | VT_UI1: 120 | TRACE((L"(VT_VECTOR|VT_UI1) = <>")); 121 | break; 122 | 123 | case VT_UNKNOWN: 124 | TRACE((L"VT_UNKNOWN = IUnknown")); 125 | break; 126 | 127 | case VT_EMPTY: 128 | TRACE((L"VT_EMPTY")); 129 | break; 130 | 131 | case VT_R4: 132 | TRACE((L"VT_R4 = %f", var.fltVal)); 133 | break; 134 | 135 | // 8195 = VT_ARRAY | VT_I4 136 | 137 | default: 138 | TRACE((L"Unexpected attribute type (vt = %hu)", var.vt)); 139 | break; 140 | } 141 | } 142 | } 143 | 144 | inline void LogAttributeValueByIndex(IMFAttributes* pAttributes, UINT32 uiIndex, GetGUIDStringName pGetGUIDString){ 145 | 146 | HRESULT hr; 147 | PROPVARIANT var; 148 | GUID guid = GUID_NULL; 149 | 150 | PropVariantInit(&var); 151 | 152 | hr = pAttributes->GetItemByIndex(uiIndex, &guid, &var); 153 | 154 | if(SUCCEEDED(hr)){ 155 | 156 | LPCWSTR pwszGUIDNameAttributes = pGetGUIDString(guid); 157 | 158 | if(pwszGUIDNameAttributes != NULL){ 159 | TRACE_NO_END_LINE((L"\t%s\t", pwszGUIDNameAttributes)); 160 | } 161 | else{ 162 | 163 | LogGuidHexa(guid, TRUE); 164 | } 165 | 166 | LogPropertyVariant(&guid, var, pGetGUIDString); 167 | } 168 | else{ 169 | TRACE((L"\tGetItemByIndex (Index = %u) hr = %s", uiIndex, MFErrorString(hr))); 170 | } 171 | 172 | PropVariantClear(&var); 173 | } 174 | 175 | #endif 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /VideoStabilizationMFT/MFLogging.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogging.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGGING_H 5 | #define MFLOGGING_H 6 | 7 | #ifdef _DEBUG 8 | 9 | class DebugLog{ 10 | 11 | public: 12 | 13 | static void Initialize(){ 14 | _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); 15 | //_CrtSetBreakAlloc(171); 16 | } 17 | 18 | static void Trace(const WCHAR* sFormatString, ...){ 19 | 20 | HRESULT hr = S_OK; 21 | va_list va; 22 | 23 | const DWORD TRACE_STRING_LEN = 512; 24 | 25 | WCHAR message[TRACE_STRING_LEN]; 26 | 27 | va_start(va, sFormatString); 28 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 29 | va_end(va); 30 | 31 | if(SUCCEEDED(hr)){ 32 | 33 | size_t size = _tcslen(message); 34 | 35 | if(size != 0 && size < TRACE_STRING_LEN){ 36 | message[size] = '\n'; 37 | message[size + 1] = '\0'; 38 | } 39 | 40 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 41 | } 42 | } 43 | 44 | static void TraceNoEndLine(const WCHAR* sFormatString, ...){ 45 | 46 | HRESULT hr = S_OK; 47 | va_list va; 48 | 49 | const DWORD TRACE_STRING_LEN = 512; 50 | 51 | WCHAR message[TRACE_STRING_LEN]; 52 | 53 | va_start(va, sFormatString); 54 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 55 | va_end(va); 56 | 57 | if(SUCCEEDED(hr)){ 58 | 59 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 60 | } 61 | } 62 | 63 | static void Close(){ 64 | int bLeak = _CrtDumpMemoryLeaks(); 65 | assert(bLeak == FALSE); 66 | } 67 | }; 68 | 69 | #define TRACE_INIT() DebugLog::Initialize() 70 | #define TRACE(x) DebugLog::Trace x 71 | #define TRACE_NO_END_LINE(x) DebugLog::TraceNoEndLine x 72 | #define TRACE_CLOSE() DebugLog::Close() 73 | 74 | inline HRESULT _LOG_HRESULT(HRESULT hr, const char* sFileName, long lLineNo){ 75 | 76 | if(FAILED(hr)){ 77 | TRACE((L"\n%S - Line: %d hr = %s\n", sFileName, lLineNo, MFErrorString(hr))); 78 | } 79 | 80 | return hr; 81 | } 82 | 83 | #define LOG_HRESULT(hr) _LOG_HRESULT(hr, __FILE__, __LINE__) 84 | #define LOG_LAST_ERROR() _LOG_HRESULT(HRESULT_FROM_WIN32(GetLastError()), __FILE__, __LINE__) 85 | 86 | #else 87 | #define TRACE_INIT() 88 | #define TRACE(x) 89 | #define TRACE_NO_END_LINE(x) 90 | #define TRACE_CLOSE() 91 | #define LOG_HRESULT(hr) hr 92 | #define LOG_LAST_ERROR() 93 | #endif 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /VideoStabilizationMFT/MFMacro.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFMacro.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFMACRO_H 5 | #define MFMACRO_H 6 | 7 | #ifndef MF_SAFE_RELEASE 8 | #define MF_SAFE_RELEASE 9 | template inline void SAFE_RELEASE(T*& p){ 10 | 11 | if(p){ 12 | p->Release(); 13 | p = NULL; 14 | } 15 | } 16 | #endif 17 | 18 | #ifndef MF_SAFE_DELETE 19 | #define MF_SAFE_DELETE 20 | template inline void SAFE_DELETE(T*& p){ 21 | 22 | if(p){ 23 | delete p; 24 | p = NULL; 25 | } 26 | } 27 | #endif 28 | 29 | #ifndef MF_SAFE_DELETE_ARRAY 30 | #define MF_SAFE_DELETE_ARRAY 31 | template inline void SAFE_DELETE_ARRAY(T*& p){ 32 | 33 | if(p){ 34 | delete[] p; 35 | p = NULL; 36 | } 37 | } 38 | #endif 39 | 40 | #ifndef IF_FAILED_RETURN 41 | #if(_DEBUG && MF_USE_LOGGING) 42 | #define IF_FAILED_RETURN(X) if(FAILED(hr = (X))){ LOG_HRESULT(hr); return hr; } 43 | #else 44 | #define IF_FAILED_RETURN(X) if(FAILED(hr = (X))){ return hr; } 45 | #endif 46 | #endif 47 | 48 | #ifndef IF_FAILED_THROW 49 | #if(_DEBUG && MF_USE_LOGGING) 50 | #define IF_FAILED_THROW(X) if(FAILED(hr = (X))){ LOG_HRESULT(hr); throw hr; } 51 | #else 52 | #define IF_FAILED_THROW(X) if(FAILED(hr = (X))){ throw hr; } 53 | #endif 54 | #endif 55 | 56 | #ifndef IF_ERROR_RETURN 57 | #if (_DEBUG && MF_USE_LOGGING) 58 | #define IF_ERROR_RETURN(b) if(b == FALSE){ LOG_LAST_ERROR(); return b; } 59 | #else 60 | #define IF_ERROR_RETURN(b) if(b == FALSE){ return b; } 61 | #endif 62 | #endif 63 | 64 | #ifndef CLOSE_HANDLE_IF 65 | #if (_DEBUG && MF_USE_LOGGING) 66 | #define CLOSE_HANDLE_IF(h) if(h != INVALID_HANDLE_VALUE){ if(CloseHandle(h) == FALSE){ LOG_LAST_ERROR(); } h = INVALID_HANDLE_VALUE; } 67 | #else 68 | #define CLOSE_HANDLE_IF(h) if(h != INVALID_HANDLE_VALUE){ CloseHandle(h); h = INVALID_HANDLE_VALUE; } 69 | #endif 70 | #endif 71 | 72 | #ifndef RETURN_STRING 73 | #define RETURN_STRING(x) case x: return L#x 74 | #endif 75 | 76 | #ifndef IF_EQUAL_RETURN 77 | #define IF_EQUAL_RETURN(param, val) if(val == param) return L#val 78 | #endif 79 | 80 | #ifndef VALUE_NOT_FOUND 81 | #define VALUE_NOT_FOUND(val) return L#val 82 | #endif 83 | 84 | #ifndef MIN 85 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 86 | #endif 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /VideoStabilizationMFT/MFTExternTrace.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFTExternTrace.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFTEXTERNTRACE_H 5 | #define MFTEXTERNTRACE_H 6 | 7 | // CExternTrace initializes the memory leaks detection (see "crtdbg.h"). 8 | // CExternTrace ensures that no object is allocated before TRACE_INIT is called. 9 | // Because DllMain.cpp contains external objects, you will see "FAKE" memory leaks. 10 | #ifdef _DEBUG 11 | 12 | class CExternTrace{ 13 | 14 | public: 15 | 16 | CExternTrace(){ TRACE_INIT(); }; 17 | ~CExternTrace(){ TRACE_CLOSE(); }; 18 | }; 19 | 20 | CExternTrace cExternTrace; 21 | 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /VideoStabilizationMFT/MFTime.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFTime.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFTIME_H 5 | #define MFTIME_H 6 | 7 | // One second in hns 8 | const MFTIME ONE_SECOND = 10000000; 9 | 10 | // One msec in hns 11 | const LONG ONE_MSEC = 1000; 12 | 13 | inline LONG MFTimeToMilliSec(const LONGLONG& time){ 14 | 15 | return (LONG)(time / (ONE_SECOND / ONE_MSEC)); 16 | } 17 | 18 | inline LONG MFTimeToSec(const LONGLONG& time){ 19 | 20 | return (LONG)(time / ONE_SECOND); 21 | } 22 | 23 | #if (_DEBUG && MF_USE_LOGGING) 24 | 25 | inline void MFTimeString(const MFTIME& Duration){ 26 | 27 | MFTIME DurationInMilliSec = 0; 28 | MFTIME DurationInSec = 0; 29 | MFTIME Hours = 0; 30 | MFTIME Minutes = 0; 31 | MFTIME Seconds = 0; 32 | 33 | DurationInSec = MFTimeToSec(Duration); 34 | DurationInMilliSec = MFTimeToMilliSec(Duration); 35 | 36 | if(DurationInSec > 60){ 37 | 38 | Minutes = DurationInSec / 60; 39 | 40 | if(Minutes > 60){ 41 | 42 | Hours = Minutes / 60; 43 | Minutes = Minutes % 60; 44 | } 45 | 46 | Seconds = (DurationInSec % 60); 47 | } 48 | else{ 49 | 50 | Seconds = DurationInSec; 51 | } 52 | 53 | if(Seconds){ 54 | DurationInMilliSec = DurationInMilliSec % (Seconds * ONE_MSEC); 55 | } 56 | 57 | TRACE((L"%02dh:%02dmn:%02ds:%03dms", (int)Hours, (int)Minutes, (int)Seconds, DurationInMilliSec)); 58 | } 59 | 60 | #else 61 | #define MFTimeString(x) 62 | #endif 63 | 64 | #endif -------------------------------------------------------------------------------- /VideoStabilizationMFT/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" -------------------------------------------------------------------------------- /VideoStabilizationMFT/StdAfx.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef STDAFX_H 5 | #define STDAFX_H 6 | 7 | #pragma once 8 | #define WIN32_LEAN_AND_MEAN 9 | #define STRICT 10 | 11 | #pragma comment(lib, "mf") 12 | #pragma comment(lib, "mfplat") 13 | #pragma comment(lib, "mfuuid") 14 | #pragma comment(lib, "mfreadwrite") 15 | #pragma comment(lib, "strmiids") 16 | #pragma comment(lib, "wmcodecdspuuid") 17 | 18 | //---------------------------------------------------------------------------------------------- 19 | // Microsoft Windows SDK for Windows 7 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #ifdef _DEBUG 27 | #include 28 | #endif 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #pragma warning(push) 40 | #pragma warning(disable:4201) 41 | #include 42 | #pragma warning(pop) 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | //---------------------------------------------------------------------------------------------- 49 | // Common Project Files 50 | #ifdef _DEBUG 51 | #define MF_USE_LOGGING 1 52 | #else 53 | #define MF_USE_LOGGING 0 54 | #endif 55 | 56 | #include "MFMacro.h" 57 | #include "MFTrace.h" 58 | #include "MFLogging.h" 59 | #include "MFTExternTrace.h" 60 | #include "MFGuid.h" 61 | #include "MFLogCommon.h" 62 | #include "MFLogMediaType.h" 63 | #include "MFTime.h" 64 | 65 | #endif -------------------------------------------------------------------------------- /VideoStabilizationMFT/VideoStabilizationMFT.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoStabilizationMFT", "VideoStabilizationMFT.vcxproj", "{60D1E64A-55AB-482F-A523-FD02C5D00ACC}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {60D1E64A-55AB-482F-A523-FD02C5D00ACC}.Debug|x64.ActiveCfg = Debug|x64 17 | {60D1E64A-55AB-482F-A523-FD02C5D00ACC}.Debug|x64.Build.0 = Debug|x64 18 | {60D1E64A-55AB-482F-A523-FD02C5D00ACC}.Debug|x86.ActiveCfg = Debug|Win32 19 | {60D1E64A-55AB-482F-A523-FD02C5D00ACC}.Debug|x86.Build.0 = Debug|Win32 20 | {60D1E64A-55AB-482F-A523-FD02C5D00ACC}.Release|x64.ActiveCfg = Release|x64 21 | {60D1E64A-55AB-482F-A523-FD02C5D00ACC}.Release|x64.Build.0 = Release|x64 22 | {60D1E64A-55AB-482F-A523-FD02C5D00ACC}.Release|x86.ActiveCfg = Release|Win32 23 | {60D1E64A-55AB-482F-A523-FD02C5D00ACC}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {602CAF08-27F6-4E46-A576-1C00B673BB0A} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /VideoStabilizationMFT/VideoStabilizationMFT.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Fichiers d%27en-tête 20 | 21 | 22 | Fichiers d%27en-tête 23 | 24 | 25 | Fichiers d%27en-tête 26 | 27 | 28 | Fichiers d%27en-tête 29 | 30 | 31 | Fichiers d%27en-tête 32 | 33 | 34 | Fichiers d%27en-tête 35 | 36 | 37 | Fichiers d%27en-tête 38 | 39 | 40 | Fichiers d%27en-tête 41 | 42 | 43 | Fichiers d%27en-tête 44 | 45 | 46 | 47 | 48 | Fichiers sources 49 | 50 | 51 | Fichiers sources 52 | 53 | 54 | -------------------------------------------------------------------------------- /VideoStabilizationMFT/VideoStabilizationMFT.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WasapiCapture/MFLogging.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFLogging.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFLOGGING_H 5 | #define MFLOGGING_H 6 | 7 | #ifdef _DEBUG 8 | 9 | class DebugLog{ 10 | 11 | public: 12 | 13 | static void Initialize(){ 14 | _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); 15 | //_CrtSetBreakAlloc(171); 16 | } 17 | 18 | static void Trace(const WCHAR* sFormatString, ...){ 19 | 20 | HRESULT hr = S_OK; 21 | va_list va; 22 | 23 | const DWORD TRACE_STRING_LEN = 512; 24 | 25 | WCHAR message[TRACE_STRING_LEN]; 26 | 27 | va_start(va, sFormatString); 28 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 29 | va_end(va); 30 | 31 | if(SUCCEEDED(hr)){ 32 | 33 | size_t size = _tcslen(message); 34 | 35 | if(size != 0 && size < TRACE_STRING_LEN){ 36 | message[size] = '\n'; 37 | message[size + 1] = '\0'; 38 | } 39 | 40 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 41 | } 42 | } 43 | 44 | static void TraceNoEndLine(const WCHAR* sFormatString, ...){ 45 | 46 | HRESULT hr = S_OK; 47 | va_list va; 48 | 49 | const DWORD TRACE_STRING_LEN = 512; 50 | 51 | WCHAR message[TRACE_STRING_LEN]; 52 | 53 | va_start(va, sFormatString); 54 | hr = StringCchVPrintf(message, TRACE_STRING_LEN, sFormatString, va); 55 | va_end(va); 56 | 57 | if(SUCCEEDED(hr)){ 58 | 59 | _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%S", message); 60 | } 61 | } 62 | 63 | static void Close(){ 64 | int bLeak = _CrtDumpMemoryLeaks(); 65 | assert(bLeak == FALSE); 66 | } 67 | }; 68 | 69 | #define TRACE_INIT() DebugLog::Initialize() 70 | #define TRACE(x) DebugLog::Trace x 71 | #define TRACE_NO_END_LINE(x) DebugLog::TraceNoEndLine x 72 | #define TRACE_CLOSE() DebugLog::Close() 73 | 74 | inline HRESULT _LOG_HRESULT(HRESULT hr, const char* sFileName, long lLineNo){ 75 | 76 | if(FAILED(hr)){ 77 | TRACE((L"\n%S - Line: %d hr = %s\n", sFileName, lLineNo, MFErrorString(hr))); 78 | } 79 | 80 | return hr; 81 | } 82 | 83 | #define LOG_HRESULT(hr) _LOG_HRESULT(hr, __FILE__, __LINE__) 84 | #define LOG_LAST_ERROR() _LOG_HRESULT(HRESULT_FROM_WIN32(GetLastError()), __FILE__, __LINE__) 85 | 86 | #else 87 | #define TRACE_INIT() 88 | #define TRACE(x) 89 | #define TRACE_NO_END_LINE(x) 90 | #define TRACE_CLOSE() 91 | #define LOG_HRESULT(hr) hr 92 | #define LOG_LAST_ERROR() 93 | #endif 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /WasapiCapture/MFMacro.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFMacro.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFMACRO_H 5 | #define MFMACRO_H 6 | 7 | #ifndef MF_SAFE_RELEASE 8 | #define MF_SAFE_RELEASE 9 | template inline void SAFE_RELEASE(T*& p){ 10 | 11 | if(p){ 12 | p->Release(); 13 | p = NULL; 14 | } 15 | } 16 | #endif 17 | 18 | #ifndef MF_SAFE_DELETE 19 | #define MF_SAFE_DELETE 20 | template inline void SAFE_DELETE(T*& p){ 21 | 22 | if(p){ 23 | delete p; 24 | p = NULL; 25 | } 26 | } 27 | #endif 28 | 29 | #ifndef MF_SAFE_DELETE_ARRAY 30 | #define MF_SAFE_DELETE_ARRAY 31 | template inline void SAFE_DELETE_ARRAY(T*& p){ 32 | 33 | if(p){ 34 | delete[] p; 35 | p = NULL; 36 | } 37 | } 38 | #endif 39 | 40 | #ifndef IF_FAILED_RETURN 41 | #if(_DEBUG && MF_USE_LOGGING) 42 | #define IF_FAILED_RETURN(X) if(FAILED(hr = (X))){ LOG_HRESULT(hr); return hr; } 43 | #else 44 | #define IF_FAILED_RETURN(X) if(FAILED(hr = (X))){ return hr; } 45 | #endif 46 | #endif 47 | 48 | #ifndef IF_FAILED_THROW 49 | #if(_DEBUG && MF_USE_LOGGING) 50 | #define IF_FAILED_THROW(X) if(FAILED(hr = (X))){ LOG_HRESULT(hr); throw hr; } 51 | #else 52 | #define IF_FAILED_THROW(X) if(FAILED(hr = (X))){ throw hr; } 53 | #endif 54 | #endif 55 | 56 | #ifndef IF_ERROR_RETURN 57 | #if (_DEBUG && MF_USE_LOGGING) 58 | #define IF_ERROR_RETURN(b) if(b == FALSE){ LOG_LAST_ERROR(); return b; } 59 | #else 60 | #define IF_ERROR_RETURN(b) if(b == FALSE){ return b; } 61 | #endif 62 | #endif 63 | 64 | #ifndef CLOSE_HANDLE_IF 65 | #if (_DEBUG && MF_USE_LOGGING) 66 | #define CLOSE_HANDLE_IF(h) if(h != INVALID_HANDLE_VALUE){ if(CloseHandle(h) == FALSE){ LOG_LAST_ERROR(); } h = INVALID_HANDLE_VALUE; } 67 | #else 68 | #define CLOSE_HANDLE_IF(h) if(h != INVALID_HANDLE_VALUE){ CloseHandle(h); h = INVALID_HANDLE_VALUE; } 69 | #endif 70 | #endif 71 | 72 | #ifndef RETURN_STRING 73 | #define RETURN_STRING(x) case x: return L#x 74 | #endif 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /WasapiCapture/MFTExternTrace.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFTExternTrace.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFTEXTERNTRACE_H 5 | #define MFTEXTERNTRACE_H 6 | 7 | // CExternTrace initializes the memory leaks detection (see "crtdbg.h"). 8 | // CExternTrace ensures that no object is allocated before TRACE_INIT is called. 9 | // Because DllMain.cpp contains external objects, you will see "FAKE" memory leaks. 10 | #ifdef _DEBUG 11 | 12 | class CExternTrace{ 13 | 14 | public: 15 | 16 | CExternTrace(){ TRACE_INIT(); }; 17 | ~CExternTrace(){ TRACE_CLOSE(); }; 18 | }; 19 | 20 | CExternTrace cExternTrace; 21 | 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /WasapiCapture/MFWaveWriter.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFWaveWriter.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "Stdafx.h" 5 | 6 | BOOL CMFWaveWriter::Initialize(const WCHAR* wszFile, const BOOL bExtensibleFormat) 7 | { 8 | BOOL bRet = FALSE; 9 | const UINT32 bHeaderLenght = bExtensibleFormat ? WAVE_HEAD_EXT_LEN : WAVE_HEAD_LEN; 10 | CLOSE_HANDLE_IF(m_hFile); 11 | 12 | m_hFile = CreateFile(wszFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 13 | 14 | if(m_hFile == INVALID_HANDLE_VALUE) 15 | { 16 | IF_ERROR_RETURN(bRet); 17 | } 18 | 19 | BYTE WavHeader[WAVE_HEAD_EXT_LEN]; 20 | memset(WavHeader, 0, sizeof(WavHeader)); 21 | 22 | DWORD dwWritten; 23 | 24 | if(!WriteFile(m_hFile, (LPCVOID)WavHeader, bHeaderLenght, &dwWritten, 0) || dwWritten != bHeaderLenght) 25 | { 26 | IF_ERROR_RETURN(bRet); 27 | } 28 | 29 | return bRet = TRUE; 30 | } 31 | 32 | BOOL CMFWaveWriter::WriteWaveData(const BYTE* pData, const DWORD dwLength) 33 | { 34 | BOOL bRet = FALSE; 35 | DWORD dwWritten; 36 | 37 | if(!WriteFile(m_hFile, (LPCVOID)pData, dwLength, &dwWritten, 0) || dwWritten != dwLength) 38 | { 39 | IF_ERROR_RETURN(bRet); 40 | } 41 | 42 | return bRet = TRUE; 43 | } 44 | 45 | BOOL CMFWaveWriter::FinalizeHeader(WAVEFORMATEX* pwfx, const UINT32 uiFileLength, const BOOL bExtensibleFormat) 46 | { 47 | BOOL bRet = FALSE; 48 | DWORD dwMove; 49 | DWORD dwWritten; 50 | const UINT32 bHeaderLenght = bExtensibleFormat ? WAVE_HEAD_EXT_LEN : WAVE_HEAD_LEN; 51 | 52 | BYTE WavHeader[WAVE_HEAD_EXT_LEN]; 53 | memset(WavHeader, 0, sizeof(WavHeader)); 54 | 55 | if((dwMove = SetFilePointer(m_hFile, 0, NULL, FILE_BEGIN)) == INVALID_SET_FILE_POINTER) 56 | { 57 | IF_ERROR_RETURN(bRet); 58 | } 59 | 60 | if(bExtensibleFormat) 61 | { 62 | if(!SetWaveHeaderExt(pwfx, uiFileLength, WavHeader)) 63 | { 64 | IF_ERROR_RETURN(bRet); 65 | } 66 | } 67 | else 68 | { 69 | if(!SetWaveHeader(pwfx, uiFileLength, WavHeader)) 70 | { 71 | IF_ERROR_RETURN(bRet); 72 | } 73 | } 74 | 75 | if(!WriteFile(m_hFile, (LPCVOID)WavHeader, bHeaderLenght, &dwWritten, 0) || dwWritten != bHeaderLenght) 76 | { 77 | IF_ERROR_RETURN(bRet); 78 | } 79 | 80 | return bRet = TRUE; 81 | } 82 | 83 | BOOL CMFWaveWriter::SetWaveHeaderExt(WAVEFORMATEX* pwfx, const UINT32 uiDataLen, BYTE* head) 84 | { 85 | if(uiDataLen == 0) 86 | return FALSE; 87 | 88 | assert((uiDataLen * pwfx->nBlockAlign) % 2 == 0); 89 | 90 | RIFFCHUNK* pch; 91 | RIFFLIST *priff; 92 | WAVEFORM_EXT *pwaveExt; 93 | FACT* pFact; 94 | WAVEFORMATEXTENSIBLE *pWaveFormatExtensible = reinterpret_cast(pwfx); 95 | 96 | priff = (RIFFLIST*)head; 97 | priff->fcc = SWAP32('RIFF'); 98 | 99 | priff->cb = (uiDataLen * pwfx->nBlockAlign) + WAVE_HEAD_EXT_LEN - sizeof(RIFFCHUNK); 100 | priff->fccListType = SWAP32('WAVE'); 101 | 102 | pwaveExt = (WAVEFORM_EXT*)(priff + 1); 103 | pwaveExt->fcc = SWAP32('fmt '); 104 | pwaveExt->cb = sizeof(WAVEFORM_EXT) - sizeof(RIFFCHUNK); 105 | pwaveExt->wFormatTag = pwfx->wFormatTag; 106 | pwaveExt->nChannels = pwfx->nChannels; 107 | pwaveExt->nSamplesPerSec = pwfx->nSamplesPerSec; 108 | pwaveExt->nAvgBytesPerSec = pwfx->nAvgBytesPerSec; 109 | pwaveExt->nBlockAlign = pwfx->nBlockAlign; 110 | pwaveExt->wBitsPerSample = pwfx->wBitsPerSample; 111 | pwaveExt->cbSize = pwfx->cbSize; 112 | pwaveExt->wValidBitsPerSample = pWaveFormatExtensible->Samples.wValidBitsPerSample; 113 | pwaveExt->dwChannelMask = pWaveFormatExtensible->dwChannelMask; 114 | pwaveExt->SubFormat = pWaveFormatExtensible->SubFormat; 115 | 116 | pFact = (FACT*)(pwaveExt + 1); 117 | pFact->fcc = SWAP32('fact'); 118 | pFact->cb = 4; 119 | pFact->lenght = uiDataLen * pwaveExt->nChannels; 120 | 121 | pch = (RIFFCHUNK*)(pFact + 1); 122 | pch->fcc = SWAP32('data'); 123 | pch->cb = (uiDataLen * pwfx->nBlockAlign); 124 | 125 | return TRUE; 126 | } 127 | 128 | BOOL CMFWaveWriter::SetWaveHeader(const WAVEFORMATEX* pwfx, const UINT32 uiDataLen, BYTE* head) 129 | { 130 | if(uiDataLen == 0) 131 | return FALSE; 132 | 133 | RIFFCHUNK* pch; 134 | RIFFLIST *priff; 135 | WAVEFORM *pwave; 136 | 137 | priff = (RIFFLIST*)head; 138 | priff->fcc = SWAP32('RIFF'); 139 | 140 | priff->cb = (uiDataLen * pwfx->nBlockAlign) + WAVE_HEAD_LEN - sizeof(RIFFCHUNK); 141 | priff->fccListType = SWAP32('WAVE'); 142 | 143 | pwave = (WAVEFORM*)(priff + 1); 144 | pwave->fcc = SWAP32('fmt '); 145 | pwave->cb = sizeof(WAVEFORM) - sizeof(RIFFCHUNK); 146 | pwave->wFormatTag = pwfx->wFormatTag; 147 | pwave->nChannels = pwfx->nChannels; 148 | pwave->nSamplesPerSec = pwfx->nSamplesPerSec; 149 | pwave->nAvgBytesPerSec = pwfx->nAvgBytesPerSec; 150 | pwave->nBlockAlign = pwfx->nBlockAlign; 151 | pwave->wBitsPerSample = pwfx->wBitsPerSample; 152 | 153 | pch = (RIFFCHUNK*)(pwave + 1); 154 | pch->fcc = SWAP32('data'); 155 | pch->cb = (uiDataLen * pwfx->nBlockAlign); 156 | 157 | return TRUE; 158 | } -------------------------------------------------------------------------------- /WasapiCapture/MFWaveWriter.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // MFWaveWriter.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef MFWAVEWRITER_H 5 | #define MFWAVEWRITER_H 6 | 7 | const UINT32 WAVE_HEAD_LEN = 44; 8 | const UINT32 WAVE_HEAD_EXT_LEN = 80; 9 | 10 | #define SWAP32(val) (UINT32)((((UINT32)(val)) & 0x000000FF)<<24 | (((UINT32)(val)) & 0x0000FF00)<<8 | (((UINT32)(val)) & 0x00FF0000)>>8 | (((UINT32)(val)) & 0xFF000000)>>24) 11 | 12 | #pragma pack(push, 1) 13 | 14 | struct RIFFCHUNK 15 | { 16 | UINT32 fcc; 17 | UINT32 cb; 18 | }; 19 | 20 | struct RIFFLIST 21 | { 22 | UINT32 fcc; 23 | UINT32 cb; 24 | UINT32 fccListType; 25 | 26 | }; 27 | 28 | struct WAVEFORM 29 | { 30 | UINT32 fcc; 31 | UINT32 cb; 32 | UINT16 wFormatTag; 33 | UINT16 nChannels; 34 | UINT32 nSamplesPerSec; 35 | UINT32 nAvgBytesPerSec; 36 | UINT16 nBlockAlign; 37 | UINT16 wBitsPerSample; 38 | }; 39 | 40 | struct WAVEFORM_EXT : public WAVEFORM 41 | { 42 | UINT16 cbSize; 43 | UINT16 wValidBitsPerSample; 44 | UINT32 dwChannelMask; 45 | GUID SubFormat; 46 | }; 47 | 48 | struct FACT 49 | { 50 | UINT32 fcc; 51 | UINT32 cb; 52 | UINT32 lenght; 53 | 54 | }; 55 | 56 | #pragma pack(pop) 57 | 58 | class CMFWaveWriter 59 | { 60 | public: 61 | 62 | CMFWaveWriter() : m_hFile(INVALID_HANDLE_VALUE){} 63 | ~CMFWaveWriter(){ CLOSE_HANDLE_IF(m_hFile); } 64 | 65 | BOOL Initialize(const WCHAR*, const BOOL); 66 | BOOL WriteWaveData(const BYTE*, const DWORD); 67 | BOOL FinalizeHeader(WAVEFORMATEX*, const UINT32, const BOOL); 68 | 69 | private: 70 | 71 | HANDLE m_hFile; 72 | 73 | BOOL SetWaveHeader(const WAVEFORMATEX*, const UINT32, BYTE*); 74 | BOOL SetWaveHeaderExt(WAVEFORMATEX*, const UINT32, BYTE*); 75 | }; 76 | 77 | #endif -------------------------------------------------------------------------------- /WasapiCapture/Main.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // Main.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "Stdafx.h" 5 | 6 | #define AUDIO_CAPTURE_FILE L"Capture.wav" 7 | #define REFTIMES_PER_SEC 10000000 8 | #define REFTIMES_PER_MILLISEC 10000 9 | #define MAX_LOOP_BEFORE_STOP 20 10 | 11 | const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); 12 | const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); 13 | const IID IID_IAudioClient = __uuidof(IAudioClient); 14 | const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient); 15 | 16 | HRESULT RecordAudioStream(); 17 | 18 | void main() 19 | { 20 | HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); 21 | 22 | if(SUCCEEDED(hr)) 23 | { 24 | LOG_HRESULT(RecordAudioStream()); 25 | 26 | CoUninitialize(); 27 | } 28 | } 29 | 30 | HRESULT RecordAudioStream() 31 | { 32 | HRESULT hr = S_OK; 33 | IMMDeviceEnumerator* pEnumerator = NULL; 34 | IMMDevice* pDevice = NULL; 35 | IAudioClient* pAudioClient = NULL; 36 | IAudioCaptureClient* pCaptureClient = NULL; 37 | WAVEFORMATEX* pwfx = NULL; 38 | REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC; 39 | REFERENCE_TIME hnsActualDuration; 40 | UINT32 bufferFrameCount; 41 | CMFWaveWriter cMFWaveWriter; 42 | UINT32 uiFileLength = 0; 43 | BOOL bExtensibleFormat = FALSE; 44 | 45 | try 46 | { 47 | IF_FAILED_THROW(CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator)); 48 | IF_FAILED_THROW(pEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice)); 49 | IF_FAILED_THROW(pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient)); 50 | 51 | IF_FAILED_THROW(pAudioClient->GetMixFormat(&pwfx)); 52 | 53 | switch(pwfx->wFormatTag) 54 | { 55 | case WAVE_FORMAT_PCM: 56 | TRACE((L"WAVE_FORMAT_PCM")); 57 | break; 58 | 59 | case WAVE_FORMAT_IEEE_FLOAT: 60 | TRACE((L"WAVE_FORMAT_IEEE_FLOAT")); 61 | break; 62 | 63 | case WAVE_FORMAT_EXTENSIBLE: 64 | TRACE((L"WAVE_FORMAT_EXTENSIBLE")); 65 | bExtensibleFormat = TRUE; 66 | 67 | WAVEFORMATEXTENSIBLE *pWaveFormatExtensible = reinterpret_cast(pwfx); 68 | 69 | if(pWaveFormatExtensible->SubFormat == KSDATAFORMAT_SUBTYPE_PCM) 70 | { 71 | TRACE((L"KSDATAFORMAT_SUBTYPE_PCM")); 72 | } 73 | else if(pWaveFormatExtensible->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) 74 | { 75 | TRACE((L"KSDATAFORMAT_SUBTYPE_IEEE_FLOAT")); 76 | } 77 | break; 78 | } 79 | 80 | IF_FAILED_THROW(pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, hnsRequestedDuration, 0, pwfx, NULL)); 81 | IF_FAILED_THROW(pAudioClient->GetBufferSize(&bufferFrameCount)); 82 | IF_FAILED_THROW(pAudioClient->GetService(IID_IAudioCaptureClient, (void**)&pCaptureClient)); 83 | 84 | IF_FAILED_THROW(cMFWaveWriter.Initialize(AUDIO_CAPTURE_FILE, bExtensibleFormat) ? S_OK : E_FAIL); 85 | 86 | hnsActualDuration = (double)REFTIMES_PER_SEC * bufferFrameCount / pwfx->nSamplesPerSec; 87 | 88 | IF_FAILED_THROW(pAudioClient->Start()); 89 | 90 | BOOL bDone = FALSE; 91 | UINT32 packetLength = 0; 92 | UINT32 numFramesAvailable; 93 | BYTE* pData; 94 | DWORD flags; 95 | int iLoop = 0; 96 | 97 | while(bDone == FALSE) 98 | { 99 | Sleep(hnsActualDuration / REFTIMES_PER_MILLISEC / 2); 100 | 101 | IF_FAILED_THROW(pCaptureClient->GetNextPacketSize(&packetLength)); 102 | 103 | while(packetLength != 0) 104 | { 105 | IF_FAILED_THROW(pCaptureClient->GetBuffer(&pData, &numFramesAvailable, &flags, NULL, NULL)); 106 | 107 | if(flags & AUDCLNT_BUFFERFLAGS_SILENT) 108 | { 109 | TRACE((L"AUDCLNT_BUFFERFLAGS_SILENT")); 110 | break; 111 | } 112 | 113 | if(flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY) 114 | { 115 | TRACE((L"AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY")); 116 | } 117 | 118 | if(flags & AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR) 119 | { 120 | TRACE((L"AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR")); 121 | } 122 | 123 | //TRACE((L"numFramesAvailable : %u", numFramesAvailable)); 124 | 125 | assert(packetLength == numFramesAvailable); 126 | 127 | IF_FAILED_THROW(cMFWaveWriter.WriteWaveData(pData, numFramesAvailable * pwfx->nBlockAlign) ? S_OK : E_FAIL); 128 | 129 | uiFileLength += numFramesAvailable; 130 | 131 | IF_FAILED_THROW(pCaptureClient->ReleaseBuffer(numFramesAvailable)); 132 | 133 | IF_FAILED_THROW(pCaptureClient->GetNextPacketSize(&packetLength)); 134 | } 135 | 136 | if(iLoop++ == MAX_LOOP_BEFORE_STOP) 137 | bDone = TRUE; 138 | } 139 | } 140 | catch(HRESULT){} 141 | 142 | TRACE((L"uiFileLength : %u", uiFileLength)); 143 | 144 | if(hr == S_OK && pwfx != NULL) 145 | cMFWaveWriter.FinalizeHeader(pwfx, uiFileLength, bExtensibleFormat); 146 | 147 | if(pAudioClient) 148 | { 149 | LOG_HRESULT(pAudioClient->Stop()); 150 | SAFE_RELEASE(pAudioClient); 151 | } 152 | 153 | CoTaskMemFree(pwfx); 154 | SAFE_RELEASE(pCaptureClient); 155 | SAFE_RELEASE(pEnumerator); 156 | SAFE_RELEASE(pDevice); 157 | 158 | return hr; 159 | } -------------------------------------------------------------------------------- /WasapiCapture/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.cpp 3 | //---------------------------------------------------------------------------------------------- 4 | #include "StdAfx.h" -------------------------------------------------------------------------------- /WasapiCapture/StdAfx.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------- 2 | // StdAfx.h 3 | //---------------------------------------------------------------------------------------------- 4 | #ifndef STDAFX_H 5 | #define STDAFX_H 6 | 7 | #pragma once 8 | #define WIN32_LEAN_AND_MEAN 9 | #define STRICT 10 | 11 | //---------------------------------------------------------------------------------------------- 12 | // Microsoft Windows SDK for Windows 7 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #ifdef _DEBUG 20 | #include 21 | #endif 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #pragma warning(push) 33 | #pragma warning(disable:4201) 34 | #include 35 | #pragma warning(pop) 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | //---------------------------------------------------------------------------------------------- 44 | // Common Project Files 45 | #ifdef _DEBUG 46 | #define MF_USE_LOGGING 1 47 | #else 48 | #define MF_USE_LOGGING 0 49 | #endif 50 | 51 | #include "MFMacro.h" 52 | #include "MFTrace.h" 53 | #include "MFLogging.h" 54 | #include "MFTExternTrace.h" 55 | #include "MFWaveWriter.h" 56 | 57 | #endif -------------------------------------------------------------------------------- /WasapiCapture/WasapiCapture.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WasapiCapture", "WasapiCapture.vcxproj", "{CD9AB404-9765-487C-8718-AC7F710D0663}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {CD9AB404-9765-487C-8718-AC7F710D0663}.Debug|x64.ActiveCfg = Debug|x64 17 | {CD9AB404-9765-487C-8718-AC7F710D0663}.Debug|x64.Build.0 = Debug|x64 18 | {CD9AB404-9765-487C-8718-AC7F710D0663}.Debug|x86.ActiveCfg = Debug|Win32 19 | {CD9AB404-9765-487C-8718-AC7F710D0663}.Debug|x86.Build.0 = Debug|Win32 20 | {CD9AB404-9765-487C-8718-AC7F710D0663}.Release|x64.ActiveCfg = Release|x64 21 | {CD9AB404-9765-487C-8718-AC7F710D0663}.Release|x64.Build.0 = Release|x64 22 | {CD9AB404-9765-487C-8718-AC7F710D0663}.Release|x86.ActiveCfg = Release|Win32 23 | {CD9AB404-9765-487C-8718-AC7F710D0663}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {F4F8E561-87BC-44BC-8C6A-341B7BEDF42D} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /WasapiCapture/WasapiCapture.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Fichiers sources 20 | 21 | 22 | Fichiers sources 23 | 24 | 25 | Fichiers sources 26 | 27 | 28 | 29 | 30 | Fichiers d%27en-tête 31 | 32 | 33 | Fichiers d%27en-tête 34 | 35 | 36 | Fichiers d%27en-tête 37 | 38 | 39 | Fichiers d%27en-tête 40 | 41 | 42 | Fichiers d%27en-tête 43 | 44 | 45 | Fichiers d%27en-tête 46 | 47 | 48 | -------------------------------------------------------------------------------- /WasapiCapture/WasapiCapture.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------