diff --git a/modules/highgui/src/agile_wrl.h b/modules/highgui/src/agile_wrl.h new file mode 100644 index 000000000..99fbf4185 --- /dev/null +++ b/modules/highgui/src/agile_wrl.h @@ -0,0 +1,568 @@ +// +// Copyright (C) Microsoft Corporation +// All rights reserved. +// Modified for native C++ WRL support by Gregory Morse +// +// Code in Details namespace is for internal usage within the library code +// + +#ifndef _PLATFORM_AGILE_H_ +#define _PLATFORM_AGILE_H_ + +#ifdef _MSC_VER +#pragma once +#endif // _MSC_VER + +#include +#include + +template class Agile; + +template +struct UnwrapAgile +{ + static const bool _IsAgile = false; +}; +template +struct UnwrapAgile> +{ + static const bool _IsAgile = true; +}; +template +struct UnwrapAgile> +{ + static const bool _IsAgile = true; +}; + +#define IS_AGILE(T) UnwrapAgile::_IsAgile + +#define __is_winrt_agile(T) (std::is_same::value || std::is_base_of::value || std::is_base_of::value) //derived from Microsoft::WRL::FtmBase or IAgileObject + +#define __is_win_interface(T) (std::is_base_of::value || std::is_base_of::value) //derived from IUnknown or IInspectable + +#define __is_win_class(T) (std::is_same::value || std::is_base_of::value) //derived from Microsoft::WRL::RuntimeClass or HSTRING + + namespace Details + { + IUnknown* __stdcall GetObjectContext(); + HRESULT __stdcall GetProxyImpl(IUnknown*, REFIID, IUnknown*, IUnknown**); + HRESULT __stdcall ReleaseInContextImpl(IUnknown*, IUnknown*); + + template +#if _MSC_VER >= 1800 + __declspec(no_refcount) inline HRESULT GetProxy(T *ObjectIn, IUnknown *ContextCallBack, T **Proxy) +#else + inline HRESULT GetProxy(T *ObjectIn, IUnknown *ContextCallBack, T **Proxy) +#endif + { +#if _MSC_VER >= 1800 + return GetProxyImpl(*reinterpret_cast(&ObjectIn), __uuidof(T*), ContextCallBack, reinterpret_cast(Proxy)); +#else + return GetProxyImpl(*reinterpret_cast(&const_cast(ObjectIn)), __uuidof(T*), ContextCallBack, reinterpret_cast(Proxy)); +#endif + } + + template + inline HRESULT ReleaseInContext(T *ObjectIn, IUnknown *ContextCallBack) + { + return ReleaseInContextImpl(ObjectIn, ContextCallBack); + } + + template + class AgileHelper + { + __abi_IUnknown* _p; + bool _release; + public: + AgileHelper(__abi_IUnknown* p, bool release = true) : _p(p), _release(release) + { + } + AgileHelper(AgileHelper&& other) : _p(other._p), _release(other._release) + { + _other._p = nullptr; + _other._release = true; + } + AgileHelper operator=(AgileHelper&& other) + { + _p = other._p; + _release = other._release; + _other._p = nullptr; + _other._release = true; + return *this; + } + + ~AgileHelper() + { + if (_release && _p) + { + _p->__abi_Release(); + } + } + + __declspec(no_refcount) __declspec(no_release_return) + T* operator->() + { + return reinterpret_cast(_p); + } + + __declspec(no_refcount) __declspec(no_release_return) + operator T * () + { + return reinterpret_cast(_p); + } + private: + AgileHelper(const AgileHelper&); + AgileHelper operator=(const AgileHelper&); + }; + template + struct __remove_hat + { + typedef T type; + }; + template + struct __remove_hat + { + typedef T type; + }; + template + struct AgileTypeHelper + { + typename typedef __remove_hat::type type; + typename typedef __remove_hat::type* agileMemberType; + }; + } // namespace Details + +#pragma warning(push) +#pragma warning(disable: 4451) // Usage of ref class inside this context can lead to invalid marshaling of object across contexts + + template < + typename T, + bool TIsNotAgile = (__is_win_class(typename Details::AgileTypeHelper::type) && !__is_winrt_agile(typename Details::AgileTypeHelper::type)) || + __is_win_interface(typename Details::AgileTypeHelper::type) + > + class Agile + { + static_assert(__is_win_class(typename Details::AgileTypeHelper::type) || __is_win_interface(typename Details::AgileTypeHelper::type), "Agile can only be used with ref class or interface class types"); + typename typedef Details::AgileTypeHelper::agileMemberType TypeT; + TypeT _object; + ::Microsoft::WRL::ComPtr _contextCallback; + ULONG_PTR _contextToken; + +#if _MSC_VER >= 1800 + enum class AgileState + { + NonAgilePointer = 0, + AgilePointer = 1, + Unknown = 2 + }; + AgileState _agileState; +#endif + + void CaptureContext() + { + _contextCallback = Details::GetObjectContext(); + __abi_ThrowIfFailed(CoGetContextToken(&_contextToken)); + } + + void SetObject(TypeT object) + { + // Capture context before setting the pointer + // If context capture fails then nothing to cleanup + Release(); + if (object != nullptr) + { + ::Microsoft::WRL::ComPtr checkIfAgile; + HRESULT hr = reinterpret_cast(object)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile); + // Don't Capture context if object is agile + if (hr != S_OK) + { +#if _MSC_VER >= 1800 + _agileState = AgileState::NonAgilePointer; +#endif + CaptureContext(); + } +#if _MSC_VER >= 1800 + else + { + _agileState = AgileState::AgilePointer; + } +#endif + } + _object = object; + } + + public: + Agile() throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + } + + Agile(nullptr_t) throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + } + + explicit Agile(TypeT object) throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + // Assumes that the source object is from the current context + SetObject(object); + } + + Agile(const Agile& object) throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + // Get returns pointer valid for current context + SetObject(object.Get()); + } + + Agile(Agile&& object) throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + // Assumes that the source object is from the current context + Swap(object); + } + + ~Agile() throw() + { + Release(); + } + + TypeT Get() const + { + // Agile object, no proxy required +#if _MSC_VER >= 1800 + if (_agileState == AgileState::AgilePointer || _object == nullptr) +#else + if (_contextToken == 0 || _contextCallback == nullptr || _object == nullptr) +#endif + { + return _object; + } + + // Do the check for same context + ULONG_PTR currentContextToken; + __abi_ThrowIfFailed(CoGetContextToken(¤tContextToken)); + if (currentContextToken == _contextToken) + { + return _object; + } + +#if _MSC_VER >= 1800 + // Different context and holding on to a non agile object + // Do the costly work of getting a proxy + TypeT localObject; + __abi_ThrowIfFailed(Details::GetProxy(_object, _contextCallback.Get(), &localObject)); + + if (_agileState == AgileState::Unknown) +#else + // Object is agile if it implements IAgileObject + // GetAddressOf captures the context with out knowing the type of object that it will hold + if (_object != nullptr) +#endif + { +#if _MSC_VER >= 1800 + // Object is agile if it implements IAgileObject + // GetAddressOf captures the context with out knowing the type of object that it will hold + ::Microsoft::WRL::ComPtr checkIfAgile; + HRESULT hr = reinterpret_cast(localObject)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile); +#else + ::Microsoft::WRL::ComPtr checkIfAgile; + HRESULT hr = reinterpret_cast(_object)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile); +#endif + if (hr == S_OK) + { + auto pThis = const_cast(this); +#if _MSC_VER >= 1800 + pThis->_agileState = AgileState::AgilePointer; +#endif + pThis->_contextToken = 0; + pThis->_contextCallback = nullptr; + return _object; + } +#if _MSC_VER >= 1800 + else + { + auto pThis = const_cast(this); + pThis->_agileState = AgileState::NonAgilePointer; + } +#endif + } + +#if _MSC_VER < 1800 + // Different context and holding on to a non agile object + // Do the costly work of getting a proxy + TypeT localObject; + __abi_ThrowIfFailed(Details::GetProxy(_object, _contextCallback.Get(), &localObject)); +#endif + return localObject; + } + + TypeT* GetAddressOf() throw() + { + Release(); + CaptureContext(); + return &_object; + } + + TypeT* GetAddressOfForInOut() throw() + { + CaptureContext(); + return &_object; + } + + TypeT operator->() const throw() + { + return Get(); + } + + Agile& operator=(nullptr_t) throw() + { + Release(); + return *this; + } + + Agile& operator=(TypeT object) throw() + { + Agile(object).Swap(*this); + return *this; + } + + Agile& operator=(Agile object) throw() + { + // parameter is by copy which gets pointer valid for current context + object.Swap(*this); + return *this; + } + +#if _MSC_VER < 1800 + Agile& operator=(IUnknown* lp) throw() + { + // bump ref count + ::Microsoft::WRL::ComPtr spObject(lp); + + // put it into Platform Object + Platform::Object object; + *(IUnknown**)(&object) = spObject.Detach(); + + SetObject(object); + return *this; + } +#endif + + void Swap(Agile& object) + { + std::swap(_object, object._object); + std::swap(_contextCallback, object._contextCallback); + std::swap(_contextToken, object._contextToken); +#if _MSC_VER >= 1800 + std::swap(_agileState, object._agileState); +#endif + } + + // Release the interface and set to NULL + void Release() throw() + { + if (_object) + { + // Cast to IInspectable (no QI) + IUnknown* pObject = *(IUnknown**)(&_object); + // Set * to null without release + *(IUnknown**)(&_object) = nullptr; + + ULONG_PTR currentContextToken; + __abi_ThrowIfFailed(CoGetContextToken(¤tContextToken)); + if (_contextToken == 0 || _contextCallback == nullptr || _contextToken == currentContextToken) + { + pObject->Release(); + } + else + { + Details::ReleaseInContext(pObject, _contextCallback.Get()); + } + _contextCallback = nullptr; + _contextToken = 0; +#if _MSC_VER >= 1800 + _agileState = AgileState::Unknown; +#endif + } + } + + bool operator==(nullptr_t) const throw() + { + return _object == nullptr; + } + + bool operator==(const Agile& other) const throw() + { + return _object == other._object && _contextToken == other._contextToken; + } + + bool operator<(const Agile& other) const throw() + { + if (reinterpret_cast(_object) < reinterpret_cast(other._object)) + { + return true; + } + + return _object == other._object && _contextToken < other._contextToken; + } + }; + + template + class Agile + { + static_assert(__is_win_class(typename Details::AgileTypeHelper::type) || __is_win_interface(typename Details::AgileTypeHelper::type), "Agile can only be used with ref class or interface class types"); + typename typedef Details::AgileTypeHelper::agileMemberType TypeT; + TypeT _object; + + public: + Agile() throw() : _object(nullptr) + { + } + + Agile(nullptr_t) throw() : _object(nullptr) + { + } + + explicit Agile(TypeT object) throw() : _object(object) + { + } + + Agile(const Agile& object) throw() : _object(object._object) + { + } + + Agile(Agile&& object) throw() : _object(nullptr) + { + Swap(object); + } + + ~Agile() throw() + { + Release(); + } + + TypeT Get() const + { + return _object; + } + + TypeT* GetAddressOf() throw() + { + Release(); + return &_object; + } + + TypeT* GetAddressOfForInOut() throw() + { + return &_object; + } + + TypeT operator->() const throw() + { + return Get(); + } + + Agile& operator=(nullptr_t) throw() + { + Release(); + return *this; + } + + Agile& operator=(TypeT object) throw() + { + if (_object != object) + { + _object = object; + } + return *this; + } + + Agile& operator=(Agile object) throw() + { + object.Swap(*this); + return *this; + } + +#if _MSC_VER < 1800 + Agile& operator=(IUnknown* lp) throw() + { + Release(); + // bump ref count + ::Microsoft::WRL::ComPtr spObject(lp); + + // put it into Platform Object + Platform::Object object; + *(IUnknown**)(&object) = spObject.Detach(); + + _object = object; + return *this; + } +#endif + + // Release the interface and set to NULL + void Release() throw() + { + _object = nullptr; + } + + void Swap(Agile& object) + { + std::swap(_object, object._object); + } + + bool operator==(nullptr_t) const throw() + { + return _object == nullptr; + } + + bool operator==(const Agile& other) const throw() + { + return _object == other._object; + } + + bool operator<(const Agile& other) const throw() + { + return reinterpret_cast(_object) < reinterpret_cast(other._object); + } + }; + +#pragma warning(pop) + + template + bool operator==(nullptr_t, const Agile& a) throw() + { + return a == nullptr; + } + + template + bool operator!=(const Agile& a, nullptr_t) throw() + { + return !(a == nullptr); + } + + template + bool operator!=(nullptr_t, const Agile& a) throw() + { + return !(a == nullptr); + } + + template + bool operator!=(const Agile& a, const Agile& b) throw() + { + return !(a == b); + } + + +#endif // _PLATFORM_AGILE_H_ diff --git a/modules/highgui/src/cap_msmf.cpp b/modules/highgui/src/cap_msmf.cpp index b1122efbe..2a9ee20a9 100644 --- a/modules/highgui/src/cap_msmf.cpp +++ b/modules/highgui/src/cap_msmf.cpp @@ -47,12 +47,21 @@ Originaly licensed under The Code Project Open License (CPOL) 1.02: http://www.codeproject.com/info/cpol10.aspx */ +//require Windows 8 for some of the formats defined otherwise could baseline on lower version +#if WINVER < _WIN32_WINNT_WIN7 +#undef WINVER +#define WINVER _WIN32_WINNT_WIN7 +#endif +#if defined _MSC_VER && _MSC_VER >= 1600 + #define HAVE_CONCURRENCY +#endif #include #include #include #include #include #include +#include #include #include #include @@ -71,13 +80,11 @@ #pragma comment(lib, "Mfreadwrite") #pragma comment(lib, "MinCore_Downlevel") -// for ComPtr usage -#include -using namespace Microsoft::WRL; - #include #ifdef HAVE_WINRT + // for ComPtr usage +#include #ifdef __cplusplus_winrt #include #include @@ -89,10 +96,169 @@ using namespace Microsoft::WRL; #include #include #include +#ifdef HAVE_CONCURRENCY #include -#include +#ifndef __cplusplus_winrt +__declspec(noreturn) void __stdcall __abi_WinRTraiseException(long); -using namespace Microsoft::WRL::Wrappers; +inline void __abi_ThrowIfFailed(long __hrArg) +{ + if (__hrArg < 0) + { + __abi_WinRTraiseException(__hrArg); + } +} + +struct Guid +{ +public: + Guid(); + Guid(__rcGUID_t); + operator ::__rcGUID_t(); + bool Equals(Guid __guidArg); + bool Equals(__rcGUID_t __guidArg); + Guid(unsigned int __aArg, unsigned short __bArg, unsigned short __cArg, unsigned __int8 __dArg, + unsigned __int8 __eArg, unsigned __int8 __fArg, unsigned __int8 __gArg, unsigned __int8 __hArg, + unsigned __int8 __iArg, unsigned __int8 __jArg, unsigned __int8 __kArg); + Guid(unsigned int __aArg, unsigned short __bArg, unsigned short __cArg, const unsigned __int8* __dArg); +private: + unsigned long __a; + unsigned short __b; + unsigned short __c; + unsigned char __d; + unsigned char __e; + unsigned char __f; + unsigned char __g; + unsigned char __h; + unsigned char __i; + unsigned char __j; + unsigned char __k; +}; + +static_assert(sizeof(Guid) == sizeof(::_GUID), "Incorect size for Guid"); +static_assert(sizeof(__rcGUID_t) == sizeof(::_GUID), "Incorect size for __rcGUID_t"); + +//////////////////////////////////////////////////////////////////////////////// +inline Guid::Guid() : __a(0), __b(0), __c(0), __d(0), __e(0), __f(0), __g(0), __h(0), __i(0), __j(0), __k(0) +{ +} + +inline Guid::Guid(__rcGUID_t __guid) : +__a(reinterpret_cast(__guid).Data1), +__b(reinterpret_cast(__guid).Data2), +__c(reinterpret_cast(__guid).Data3), +__d(reinterpret_cast(__guid).Data4[0]), +__e(reinterpret_cast(__guid).Data4[1]), +__f(reinterpret_cast(__guid).Data4[2]), +__g(reinterpret_cast(__guid).Data4[3]), +__h(reinterpret_cast(__guid).Data4[4]), +__i(reinterpret_cast(__guid).Data4[5]), +__j(reinterpret_cast(__guid).Data4[6]), +__k(reinterpret_cast(__guid).Data4[7]) +{ +} + +inline Guid::operator ::__rcGUID_t() +{ + return reinterpret_cast<__rcGUID_t>(*this); +} + +inline bool Guid::Equals(Guid __guidArg) +{ + return *this == __guidArg; +} + +inline bool Guid::Equals(__rcGUID_t __guidArg) +{ + return *this == static_cast< Guid>(__guidArg); +} + +inline bool operator==(Guid __aArg, Guid __bArg) +{ + auto __a = reinterpret_cast(&__aArg); + auto __b = reinterpret_cast(&__bArg); + + return (__a[0] == __b[0] && __a[1] == __b[1] && __a[2] == __b[2] && __a[3] == __b[3]); +} + +inline bool operator!=(Guid __aArg, Guid __bArg) +{ + return !(__aArg == __bArg); +} + +inline bool operator<(Guid __aArg, Guid __bArg) +{ + auto __a = reinterpret_cast(&__aArg); + auto __b = reinterpret_cast(&__bArg); + + if (__a[0] != __b[0]) + { + return __a[0] < __b[0]; + } + + if (__a[1] != __b[1]) + { + return __a[1] < __b[1]; + } + + if (__a[2] != __b[2]) + { + return __a[2] < __b[2]; + } + + if (__a[3] != __b[3]) + { + return __a[3] < __b[3]; + } + + return false; +} + +inline Guid::Guid(unsigned int __aArg, unsigned short __bArg, unsigned short __cArg, unsigned __int8 __dArg, + unsigned __int8 __eArg, unsigned __int8 __fArg, unsigned __int8 __gArg, unsigned __int8 __hArg, + unsigned __int8 __iArg, unsigned __int8 __jArg, unsigned __int8 __kArg) : + __a(__aArg), __b(__bArg), __c(__cArg), __d(__dArg), __e(__eArg), __f(__fArg), __g(__gArg), __h(__hArg), __i(__iArg), __j(__jArg), __k(__kArg) +{ +} + +inline Guid::Guid(unsigned int __aArg, unsigned short __bArg, unsigned short __cArg, const unsigned __int8 __dArg[8]) : +__a(__aArg), __b(__bArg), __c(__cArg) +{ + __d = __dArg[0]; + __e = __dArg[1]; + __f = __dArg[2]; + __g = __dArg[3]; + __h = __dArg[4]; + __i = __dArg[5]; + __j = __dArg[6]; + __k = __dArg[7]; +} + +__declspec(selectany) Guid __winrt_GUID_NULL(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + +// +//// Don't want to define the real IUnknown from unknown.h here. That would means if the user has +//// any broken code that uses it, compile errors will take the form of e.g.: +//// predefined C++ WinRT types (compiler internal)(41) : see declaration of 'IUnknown::QueryInterface' +//// This is not helpful. If they use IUnknown, we still need to point them to the actual unknown.h so +//// that they can see the original definition. +//// +//// For WinRT, we'll instead have a parallel COM interface hierarchy for basic interfaces starting with _. +//// The type mismatch is not an issue. COM passes types through GUID / void* combos - the original type +//// doesn't come into play unless the user static_casts an implementation type to one of these, but +//// the WinRT implementation types are hidden. +__interface __declspec(uuid("00000000-0000-0000-C000-000000000046")) __abi_IUnknown +{ +public: + virtual long __stdcall __abi_QueryInterface(Guid&, void**) = 0; + virtual unsigned long __stdcall __abi_AddRef() = 0; + virtual unsigned long __stdcall __abi_Release() = 0; +}; +#endif +#include "ppltasks_winrt.h" +#endif +#else +#include #endif struct IMFMediaType; @@ -114,18 +280,23 @@ template void SafeRelease(T **ppT) } } -/// Class for printing info into consol -class DebugPrintOut +#ifdef _DEBUG +/// Class for printing info into console +class DPO { public: - ~DebugPrintOut(void); - static DebugPrintOut& getInstance(); + ~DPO(void); + static DPO& getInstance(); void printOut(const wchar_t *format, ...); void setVerbose(bool state); bool verbose; private: - DebugPrintOut(void); + DPO(void); }; +#define DebugPrintOut(...) DPO::getInstance().printOut(__VA_ARGS__) +#else +#define DebugPrintOut(...) void() +#endif #include "cap_msmf.hpp" @@ -227,7 +398,9 @@ protected: RawImage *ig_RIFirst; RawImage *ig_RISecond; RawImage *ig_RIOut; -}; +private: + ImageGrabberCallback& operator=(const ImageGrabberCallback&); // Declared to fix compilation warning. + }; #ifdef HAVE_WINRT extern const __declspec(selectany) WCHAR RuntimeClass_CV_ImageGrabberWinRT[] = L"cv.ImageGrabberWinRT"; @@ -271,7 +444,7 @@ class ImageGrabber : public ImageGrabberCallback { public: ~ImageGrabber(void); - HRESULT initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat); + HRESULT initImageGrabber(IMFMediaSource *pSource); HRESULT startGrabbing(void); void stopGrabbing(); // IUnknown methods @@ -292,6 +465,8 @@ private: HRESULT AddSourceNode(IMFTopology *pTopology, IMFMediaSource *pSource, IMFPresentationDescriptor *pPD, IMFStreamDescriptor *pSD, IMFTopologyNode **ppNode); HRESULT AddOutputNode(IMFTopology *pTopology, IMFActivate *pActivate, DWORD dwId, IMFTopologyNode **ppNode); + + ImageGrabber& operator=(const ImageGrabber&); // Declared to fix comiplation error. }; /// Class for controlling of thread of the grabbing raw data from video device @@ -373,8 +548,9 @@ public: void waitForDevice() { if (vd_pAction) { - HRESULT hr; - DO_ACTION_SYNCHRONOUSLY(hr, vd_pAction, GET_CURRENT_CONTEXT); +#ifdef HAVE_CONCURRENCY + CREATE_TASK DEFINE_RET_TYPE(void)(vd_pAction).wait(); +#endif vd_pAction = nullptr; } } @@ -385,6 +561,7 @@ public: int getCountFormats(); unsigned int getWidth(); unsigned int getHeight(); + unsigned int getFrameRate() const; MediaType getFormat(unsigned int id); bool setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate = 0); bool setupDevice(unsigned int id); @@ -406,6 +583,7 @@ private: CamParametrs vd_PrevParametrs; unsigned int vd_Width; unsigned int vd_Height; + unsigned int vd_FrameRate; unsigned int vd_CurrentNumber; bool vd_IsSetuped; std::map vd_CaptureFormats; @@ -413,10 +591,12 @@ private: IMFMediaSource *vd_pSource; #ifdef HAVE_WINRT MAKE_WRL_AGILE_REF(_MediaCapture) vd_pMedCap; - IMedCapFailHandler* vd_pMedCapFail; + EventRegistrationToken vd_cookie; ImageGrabberWinRT *vd_pImGr; MAKE_WRL_REF(_AsyncAction) vd_pAction; +#ifdef HAVE_CONCURRENCY Concurrency::critical_section vd_lock; +#endif #endif emergensyStopEventCallback vd_func; void *vd_userData; @@ -428,7 +608,9 @@ private: HRESULT enumerateCaptureFormats(MAKE_WRL_REF(_MediaCapture) pSource); long setDeviceFormat(MAKE_WRL_REF(_MediaCapture) pSource, unsigned long dwFormatIndex, MAKE_WRL_REF(_AsyncAction)* pAction); long resetDevice(MAKE_WRL_REF(_IDeviceInformation) pDevice); - long checkDevice(_DeviceClass devClass, DEFINE_TASK* pTask, MAKE_WRL_REF(_IDeviceInformation)* ppDevice); +#ifdef HAVE_CONCURRENCY + long checkDevice(_DeviceClass devClass, DEFINE_TASK* pTask, MAKE_WRL_REF(_IDeviceInformation)* ppDevice); +#endif #else long resetDevice(IMFActivate *pActivate); long checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice); @@ -445,8 +627,9 @@ public: long initDevices(_DeviceClass devClass); void waitInit() { if (vds_enumTask) { - HRESULT hr; - DO_ACTION_SYNCHRONOUSLY(hr, vds_enumTask, GET_CURRENT_CONTEXT); +#ifdef HAVE_CONCURRENCY + CREATE_TASK DEFINE_RET_TYPE(void)(vds_enumTask).wait(); +#endif vds_enumTask = nullptr; } } @@ -502,6 +685,8 @@ public: unsigned int getWidth(int deviceID); // Getting height of image, which is getting from videodevice with deviceID unsigned int getHeight(int deviceID); + // Getting frame rate, which is getting from videodevice with deviceID + unsigned int getFrameRate(int deviceID) const; // Getting name of videodevice with deviceID wchar_t *getNameVideoDevice(int deviceID); // Getting interface MediaSource for Media Foundation from videodevice with deviceID @@ -516,8 +701,10 @@ public: bool isDeviceMediaSource(int deviceID); // Checking of using Raw Data of pixels from videodevice with deviceID bool isDeviceRawDataSource(int deviceID); +#ifdef _DEBUG // Setting of the state of outprinting info in console static void setVerbose(bool state); +#endif // Initialization of video device with deviceID by media type with id bool setupDevice(int deviceID, unsigned int id = 0); // Initialization of video device with deviceID by wisth w, height h and fps idealFramerate @@ -536,21 +723,22 @@ private: void updateListOfDevices(); }; -DebugPrintOut::DebugPrintOut(void):verbose(true) +#ifdef _DEBUG +DPO::DPO(void):verbose(true) { } -DebugPrintOut::~DebugPrintOut(void) +DPO::~DPO(void) { } -DebugPrintOut& DebugPrintOut::getInstance() +DPO& DPO::getInstance() { - static DebugPrintOut instance; + static DPO instance; return instance; } -void DebugPrintOut::printOut(const wchar_t *format, ...) +void DPO::printOut(const wchar_t *format, ...) { if(verbose) { @@ -558,23 +746,33 @@ void DebugPrintOut::printOut(const wchar_t *format, ...) wchar_t *p = NULL; va_list args; va_start(args, format); - if(wcscmp(format, L"%i")) + if( ::IsDebuggerPresent() ) { - i = va_arg (args, int); + WCHAR szMsg[512]; + ::StringCchVPrintfW(szMsg, sizeof(szMsg)/sizeof(szMsg[0]), format, args); + ::OutputDebugStringW(szMsg); } - if(wcscmp(format, L"%s")) + else { - p = va_arg (args, wchar_t *); + if(wcscmp(format, L"%i")) + { + i = va_arg (args, int); + } + if(wcscmp(format, L"%s")) + { + p = va_arg (args, wchar_t *); + } + wprintf(format, i,p); } - wprintf(format, i,p); va_end (args); } } -void DebugPrintOut::setVerbose(bool state) +void DPO::setVerbose(bool state) { verbose = state; } +#endif LPCWSTR GetGUIDNameConstNew(const GUID& guid); HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz); @@ -650,7 +848,7 @@ HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType hr = GetGUIDNameNew(*var.puuid, &pGuidValName); if (SUCCEEDED(hr)) { - out.MF_MT_AM_FORMAT_TYPE = MF_MT_AM_FORMAT_TYPE; + out.MF_MT_AM_FORMAT_TYPE = *var.puuid; out.pMF_MT_AM_FORMAT_TYPEName = pGuidValName; pGuidValName = NULL; } @@ -660,7 +858,7 @@ HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType hr = GetGUIDNameNew(*var.puuid, &pGuidValName); if (SUCCEEDED(hr)) { - out.MF_MT_MAJOR_TYPE = MF_MT_MAJOR_TYPE; + out.MF_MT_MAJOR_TYPE = *var.puuid; out.pMF_MT_MAJOR_TYPEName = pGuidValName; pGuidValName = NULL; } @@ -670,7 +868,7 @@ HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType hr = GetGUIDNameNew(*var.puuid, &pGuidValName); if (SUCCEEDED(hr)) { - out.MF_MT_SUBTYPE = MF_MT_SUBTYPE; + out.MF_MT_SUBTYPE = *var.puuid; out.pMF_MT_SUBTYPEName = pGuidValName; pGuidValName = NULL; } @@ -963,9 +1161,8 @@ FormatReader::FormatReader(void) MediaType FormatReader::Read(IMFMediaType *pType) { UINT32 count = 0; - HRESULT hr = S_OK; MediaType out; - hr = pType->LockStore(); + HRESULT hr = pType->LockStore(); if (FAILED(hr)) { return out; @@ -1032,9 +1229,8 @@ ImageGrabber::~ImageGrabber(void) SafeRelease(&ig_pSession); SafeRelease(&ig_pTopology); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Destroying instance of the ImageGrabber class\n", ig_DeviceID); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Destroying instance of the ImageGrabber class\n", ig_DeviceID); } #ifdef HAVE_WINRT @@ -1063,9 +1259,7 @@ ImageGrabberWinRT::~ImageGrabberWinRT(void) CloseHandle(ig_hFrameGrabbed); } - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE: Destroying instance of the ImageGrabberWinRT class\n"); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE: Destroying instance of the ImageGrabberWinRT class\n"); } HRESULT ImageGrabberWinRT::initImageGrabber(MAKE_WRL_REF(_MediaCapture) pSource, @@ -1082,7 +1276,7 @@ HRESULT ImageGrabberWinRT::initImageGrabber(MAKE_WRL_REF(_MediaCapture) pSource, if (FAILED(hr)) return hr; GET_WRL_OBJ_FROM_OBJ(_VideoEncodingProperties, pVidProps, pMedEncProps, hr); if (FAILED(hr)) return hr; - ComPtr pType = NULL; + _ComPtr pType = NULL; hr = MediaSink::ConvertPropertiesToMediaType(DEREF_AS_NATIVE_WRL_OBJ(ABI::Windows::Media::MediaProperties::IMediaEncodingProperties, pMedEncProps), &pType); if (FAILED(hr)) return hr; MediaType MT = FormatReader::Read(pType.Get()); @@ -1113,13 +1307,17 @@ HRESULT ImageGrabberWinRT::stopGrabbing(MAKE_WRL_REF(_AsyncAction)* action) MAKE_WRL_REF(_AsyncAction) pAction; WRL_METHOD_BASE(imedPrevCap, StopPreviewAsync, pAction, hr) if (SUCCEEDED(hr)) { - SAVE_CURRENT_CONTEXT(context); - *action = reinterpret_cast(BEGIN_CREATE_ASYNC(pAction, context, this) - HRESULT hr; - DO_ACTION_SYNCHRONOUSLY(hr, pAction, context); +#ifdef HAVE_CONCURRENCY + DEFINE_TASK _task = CREATE_TASK DEFINE_RET_TYPE(void)(pAction); + *action = reinterpret_cast(BEGIN_CREATE_ASYNC(void, _task, this) + HRESULT hr = S_OK; + _task.wait(); SafeRelease(&ig_pMediaSink); SetEvent(ig_hFinish); END_CREATE_ASYNC(hr)); +#else + *action = nullptr; +#endif } } return hr; @@ -1180,21 +1378,19 @@ HRESULT ImageGrabberWinRT::CreateInstance(ImageGrabberWinRT **ppIG, bool synchro { return E_OUTOFMEMORY; } - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE: Creating instance of ImageGrabberWinRT\n"); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE: Creating instance of ImageGrabberWinRT\n"); return S_OK; } #endif -HRESULT ImageGrabber::initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat) +HRESULT ImageGrabber::initImageGrabber(IMFMediaSource *pSource) { - ComPtr pSinkActivate = NULL; - ComPtr pType = NULL; - ComPtr pPD = NULL; - ComPtr pSD = NULL; - ComPtr pHandler = NULL; - ComPtr pCurrentType = NULL; - HRESULT hr = S_OK; + _ComPtr pSinkActivate = NULL; + _ComPtr pType = NULL; + _ComPtr pPD = NULL; + _ComPtr pSD = NULL; + _ComPtr pHandler = NULL; + _ComPtr pCurrentType = NULL; MediaType MT; // Clean up. if (ig_pSession) @@ -1204,7 +1400,7 @@ HRESULT ImageGrabber::initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat SafeRelease(&ig_pSession); SafeRelease(&ig_pTopology); ig_pSource = pSource; - hr = pSource->CreatePresentationDescriptor(&pPD); + HRESULT hr = pSource->CreatePresentationDescriptor(&pPD); if (FAILED(hr)) { goto err; @@ -1232,25 +1428,16 @@ HRESULT ImageGrabber::initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat MT = FormatReader::Read(pCurrentType.Get()); } err: - unsigned int sizeRawImage = 0; - if(VideoFormat == MFVideoFormat_RGB24) - { - sizeRawImage = MT.MF_MT_FRAME_SIZE * 3; - } - else if(VideoFormat == MFVideoFormat_RGB32) - { - sizeRawImage = MT.MF_MT_FRAME_SIZE * 4; - } - //sizeRawImage = MT.MF_MT_SAMPLE_SIZE; - CHECK_HR(hr = RawImage::CreateInstance(&ig_RIFirst, sizeRawImage)); - CHECK_HR(hr = RawImage::CreateInstance(&ig_RISecond, sizeRawImage)); + CHECK_HR(hr); + CHECK_HR(hr = RawImage::CreateInstance(&ig_RIFirst, MT.MF_MT_SAMPLE_SIZE)); + CHECK_HR(hr = RawImage::CreateInstance(&ig_RISecond, MT.MF_MT_SAMPLE_SIZE)); ig_RIOut = ig_RISecond; // Configure the media type that the Sample Grabber will receive. // Setting the major and subtype is usually enough for the topology loader // to resolve the topology. CHECK_HR(hr = MFCreateMediaType(pType.GetAddressOf())); - CHECK_HR(hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); - CHECK_HR(hr = pType->SetGUID(MF_MT_SUBTYPE, VideoFormat)); + CHECK_HR(hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MT.MF_MT_MAJOR_TYPE)); + CHECK_HR(hr = pType->SetGUID(MF_MT_SUBTYPE, MT.MF_MT_SUBTYPE)); // Create the sample grabber sink. CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(pType.Get(), this, pSinkActivate.GetAddressOf())); // To run as fast as possible, set this attribute (requires Windows 7): @@ -1277,19 +1464,16 @@ void ImageGrabber::stopGrabbing() { if(ig_pSession) ig_pSession->Stop(); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Stopping of of grabbing of images\n", ig_DeviceID); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Stopping of of grabbing of images\n", ig_DeviceID); } HRESULT ImageGrabber::startGrabbing(void) { - HRESULT hr = S_OK; - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - ComPtr pEvent = NULL; + _ComPtr pEvent = NULL; PROPVARIANT var; PropVariantInit(&var); - hr = ig_pSession->SetTopology(0, ig_pTopology); - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Start Grabbing of the images\n", ig_DeviceID); + HRESULT hr = ig_pSession->SetTopology(0, ig_pTopology); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Start Grabbing of the images\n", ig_DeviceID); hr = ig_pSession->Start(&GUID_NULL, &var); for(;;) { @@ -1316,28 +1500,28 @@ HRESULT ImageGrabber::startGrabbing(void) } if (met == MESessionEnded) { - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionEnded \n", ig_DeviceID); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionEnded\n", ig_DeviceID); ig_pSession->Stop(); break; } if (met == MESessionStopped) { - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionStopped \n", ig_DeviceID); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionStopped \n", ig_DeviceID); break; } if (met == MEVideoCaptureDeviceRemoved) { - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MEVideoCaptureDeviceRemoved \n", ig_DeviceID); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MEVideoCaptureDeviceRemoved \n", ig_DeviceID); break; } if ((met == MEError) || (met == MENonFatalError)) { pEvent->GetStatus(&hrStatus); - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MEError | MENonFatalError: %u\n", ig_DeviceID, hrStatus); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MEError | MENonFatalError: %u\n", ig_DeviceID, hrStatus); break; } } - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Finish startGrabbing \n", ig_DeviceID); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Finish startGrabbing \n", ig_DeviceID); done: SetEvent(ig_hFinish); @@ -1356,11 +1540,11 @@ void ImageGrabberCallback::resumeGrabbing() HRESULT ImageGrabber::CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo) { IMFTopology* pTopology = NULL; - ComPtr pPD = NULL; - ComPtr pSD = NULL; - ComPtr pHandler = NULL; - ComPtr pNode1 = NULL; - ComPtr pNode2 = NULL; + _ComPtr pPD = NULL; + _ComPtr pSD = NULL; + _ComPtr pHandler = NULL; + _ComPtr pNode1 = NULL; + _ComPtr pNode2 = NULL; HRESULT hr = S_OK; DWORD cStreams = 0; CHECK_HR(hr = MFCreateTopology(&pTopology)); @@ -1400,7 +1584,7 @@ HRESULT ImageGrabber::AddSourceNode( IMFStreamDescriptor *pSD, // Stream descriptor. IMFTopologyNode **ppNode) // Receives the node pointer. { - ComPtr pNode = NULL; + _ComPtr pNode = NULL; HRESULT hr = S_OK; CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, pNode.GetAddressOf())); CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource)); @@ -1421,7 +1605,7 @@ HRESULT ImageGrabber::AddOutputNode( DWORD dwId, // Identifier of the stream sink. IMFTopologyNode **ppNode) // Receives the node pointer. { - ComPtr pNode = NULL; + _ComPtr pNode = NULL; HRESULT hr = S_OK; CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, pNode.GetAddressOf())); CHECK_HR(hr = pNode->SetObject(pActivate)); @@ -1443,8 +1627,7 @@ HRESULT ImageGrabber::CreateInstance(ImageGrabber **ppIG, unsigned int deviceID, { return E_OUTOFMEMORY; } - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Creating instance of ImageGrabber\n", deviceID); + DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Creating instance of ImageGrabber\n", deviceID); return S_OK; } @@ -1537,7 +1720,7 @@ STDMETHODIMP ImageGrabberCallback::OnProcessSample(REFGUID guidMajorMediaType, D DWORD status = WaitForMultipleObjects(2, tmp, FALSE, INFINITE); if (status == WAIT_OBJECT_0) { - printf("OnProcessFrame called after ig_hFinish event\n"); + DebugPrintOut(L"OnProcessFrame called after ig_hFinish event\n"); return S_OK; } @@ -1584,15 +1767,14 @@ DWORD WINAPI MainThreadFunction( LPVOID lpParam ) HRESULT ImageGrabberThread::CreateInstance(ImageGrabberThread **ppIGT, IMFMediaSource *pSource, unsigned int deviceID, bool synchronious) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); *ppIGT = new (std::nothrow) ImageGrabberThread(pSource, deviceID, synchronious); if (ppIGT == NULL) { - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Memory cannot be allocated\n", deviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Memory cannot be allocated\n", deviceID); return E_OUTOFMEMORY; } else - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Creating of the instance of ImageGrabberThread\n", deviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Creating of the instance of ImageGrabberThread\n", deviceID); return S_OK; } @@ -1601,24 +1783,23 @@ ImageGrabberThread::ImageGrabberThread(IMFMediaSource *pSource, unsigned int dev igt_Handle(NULL), igt_stop(false) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); HRESULT hr = ImageGrabber::CreateInstance(&igt_pImageGrabber, deviceID, synchronious); igt_DeviceID = deviceID; if(SUCCEEDED(hr)) { - hr = igt_pImageGrabber->initImageGrabber(pSource, MFVideoFormat_RGB24); + hr = igt_pImageGrabber->initImageGrabber(pSource); if(!SUCCEEDED(hr)) { - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with initialization of the instance of the ImageGrabber class\n", deviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with initialization of the instance of the ImageGrabber class\n", deviceID); } else { - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Initialization of instance of the ImageGrabber class\n", deviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Initialization of instance of the ImageGrabber class\n", deviceID); } } else { - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with creation of the instance of the ImageGrabber class\n", deviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with creation of the instance of the ImageGrabber class\n", deviceID); } } @@ -1633,8 +1814,7 @@ void ImageGrabberThread::setEmergencyStopEvent(void *userData, void(*func)(int, ImageGrabberThread::~ImageGrabberThread(void) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Destroing ImageGrabberThread\n", igt_DeviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Destroing ImageGrabberThread\n", igt_DeviceID); if (igt_Handle) WaitForSingleObject(igt_Handle, INFINITE); delete igt_pImageGrabber; @@ -1662,30 +1842,29 @@ void ImageGrabberThread::start() void ImageGrabberThread::run() { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if(igt_pImageGrabber) { - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Thread for grabbing images is started\n", igt_DeviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Thread for grabbing images is started\n", igt_DeviceID); HRESULT hr = igt_pImageGrabber->startGrabbing(); if(!SUCCEEDED(hr)) { - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with starting the process of grabbing\n", igt_DeviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with starting the process of grabbing\n", igt_DeviceID); } } else { - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i The thread is finished without execution of grabbing\n", igt_DeviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i The thread is finished without execution of grabbing\n", igt_DeviceID); } if(!igt_stop) { - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Emergency Stop thread\n", igt_DeviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Emergency Stop thread\n", igt_DeviceID); if(igt_func) { igt_func(igt_DeviceID, igt_userData); } } else - DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Finish thread\n", igt_DeviceID); + DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Finish thread\n", igt_DeviceID); } ImageGrabber *ImageGrabberThread::getImageGrabber() @@ -1698,8 +1877,7 @@ Media_Foundation::Media_Foundation(void) HRESULT hr = MFStartup(MF_VERSION); if(!SUCCEEDED(hr)) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MEDIA FOUNDATION: It cannot be created!!!\n"); + DebugPrintOut(L"MEDIA FOUNDATION: It cannot be created!!!\n"); } } @@ -1708,8 +1886,7 @@ Media_Foundation::~Media_Foundation(void) HRESULT hr = MFShutdown(); if(!SUCCEEDED(hr)) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MEDIA FOUNDATION: Resources cannot be released\n"); + DebugPrintOut(L"MEDIA FOUNDATION: Resources cannot be released\n"); } } @@ -1720,7 +1897,7 @@ bool Media_Foundation::buildListOfDevices() videoDevices *vDs = &videoDevices::getInstance(); hr = vDs->initDevices(WRL_ENUM_GET(_DeviceClass, DeviceClass, VideoCapture)); #else - ComPtr pAttributes = NULL; + _ComPtr pAttributes = NULL; CoInitialize(NULL); hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1); if (SUCCEEDED(hr)) @@ -1738,8 +1915,7 @@ bool Media_Foundation::buildListOfDevices() #endif if (FAILED(hr)) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MEDIA FOUNDATION: The access to the video cameras denied\n"); + DebugPrintOut(L"MEDIA FOUNDATION: The access to the video cameras denied\n"); } return (SUCCEEDED(hr)); @@ -1803,11 +1979,11 @@ unsigned char * RawImage::getpPixels() } videoDevice::videoDevice(void): vd_IsSetuped(false), vd_LockOut(OpenLock), vd_pFriendlyName(NULL), - vd_Width(0), vd_Height(0), vd_pSource(NULL), vd_pImGrTh(NULL), vd_func(NULL), vd_userData(NULL) + vd_Width(0), vd_Height(0), vd_FrameRate(0), vd_pSource(NULL), vd_pImGrTh(NULL), vd_func(NULL), vd_userData(NULL) { #ifdef HAVE_WINRT vd_pMedCap = nullptr; - vd_pMedCapFail = NULL; + vd_cookie.value = 0; vd_pImGr = NULL; vd_pAction = nullptr; #endif @@ -1899,7 +2075,7 @@ long videoDevice::resetDevice(MAKE_WRL_REF(_IDeviceInformation) pDevice) long videoDevice::resetDevice(IMFActivate *pActivate) #endif { - HRESULT hr = -1; + HRESULT hr = E_FAIL; vd_CurrentFormats.clear(); if(vd_pFriendlyName) CoTaskMemFree(vd_pFriendlyName); @@ -1926,25 +2102,28 @@ long videoDevice::resetDevice(IMFActivate *pActivate) if (FAILED(hr)) return hr; MAKE_WRL_REF(_AsyncAction) pAction; WRL_METHOD(DEREF_WRL_OBJ(pIMedCap), _InitializeWithSettingsAsync, pAction, hr, DEREF_WRL_OBJ(pCapInitSet)) +#ifdef HAVE_CONCURRENCY + DEFINE_TASK _task = CREATE_TASK DEFINE_RET_TYPE(void)(pAction); if (FAILED(hr)) return hr; MAKE_WRL_AGILE_REF(_MediaCapture) pAgileMedCap; pAgileMedCap = PREPARE_TRANSFER_WRL_OBJ(pIMedCap); Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; SAVE_CURRENT_CONTEXT(context); - vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(pAction, pOldAction, context, &pAgileMedCap, this) - HRESULT hr; - if (pOldAction) DO_ACTION_SYNCHRONOUSLY(hr, pOldAction, GET_CURRENT_CONTEXT); - DO_ACTION_SYNCHRONOUSLY(hr, pAction, context); + vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(void, _task, pOldAction, context, &pAgileMedCap, this) + HRESULT hr = S_OK; + if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); + _task.wait(); if (SUCCEEDED(hr)) { //all camera capture calls only in original context BEGIN_CALL_IN_CONTEXT(hr, context, pAgileMedCap, this) enumerateCaptureFormats(DEREF_AGILE_WRL_OBJ(pAgileMedCap)); - END_CALL_IN_CONTEXT(S_OK) + END_CALL_IN_CONTEXT_BASE } buildLibraryofTypes(); RELEASE_AGILE_WRL(pAgileMedCap) END_CREATE_ASYNC(hr)); +#endif } #else if(pActivate) @@ -1965,8 +2144,7 @@ long videoDevice::resetDevice(IMFActivate *pActivate) if(FAILED(hr)) { vd_pFriendlyName = NULL; - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"VIDEODEVICE %i: IMFMediaSource interface cannot be created \n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: IMFMediaSource interface cannot be created \n", vd_CurrentNumber); } } #endif @@ -1984,15 +2162,14 @@ long videoDevice::readInfoOfDevice(MAKE_WRL_REF(_IDeviceInformation) pDevice, un #else long videoDevice::readInfoOfDevice(IMFActivate *pActivate, unsigned int Num) { - HRESULT hr = -1; vd_CurrentNumber = Num; - hr = resetDevice(pActivate); - return hr; + return resetDevice(pActivate); } #endif #ifdef HAVE_WINRT -long videoDevice::checkDevice(_DeviceClass devClass, DEFINE_TASK* pTask, MAKE_WRL_REF(_IDeviceInformation)* ppDevice) +#ifdef HAVE_CONCURRENCY +long videoDevice::checkDevice(_DeviceClass devClass, DEFINE_TASK* pTask, MAKE_WRL_REF(_IDeviceInformation)* ppDevice) { HRESULT hr = S_OK; ACTIVATE_STATIC_OBJ(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation, MAKE_WRL_OBJ(_DeviceInformationStatics), pDevStat, hr) @@ -2000,10 +2177,10 @@ long videoDevice::checkDevice(_DeviceClass devClass, DEFINE_TASK* pTask MAKE_WRL_REF(_AsyncOperation) pAction; WRL_METHOD(pDevStat, _FindAllAsyncDeviceClass, pAction, hr, devClass) if (SUCCEEDED(hr)) { - *pTask = CREATE_TASK([pAction, &ppDevice, this]() -> HRESULT { - HRESULT hr; - MAKE_WRL_OBJ(_VectorView) pVector; - DO_OPERATION_SYNCHRONOUSLY_VECTOR(hr, pAction, GET_CURRENT_CONTEXT, pVector, _VectorView, _DeviceInformation, _DeviceInformationCollection); + *pTask = CREATE_TASK DEFINE_RET_TYPE(void)([pAction, &ppDevice, this]() -> DEFINE_RET_FORMAL(void) { + HRESULT hr = S_OK; + MAKE_WRL_OBJ(_VectorView) pVector = + CREATE_TASK DEFINE_RET_TYPE(MAKE_WRL_REF(_VectorView))(pAction).get(); UINT32 count = 0; if (SUCCEEDED(hr)) WRL_PROP_GET(pVector, Size, count, hr) if (SUCCEEDED(hr) && count > 0) { @@ -2021,20 +2198,19 @@ long videoDevice::checkDevice(_DeviceClass devClass, DEFINE_TASK* pTask } } } - return hr; + RET_VAL_BASE; }); } return hr; } +#endif #else long videoDevice::checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice) { - HRESULT hr = S_OK; IMFActivate **ppDevices = NULL; - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); UINT32 count; wchar_t *newFriendlyName = NULL; - hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count); + HRESULT hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count); if (SUCCEEDED(hr)) { if(count > 0) @@ -2050,8 +2226,8 @@ long videoDevice::checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice) { if(wcscmp(newFriendlyName, vd_pFriendlyName) != 0) { - DPO->printOut(L"VIDEODEVICE %i: Chosen device cannot be found \n", vd_CurrentNumber); - hr = -1; + DebugPrintOut(L"VIDEODEVICE %i: Chosen device cannot be found \n", vd_CurrentNumber); + hr = E_INVALIDARG; pDevice = NULL; } else @@ -2062,13 +2238,13 @@ long videoDevice::checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice) } else { - DPO->printOut(L"VIDEODEVICE %i: Name of device cannot be gotten \n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: Name of device cannot be gotten \n", vd_CurrentNumber); } } else { - DPO->printOut(L"VIDEODEVICE %i: Number of devices more than corrent number of the device \n", vd_CurrentNumber); - hr = -1; + DebugPrintOut(L"VIDEODEVICE %i: Number of devices more than corrent number of the device \n", vd_CurrentNumber); + hr = E_INVALIDARG; } for(UINT32 i = 0; i < count; i++) { @@ -2077,11 +2253,11 @@ long videoDevice::checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice) SafeRelease(ppDevices); } else - hr = -1; + hr = E_FAIL; } else { - DPO->printOut(L"VIDEODEVICE %i: List of DeviceSources cannot be enumerated \n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: List of DeviceSources cannot be enumerated \n", vd_CurrentNumber); } return hr; } @@ -2092,19 +2268,20 @@ long videoDevice::initDevice() HRESULT hr = S_OK; CoInitialize(NULL); #ifdef HAVE_WINRT +#ifdef HAVE_CONCURRENCY Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; SAVE_CURRENT_CONTEXT(context); - vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(pOldAction, context, this) + vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(void, pOldAction, context, this) HRESULT hr; - if (pOldAction) DO_ACTION_SYNCHRONOUSLY(hr, pOldAction, GET_CURRENT_CONTEXT); - DEFINE_TASK pTask; + if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); + DEFINE_TASK pTask; MAKE_WRL_OBJ(_IDeviceInformation) pDevInfo; hr = checkDevice(WRL_ENUM_GET(_DeviceClass, DeviceClass, VideoCapture), &pTask, REF_WRL_OBJ(pDevInfo)); - if (SUCCEEDED(hr)) hr = pTask.get(); + if (SUCCEEDED(hr)) pTask.wait(); if (SUCCEEDED(hr)) { - MAKE_WRL_REF(_AsyncAction) pAction; - BEGIN_CALL_IN_CONTEXT(hr, context, pDevInfo, &pAction, context, this) + DEFINE_TASK _task; + BEGIN_CALL_IN_CONTEXT(hr, context, pDevInfo, &_task, context, this) HRESULT hr; ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCapture, _MediaCapture, pIMedCap, hr) if (SUCCEEDED(hr)) { @@ -2120,24 +2297,24 @@ long videoDevice::initDevice() } if (SUCCEEDED(hr)) WRL_PROP_PUT(pCapInitSet, StreamingCaptureMode, WRL_ENUM_GET(_StreamingCaptureMode, StreamingCaptureMode, Video), hr) - if (SUCCEEDED(hr)) { - vd_pMedCapFail = create_medcapfailedhandler([this, context](){ + if (SUCCEEDED(hr)) reinterpret_cast(DEREF_AGILE_WRL_OBJ(vd_pMedCap))->add_Failed(Microsoft::WRL::Callback([this, context](ABI::Windows::Media::Capture::IMediaCapture*, ABI::Windows::Media::Capture::IMediaCaptureFailedEventArgs*) -> HRESULT { HRESULT hr; BEGIN_CALL_IN_CONTEXT(hr, context, this) closeDevice(); - END_CALL_IN_CONTEXT(S_OK) - }); - } - if (SUCCEEDED(hr)) hr = vd_pMedCapFail->AddHandler(reinterpret_cast(DEREF_AGILE_WRL_OBJ(vd_pMedCap))); - if (SUCCEEDED(hr)) WRL_METHOD(vd_pMedCap, _InitializeWithSettingsAsync, pAction, hr, DEREF_WRL_OBJ(pCapInitSet)) + END_CALL_IN_CONTEXT_BASE + return hr; + }).Get(), &vd_cookie); + MAKE_WRL_OBJ(_AsyncAction) pAction; + if (SUCCEEDED(hr)) WRL_METHOD(vd_pMedCap, _InitializeWithSettingsAsync, *REF_WRL_OBJ(pAction), hr, DEREF_WRL_OBJ(pCapInitSet)) + if (SUCCEEDED(hr)) _task = CREATE_TASK DEFINE_RET_TYPE(void)(DEREF_WRL_OBJ(pAction)); } END_CALL_IN_CONTEXT(hr) - DO_ACTION_SYNCHRONOUSLY(hr, pAction, context); + _task.wait(); } END_CREATE_ASYNC(hr)); +#endif #else - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - ComPtr pAttributes = NULL; + _ComPtr pAttributes = NULL; IMFActivate *vd_pActivate = NULL; hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1); if (SUCCEEDED(hr)) @@ -2164,12 +2341,12 @@ long videoDevice::initDevice() } else { - DPO->printOut(L"VIDEODEVICE %i: Device there is not \n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: Device there is not \n", vd_CurrentNumber); } } else { - DPO->printOut(L"VIDEODEVICE %i: The attribute of video cameras cannot be getting \n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: The attribute of video cameras cannot be getting \n", vd_CurrentNumber); } #endif return hr; @@ -2199,17 +2376,18 @@ void videoDevice::closeDevice() vd_IsSetuped = false; #ifdef HAVE_WINRT +#ifdef HAVE_CONCURRENCY if (DEREF_AGILE_WRL_OBJ(vd_pMedCap)) { MAKE_WRL_REF(_AsyncAction) action; Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; vd_pImGr->stopGrabbing(&action); - vd_pMedCapFail->RemoveHandler(reinterpret_cast(DEREF_AGILE_WRL_OBJ(vd_pMedCap))); - SafeRelease(&vd_pMedCapFail); - vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(action, pOldAction, this) - HRESULT hr; - if (pOldAction) DO_ACTION_SYNCHRONOUSLY(hr, pOldAction, GET_CURRENT_CONTEXT); - DO_ACTION_SYNCHRONOUSLY(hr, action, GET_CURRENT_CONTEXT); + reinterpret_cast(DEREF_AGILE_WRL_OBJ(vd_pMedCap))->remove_Failed(vd_cookie); + vd_cookie.value = 0; + vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(void, action, pOldAction, this) + HRESULT hr = S_OK; + if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); + CREATE_TASK DEFINE_RET_TYPE(void)(action).wait(); RELEASE_WRL(vd_pMedCap) if(vd_LockOut == RawDataLock) { delete vd_pImGr; @@ -2219,9 +2397,10 @@ void videoDevice::closeDevice() END_CREATE_ASYNC(hr)); return; } +#endif #endif - vd_pSource->Stop(); + vd_pSource->Shutdown(); SafeRelease(&vd_pSource); if(vd_LockOut == RawDataLock) { @@ -2231,8 +2410,7 @@ void videoDevice::closeDevice() } vd_pImGrTh = NULL; vd_LockOut = OpenLock; - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"VIDEODEVICE %i: Device is stopped \n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: Device is stopped \n", vd_CurrentNumber); } } unsigned int videoDevice::getWidth() @@ -2249,6 +2427,15 @@ unsigned int videoDevice::getHeight() else return 0; } + +unsigned int videoDevice::getFrameRate() const +{ + if(vd_IsSetuped) + return vd_FrameRate; + else + return 0; +} + IMFMediaSource *videoDevice::getMediaSource() { IMFMediaSource *out = NULL; @@ -2261,17 +2448,26 @@ IMFMediaSource *videoDevice::getMediaSource() } int videoDevice::findType(unsigned int size, unsigned int frameRate) { - if(vd_CaptureFormats.size() == 0) - return 0; - FrameRateMap FRM = vd_CaptureFormats[size]; - if(FRM.size() == 0) - return 0; + // For required frame size look for the suitable video format. + // If not found, get the format for the largest available frame size. + FrameRateMap FRM; + std::map::const_iterator fmt; + fmt = vd_CaptureFormats.find(size); + if( fmt != vd_CaptureFormats.end() ) + FRM = fmt->second; + else + FRM = vd_CaptureFormats.rbegin()->second; + + if( FRM.empty() ) + return -1; + UINT64 frameRateMax = 0; SUBTYPEMap STMMax; if(frameRate == 0) { std::map::iterator f = FRM.begin(); for(; f != FRM.end(); f++) { + // Looking for highest possible frame rate. if((*f).first >= frameRateMax) { frameRateMax = (*f).first; @@ -2284,22 +2480,26 @@ int videoDevice::findType(unsigned int size, unsigned int frameRate) std::map::iterator f = FRM.begin(); for(; f != FRM.end(); f++) { - if((*f).first >= frameRateMax) - { - if(frameRate > (*f).first) - { - frameRateMax = (*f).first; - STMMax = (*f).second; - } - } + // Looking for frame rate higher that recently found but not higher then demanded. + if( (*f).first >= frameRateMax && (*f).first <= frameRate ) + { + frameRateMax = (*f).first; + STMMax = (*f).second; + } } } - if(STMMax.size() == 0) - return 0; - std::map::iterator S = STMMax.begin(); - vectorNum VN = (*S).second; - if(VN.size() == 0) - return 0; + // Get first (default) item from the list if no suitable frame rate found. + if( STMMax.empty() ) + STMMax = FRM.begin()->second; + + // Check if there are any format types on the list. + if( STMMax.empty() ) + return -1; + + vectorNum VN = STMMax.begin()->second; + if( VN.empty() ) + return -1; + return VN[0]; } @@ -2311,16 +2511,20 @@ void videoDevice::buildLibraryofTypes() int count = 0; for(; i != vd_CurrentFormats.end(); i++) { - size = (*i).MF_MT_FRAME_SIZE; - framerate = (*i).MF_MT_FRAME_RATE_NUMERATOR; - FrameRateMap FRM = vd_CaptureFormats[size]; - SUBTYPEMap STM = FRM[framerate]; - String subType((*i).pMF_MT_SUBTYPEName); - vectorNum VN = STM[subType]; - VN.push_back(count); - STM[subType] = VN; - FRM[framerate] = STM; - vd_CaptureFormats[size] = FRM; + // Count only supported video formats. + if( (*i).MF_MT_SUBTYPE == MFVideoFormat_RGB24 ) + { + size = (*i).MF_MT_FRAME_SIZE; + framerate = (*i).MF_MT_FRAME_RATE_NUMERATOR / (*i).MF_MT_FRAME_RATE_DENOMINATOR; + FrameRateMap FRM = vd_CaptureFormats[size]; + SUBTYPEMap STM = FRM[framerate]; + String subType((*i).pMF_MT_SUBTYPEName); + vectorNum VN = STM[subType]; + VN.push_back(count); + STM[subType] = VN; + FRM[framerate] = STM; + vd_CaptureFormats[size] = FRM; + } count++; } } @@ -2347,10 +2551,10 @@ long videoDevice::setDeviceFormat(MAKE_WRL_REF(_MediaCapture) pSource, unsigned long videoDevice::setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex) { - ComPtr pPD = NULL; - ComPtr pSD = NULL; - ComPtr pHandler = NULL; - ComPtr pType = NULL; + _ComPtr pPD = NULL; + _ComPtr pSD = NULL; + _ComPtr pHandler = NULL; + _ComPtr pType = NULL; HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf()); if (FAILED(hr)) { @@ -2393,8 +2597,7 @@ RawImage * videoDevice::getRawImageOut() return vd_pImGrTh->getImageGrabber()->getRawImage(); else { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class does not exist \n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class does not exist \n", vd_CurrentNumber); } return NULL; } @@ -2417,22 +2620,23 @@ bool videoDevice::isFrameNew() delete vd_pImGr; return false; } +#ifdef HAVE_CONCURRENCY Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; - SAVE_CURRENT_CONTEXT(context); - vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(action, pOldAction, context, this) - HRESULT hr; - if (pOldAction) DO_ACTION_SYNCHRONOUSLY(hr, pOldAction, GET_CURRENT_CONTEXT); - DO_ACTION_SYNCHRONOUSLY(hr, action, context); + DEFINE_TASK _task = CREATE_TASK DEFINE_RET_TYPE(void)(action); + vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(void, _task, pOldAction, this) + HRESULT hr = S_OK; + if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); + _task.wait(); END_CREATE_ASYNC(hr)); +#endif return true; } #endif HRESULT hr = ImageGrabberThread::CreateInstance(&vd_pImGrTh, vd_pSource, vd_CurrentNumber); if(FAILED(hr)) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class cannot be created.\n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class cannot be created.\n", vd_CurrentNumber); return false; } vd_pImGrTh->setEmergencyStopEvent(vd_userData, vd_func); @@ -2463,38 +2667,47 @@ bool videoDevice::isDeviceRawDataSource() bool videoDevice::setupDevice(unsigned int id) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if(!vd_IsSetuped) { - HRESULT hr = -1; - hr = initDevice(); + HRESULT hr = initDevice(); if(SUCCEEDED(hr)) { #ifdef HAVE_WINRT +#ifdef HAVE_CONCURRENCY Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; SAVE_CURRENT_CONTEXT(context); - vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(pOldAction, context, id, DPO, this) + vd_pAction = reinterpret_cast(BEGIN_CREATE_ASYNC(void, pOldAction, context, id, this) HRESULT hr; - if (pOldAction) DO_ACTION_SYNCHRONOUSLY(hr, pOldAction, GET_CURRENT_CONTEXT); + if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); +#endif #endif vd_Width = vd_CurrentFormats[id].width; vd_Height = vd_CurrentFormats[id].height; + vd_FrameRate = vd_CurrentFormats[id].MF_MT_FRAME_RATE_NUMERATOR / + vd_CurrentFormats[id].MF_MT_FRAME_RATE_DENOMINATOR; #ifdef HAVE_WINRT +#ifdef HAVE_CONCURRENCY if (DEREF_AGILE_WRL_OBJ(vd_pMedCap)) { - MAKE_WRL_REF(_AsyncAction) pAction; - BEGIN_CALL_IN_CONTEXT(hr, context, id, &pAction, this) - END_CALL_IN_CONTEXT(setDeviceFormat(DEREF_AGILE_WRL_OBJ(vd_pMedCap), (DWORD) id, &pAction)) - if (SUCCEEDED(hr)) DO_ACTION_SYNCHRONOUSLY(hr, pAction, context); + DEFINE_TASK _task; + BEGIN_CALL_IN_CONTEXT(hr, context, id, &_task, this) + MAKE_WRL_REF(_AsyncAction) pAction; + HRESULT hr = setDeviceFormat(DEREF_AGILE_WRL_OBJ(vd_pMedCap), (DWORD) id, &pAction); + if (SUCCEEDED(hr)) _task = CREATE_TASK DEFINE_RET_TYPE(void)(pAction); + END_CALL_IN_CONTEXT(hr) + if (SUCCEEDED(hr)) _task.wait(); } else +#endif #endif hr = setDeviceFormat(vd_pSource, (DWORD) id); vd_IsSetuped = (SUCCEEDED(hr)); if(vd_IsSetuped) - DPO->printOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber); + DebugPrintOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber); vd_PrevParametrs = getParametrs(); #ifdef HAVE_WINRT +#ifdef HAVE_CONCURRENCY END_CREATE_ASYNC(hr)); +#endif return true; #else return vd_IsSetuped; @@ -2502,13 +2715,13 @@ bool videoDevice::setupDevice(unsigned int id) } else { - DPO->printOut(L"VIDEODEVICE %i: Interface IMFMediaSource cannot be got \n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: Interface IMFMediaSource cannot be got \n", vd_CurrentNumber); return false; } } else { - DPO->printOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber); + DebugPrintOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber); return false; } } @@ -2516,6 +2729,9 @@ bool videoDevice::setupDevice(unsigned int id) bool videoDevice::setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate) { unsigned int id = findType(w * h, idealFramerate); + if( id < 0 ) + return false; + return setupDevice(id); } @@ -2554,7 +2770,7 @@ HRESULT videoDevice::enumerateCaptureFormats(MAKE_WRL_REF(_MediaCapture) pSource MAKE_WRL_OBJ(_MediaEncodingProperties) pMedEncProps; WRL_METHOD(pVector, GetAt, pMedEncProps, hr, i) if (FAILED(hr)) return hr; - ComPtr pType = NULL; + _ComPtr pType = NULL; hr = MediaSink::ConvertPropertiesToMediaType(DEREF_AS_NATIVE_WRL_OBJ(ABI::Windows::Media::MediaProperties::IMediaEncodingProperties, pMedEncProps), &pType); if (FAILED(hr)) return hr; MediaType MT = FormatReader::Read(pType.Get()); @@ -2566,10 +2782,10 @@ HRESULT videoDevice::enumerateCaptureFormats(MAKE_WRL_REF(_MediaCapture) pSource HRESULT videoDevice::enumerateCaptureFormats(IMFMediaSource *pSource) { - ComPtr pPD = NULL; - ComPtr pSD = NULL; - ComPtr pHandler = NULL; - ComPtr pType = NULL; + _ComPtr pPD = NULL; + _ComPtr pSD = NULL; + _ComPtr pHandler = NULL; + _ComPtr pType = NULL; HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf()); if (FAILED(hr)) { @@ -2649,11 +2865,12 @@ long videoDevices::initDevices(_DeviceClass devClass) MAKE_WRL_REF(_AsyncOperation) pAction; WRL_METHOD(pDevStat, _FindAllAsyncDeviceClass, pAction, hr, devClass) if (SUCCEEDED(hr)) { +#ifdef HAVE_CONCURRENCY SAVE_CURRENT_CONTEXT(context); - vds_enumTask = reinterpret_cast(BEGIN_CREATE_ASYNC(pAction, context, this) - HRESULT hr; - MAKE_WRL_OBJ(_VectorView) pVector; - DO_OPERATION_SYNCHRONOUSLY_VECTOR(hr, pAction, GET_CURRENT_CONTEXT, pVector, _VectorView, _DeviceInformation, _DeviceInformationCollection); + vds_enumTask = reinterpret_cast(BEGIN_CREATE_ASYNC(void, pAction, context, this) + HRESULT hr = S_OK; + MAKE_WRL_OBJ(_VectorView) pVector = + CREATE_TASK DEFINE_RET_TYPE(MAKE_WRL_REF(_VectorView))(pAction).get(); if (SUCCEEDED(hr)) WRL_PROP_GET(pVector, Size, count, hr) if (SUCCEEDED(hr) && count > 0) { for (UINT32 i = 0; i < count; i++) { @@ -2663,22 +2880,22 @@ long videoDevices::initDevices(_DeviceClass devClass) if (SUCCEEDED(hr)) { BEGIN_CALL_IN_CONTEXT(hr, context, vd, pDevice, i) vd->readInfoOfDevice(DEREF_WRL_OBJ(pDevice), i); - END_CALL_IN_CONTEXT(S_OK) + END_CALL_IN_CONTEXT_BASE vds_Devices.push_back(vd); } } } END_CREATE_ASYNC(hr)); +#endif } return hr; } #else long videoDevices::initDevices(IMFAttributes *pAttributes) { - HRESULT hr = S_OK; clearDevices(); IMFActivate **ppDevices = NULL; - hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count); + HRESULT hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count); if (SUCCEEDED(hr)) { if(count > 0) @@ -2693,12 +2910,11 @@ long videoDevices::initDevices(IMFAttributes *pAttributes) SafeRelease(ppDevices); } else - hr = -1; + hr = E_INVALIDARG; } else { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"VIDEODEVICES: The instances of the videoDevice class cannot be created\n"); + DebugPrintOut(L"VIDEODEVICES: The instances of the videoDevice class cannot be created\n"); } return hr; } @@ -2768,56 +2984,50 @@ void MediaType::Clear() videoInput::videoInput(void): accessToDevices(false) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"\n***** VIDEOINPUT LIBRARY - 2013 (Author: Evgeny Pereguda) *****\n\n"); + DebugPrintOut(L"\n***** VIDEOINPUT LIBRARY - 2013 (Author: Evgeny Pereguda) *****\n\n"); updateListOfDevices(); if(!accessToDevices) - DPO->printOut(L"INITIALIZATION: There is not any suitable video device\n"); + DebugPrintOut(L"INITIALIZATION: There is not any suitable video device\n"); } void videoInput::updateListOfDevices() { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); Media_Foundation *MF = &Media_Foundation::getInstance(); accessToDevices = MF->buildListOfDevices(); if(!accessToDevices) - DPO->printOut(L"UPDATING: There is not any suitable video device\n"); + DebugPrintOut(L"UPDATING: There is not any suitable video device\n"); } videoInput::~videoInput(void) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"\n***** CLOSE VIDEOINPUT LIBRARY - 2013 *****\n\n"); + DebugPrintOut(L"\n***** CLOSE VIDEOINPUT LIBRARY - 2013 *****\n\n"); } IMFMediaSource *videoInput::getMediaSource(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if(accessToDevices) { - videoDevices *VDS = &videoDevices::getInstance(); - videoDevice * VD = VDS->getDevice(deviceID); + videoDevice * VD = videoDevices::getInstance().getDevice(deviceID); if(VD) { IMFMediaSource *out = VD->getMediaSource(); if(!out) - DPO->printOut(L"VideoDevice %i: There is not any suitable IMFMediaSource interface\n", deviceID); + DebugPrintOut(L"VideoDevice %i: There is not any suitable IMFMediaSource interface\n", deviceID); return out; } } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return NULL; } bool videoInput::setupDevice(int deviceID, unsigned int id) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0 ) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return false; } if(accessToDevices) @@ -2828,23 +3038,22 @@ bool videoInput::setupDevice(int deviceID, unsigned int id) { bool out = VD->setupDevice(id); if(!out) - DPO->printOut(L"VIDEODEVICE %i: This device cannot be started\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: This device cannot be started\n", deviceID); return out; } } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return false; } bool videoInput::setupDevice(int deviceID, unsigned int w, unsigned int h, unsigned int idealFramerate) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0 ) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return false; } if(accessToDevices) @@ -2855,23 +3064,22 @@ bool videoInput::setupDevice(int deviceID, unsigned int w, unsigned int h, unsig { bool out = VD->setupDevice(w, h, idealFramerate); if(!out) - DPO->printOut(L"VIDEODEVICE %i: this device cannot be started\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: this device cannot be started\n", deviceID); return out; } } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n", deviceID); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n", deviceID); } return false; } MediaType videoInput::getFormat(int deviceID, unsigned int id) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return MediaType(); } if(accessToDevices) @@ -2883,17 +3091,16 @@ MediaType videoInput::getFormat(int deviceID, unsigned int id) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return MediaType(); } bool videoInput::isDeviceSetup(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return false; } if(accessToDevices) @@ -2905,17 +3112,16 @@ bool videoInput::isDeviceSetup(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return false; } bool videoInput::isDeviceMediaSource(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return false; } if(accessToDevices) @@ -2927,17 +3133,16 @@ bool videoInput::isDeviceMediaSource(int deviceID) } else { - DPO->printOut(L"Device(s): There is not any suitable video device\n"); + DebugPrintOut(L"Device(s): There is not any suitable video device\n"); } return false; } bool videoInput::isDeviceRawDataSource(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return false; } if(accessToDevices) @@ -2952,17 +3157,16 @@ bool videoInput::isDeviceRawDataSource(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return false; } bool videoInput::isFrameNew(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return false; } if(accessToDevices) @@ -2981,7 +3185,7 @@ bool videoInput::isFrameNew(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return false; } @@ -2989,10 +3193,9 @@ bool videoInput::isFrameNew(int deviceID) #ifdef HAVE_WINRT void videoInput::waitForDevice(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return; } if(accessToDevices) @@ -3011,7 +3214,7 @@ void videoInput::waitForDevice(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return; } @@ -3019,10 +3222,9 @@ void videoInput::waitForDevice(int deviceID) unsigned int videoInput::getCountFormats(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return 0; } if(accessToDevices) @@ -3034,7 +3236,7 @@ unsigned int videoInput::getCountFormats(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return 0; } @@ -3048,10 +3250,9 @@ void videoInput::closeAllDevices() void videoInput::setParametrs(int deviceID, CamParametrs parametrs) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return; } if(accessToDevices) @@ -3063,17 +3264,16 @@ void videoInput::setParametrs(int deviceID, CamParametrs parametrs) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } } CamParametrs videoInput::getParametrs(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); CamParametrs out; if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return out; } if(accessToDevices) @@ -3085,17 +3285,16 @@ CamParametrs videoInput::getParametrs(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return out; } void videoInput::closeDevice(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return; } if(accessToDevices) @@ -3107,16 +3306,15 @@ void videoInput::closeDevice(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } } unsigned int videoInput::getWidth(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return 0; } if(accessToDevices) @@ -3128,17 +3326,16 @@ unsigned int videoInput::getWidth(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return 0; } unsigned int videoInput::getHeight(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return 0; } if(accessToDevices) @@ -3150,17 +3347,36 @@ unsigned int videoInput::getHeight(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + } + return 0; +} + +unsigned int videoInput::getFrameRate(int deviceID) const +{ + if (deviceID < 0) + { + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + return 0; + } + if(accessToDevices) + { + videoDevice * VD = videoDevices::getInstance().getDevice(deviceID); + if(VD) + return VD->getFrameRate(); + } + else + { + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return 0; } wchar_t *videoInput::getNameVideoDevice(int deviceID) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return NULL; } if(accessToDevices) @@ -3172,14 +3388,13 @@ wchar_t *videoInput::getNameVideoDevice(int deviceID) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return L"Empty"; } unsigned int videoInput::listDevices(bool silent) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); int out = 0; if(accessToDevices) { @@ -3188,18 +3403,17 @@ unsigned int videoInput::listDevices(bool silent) VDS->waitInit(); #endif out = VDS->getCount(); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - if(!silent)DPO->printOut(L"\nVIDEOINPUT SPY MODE!\n\n"); - if(!silent)DPO->printOut(L"SETUP: Looking For Capture Devices\n"); + if(!silent) DebugPrintOut(L"\nVIDEOINPUT SPY MODE!\n\n"); + if(!silent) DebugPrintOut(L"SETUP: Looking For Capture Devices\n"); for(int i = 0; i < out; i++) { - if(!silent)DPO->printOut(L"SETUP: %i) %s \n",i, getNameVideoDevice(i)); + if(!silent) DebugPrintOut(L"SETUP: %i) %s \n",i, getNameVideoDevice(i)); } - if(!silent)DPO->printOut(L"SETUP: %i Device(s) found\n\n", out); + if(!silent) DebugPrintOut(L"SETUP: %i Device(s) found\n\n", out); } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return out; } @@ -3215,18 +3429,19 @@ bool videoInput::isDevicesAcceable() return accessToDevices; } +#ifdef _DEBUG void videoInput::setVerbose(bool state) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->setVerbose(state); + DPO *dpo = &DPO::getInstance(); + dpo->setVerbose(state); } +#endif void videoInput::setEmergencyStopEvent(int deviceID, void *userData, void(*func)(int, void *)) { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return; } if(accessToDevices) @@ -3241,18 +3456,16 @@ void videoInput::setEmergencyStopEvent(int deviceID, void *userData, void(*func) } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } } bool videoInput::getPixels(int deviceID, unsigned char * dstBuffer, bool flipRedAndBlue, bool flipImage) { bool success = false; - unsigned int bytes = 3; - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (deviceID < 0) { - DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); + DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); return success; } if(accessToDevices) @@ -3260,14 +3473,14 @@ bool videoInput::getPixels(int deviceID, unsigned char * dstBuffer, bool flipRed bool isRaw = isDeviceRawDataSource(deviceID); if(isRaw) { - videoDevices *VDS = &videoDevices::getInstance(); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - RawImage *RIOut = VDS->getDevice(deviceID)->getRawImageOut(); + videoDevice *VD = videoDevices::getInstance().getDevice(deviceID); + RawImage *RIOut = VD->getRawImageOut(); if(RIOut) { - unsigned int height = VDS->getDevice(deviceID)->getHeight(); - unsigned int width = VDS->getDevice(deviceID)->getWidth(); - unsigned int size = bytes * width * height; + const unsigned int bytes = 3; + const unsigned int height = VD->getHeight(); + const unsigned int width = VD->getWidth(); + const unsigned int size = bytes * width * height; if(size == RIOut->getSize()) { processPixels(RIOut->getpPixels(), dstBuffer, width, height, bytes, flipRedAndBlue, flipImage); @@ -3275,22 +3488,22 @@ bool videoInput::getPixels(int deviceID, unsigned char * dstBuffer, bool flipRed } else { - DPO->printOut(L"ERROR: GetPixels() - bufferSizes do not match!\n"); + DebugPrintOut(L"ERROR: GetPixels() - bufferSizes do not match!\n"); } } else { - DPO->printOut(L"ERROR: GetPixels() - Unable to grab frame for device %i\n", deviceID); + DebugPrintOut(L"ERROR: GetPixels() - Unable to grab frame for device %i\n", deviceID); } } else { - DPO->printOut(L"ERROR: GetPixels() - Not raw data source device %i\n", deviceID); + DebugPrintOut(L"ERROR: GetPixels() - Not raw data source device %i\n", deviceID); } } else { - DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); + DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); } return success; } @@ -3377,17 +3590,21 @@ protected: IplImage* frame; videoInput VI; #ifdef HAVE_WINRT +#ifdef HAVE_CONCURRENCY DEFINE_TASK openTask; Concurrency::critical_section lock; #endif +#endif }; +#ifdef _DEBUG struct SuppressVideoInputMessages { SuppressVideoInputMessages() { videoInput::setVerbose(true); } }; static SuppressVideoInputMessages do_it; +#endif CvCaptureCAM_MSMF::CvCaptureCAM_MSMF(): index(-1), @@ -3421,8 +3638,10 @@ void CvCaptureCAM_MSMF::close() bool CvCaptureCAM_MSMF::open( int _index ) { #ifdef HAVE_WINRT +#ifdef HAVE_CONCURRENCY SAVE_CURRENT_CONTEXT(context); - auto func = [_index, context, this]() -> bool { + auto func = [_index, context, this](DEFINE_RET_VAL(bool)) -> DEFINE_RET_FORMAL(bool) { +#endif #endif int try_index = _index; int devices = 0; @@ -3433,14 +3652,18 @@ bool CvCaptureCAM_MSMF::open( int _index ) try_index = try_index < 0 ? 0 : (try_index > devices-1 ? devices-1 : try_index); #ifdef HAVE_WINRT HRESULT hr; +#ifdef HAVE_CONCURRENCY BEGIN_CALL_IN_CONTEXT(hr, context, this, try_index) #endif - VI.setupDevice(try_index); +#endif + VI.setupDevice(try_index, 0, 0, 0); // With maximum frame size. #ifdef HAVE_WINRT - END_CALL_IN_CONTEXT(S_OK) +#ifdef HAVE_CONCURRENCY + END_CALL_IN_CONTEXT_BASE VI.waitForDevice(try_index); BEGIN_CALL_IN_CONTEXT(hr, context, this, try_index) HRESULT hr = S_OK; +#endif #endif if( !VI.isFrameNew(try_index) ) #ifdef HAVE_WINRT @@ -3450,11 +3673,13 @@ bool CvCaptureCAM_MSMF::open( int _index ) #endif index = try_index; #ifdef HAVE_WINRT - END_CALL_IN_CONTEXT(hr); - return true; +#ifdef HAVE_CONCURRENCY + END_CALL_IN_CONTEXT_BASE + RET_VAL(true) }; Concurrency::critical_section::scoped_lock _LockHolder(lock); CREATE_OR_CONTINUE_TASK(openTask, bool, func) +#endif #endif return true; } @@ -3468,11 +3693,12 @@ bool CvCaptureCAM_MSMF::grabFrame() IplImage* CvCaptureCAM_MSMF::retrieveFrame(int) { - if( !frame || (int)VI.getWidth(index) != frame->width || (int)VI.getHeight(index) != frame->height ) + const int w = (int)VI.getWidth(index); + const int h = (int)VI.getHeight(index); + if( !frame || w != frame->width || h != frame->height ) { if (frame) cvReleaseImage( &frame ); - unsigned int w = VI.getWidth(index), h = VI.getHeight(index); frame = cvCreateImage( cvSize(w,h), 8, 3 ); } VI.getPixels( index, (uchar*)frame->imageData, false, true ); @@ -3488,33 +3714,47 @@ double CvCaptureCAM_MSMF::getProperty( int property_id ) return VI.getWidth(index); case CV_CAP_PROP_FRAME_HEIGHT: return VI.getHeight(index); + case CV_CAP_PROP_FPS: + return VI.getFrameRate(index); + default: + break; } - return -1; + return 0; } bool CvCaptureCAM_MSMF::setProperty( int property_id, double value ) { // image capture properties + unsigned int fps = 0; bool handled = false; switch( property_id ) { case CV_CAP_PROP_FRAME_WIDTH: width = cvRound(value); + fps = VI.getFrameRate(index); handled = true; break; case CV_CAP_PROP_FRAME_HEIGHT: height = cvRound(value); + fps = VI.getFrameRate(index); handled = true; break; + case CV_CAP_PROP_FPS: + width = (int)VI.getHeight(index); + height = (int)VI.getWidth(index); + fps = cvRound(value); + break; } if ( handled ) { if( width > 0 && height > 0 ) { - if( width != (int)VI.getWidth(index) || height != (int)VI.getHeight(index) && VI.isDeviceSetup(index))//|| fourcc != VI.getFourcc(index) ) + if( (width != (int)VI.getWidth(index) || height != (int)VI.getHeight(index) || fps != VI.getFrameRate(index)) + && VI.isDeviceSetup(index))//|| fourcc != VI.getFourcc(index) ) { VI.closeDevice(index); - VI.setupDevice(index, width, height); + VI.setupDevice(index, width, height, fps); } + width = height = -1; return VI.isDeviceSetup(index); } return true; @@ -3573,14 +3813,12 @@ bool CvCaptureFile_MSMF::open(const char* filename) wchar_t* unicodeFileName = new wchar_t[strlen(filename)+1]; MultiByteToWideChar(CP_ACP, 0, filename, -1, unicodeFileName, (int)strlen(filename)+1); - HRESULT hr = S_OK; - MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID; - ComPtr pSourceResolver = NULL; + _ComPtr pSourceResolver = NULL; IUnknown* pUnkSource = NULL; - hr = MFCreateSourceResolver(pSourceResolver.GetAddressOf()); + HRESULT hr = MFCreateSourceResolver(pSourceResolver.GetAddressOf()); if (SUCCEEDED(hr)) { @@ -3714,10 +3952,10 @@ IplImage* CvCaptureFile_MSMF::retrieveFrame(int) HRESULT CvCaptureFile_MSMF::enumerateCaptureFormats(IMFMediaSource *pSource) { - ComPtr pPD = NULL; - ComPtr pSD = NULL; - ComPtr pHandler = NULL; - ComPtr pType = NULL; + _ComPtr pPD = NULL; + _ComPtr pSD = NULL; + _ComPtr pHandler = NULL; + _ComPtr pType = NULL; HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf()); if (FAILED(hr)) { @@ -3834,7 +4072,7 @@ private: GUID inputFormat; DWORD streamIndex; - ComPtr sinkWriter; + _ComPtr sinkWriter; bool initiated; @@ -3874,8 +4112,10 @@ const GUID CvVideoWriter_MSMF::FourCC2GUID(int fourcc) return MFVideoFormat_DVSD; break; case CV_FOURCC_MACRO('d', 'v', 's', 'l'): return MFVideoFormat_DVSL; break; - case CV_FOURCC_MACRO('H', '2', '6', '3'): +#if (WINVER >= _WIN32_WINNT_WIN8) + case CV_FOURCC_MACRO('H', '2', '6', '3'): // Available only for Win 8 target. return MFVideoFormat_H263; break; +#endif case CV_FOURCC_MACRO('H', '2', '6', '4'): return MFVideoFormat_H264; break; case CV_FOURCC_MACRO('M', '4', 'S', '2'): @@ -3985,10 +4225,10 @@ bool CvVideoWriter_MSMF::writeFrame(const IplImage* img) HRESULT CvVideoWriter_MSMF::InitializeSinkWriter(const char* filename) { - ComPtr spAttr; - ComPtr mediaTypeOut; - ComPtr mediaTypeIn; - ComPtr spByteStream; + _ComPtr spAttr; + _ComPtr mediaTypeOut; + _ComPtr mediaTypeIn; + _ComPtr spByteStream; MFCreateAttributes(&spAttr, 10); spAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true); @@ -4085,8 +4325,8 @@ HRESULT CvVideoWriter_MSMF::InitializeSinkWriter(const char* filename) HRESULT CvVideoWriter_MSMF::WriteFrame(DWORD *videoFrameBuffer, const LONGLONG& Start, const LONGLONG& Duration) { - ComPtr sample; - ComPtr buffer; + _ComPtr sample; + _ComPtr buffer; const LONG cbWidth = 4 * videoWidth; const DWORD cbBuffer = cbWidth * videoHeight; diff --git a/modules/highgui/src/cap_msmf.hpp b/modules/highgui/src/cap_msmf.hpp index c212ca910..bf3741b7d 100644 --- a/modules/highgui/src/cap_msmf.hpp +++ b/modules/highgui/src/cap_msmf.hpp @@ -1,6 +1,206 @@ #ifdef HAVE_WINRT #define ICustomStreamSink StreamSink -#include "ppltasks_winrt.h" +#ifndef __cplusplus_winrt + +#define __is_winrt_array(type) (type == ABI::Windows::Foundation::PropertyType::PropertyType_UInt8Array || type == ABI::Windows::Foundation::PropertyType::PropertyType_Int16Array ||\ + type == ABI::Windows::Foundation::PropertyType::PropertyType_UInt16Array || type == ABI::Windows::Foundation::PropertyType::PropertyType_Int32Array ||\ + type == ABI::Windows::Foundation::PropertyType::PropertyType_UInt32Array || type == ABI::Windows::Foundation::PropertyType::PropertyType_Int64Array ||\ + type == ABI::Windows::Foundation::PropertyType::PropertyType_UInt64Array || type == ABI::Windows::Foundation::PropertyType::PropertyType_SingleArray ||\ + type == ABI::Windows::Foundation::PropertyType::PropertyType_DoubleArray || type == ABI::Windows::Foundation::PropertyType::PropertyType_Char16Array ||\ + type == ABI::Windows::Foundation::PropertyType::PropertyType_BooleanArray || type == ABI::Windows::Foundation::PropertyType::PropertyType_StringArray ||\ + type == ABI::Windows::Foundation::PropertyType::PropertyType_InspectableArray || type == ABI::Windows::Foundation::PropertyType::PropertyType_DateTimeArray ||\ + type == ABI::Windows::Foundation::PropertyType::PropertyType_TimeSpanArray || type == ABI::Windows::Foundation::PropertyType::PropertyType_GuidArray ||\ + type == ABI::Windows::Foundation::PropertyType::PropertyType_PointArray || type == ABI::Windows::Foundation::PropertyType::PropertyType_SizeArray ||\ + type == ABI::Windows::Foundation::PropertyType::PropertyType_RectArray || type == ABI::Windows::Foundation::PropertyType::PropertyType_OtherTypeArray) + +template::value> +struct winrt_type +{ +}; +template +struct winrt_type<_Type, true> +{ + static IUnknown* create(_Type* _ObjInCtx) { + return reinterpret_cast(_ObjInCtx); + } + static IID getuuid() { return __uuidof(_Type); } + static const ABI::Windows::Foundation::PropertyType _PropType = ABI::Windows::Foundation::PropertyType::PropertyType_OtherType; +}; +template +struct winrt_type<_Type, false> +{ + static IUnknown* create(_Type* _ObjInCtx) { + Microsoft::WRL::ComPtr _PObj; + Microsoft::WRL::ComPtr objFactory; + HRESULT hr = Windows::Foundation::GetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), objFactory.ReleaseAndGetAddressOf()); + if (FAILED(hr)) return nullptr; + Microsoft::WRL::ComPtr spPropVal; + if (SUCCEEDED(hr)) + hr = objFactory.As(&spPropVal); + if (SUCCEEDED(hr)) { + hr = winrt_type<_Type>::create(spPropVal.Get(), _ObjInCtx, _PObj.GetAddressOf()); + if (SUCCEEDED(hr)) + return reinterpret_cast(_PObj.Detach()); + } + return nullptr; + } + static IID getuuid() { return __uuidof(ABI::Windows::Foundation::IPropertyValue); } + static const ABI::Windows::Foundation::PropertyType _PropType = ABI::Windows::Foundation::PropertyType::PropertyType_OtherType; +}; + +template<> +struct winrt_type +{ + static HRESULT create(ABI::Windows::Foundation::IPropertyValueStatics* spPropVal, void* _ObjInCtx, IInspectable** ppInsp) { + (void)_ObjInCtx; + return spPropVal->CreateEmpty(ppInsp); + } + static const ABI::Windows::Foundation::PropertyType _PropType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; +}; +#define MAKE_TYPE(Type, Name) template<>\ +struct winrt_type\ +{\ + static HRESULT create(ABI::Windows::Foundation::IPropertyValueStatics* spPropVal, Type* _ObjInCtx, IInspectable** ppInsp) {\ + return spPropVal->Create##Name(*_ObjInCtx, ppInsp);\ +}\ + static const ABI::Windows::Foundation::PropertyType _PropType = ABI::Windows::Foundation::PropertyType::PropertyType_##Name;\ +}; + +template +struct winrt_array_type +{ + static IUnknown* create(_Type* _ObjInCtx, size_t N) { + Microsoft::WRL::ComPtr _PObj; + Microsoft::WRL::ComPtr objFactory; + HRESULT hr = Windows::Foundation::GetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), objFactory.ReleaseAndGetAddressOf()); + if (FAILED(hr)) return nullptr; + Microsoft::WRL::ComPtr spPropVal; + if (SUCCEEDED(hr)) + hr = objFactory.As(&spPropVal); + if (SUCCEEDED(hr)) { + hr = winrt_array_type<_Type>::create(spPropVal.Get(), N, _ObjInCtx, _PObj.GetAddressOf()); + if (SUCCEEDED(hr)) + return reinterpret_cast(_PObj.Detach()); + } + return nullptr; + } + static const ABI::Windows::Foundation::PropertyType _PropType = ABI::Windows::Foundation::PropertyType::PropertyType_OtherTypeArray; +}; +template +struct winrt_prop_type {}; + +template <> +struct winrt_prop_type { + typedef void _Type; +}; + +template <> +struct winrt_prop_type { + typedef void _Type; +}; + +template <> +struct winrt_prop_type { + typedef void _Type; +}; + +#define MAKE_PROP(Prop, Type) template <>\ +struct winrt_prop_type {\ + typedef Type _Type;\ +}; + +#define MAKE_ARRAY_TYPE(Type, Name) MAKE_PROP(Name, Type)\ + MAKE_PROP(Name##Array, Type*)\ + MAKE_TYPE(Type, Name)\ + template<>\ +struct winrt_array_type\ +{\ + static HRESULT create(ABI::Windows::Foundation::IPropertyValueStatics* spPropVal, UINT32 __valueSize, Type** _ObjInCtx, IInspectable** ppInsp) {\ + return spPropVal->Create##Name##Array(__valueSize, *_ObjInCtx, ppInsp);\ +}\ + static const ABI::Windows::Foundation::PropertyType _PropType = ABI::Windows::Foundation::PropertyType::PropertyType_##Name##Array;\ + static std::vector PropertyValueToVector(ABI::Windows::Foundation::IPropertyValue* propValue)\ +{\ + UINT32 uLen = 0;\ + Type* pArray = nullptr;\ + propValue->Get##Name##Array(&uLen, &pArray);\ + return std::vector(pArray, pArray + uLen);\ +}\ +}; +MAKE_ARRAY_TYPE(BYTE, UInt8) +MAKE_ARRAY_TYPE(INT16, Int16) +MAKE_ARRAY_TYPE(UINT16, UInt16) +MAKE_ARRAY_TYPE(INT32, Int32) +MAKE_ARRAY_TYPE(UINT32, UInt32) +MAKE_ARRAY_TYPE(INT64, Int64) +MAKE_ARRAY_TYPE(UINT64, UInt64) +MAKE_ARRAY_TYPE(FLOAT, Single) +MAKE_ARRAY_TYPE(DOUBLE, Double) +MAKE_ARRAY_TYPE(WCHAR, Char16) +//MAKE_ARRAY_TYPE(boolean, Boolean) //conflict with identical type in C++ of BYTE/UInt8 +MAKE_ARRAY_TYPE(HSTRING, String) +MAKE_ARRAY_TYPE(IInspectable*, Inspectable) +MAKE_ARRAY_TYPE(GUID, Guid) +MAKE_ARRAY_TYPE(ABI::Windows::Foundation::DateTime, DateTime) +MAKE_ARRAY_TYPE(ABI::Windows::Foundation::TimeSpan, TimeSpan) +MAKE_ARRAY_TYPE(ABI::Windows::Foundation::Point, Point) +MAKE_ARRAY_TYPE(ABI::Windows::Foundation::Size, Size) +MAKE_ARRAY_TYPE(ABI::Windows::Foundation::Rect, Rect) + +template < typename T > +struct DerefHelper +{ + typedef T DerefType; +}; + +template < typename T > +struct DerefHelper +{ + typedef T DerefType; +}; + +#define __is_valid_winrt_type(_Type) (std::is_void<_Type>::value || \ + std::is_same<_Type, BYTE>::value || \ + std::is_same<_Type, INT16>::value || \ + std::is_same<_Type, UINT16>::value || \ + std::is_same<_Type, INT32>::value || \ + std::is_same<_Type, UINT32>::value || \ + std::is_same<_Type, INT64>::value || \ + std::is_same<_Type, UINT64>::value || \ + std::is_same<_Type, FLOAT>::value || \ + std::is_same<_Type, DOUBLE>::value || \ + std::is_same<_Type, WCHAR>::value || \ + std::is_same<_Type, boolean>::value || \ + std::is_same<_Type, HSTRING>::value || \ + std::is_same<_Type, IInspectable *>::value || \ + std::is_base_of::value || \ + std::is_base_of::DerefType>::value || \ + std::is_same<_Type, GUID>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::DateTime>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::TimeSpan>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::Point>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::Size>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::Rect>::value || \ + std::is_same<_Type, BYTE*>::value || \ + std::is_same<_Type, INT16*>::value || \ + std::is_same<_Type, UINT16*>::value || \ + std::is_same<_Type, INT32*>::value || \ + std::is_same<_Type, UINT32*>::value || \ + std::is_same<_Type, INT64*>::value || \ + std::is_same<_Type, UINT64*>::value || \ + std::is_same<_Type, FLOAT*>::value || \ + std::is_same<_Type, DOUBLE*>::value || \ + std::is_same<_Type, WCHAR*>::value || \ + std::is_same<_Type, boolean*>::value || \ + std::is_same<_Type, HSTRING*>::value || \ + std::is_same<_Type, IInspectable **>::value || \ + std::is_same<_Type, GUID*>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::DateTime*>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::TimeSpan*>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::Point*>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::Size*>::value || \ + std::is_same<_Type, ABI::Windows::Foundation::Rect*>::value) +#endif #else EXTERN_C const IID IID_ICustomStreamSink; @@ -178,12 +378,33 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #ifdef HAVE_WINRT +#ifdef __cplusplus_winrt +#define _ContextCallback Concurrency::details::_ContextCallback +#define BEGIN_CALL_IN_CONTEXT(hr, var, ...) hr = S_OK;\ + var._CallInContext([__VA_ARGS__]() { +#define END_CALL_IN_CONTEXT(hr) if (FAILED(hr)) throw Platform::Exception::CreateException(hr);\ +}); +#define END_CALL_IN_CONTEXT_BASE }); +#else +#define _ContextCallback Concurrency_winrt::details::_ContextCallback +#define BEGIN_CALL_IN_CONTEXT(hr, var, ...) hr = var._CallInContext([__VA_ARGS__]() -> HRESULT { +#define END_CALL_IN_CONTEXT(hr) return hr;\ +}); +#define END_CALL_IN_CONTEXT_BASE return S_OK;\ +}); +#endif +#define GET_CURRENT_CONTEXT _ContextCallback::_CaptureCurrent() +#define SAVE_CURRENT_CONTEXT(var) _ContextCallback var = GET_CURRENT_CONTEXT + +#define COMMA , + #ifdef __cplusplus_winrt #define _Object Platform::Object^ #define _ObjectObj Platform::Object^ #define _String Platform::String^ #define _StringObj Platform::String^ #define _StringReference ref new Platform::String +#define _StringReferenceObj Platform::String^ #define _DeviceInformationCollection Windows::Devices::Enumeration::DeviceInformationCollection #define _MediaCapture Windows::Media::Capture::MediaCapture #define _MediaCaptureVideoPreview Windows::Media::Capture::MediaCapture @@ -193,6 +414,7 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #define _MediaEncodingProperties Windows::Media::MediaProperties::IMediaEncodingProperties #define _VideoEncodingProperties Windows::Media::MediaProperties::VideoEncodingProperties #define _MediaStreamType Windows::Media::Capture::MediaStreamType +#define _AsyncInfo Windows::Foundation::IAsyncInfo #define _AsyncAction Windows::Foundation::IAsyncAction #define _AsyncOperation Windows::Foundation::IAsyncOperation #define _DeviceClass Windows::Devices::Enumeration::DeviceClass @@ -209,29 +431,37 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #define _InitializeWithSettingsAsync InitializeAsync #define _FindAllAsyncDeviceClass FindAllAsync #define _MediaExtension Windows::Media::IMediaExtension -#define _ContextCallback Concurrency::details::_ContextCallback -#define BEGIN_CALL_IN_CONTEXT(hr, var, ...) hr = S_OK;\ -var._CallInContext([__VA_ARGS__]() { -#define END_CALL_IN_CONTEXT(hr) if (FAILED(hr)) throw Platform::Exception::CreateException(hr);\ -}); -#define DO_ACTION_SYNCHRONOUSLY(hr, action, ctxt) hr = S_OK;\ -CCompletionHandler::PerformActionSynchronously(reinterpret_cast(action), ctxt) -#define DO_OPERATION_SYNCHRONOUSLY_VECTOR(hr, action, ctxt, pResult, vectortype, elementtype, _type) hr = S_OK;\ -pResult = CCompletionHandler::PerformSynchronously<_type^>(reinterpret_cast^>(action), ctxt) -#define BEGIN_CREATE_ASYNC(...) reinterpret_cast(Concurrency::create_async([__VA_ARGS__]() { +#define BEGIN_CREATE_ASYNC(type, ...) (Concurrency::create_async([__VA_ARGS__]() { #define END_CREATE_ASYNC(hr) if (FAILED(hr)) throw Platform::Exception::CreateException(hr);\ })) #define DEFINE_TASK Concurrency::task #define CREATE_TASK Concurrency::create_task #define CREATE_OR_CONTINUE_TASK(_task, rettype, func) _task = (_task == Concurrency::task()) ? Concurrency::create_task(func) : _task.then([func](rettype) -> rettype { return func(); }); +#define DEFINE_RET_VAL(x) +#define DEFINE_RET_TYPE(x) +#define DEFINE_RET_FORMAL(x) x +#define RET_VAL(x) return x; +#define RET_VAL_BASE +#define MAKE_STRING(str) str +#define GET_STL_STRING(str) std::wstring(str->Data()) +#define GET_STL_STRING_RAW(str) std::wstring(str->Data()) #define MAKE_WRL_OBJ(x) x^ #define MAKE_WRL_REF(x) x^ +#define MAKE_OBJ_REF(x) x^ #define MAKE_WRL_AGILE_REF(x) Platform::Agile +#define MAKE_PROPERTY_BACKING(Type, PropName) property Type PropName; +#define MAKE_PROPERTY(Type, PropName, PropValue) +#define MAKE_PROPERTY_STRING(Type, PropName, PropValue) +#define MAKE_READONLY_PROPERTY(Type, PropName, PropValue) property Type PropName\ +{\ + Type get() { return PropValue; }\ +} +#define THROW_INVALID_ARG throw ref new Platform::InvalidArgumentException(); #define RELEASE_AGILE_WRL(x) x = nullptr; #define RELEASE_WRL(x) x = nullptr; #define GET_WRL_OBJ_FROM_REF(objtype, obj, orig, hr) objtype^ obj = orig;\ hr = S_OK; -#define GET_WRL_OBJ_FROM_OBJ(objtype, obj, orig, hr) objtype^ obj = orig;\ +#define GET_WRL_OBJ_FROM_OBJ(objtype, obj, orig, hr) objtype^ obj = safe_cast(orig);\ hr = S_OK; #define WRL_ENUM_GET(obj, prefix, prop) obj::##prop #define WRL_PROP_GET(obj, prop, arg, hr) arg = obj->##prop;\ @@ -242,11 +472,18 @@ hr = S_OK; hr = S_OK; #define WRL_METHOD(obj, method, ret, hr, ...) ret = obj->##method(__VA_ARGS__);\ hr = S_OK; +#define WRL_METHOD_NORET_BASE(obj, method, hr) obj->##method();\ + hr = S_OK; +#define WRL_METHOD_NORET(obj, method, hr, ...) obj->##method(__VA_ARGS__);\ + hr = S_OK; #define REF_WRL_OBJ(obj) &obj #define DEREF_WRL_OBJ(obj) obj #define DEREF_AGILE_WRL_OBJ(obj) obj.Get() #define DEREF_AS_NATIVE_WRL_OBJ(type, obj) reinterpret_cast(obj) #define PREPARE_TRANSFER_WRL_OBJ(obj) obj +#define ACTIVATE_LOCAL_OBJ_BASE(objtype) ref new objtype() +#define ACTIVATE_LOCAL_OBJ(objtype, ...) ref new objtype(__VA_ARGS__) +#define ACTIVATE_EVENT_HANDLER(objtype, ...) ref new objtype(__VA_ARGS__) #define ACTIVATE_OBJ(rtclass, objtype, obj, hr) MAKE_WRL_OBJ(objtype) obj = ref new objtype();\ hr = S_OK; #define ACTIVATE_STATIC_OBJ(rtclass, objtype, obj, hr) objtype obj;\ @@ -257,6 +494,7 @@ hr = S_OK; #define _String HSTRING #define _StringObj Microsoft::WRL::Wrappers::HString #define _StringReference Microsoft::WRL::Wrappers::HStringReference +#define _StringReferenceObj Microsoft::WRL::Wrappers::HStringReference #define _DeviceInformationCollection ABI::Windows::Devices::Enumeration::DeviceInformationCollection #define _MediaCapture ABI::Windows::Media::Capture::IMediaCapture #define _MediaCaptureVideoPreview ABI::Windows::Media::Capture::IMediaCaptureVideoPreview @@ -266,6 +504,7 @@ hr = S_OK; #define _MediaEncodingProperties ABI::Windows::Media::MediaProperties::IMediaEncodingProperties #define _VideoEncodingProperties ABI::Windows::Media::MediaProperties::IVideoEncodingProperties #define _MediaStreamType ABI::Windows::Media::Capture::MediaStreamType +#define _AsyncInfo ABI::Windows::Foundation::IAsyncInfo #define _AsyncAction ABI::Windows::Foundation::IAsyncAction #define _AsyncOperation ABI::Windows::Foundation::IAsyncOperation #define _DeviceClass ABI::Windows::Devices::Enumeration::DeviceClass @@ -282,21 +521,32 @@ hr = S_OK; #define _InitializeWithSettingsAsync InitializeWithSettingsAsync #define _FindAllAsyncDeviceClass FindAllAsyncDeviceClass #define _MediaExtension ABI::Windows::Media::IMediaExtension -#define _ContextCallback Concurrency_winrt::details::_ContextCallback -#define BEGIN_CALL_IN_CONTEXT(hr, var, ...) hr = var._CallInContext([__VA_ARGS__]() -> HRESULT { -#define END_CALL_IN_CONTEXT(hr) return hr;\ -}); -#define DO_ACTION_SYNCHRONOUSLY(hr, action, ctxt) hr = CCompletionHandler::PerformActionSynchronously(action, ctxt) -#define DO_OPERATION_SYNCHRONOUSLY_VECTOR(hr, action, ctxt, pResult, vectortype, elementtype, _type) hr = CCompletionHandler, ABI::Windows::Foundation::IAsyncOperation<_type*>>::PerformSynchronously*>(action, ctxt, pResult.GetAddressOf()) -#define BEGIN_CREATE_ASYNC(...) Concurrency_winrt::create_async([__VA_ARGS__]() -> HRESULT { +#define BEGIN_CREATE_ASYNC(type, ...) Concurrency_winrt::create_async([__VA_ARGS__]() -> HRESULT { #define END_CREATE_ASYNC(hr) return hr;\ }) #define DEFINE_TASK Concurrency_winrt::task #define CREATE_TASK Concurrency_winrt::create_task -#define CREATE_OR_CONTINUE_TASK(_task, rettype, func) _task = (_task == Concurrency_winrt::task()) ? Concurrency_winrt::create_task(func) : _task.then([func](rettype) -> rettype { return func(); }); +#define CREATE_OR_CONTINUE_TASK(_task, rettype, func) _task = (_task == Concurrency_winrt::task()) ? Concurrency_winrt::create_task(func) : _task.then([func](rettype, rettype* retVal) -> HRESULT { return func(retVal); }); +#define DEFINE_RET_VAL(x) x* retVal +#define DEFINE_RET_TYPE(x) +#define DEFINE_RET_FORMAL(x) HRESULT +#define RET_VAL(x) *retVal = x;\ +return S_OK; +#define RET_VAL_BASE return S_OK; +#define MAKE_STRING(str) Microsoft::WRL::Wrappers::HStringReference(L##str) +#define GET_STL_STRING(str) std::wstring(str.GetRawBuffer(NULL)) +#define GET_STL_STRING_RAW(str) WindowsGetStringRawBuffer(str, NULL) #define MAKE_WRL_OBJ(x) Microsoft::WRL::ComPtr #define MAKE_WRL_REF(x) x* +#define MAKE_OBJ_REF(x) x #define MAKE_WRL_AGILE_REF(x) x* +#define MAKE_PROPERTY_BACKING(Type, PropName) Type PropName; +#define MAKE_PROPERTY(Type, PropName, PropValue) STDMETHODIMP get_##PropName(Type* pVal) { if (pVal) { *pVal = PropValue; } else { return E_INVALIDARG; } return S_OK; }\ + STDMETHODIMP put_##PropName(Type Val) { PropValue = Val; return S_OK; } +#define MAKE_PROPERTY_STRING(Type, PropName, PropValue) STDMETHODIMP get_##PropName(Type* pVal) { if (pVal) { return ::WindowsDuplicateString(PropValue.Get(), pVal); } else { return E_INVALIDARG; } }\ + STDMETHODIMP put_##PropName(Type Val) { return PropValue.Set(Val); } +#define MAKE_READONLY_PROPERTY(Type, PropName, PropValue) STDMETHODIMP get_##PropName(Type* pVal) { if (pVal) { *pVal = PropValue; } else { return E_INVALIDARG; } return S_OK; } +#define THROW_INVALID_ARG RoOriginateError(E_INVALIDARG, nullptr); #define RELEASE_AGILE_WRL(x) if (x) { (x)->Release(); x = nullptr; } #define RELEASE_WRL(x) if (x) { (x)->Release(); x = nullptr; } #define GET_WRL_OBJ_FROM_REF(objtype, obj, orig, hr) Microsoft::WRL::ComPtr obj;\ @@ -308,11 +558,15 @@ hr = orig.As(&obj); #define WRL_PROP_PUT(obj, prop, arg, hr) hr = obj->put_##prop(arg); #define WRL_METHOD_BASE(obj, method, ret, hr) hr = obj->##method(&ret); #define WRL_METHOD(obj, method, ret, hr, ...) hr = obj->##method(__VA_ARGS__, &ret); +#define WRL_METHOD_NORET_BASE(obj, method, hr) hr = obj->##method(); #define REF_WRL_OBJ(obj) obj.GetAddressOf() #define DEREF_WRL_OBJ(obj) obj.Get() #define DEREF_AGILE_WRL_OBJ(obj) obj #define DEREF_AS_NATIVE_WRL_OBJ(type, obj) obj.Get() #define PREPARE_TRANSFER_WRL_OBJ(obj) obj.Detach() +#define ACTIVATE_LOCAL_OBJ_BASE(objtype) Microsoft::WRL::Make() +#define ACTIVATE_LOCAL_OBJ(objtype, ...) Microsoft::WRL::Make(__VA_ARGS__) +#define ACTIVATE_EVENT_HANDLER(objtype, ...) Microsoft::WRL::Callback(__VA_ARGS__).Get() #define ACTIVATE_OBJ(rtclass, objtype, obj, hr) MAKE_WRL_OBJ(objtype) obj;\ {\ Microsoft::WRL::ComPtr objFactory;\ @@ -333,272 +587,96 @@ hr = orig.As(&obj); } #endif -#define GET_CURRENT_CONTEXT _ContextCallback::_CaptureCurrent() -#define SAVE_CURRENT_CONTEXT(var) _ContextCallback var = GET_CURRENT_CONTEXT - -#ifdef __cplusplus_winrt -ref class CCompletionHandler sealed +#define _ComPtr Microsoft::WRL::ComPtr #else -template -class CCompletionHandler - : public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::ClassicCom>, - TCompletionHandler, IAgileObject, FtmBase> -#endif + +template +class ComPtr : public ATL::CComPtr { - MixInHelper() -#ifndef __cplusplus_winrt public: - CCompletionHandler() {} - - STDMETHODIMP Invoke(TAction* /*asyncInfo*/, AsyncStatus /*asyncStatus*/) + ComPtr() throw() { - m_Event.set(); - return S_OK; } - void wait() { m_Event.wait(); } -#endif -#ifdef __cplusplus_winrt -internal: - template - static TResult PerformSynchronously(Windows::Foundation::IAsyncOperation^ asyncOp, _ContextCallback context) + ComPtr(int nNull) throw() : + CComPtr((T*)nNull) { - TResult pResult; - context._CallInContext([asyncOp, &pResult]() { Concurrency::task asyncTask = Concurrency::task(asyncOp); pResult = asyncTask.get(); }); - return pResult; -#else - template - static HRESULT PerformSynchronously(TAction* asyncOp, _ContextCallback context, TResult* pResult) + } + ComPtr(T* lp) throw() : + CComPtr(lp) + { - HRESULT hr; - ComPtr> completeHandler = Microsoft::WRL::Make>(); - hr = context._CallInContext([&asyncOp, &completeHandler]() -> HRESULT { - HRESULT hr = asyncOp->put_Completed(completeHandler.Get()); - if (FAILED(hr)) asyncOp->Release(); - return hr; - }); - if (SUCCEEDED(hr)) - completeHandler->wait(); - else - return hr; - hr = context._CallInContext([&asyncOp, &pResult]() -> HRESULT { - HRESULT hr = asyncOp->GetResults(pResult); - asyncOp->Release(); - return hr; - }); - return hr; -#endif + } + ComPtr(_In_ const CComPtr& lp) throw() : + CComPtr(lp.p) + { + } + virtual ~ComPtr() {} + + T* const* GetAddressOf() const throw() + { + return &p; } -#ifdef __cplusplus_winrt - static void PerformActionSynchronously(Windows::Foundation::IAsyncAction^ asyncOp, _ContextCallback context) + T** GetAddressOf() throw() { - context._CallInContext([asyncOp](){ Concurrency::task(asyncOp).get(); }); -#else - static HRESULT PerformActionSynchronously(TAction* asyncOp, _ContextCallback context) - { - HRESULT hr; - ComPtr> completeHandler = Microsoft::WRL::Make>(); - hr = context._CallInContext([&asyncOp, &completeHandler]() -> HRESULT { - HRESULT hr = asyncOp->put_Completed(completeHandler.Get()); - if (FAILED(hr)) asyncOp->Release(); - return hr; - }); - if (SUCCEEDED(hr)) - completeHandler->wait(); - else - return hr; - hr = context._CallInContext([&asyncOp]() -> HRESULT { - HRESULT hr = asyncOp->GetResults(); - asyncOp->Release(); - return hr; - }); - return hr; -#endif + return &p; + } + + T** ReleaseAndGetAddressOf() throw() + { + InternalRelease(); + return &p; + } + + T* Get() const throw() + { + return p; + } + ComPtr& operator=(decltype(__nullptr)) throw() + { + InternalRelease(); + return *this; + } + ComPtr& operator=(_In_ const int nNull) throw() + { + ASSERT(nNull == 0); + (void)nNull; + InternalRelease(); + return *this; + } + unsigned long Reset() + { + return InternalRelease(); + } + // query for U interface + template + HRESULT As(_Inout_ U** lp) const throw() + { + return p->QueryInterface(__uuidof(U), (void**)lp); + } + // query for U interface + template + HRESULT As(_Out_ ComPtr* lp) const throw() + { + return p->QueryInterface(__uuidof(U), reinterpret_cast(lp->ReleaseAndGetAddressOf())); } -#ifndef __cplusplus_winrt private: - Concurrency::event m_Event; -#endif -}; - -#ifndef __cplusplus_winrt - -// Helpers for create_async validation -// -// A parameter lambda taking no arguments is valid -template -static auto _IsValidCreateAsync(_Ty _Param, int, int, int, int) -> typename decltype(_Param(), std::true_type()); - -// A parameter lambda taking an cancellation_token argument is valid -template -static auto _IsValidCreateAsync(_Ty _Param, int, int, int, ...) -> typename decltype(_Param(cancellation_token::none()), std::true_type()); - -// A parameter lambda taking a progress report argument is valid -template -static auto _IsValidCreateAsync(_Ty _Param, int, int, ...) -> typename decltype(_Param(details::_ProgressReporterCtorArgType()), std::true_type()); - -// A parameter lambda taking a progress report and a cancellation_token argument is valid -template -static auto _IsValidCreateAsync(_Ty _Param, int, ...) -> typename decltype(_Param(details::_ProgressReporterCtorArgType(), cancellation_token::none()), std::true_type()); - -// All else is invalid -template -static std::false_type _IsValidCreateAsync(_Ty _Param, ...); - -//for task specific architecture -//could add a CancelPending which is set when Cancel is called, return as Cancel when get_Status is called and set when a task_canceled exception is thrown - -extern const __declspec(selectany) WCHAR RuntimeClass_CV_CAsyncAction[] = L"cv.CAsyncAction"; - -template -class CAsyncAction - : public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::WinRt>, - Microsoft::WRL::Implements, Microsoft::WRL::AsyncBase> -{ - InspectableClass(RuntimeClass_CV_CAsyncAction, BaseTrust) -public: - STDMETHOD(RuntimeClassInitialize)() { return S_OK; } - virtual ~CAsyncAction() {} - CAsyncAction(const _Function &_Func) : _M_func(_Func) { - Start(); - } - void _SetTaskCreationAddressHint(void* _SourceAddressHint) + unsigned long InternalRelease() throw() { - if (!(std::is_same>::_AsyncKind, Concurrency_winrt::details::_TypeSelectorAsyncTask>::value)) + unsigned long ref = 0; + T* temp = p; + + if (temp != nullptr) { - // Overwrite the creation address with the return address of create_async unless the - // lambda returned a task. If the create async lambda returns a task, that task is reused and - // we want to preserve its creation address hint. - _M_task._SetTaskCreationAddressHint(_SourceAddressHint); + p = nullptr; + ref = temp->Release(); } - } - HRESULT STDMETHODCALLTYPE put_Completed( - /* [in] */ __RPC__in_opt ABI::Windows::Foundation::IAsyncActionCompletedHandler *handler) - { - HRESULT hr; - if (SUCCEEDED(hr = PutOnComplete(handler)) && cCallbackMade_ == 0) { - //okay to use default implementation even for the callback as already running in context - //otherwise check for the alternate case and save the context - _M_completeDelegateContext = _ContextCallback::_CaptureCurrent(); - } - return hr; - } - HRESULT STDMETHODCALLTYPE get_Completed( - /* [out][retval] */ __RPC__deref_out_opt ABI::Windows::Foundation::IAsyncActionCompletedHandler **handler) { - if (!handler) return E_POINTER; - return GetOnComplete(handler); - } - HRESULT STDMETHODCALLTYPE GetResults(void) { - HRESULT hr = CheckValidStateForResultsCall(); - if (SUCCEEDED(hr)) { - _M_task.get(); - } - return hr; - } - HRESULT OnStart() { - _M_task = Concurrency_winrt::task(_M_func, _M_cts.get_token()); - AddRef(); - _M_task.then([this](Concurrency_winrt::task _Antecedent) { - try { - HRESULT hr = _Antecedent.get(); - if (FAILED(hr)) TryTransitionToError(hr); - } - catch (Concurrency::task_canceled&){ - } - catch (...) { - TryTransitionToError(E_FAIL); - } - _FireCompletion(); - Release(); - }); - return S_OK; - } - void OnClose() {} - void OnCancel() { _M_cts.cancel(); } -protected: - //modified for _CallInContext to support UI STA thread - //can wrap the base clase implementation or duplicate it but must use get_Completed to fetch the private member variable - virtual void _FireCompletion() - { - AddRef(); - _M_completeDelegateContext._CallInContext([this]() -> HRESULT { - FireCompletion(); - Release(); - return S_OK; - }); + return ref; } -private: - - _Function _M_func; - Concurrency_winrt::task _M_task; - Concurrency::cancellation_token_source _M_cts; - _ContextCallback _M_completeDelegateContext; }; -template -__declspec(noinline) -CAsyncAction<_Function>* create_async(const _Function& _Func) -{ - static_assert(std::is_same::value, - "argument to create_async must be a callable object taking zero, one or two arguments"); - CAsyncAction<_Function>* action = Microsoft::WRL::Make>(_Func).Detach(); - action->_SetTaskCreationAddressHint(_ReturnAddress()); - return action; -} -#endif - -EXTERN_C const IID IID_IMedCapFailHandler; - -class DECLSPEC_UUID("CE22BEDB-0B3C-4BE0-BE8F-E53AB457EA2C") DECLSPEC_NOVTABLE IMedCapFailHandler : public IUnknown -{ -public: - virtual HRESULT AddHandler(ABI::Windows::Media::Capture::IMediaCapture* pMedCap) = 0; - virtual HRESULT RemoveHandler(ABI::Windows::Media::Capture::IMediaCapture* pMedCap) = 0; -}; - -template -class MediaCaptureFailedHandler : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::ClassicCom>, - IMedCapFailHandler, ABI::Windows::Media::Capture::IMediaCaptureFailedEventHandler, IAgileObject, FtmBase> -{ -public: - MediaCaptureFailedHandler(const _Function &_Func) : _M_func(_Func) { m_cookie.value = 0; } - HRESULT AddHandler(ABI::Windows::Media::Capture::IMediaCapture* pMedCap) - { - return pMedCap->add_Failed(this, &m_cookie); - } - HRESULT RemoveHandler(ABI::Windows::Media::Capture::IMediaCapture* pMedCap) - { - return pMedCap->remove_Failed(m_cookie); - } - HRESULT STDMETHODCALLTYPE Invoke( - ABI::Windows::Media::Capture::IMediaCapture *sender, - ABI::Windows::Media::Capture::IMediaCaptureFailedEventArgs *errorEventArgs) - { - (void)sender; - (void)errorEventArgs; - AddRef(); - _M_func(); - Release(); - return S_OK; - } - -private: - _Function _M_func; - EventRegistrationToken m_cookie; -}; - -template -__declspec(noinline) -MediaCaptureFailedHandler<_Function>* create_medcapfailedhandler(const _Function& _Func) -{ - return Microsoft::WRL::Make>(_Func).Detach(); -} - +#define _ComPtr ComPtr #endif template @@ -946,7 +1024,7 @@ done: } protected: - ComPtr _spAttributes; + _ComPtr _spAttributes; }; class StreamSink : @@ -1005,11 +1083,11 @@ public: #ifdef HAVE_WINRT STDMETHOD(RuntimeClassInitialize)() { return S_OK; } #else - ULONG AddRef() + ULONG STDMETHODCALLTYPE AddRef() { return InterlockedIncrement(&m_cRef); } - ULONG Release() + ULONG STDMETHODCALLTYPE Release() { ULONG cRef = InterlockedDecrement(&m_cRef); if (cRef == 0) @@ -1025,7 +1103,7 @@ public: if (m_spFTM == nullptr) { EnterCriticalSection(&m_critSec); if (m_spFTM == nullptr) { - hr = CoCreateFreeThreadedMarshaler(static_cast(this), &m_spFTM); + hr = CoCreateFreeThreadedMarshaler((IMFStreamSink*)this, &m_spFTM); } LeaveCriticalSection(&m_critSec); } @@ -1061,14 +1139,12 @@ public: InitializeCriticalSectionEx(&m_critSec, 3000, 0); ZeroMemory(&m_guiCurrentSubtype, sizeof(m_guiCurrentSubtype)); CBaseAttributes::Initialize(0U); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::StreamSink\n"); + DebugPrintOut(L"StreamSink::StreamSink\n"); } virtual ~StreamSink() { DeleteCriticalSection(&m_critSec); assert(m_IsShutdown); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::~StreamSink\n"); + DebugPrintOut(L"StreamSink::~StreamSink\n"); } HRESULT Initialize() @@ -1078,7 +1154,7 @@ public: hr = MFCreateEventQueue(&m_spEventQueue); if (SUCCEEDED(hr)) { - ComPtr pMedSink; + _ComPtr pMedSink; hr = CBaseAttributes<>::GetUnknown(MF_STREAMSINK_MEDIASINKINTERFACE, __uuidof(IMFMediaSink), (LPVOID*)pMedSink.GetAddressOf()); assert(pMedSink.Get() != NULL); if (SUCCEEDED(hr)) { @@ -1102,10 +1178,8 @@ public: // Called when the presentation clock starts. HRESULT Start(MFTIME start) { - EnterCriticalSection(&m_critSec); - HRESULT hr = S_OK; - + EnterCriticalSection(&m_critSec); if (m_state != State_TypeNotSet) { if (start != PRESENTATION_CURRENT_POSITION) { @@ -1184,7 +1258,7 @@ public: // Shuts down the stream sink. HRESULT Shutdown() { - ComPtr pSampleCallback; + _ComPtr pSampleCallback; HRESULT hr = S_OK; assert(!m_IsShutdown); hr = m_pParent->GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); @@ -1217,7 +1291,7 @@ public: if (SUCCEEDED(hr)) { - ComPtr pMedSink; + _ComPtr pMedSink; hr = CBaseAttributes<>::GetUnknown(MF_STREAMSINK_MEDIASINKINTERFACE, __uuidof(IMFMediaSink), (LPVOID*)pMedSink.GetAddressOf()); if (SUCCEEDED(hr)) { *ppMediaSink = pMedSink.Detach(); @@ -1225,8 +1299,7 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::GetMediaSink: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::GetMediaSink: HRESULT=%i\n", hr); return hr; } @@ -1247,8 +1320,7 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::GetIdentifier: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::GetIdentifier: HRESULT=%i\n", hr); return hr; } @@ -1270,14 +1342,13 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::GetMediaTypeHandler: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::GetMediaTypeHandler: HRESULT=%i\n", hr); return hr; } HRESULT STDMETHODCALLTYPE ProcessSample(IMFSample *pSample) { - ComPtr pInput; - ComPtr pSampleCallback; + _ComPtr pInput; + _ComPtr pSampleCallback; BYTE *pSrc = NULL; // Source buffer. // Stride if the buffer does not support IMF2DBuffer LONGLONG hnsTime = 0; @@ -1334,6 +1405,7 @@ public: /* [in] */ MFSTREAMSINK_MARKER_TYPE eMarkerType, /* [in] */ __RPC__in const PROPVARIANT * /*pvarMarkerValue*/, /* [in] */ __RPC__in const PROPVARIANT * /*pvarContextValue*/) { + eMarkerType; EnterCriticalSection(&m_critSec); HRESULT hr = S_OK; @@ -1345,12 +1417,12 @@ public: if (SUCCEEDED(hr)) { + //at shutdown will receive MFSTREAMSINK_MARKER_ENDOFSEGMENT hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::PlaceMarker: HRESULT=%i %s\n", hr, StreamSinkMarkerTypeMap.at(eMarkerType).c_str()); + DebugPrintOut(L"StreamSink::PlaceMarker: HRESULT=%i %s\n", hr, StreamSinkMarkerTypeMap.at(eMarkerType).c_str()); return hr; } @@ -1364,8 +1436,7 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::Flush: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::Flush: HRESULT=%i\n", hr); return hr; } @@ -1378,7 +1449,7 @@ public: HRESULT hr = S_OK; - ComPtr pQueue; + _ComPtr pQueue; { EnterCriticalSection(&m_critSec); @@ -1403,13 +1474,12 @@ public: if (SUCCEEDED(hr) && SUCCEEDED((*ppEvent)->GetType(&meType)) && meType == MEStreamSinkStopped) { } HRESULT hrStatus = S_OK; - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); if (SUCCEEDED(hr)) hr = (*ppEvent)->GetStatus(&hrStatus); if (SUCCEEDED(hr)) - DPO->printOut(L"StreamSink::GetEvent: HRESULT=%i %s\n", hrStatus, MediaEventTypeMap.at(meType).c_str()); + DebugPrintOut(L"StreamSink::GetEvent: HRESULT=%i %s\n", hrStatus, MediaEventTypeMap.at(meType).c_str()); else - DPO->printOut(L"StreamSink::GetEvent: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::GetEvent: HRESULT=%i\n", hr); return hr; } @@ -1426,8 +1496,7 @@ public: hr = m_spEventQueue->BeginGetEvent(pCallback, punkState); } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::BeginGetEvent: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::BeginGetEvent: HRESULT=%i\n", hr); return hr; } @@ -1449,14 +1518,13 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); HRESULT hrStatus = S_OK; if (SUCCEEDED(hr)) hr = (*ppEvent)->GetStatus(&hrStatus); if (SUCCEEDED(hr)) - DPO->printOut(L"StreamSink::EndGetEvent: HRESULT=%i %s\n", hrStatus, MediaEventTypeMap.at(meType).c_str()); + DebugPrintOut(L"StreamSink::EndGetEvent: HRESULT=%i %s\n", hrStatus, MediaEventTypeMap.at(meType).c_str()); else - DPO->printOut(L"StreamSink::EndGetEvent: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::EndGetEvent: HRESULT=%i\n", hr); return hr; } @@ -1475,9 +1543,8 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::QueueEvent: HRESULT=%i %s\n", hrStatus, MediaEventTypeMap.at(met).c_str()); - DPO->printOut(L"StreamSink::QueueEvent: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::QueueEvent: HRESULT=%i %s\n", hrStatus, MediaEventTypeMap.at(met).c_str()); + DebugPrintOut(L"StreamSink::QueueEvent: HRESULT=%i\n", hr); return hr; } @@ -1522,13 +1589,14 @@ public: hr = MF_E_INVALIDTYPE; } } + // We don't return any "close match" types. if (ppMediaType) { *ppMediaType = nullptr; } if (ppMediaType && SUCCEEDED(hr)) { - ComPtr pType; + _ComPtr pType; hr = MFCreateMediaType(ppMediaType); if (SUCCEEDED(hr)) { hr = m_pParent->GetUnknown(MF_MEDIASINK_PREFERREDTYPE, __uuidof(IMFMediaType), (LPVOID*)&pType); @@ -1558,8 +1626,7 @@ public: } } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::IsMediaTypeSupported: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::IsMediaTypeSupported: HRESULT=%i\n", hr); return hr; } @@ -1583,8 +1650,7 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::GetMediaTypeCount: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::GetMediaTypeCount: HRESULT=%i\n", hr); return hr; } @@ -1609,7 +1675,7 @@ public: //return preferred type based on media capture library 6 elements preferred preview type //hr = m_spCurrentType.CopyTo(ppType); if (SUCCEEDED(hr)) { - ComPtr pType; + _ComPtr pType; hr = MFCreateMediaType(ppType); if (SUCCEEDED(hr)) { hr = m_pParent->GetUnknown(MF_MEDIASINK_PREFERREDTYPE, __uuidof(IMFMediaType), (LPVOID*)&pType); @@ -1641,8 +1707,7 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::GetMediaTypeByIndex: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::GetMediaTypeByIndex: HRESULT=%i\n", hr); return hr; } @@ -1674,9 +1739,6 @@ public: if (SUCCEEDED(hr)) { - GUID guiMajorType; - pMediaType->GetMajorType(&guiMajorType); - hr = MFCreateMediaType(m_spCurrentType.ReleaseAndGetAddressOf()); if (SUCCEEDED(hr)) { @@ -1686,7 +1748,11 @@ public: { hr = m_spCurrentType->GetGUID(MF_MT_SUBTYPE, &m_guiCurrentSubtype); } + GUID guid; if (SUCCEEDED(hr)) { + hr = m_spCurrentType->GetMajorType(&guid); + } + if (SUCCEEDED(hr) && guid == MFMediaType_Video) { hr = MFGetAttributeSize(m_spCurrentType.Get(), MF_MT_FRAME_SIZE, &m_imageWidthInPixels, &m_imageHeightInPixels); } if (SUCCEEDED(hr)) @@ -1696,8 +1762,7 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::SetCurrentMediaType: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::SetCurrentMediaType: HRESULT=%i\n", hr); return hr; } @@ -1723,8 +1788,7 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::GetCurrentMediaType: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::GetCurrentMediaType: HRESULT=%i\n", hr); return hr; } @@ -1737,13 +1801,12 @@ public: return E_INVALIDARG; } - ComPtr pType; + _ComPtr pType; hr = m_pParent->GetUnknown(MF_MEDIASINK_PREFERREDTYPE, __uuidof(IMFMediaType), (LPVOID*)&pType); if (SUCCEEDED(hr)) { hr = pType->GetMajorType(pguidMajorType); } - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"StreamSink::GetMajorType: HRESULT=%i\n", hr); + DebugPrintOut(L"StreamSink::GetMajorType: HRESULT=%i\n", hr); return hr; } private: @@ -1759,10 +1822,10 @@ private: long m_cRef; #endif IMFAttributes* m_pParent; - ComPtr m_spCurrentType; - ComPtr m_spEventQueue; // Event queue + _ComPtr m_spCurrentType; + _ComPtr m_spEventQueue; // Event queue - ComPtr m_spFTM; + _ComPtr m_spFTM; State m_state; bool m_fGetStartTimeFromSample; bool m_fWaitingForFirstSample; @@ -2296,7 +2359,7 @@ class MediaSink : Microsoft::WRL::Implements, IMFMediaSink, IMFClockStateSink, - FtmBase, + Microsoft::WRL::FtmBase, CBaseAttributes<>> #else public IMFMediaSink, public IMFClockStateSink, public CBaseAttributes<> @@ -2307,11 +2370,11 @@ class MediaSink : public: #else public: - ULONG AddRef() + ULONG STDMETHODCALLTYPE AddRef() { return InterlockedIncrement(&m_cRef); } - ULONG Release() + ULONG STDMETHODCALLTYPE Release() { ULONG cRef = InterlockedDecrement(&m_cRef); if (cRef == 0) @@ -2347,13 +2410,11 @@ public: MediaSink() : m_IsShutdown(false), m_llStartTime(0) { CBaseAttributes<>::Initialize(0U); InitializeCriticalSectionEx(&m_critSec, 3000, 0); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::MediaSink\n"); + DebugPrintOut(L"MediaSink::MediaSink\n"); } virtual ~MediaSink() { - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::~MediaSink\n"); + DebugPrintOut(L"MediaSink::~MediaSink\n"); DeleteCriticalSection(&m_critSec); assert(m_IsShutdown); } @@ -2376,7 +2437,7 @@ public: Microsoft::WRL::ComPtr spInsp; Microsoft::WRL::ComPtr> spSetting; Microsoft::WRL::ComPtr spPropVal; - ComPtr pMedEncProps; + Microsoft::WRL::ComPtr pMedEncProps; UINT32 uiType = ABI::Windows::Media::Capture::MediaStreamType_VideoPreview; hr = pConfiguration->QueryInterface(IID_PPV_ARGS(&spSetting)); @@ -2385,7 +2446,7 @@ public: } if (SUCCEEDED(hr)) { - hr = spSetting->Lookup(HStringReference(MF_PROP_SAMPLEGRABBERCALLBACK).Get(), spInsp.ReleaseAndGetAddressOf()); + hr = spSetting->Lookup(Microsoft::WRL::Wrappers::HStringReference(MF_PROP_SAMPLEGRABBERCALLBACK).Get(), spInsp.ReleaseAndGetAddressOf()); if (FAILED(hr)) { hr = E_INVALIDARG; } @@ -2394,7 +2455,7 @@ public: } } if (SUCCEEDED(hr)) { - hr = spSetting->Lookup(HStringReference(MF_PROP_VIDTYPE).Get(), spInsp.ReleaseAndGetAddressOf()); + hr = spSetting->Lookup(Microsoft::WRL::Wrappers::HStringReference(MF_PROP_VIDTYPE).Get(), spInsp.ReleaseAndGetAddressOf()); if (FAILED(hr)) { hr = E_INVALIDARG; } @@ -2405,7 +2466,7 @@ public: } } if (SUCCEEDED(hr)) { - hr = spSetting->Lookup(HStringReference(MF_PROP_VIDENCPROPS).Get(), spInsp.ReleaseAndGetAddressOf()); + hr = spSetting->Lookup(Microsoft::WRL::Wrappers::HStringReference(MF_PROP_VIDENCPROPS).Get(), spInsp.ReleaseAndGetAddressOf()); if (FAILED(hr)) { hr = E_INVALIDARG; } @@ -2480,14 +2541,13 @@ public: case ABI::Windows::Foundation::PropertyType_String: { - HSTRING value; - hr = pValue->GetString(&value); + Microsoft::WRL::Wrappers::HString value; + hr = pValue->GetString(value.GetAddressOf()); if (SUCCEEDED(hr)) { UINT32 len = 0; - LPCWSTR szValue = WindowsGetStringRawBuffer(value, &len); + LPCWSTR szValue = WindowsGetStringRawBuffer(value.Get(), &len); hr = pAttr->SetString(guidKey, szValue); - WindowsDeleteString(value); } } break; @@ -2516,7 +2576,7 @@ public: case ABI::Windows::Foundation::PropertyType_Inspectable: { - ComPtr value; + Microsoft::WRL::ComPtr value; hr = TYPE_E_TYPEMISMATCH; if (SUCCEEDED(hr)) { @@ -2534,10 +2594,10 @@ public: static HRESULT ConvertPropertiesToMediaType(_In_ ABI::Windows::Media::MediaProperties::IMediaEncodingProperties *pMEP, _Outptr_ IMFMediaType **ppMT) { HRESULT hr = S_OK; - ComPtr spMT; - ComPtr> spMap; - ComPtr*>> spIterable; - ComPtr*>> spIterator; + _ComPtr spMT; + Microsoft::WRL::ComPtr> spMap; + Microsoft::WRL::ComPtr*>> spIterable; + Microsoft::WRL::ComPtr*>> spIterator; if (pMEP == nullptr || ppMT == nullptr) { @@ -2545,7 +2605,7 @@ public: } *ppMT = nullptr; - hr = pMEP->get_Properties(&spMap); + hr = pMEP->get_Properties(spMap.GetAddressOf()); if (SUCCEEDED(hr)) { @@ -2568,9 +2628,9 @@ public: while (hasCurrent) { - ComPtr > spKeyValuePair; - ComPtr spValue; - ComPtr spPropValue; + Microsoft::WRL::ComPtr > spKeyValuePair; + Microsoft::WRL::ComPtr spValue; + Microsoft::WRL::ComPtr spPropValue; GUID guidKey; hr = spIterator->get_Current(&spKeyValuePair); @@ -2609,8 +2669,8 @@ public: if (SUCCEEDED(hr)) { - ComPtr spValue; - ComPtr spPropValue; + Microsoft::WRL::ComPtr spValue; + Microsoft::WRL::ComPtr spPropValue; GUID guiMajorType; hr = spMap->Lookup(MF_MT_MAJOR_TYPE, spValue.GetAddressOf()); @@ -2639,12 +2699,12 @@ public: return hr; } - HRESULT SetMediaStreamProperties( - ABI::Windows::Media::Capture::MediaStreamType MediaStreamType, + //this should be passed through SetProperties! + HRESULT SetMediaStreamProperties(ABI::Windows::Media::Capture::MediaStreamType MediaStreamType, _In_opt_ ABI::Windows::Media::MediaProperties::IMediaEncodingProperties *mediaEncodingProperties) { HRESULT hr = S_OK; - ComPtr spMediaType; + _ComPtr spMediaType; if (MediaStreamType != ABI::Windows::Media::Capture::MediaStreamType_VideoPreview && MediaStreamType != ABI::Windows::Media::Capture::MediaStreamType_VideoRecord && @@ -2657,7 +2717,7 @@ public: if (mediaEncodingProperties != nullptr) { - ComPtr spStreamSink; + _ComPtr spStreamSink; hr = ConvertPropertiesToMediaType(mediaEncodingProperties, &spMediaType); if (SUCCEEDED(hr)) { @@ -2678,18 +2738,18 @@ public: if (pdwCharacteristics == NULL) return E_INVALIDARG; EnterCriticalSection(&m_critSec); if (SUCCEEDED(hr = CheckShutdown())) { - *pdwCharacteristics = MEDIASINK_FIXED_STREAMS; + //if had an activation object for the sink, shut down would be managed and MF_STREAM_SINK_SUPPORTS_ROTATION appears to be setable to TRUE + *pdwCharacteristics = MEDIASINK_FIXED_STREAMS;// | MEDIASINK_REQUIRE_REFERENCE_MEDIATYPE; } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::GetCharacteristics: HRESULT=%i\n", hr); - return S_OK; + DebugPrintOut(L"MediaSink::GetCharacteristics: HRESULT=%i\n", hr); + return hr; } HRESULT STDMETHODCALLTYPE AddStreamSink( DWORD dwStreamSinkIdentifier, IMFMediaType * /*pMediaType*/, IMFStreamSink **ppStreamSink) { - ComPtr spMFStream; - ComPtr pStream; + _ComPtr spMFStream; + _ComPtr pStream; EnterCriticalSection(&m_critSec); HRESULT hr = CheckShutdown(); @@ -2729,7 +2789,7 @@ public: } // Initialize the stream. - ComPtr pAttr; + _ComPtr pAttr; if (SUCCEEDED(hr)) { hr = pStream.As(&pAttr); } @@ -2752,7 +2812,7 @@ public: for (; pos != posEnd; pos = m_streams.Next(pos)) { DWORD dwCurrId; - ComPtr spCurr; + _ComPtr spCurr; hr = m_streams.GetItemPos(pos, &spCurr); if (FAILED(hr)) { @@ -2781,8 +2841,7 @@ public: *ppStreamSink = spMFStream.Detach(); } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::AddStreamSink: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::AddStreamSink: HRESULT=%i\n", hr); return hr; } @@ -2791,7 +2850,7 @@ public: HRESULT hr = CheckShutdown(); ComPtrList::POSITION pos = m_streams.FrontPosition(); ComPtrList::POSITION endPos = m_streams.EndPosition(); - ComPtr spStream; + _ComPtr spStream; if (SUCCEEDED(hr)) { @@ -2821,11 +2880,18 @@ public: if (SUCCEEDED(hr)) { hr = m_streams.Remove(pos, nullptr); - static_cast(spStream.Get())->Shutdown(); + _ComPtr spCustomSink; +#ifdef HAVE_WINRT + spCustomSink = static_cast(spStream.Get()); + hr = S_OK; +#else + hr = spStream.As(&spCustomSink); +#endif + if (SUCCEEDED(hr)) + hr = spCustomSink->Shutdown(); } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::RemoveStreamSink: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::RemoveStreamSink: HRESULT=%i\n", hr); return hr; } @@ -2845,8 +2911,7 @@ public: } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::GetStreamSinkCount: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::GetStreamSinkCount: HRESULT=%i\n", hr); return hr; } @@ -2857,7 +2922,7 @@ public: return E_INVALIDARG; } - ComPtr spStream; + _ComPtr spStream; EnterCriticalSection(&m_critSec); DWORD cStreams = m_streams.GetCount(); @@ -2894,8 +2959,7 @@ public: *ppStreamSink = spStream.Detach(); } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::GetStreamSinkByIndex: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::GetStreamSinkByIndex: HRESULT=%i\n", hr); return hr; } @@ -2908,7 +2972,7 @@ public: EnterCriticalSection(&m_critSec); HRESULT hr = CheckShutdown(); - ComPtr spResult; + _ComPtr spResult; if (SUCCEEDED(hr)) { @@ -2917,7 +2981,7 @@ public: for (; pos != endPos; pos = m_streams.Next(pos)) { - ComPtr spStream; + _ComPtr spStream; hr = m_streams.GetItemPos(pos, &spStream); DWORD dwId; @@ -2950,8 +3014,7 @@ public: *ppStreamSink = spResult.Detach(); } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::GetStreamSinkById: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::GetStreamSinkById: HRESULT=%i\n", hr); return hr; } @@ -2976,7 +3039,7 @@ public: } } - ComPtr pSampleCallback; + _ComPtr pSampleCallback; if (SUCCEEDED(hr)) { // Release the pointer to the old clock. // Store the pointer to the new clock. @@ -2986,8 +3049,7 @@ public: LeaveCriticalSection(&m_critSec); if (SUCCEEDED(hr)) hr = pSampleCallback->OnSetPresentationClock(pPresentationClock); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::SetPresentationClock: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::SetPresentationClock: HRESULT=%i\n", hr); return hr; } @@ -3010,8 +3072,7 @@ public: } } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::GetPresentationClock: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::GetPresentationClock: HRESULT=%i\n", hr); return hr; } @@ -3025,13 +3086,16 @@ public: m_streams.Clear(); m_spClock.ReleaseAndGetAddressOf(); + _ComPtr pType; + hr = CBaseAttributes<>::GetUnknown(MF_MEDIASINK_PREFERREDTYPE, __uuidof(IMFMediaType), (LPVOID*)pType.GetAddressOf()); + if (SUCCEEDED(hr)) { hr = DeleteItem(MF_MEDIASINK_PREFERREDTYPE); + } m_IsShutdown = true; } LeaveCriticalSection(&m_critSec); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::Shutdown: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::Shutdown: HRESULT=%i\n", hr); return hr; } class ShutdownFunc @@ -3039,8 +3103,16 @@ public: public: HRESULT operator()(IMFStreamSink *pStream) const { - static_cast(pStream)->Shutdown(); - return S_OK; + _ComPtr spCustomSink; + HRESULT hr; +#ifdef HAVE_WINRT + spCustomSink = static_cast(pStream); +#else + hr = pStream->QueryInterface(IID_PPV_ARGS(spCustomSink.GetAddressOf())); + if (FAILED(hr)) return hr; +#endif + hr = spCustomSink->Shutdown(); + return hr; } }; @@ -3054,7 +3126,16 @@ public: HRESULT operator()(IMFStreamSink *pStream) const { - return static_cast(pStream)->Start(_llStartTime); + _ComPtr spCustomSink; + HRESULT hr; +#ifdef HAVE_WINRT + spCustomSink = static_cast(pStream); +#else + hr = pStream->QueryInterface(IID_PPV_ARGS(spCustomSink.GetAddressOf())); + if (FAILED(hr)) return hr; +#endif + hr = spCustomSink->Start(_llStartTime); + return hr; } LONGLONG _llStartTime; @@ -3065,7 +3146,16 @@ public: public: HRESULT operator()(IMFStreamSink *pStream) const { - return static_cast(pStream)->Stop(); + _ComPtr spCustomSink; + HRESULT hr; +#ifdef HAVE_WINRT + spCustomSink = static_cast(pStream); +#else + hr = pStream->QueryInterface(IID_PPV_ARGS(spCustomSink.GetAddressOf())); + if (FAILED(hr)) return hr; +#endif + hr = spCustomSink->Stop(); + return hr; } }; @@ -3078,7 +3168,7 @@ public: for (; pos != endPos; pos = col.Next(pos)) { - ComPtr spStream; + _ComPtr spStream; hr = col.GetItemPos(pos, &spStream); if (FAILED(hr)) @@ -3104,14 +3194,13 @@ public: m_llStartTime = llClockStartOffset; hr = ForEach(m_streams, StartFunc(llClockStartOffset)); } - ComPtr pSampleCallback; + _ComPtr pSampleCallback; if (SUCCEEDED(hr)) hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); LeaveCriticalSection(&m_critSec); if (SUCCEEDED(hr)) hr = pSampleCallback->OnClockStart(hnsSystemTime, llClockStartOffset); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::OnClockStart: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::OnClockStart: HRESULT=%i\n", hr); return hr; } @@ -3125,38 +3214,35 @@ public: // Stop each stream hr = ForEach(m_streams, StopFunc()); } - ComPtr pSampleCallback; + _ComPtr pSampleCallback; if (SUCCEEDED(hr)) hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); LeaveCriticalSection(&m_critSec); if (SUCCEEDED(hr)) hr = pSampleCallback->OnClockStop(hnsSystemTime); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::OnClockStop: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::OnClockStop: HRESULT=%i\n", hr); return hr; } HRESULT STDMETHODCALLTYPE OnClockPause( MFTIME hnsSystemTime) { HRESULT hr; - ComPtr pSampleCallback; + _ComPtr pSampleCallback; hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); if (SUCCEEDED(hr)) hr = pSampleCallback->OnClockPause(hnsSystemTime); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::OnClockPause: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::OnClockPause: HRESULT=%i\n", hr); return hr; } HRESULT STDMETHODCALLTYPE OnClockRestart( MFTIME hnsSystemTime) { HRESULT hr; - ComPtr pSampleCallback; + _ComPtr pSampleCallback; hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); if (SUCCEEDED(hr)) hr = pSampleCallback->OnClockRestart(hnsSystemTime); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::OnClockRestart: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::OnClockRestart: HRESULT=%i\n", hr); return hr; } @@ -3164,12 +3250,11 @@ public: MFTIME hnsSystemTime, float flRate) { HRESULT hr; - ComPtr pSampleCallback; + _ComPtr pSampleCallback; hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); if (SUCCEEDED(hr)) hr = pSampleCallback->OnClockSetRate(hnsSystemTime, flRate); - DebugPrintOut *DPO = &DebugPrintOut::getInstance(); - DPO->printOut(L"MediaSink::OnClockSetRate: HRESULT=%i\n", hr); + DebugPrintOut(L"MediaSink::OnClockSetRate: HRESULT=%i\n", hr); return hr; } private: @@ -3179,7 +3264,7 @@ private: CRITICAL_SECTION m_critSec; bool m_IsShutdown; ComPtrList m_streams; - ComPtr m_spClock; + _ComPtr m_spClock; LONGLONG m_llStartTime; }; diff --git a/modules/highgui/src/ppltasks_winrt.h b/modules/highgui/src/ppltasks_winrt.h index 29dccbd70..1243baea9 100644 --- a/modules/highgui/src/ppltasks_winrt.h +++ b/modules/highgui/src/ppltasks_winrt.h @@ -17,24 +17,44 @@ #pragma once +#ifndef _PPLTASKS_WINRT_H +#define _PPLTASKS_WINRT_H + #include #include +#if _MSC_VER >= 1800 +#include + +// Cannot build using a compiler that is older than dev10 SP1 +#ifdef _MSC_VER +#if _MSC_FULL_VER < 160040219 /*IFSTRIP=IGN*/ +#error ERROR: Visual Studio 2010 SP1 or later is required to build ppltasks +#endif /*IFSTRIP=IGN*/ +#endif +#else #include +#endif #include #include #include #include +#if _MSC_VER >= 1800 +#include +#endif #ifndef __cplusplus_winrt #include #include +#if _MSC_VER >= 1800 +#include "agile_wrl.h" +#endif #include #include #ifndef _UITHREADCTXT_SUPPORT -#ifdef WINAPI_FAMILY +#ifdef WINAPI_FAMILY /*IFSTRIP=IGN*/ // It is safe to include winapifamily as WINAPI_FAMILY was defined by the user #include @@ -45,72 +65,72 @@ #elif WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP /*IFSTRIP=IGN*/ // UI thread context support is not required for desktop and Windows Store apps #define _UITHREADCTXT_SUPPORT 0 -#else +#else /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */ #define _UITHREADCTXT_SUPPORT 1 -#endif +#endif /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */ -#else +#else /* WINAPI_FAMILY */ // Not supported without a WINAPI_FAMILY setting. #define _UITHREADCTXT_SUPPORT 0 -#endif // #ifdef WINAPI_FAMILY +#endif /* WINAPI_FAMILY */ -#endif // #ifndef _UITHREADCTXT_SUPPORT +#endif /* _UITHREADCTXT_SUPPORT */ #if _UITHREADCTXT_SUPPORT #include -#endif // _UITHREADCTXT_SUPPORT +#endif /* _UITHREADCTXT_SUPPORT */ #pragma detect_mismatch("_PPLTASKS_WITH_WINRT", "0") + +#ifdef _DEBUG +#define _DBG_ONLY(X) X +#else +#define _DBG_ONLY(X) +#endif // #ifdef _DEBUG + +// std::copy_exception changed to std::make_exception_ptr from VS 2010 to VS 11. +#ifdef _MSC_VER +#if _MSC_VER < 1700 /*IFSTRIP=IGN*/ +namespace std +{ + template exception_ptr make_exception_ptr(_E _Except) + { + return copy_exception(_Except); + } +} +#endif +#ifndef _PPLTASK_ASYNC_LOGGING +#if _MSC_VER >= 1800 && defined(__cplusplus_winrt) +#define _PPLTASK_ASYNC_LOGGING 1 // Only enable async logging under dev12 winrt +#else +#define _PPLTASK_ASYNC_LOGGING 0 +#endif +#endif +#endif + #pragma pack(push,_CRT_PACKING) #pragma warning(push) #pragma warning(disable: 28197) #pragma warning(disable: 4100) // Unreferenced formal parameter - needed for document generation +#if _MSC_VER >= 1800 +#pragma warning(disable: 4127) // constant express in if condition - we use it for meta programming +#else #pragma warning(disable: 4702) // Unreachable code - it is caused by user lambda throw exceptions +#endif // All CRT public header files are required to be protected from the macro new #pragma push_macro("new") #undef new -#define __is_valid_winrt_type(_Type) (std::is_void<_Type>::value || \ - std::is_same<_Type, BYTE>::value || \ - std::is_same<_Type, INT16>::value || \ - std::is_same<_Type, UINT16>::value || \ - std::is_same<_Type, INT32>::value || \ - std::is_same<_Type, UINT32>::value || \ - std::is_same<_Type, INT64>::value || \ - std::is_same<_Type, UINT64>::value || \ - std::is_same<_Type, FLOAT>::value || \ - std::is_same<_Type, DOUBLE>::value || \ - std::is_same<_Type, WCHAR>::value || \ - std::is_same<_Type, boolean>::value || \ - std::is_same<_Type, HSTRING>::value || \ - std::is_same<_Type, IInspectable *>::value || \ - std::is_same<_Type, GUID>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::DateTime>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::TimeSpan>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Point>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Size>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Rect>::value || \ - std::is_same<_Type, BYTE*>::value || \ - std::is_same<_Type, INT16*>::value || \ - std::is_same<_Type, UINT16*>::value || \ - std::is_same<_Type, INT32*>::value || \ - std::is_same<_Type, UINT32*>::value || \ - std::is_same<_Type, INT64*>::value || \ - std::is_same<_Type, UINT64*>::value || \ - std::is_same<_Type, FLOAT*>::value || \ - std::is_same<_Type, DOUBLE*>::value || \ - std::is_same<_Type, WCHAR*>::value || \ - std::is_same<_Type, boolean*>::value || \ - std::is_same<_Type, HSTRING*>::value || \ - std::is_same<_Type, IInspectable **>::value || \ - std::is_same<_Type, GUID*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::DateTime*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::TimeSpan*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Point*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Size*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Rect*>::value) +// stuff ported from Dev11 CRT +// NOTE: this doesn't actually match std::declval. it behaves differently for void! +// so don't blindly change it to std::declval. +namespace stdx +{ + template + _T&& declval(); +} /// /// The Concurrency_winrt namespace provides classes and functions that give you access to the Concurrency Runtime, @@ -119,7 +139,38 @@ /**/ namespace Concurrency_winrt { + // In debug builds, default to 10 frames, unless this is overridden prior to #includ'ing ppltasks.h. In retail builds, default to only one frame. +#ifndef PPL_TASK_SAVE_FRAME_COUNT +#ifdef _DEBUG +#define PPL_TASK_SAVE_FRAME_COUNT 10 +#else +#define PPL_TASK_SAVE_FRAME_COUNT 1 +#endif +#endif + + /// + /// Helper macro to determine how many stack frames need to be saved. When any number less or equal to 1 is specified, + /// only one frame is captured and no stackwalk will be involved. Otherwise, the number of callstack frames will be captured. + /// + /// + /// This needs to be defined as a macro rather than a function so that if we're only gathering one frame, _ReturnAddress() + /// will evaluate to client code, rather than a helper function inside of _TaskCreationCallstack, itself. + /// +#ifdef _CAPTURE_CALLSTACK +#undef _CAPTURE_CALLSTACK +#endif +#if PPL_TASK_SAVE_FRAME_COUNT > 1 +#if !defined(_DEBUG) +#pragma message ("WARNING: Redefinning PPL_TASK_SAVE_FRAME_COUNT under Release build for non-desktop applications is not supported; only one frame will be captured!") +#define _CAPTURE_CALLSTACK() ::Concurrency_winrt::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress()) +#else +#define _CAPTURE_CALLSTACK() ::Concurrency_winrt::details::_TaskCreationCallstack::_CaptureMultiFramesCallstack(PPL_TASK_SAVE_FRAME_COUNT) +#endif +#else +#define _CAPTURE_CALLSTACK() ::Concurrency_winrt::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress()) +#endif /// + /// A type that represents the terminal state of a task. Valid values are completed and canceled. /// /// @@ -151,7 +202,18 @@ template <> class task; /// /// /**/ -_CRTIMP2 bool __cdecl is_task_cancellation_requested(); +#if _MSC_VER >= 1800 +inline bool __cdecl is_task_cancellation_requested() +{ + return ::Concurrency::details::_TaskCollection_t::_Is_cancellation_requested(); +} +#else +inline bool __cdecl is_task_cancellation_requested() +{ + // ConcRT scheduler under the hood is using TaskCollection, which is same as task_group + return ::Concurrency::is_current_task_group_canceling(); +} +#endif /// /// Cancels the currently executing task. This function can be called from within the body of a task to abort the @@ -164,10 +226,56 @@ _CRTIMP2 bool __cdecl is_task_cancellation_requested(); /// /// /**/ -_CRTIMP2 __declspec(noreturn) void __cdecl cancel_current_task(); +//#if _MSC_VER >= 1800 +inline __declspec(noreturn) void __cdecl cancel_current_task() +{ + throw Concurrency::task_canceled(); +} +//#else +//_CRTIMP2 __declspec(noreturn) void __cdecl cancel_current_task(); +//#endif namespace details { +#if _MSC_VER >= 1800 + /// + /// Callstack container, which is used to capture and preserve callstacks in ppltasks. + /// Members of this class is examined by vc debugger, thus there will be no public access methods. + /// Please note that names of this class should be kept stable for debugger examining. + /// + class _TaskCreationCallstack + { + private: + // If _M_SingleFrame != nullptr, there will be only one frame of callstacks, which is stored in _M_SingleFrame; + // otherwise, _M_Frame will store all the callstack frames. + void* _M_SingleFrame; + std::vector _M_frames; + public: + _TaskCreationCallstack() + { + _M_SingleFrame = nullptr; + } + + // Store one frame of callstack. This function works for both Debug / Release CRT. + static _TaskCreationCallstack _CaptureSingleFrameCallstack(void *_SingleFrame) + { + _TaskCreationCallstack _csc; + _csc._M_SingleFrame = _SingleFrame; + return _csc; + } + + // Capture _CaptureFrames number of callstack frames. This function only work properly for Desktop or Debug CRT. + __declspec(noinline) + static _TaskCreationCallstack _CaptureMultiFramesCallstack(size_t _CaptureFrames) + { + _TaskCreationCallstack _csc; + _csc._M_frames.resize(_CaptureFrames); + // skip 2 frames to make sure callstack starts from user code + _csc._M_frames.resize(::Concurrency::details::platform::CaptureCallstack(&_csc._M_frames[0], 2, _CaptureFrames)); + return _csc; + } + }; +#endif typedef UINT32 _Unit_type; struct _TypeSelectorNoAsync {}; @@ -231,12 +339,12 @@ namespace details typedef _Type _Value; }; - struct _NonUserType { public: int _Dummy; }; + //struct _NonUserType { public: int _Dummy; }; template struct _ValueTypeOrRefType { - typedef _NonUserType _Value; + typedef _Unit_type _Value; }; template @@ -245,6 +353,18 @@ namespace details typedef _Type _Value; }; + template + _Ty _UnwrapAsyncActionWithProgressSelector(ABI::Windows::Foundation::IAsyncActionWithProgress_impl<_Ty>*); + + template + _Ty _UnwrapAsyncActionWithProgressSelector(...); + + template + _Progress _UnwrapAsyncOperationWithProgressProgressSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress_impl<_Ty, _Progress>*); + + template + _Progress _UnwrapAsyncOperationWithProgressProgressSelector(...); + template _T2 _ProgressTypeSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2>*); @@ -254,42 +374,7 @@ namespace details template struct _GetProgressType { - typedef decltype(_ProgressTypeSelector(std::declval<_Type>())) _Value; - }; - - template