Commit b5a4159e authored by GregoryMorse's avatar GregoryMorse

Add support for WinRT in the MF capture framework by removing the disallowed…

Add support for WinRT in the MF capture framework by removing the disallowed calls to enumerate devices and create a sample grabber sink and adding framework for the MediaCapture interface and a custom sink which interfaces with the sample grabber callback interface. The change requires discussion for making it completely functional as redundancy is required given that if the source is a video file, the old code pathways must be used. Otherwise all IMFMediaSession, IMFMediaSource, and IMFActivate code must use a MediaCapture code path and all sink code must use the CMediaSink custom sink.

Support for the custom sink is extended to non-WinRT not for compatibility as Windows Vista client is a minimum regardless, but because it offers more flexibility, could be faster and is able to be used as an optionally different code path during sink creation based on a future configuration parameter.

My discussion and proposal to finish this change:
 Devices are so easily enumerated through WinRT Windows.Devices namespace that wrapping the calls in a library is quite a chore for little benefit though to get the various modes and formats could still be a worthwhile project. For now conditional compilation to remove videodevices and any offending non-video file related activity in videodevice. In my opinion, this is a different , far less fundamental and important change which can possibly be done as a future project and also much more easily implemented in C++/CX.

ImageGrabber has the IMFSampleGrabberSinkCallback replaced with a base class (SharedSampleGrabber) which also be is base class for ImageGrabberRT. This change is necessary as the custom sink does not require a thread to pump events which is done through MediaCapture already. IMFSampleGrabberSinkCallback is the common element between both models and that piece can be shared. Initializing the new ImageGrabberRT is as simple as passing an already initialized MediaCapture object and any video format/encoding parameters.

The concurrency event is necessary to wait for completion and is the way the underlying, IAsyncAction wrappers in the task library work as well. Native WIN32 event objects would be an option if HAVE_CONCURRENCY is not defined. I could even imagine doing it with sleep/thread yield and InterlockedCompareExchange yet I am not enthusiastic about that approach either. Since there is a specific compiler HAVE_ for concurrency, I do not like pulling it in though I think for WinRT it is safe to say we will always have it available though should probably conditionally compile with the Interlocked option as WIN32 events would require HAVE_WIN32.

It looks like C++/CX cannot be used for the IMediaExtension sink (which should not be a problem) as using COM objects requires WRL and though deriving from IMediaExtension can be done, there is little purpose without COM. Objects from C++/CX can be swapped to interact with objects from native C++ as Inspectable* can reinterpret_cast to the ref object IInspectable^ and vice-versa. A solution to the COM class with C++/CX would be great so we could have dual support. Also without #define for every WRL object in use, the code will get quite muddy given that the */^ would need to be ifdef'd everywhere.

Fixed bugs and completed the change.  I believe the new classes need to be moved to a header file as the file has become to large and more classes need to be added for handling all the asynchronous problems (one wrapping IAsyncAction in a task and another for making a task out of IAsyncAction).  Unfortunately, blocking on the UI thread is not an option in WinRT so a synchronous architecture is considered "illegal" by Microsoft's standards even if implementable (C++/CX ppltasks library throws errors if you try it).  Worse, either by design or a bug in the MF MediaCapture class with Custom Sinks causes a crash if stop/start previewing without reinitializing (spPreferredPreviewMediaType is fatally nulled).  After decompiling Windows.Media.dll, I worked around this in my own projects by using an activate-able custom sink ID which strangely assigns 1 to this pointer allowing it to be reinitialized in what can only be described as a hack by Microsoft.  This would add additional overhead to the project to implement especially for static libraries as it requires IDL/DLL exporting followed by manifest declaration.  Better to document that it is not supported.

Furthermore, an additional class for IMFAttributes should be implemented to make clean architecture for passing around attributes as opposed to directly calling non-COM interface calls on the objects and making use of SetProperties which would also be a set up for an object that uses the RuntimeClass activation ID.

The remaining changes are not difficult and will be complete soon along with debug tracing messages.

Update and rename cap_msmf.h to cap_msmf.hpp

Successful test - samples are grabbed

Library updated and cleaned up with comments, marshaling, exceptions and linker settings
Fixed trailing whitespace

VS 2013 support and cleanup consistency plus C++/CX new object fixed

Conflicts:
	modules/highgui/src/cap_msmf.cpp
	modules/highgui/src/cap_msmf.hpp
	modules/highgui/src/ppltasks_winrt.h

Fix merge conflicts

VS 2013 Update 2 library bug fix integrated

a-wi's changed integrated
parent 0f1a0a98
//
// 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 <algorithm>
#include <wrl\client.h>
template <typename T, bool TIsNotAgile> class Agile;
template <typename T>
struct UnwrapAgile
{
static const bool _IsAgile = false;
};
template <typename T>
struct UnwrapAgile<Agile<T, false>>
{
static const bool _IsAgile = true;
};
template <typename T>
struct UnwrapAgile<Agile<T, true>>
{
static const bool _IsAgile = true;
};
#define IS_AGILE(T) UnwrapAgile<T>::_IsAgile
#define __is_winrt_agile(T) (std::is_same<T, HSTRING__>::value || std::is_base_of<Microsoft::WRL::FtmBase, T>::value || std::is_base_of<IAgileObject, T>::value) //derived from Microsoft::WRL::FtmBase or IAgileObject
#define __is_win_interface(T) (std::is_base_of<IUnknown, T>::value || std::is_base_of<IInspectable, T>::value) //derived from IUnknown or IInspectable
#define __is_win_class(T) (std::is_same<T, HSTRING__>::value || std::is_base_of<Microsoft::WRL::Details::RuntimeClassBase, T>::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 <typename T>
#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<IUnknown**>(&ObjectIn), __uuidof(T*), ContextCallBack, reinterpret_cast<IUnknown**>(Proxy));
#else
return GetProxyImpl(*reinterpret_cast<IUnknown**>(&const_cast<T*>(ObjectIn)), __uuidof(T*), ContextCallBack, reinterpret_cast<IUnknown**>(Proxy));
#endif
}
template <typename T>
inline HRESULT ReleaseInContext(T *ObjectIn, IUnknown *ContextCallBack)
{
return ReleaseInContextImpl(ObjectIn, ContextCallBack);
}
template <typename T>
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<T*>(_p);
}
__declspec(no_refcount) __declspec(no_release_return)
operator T * ()
{
return reinterpret_cast<T*>(_p);
}
private:
AgileHelper(const AgileHelper&);
AgileHelper operator=(const AgileHelper&);
};
template <typename T>
struct __remove_hat
{
typedef T type;
};
template <typename T>
struct __remove_hat<T*>
{
typedef T type;
};
template <typename T>
struct AgileTypeHelper
{
typename typedef __remove_hat<T>::type type;
typename typedef __remove_hat<T>::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<T>::type) && !__is_winrt_agile(typename Details::AgileTypeHelper<T>::type)) ||
__is_win_interface(typename Details::AgileTypeHelper<T>::type)
>
class Agile
{
static_assert(__is_win_class(typename Details::AgileTypeHelper<T>::type) || __is_win_interface(typename Details::AgileTypeHelper<T>::type), "Agile can only be used with ref class or interface class types");
typename typedef Details::AgileTypeHelper<T>::agileMemberType TypeT;
TypeT _object;
::Microsoft::WRL::ComPtr<IUnknown> _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<IAgileObject> checkIfAgile;
HRESULT hr = reinterpret_cast<IUnknown*>(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(&currentContextToken));
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<IAgileObject> checkIfAgile;
HRESULT hr = reinterpret_cast<IUnknown*>(localObject)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile);
#else
::Microsoft::WRL::ComPtr<IAgileObject> checkIfAgile;
HRESULT hr = reinterpret_cast<IUnknown*>(_object)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile);
#endif
if (hr == S_OK)
{
auto pThis = const_cast<Agile*>(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<Agile*>(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<IUnknown> 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(&currentContextToken));
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<void*>(_object) < reinterpret_cast<void*>(other._object))
{
return true;
}
return _object == other._object && _contextToken < other._contextToken;
}
};
template <typename T>
class Agile<T, false>
{
static_assert(__is_win_class(typename Details::AgileTypeHelper<T>::type) || __is_win_interface(typename Details::AgileTypeHelper<T>::type), "Agile can only be used with ref class or interface class types");
typename typedef Details::AgileTypeHelper<T>::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<IUnknown> 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<void*>(_object) < reinterpret_cast<void*>(other._object);
}
};
#pragma warning(pop)
template<class U>
bool operator==(nullptr_t, const Agile<U>& a) throw()
{
return a == nullptr;
}
template<class U>
bool operator!=(const Agile<U>& a, nullptr_t) throw()
{
return !(a == nullptr);
}
template<class U>
bool operator!=(nullptr_t, const Agile<U>& a) throw()
{
return !(a == nullptr);
}
template<class U>
bool operator!=(const Agile<U>& a, const Agile<U>& b) throw()
{
return !(a == b);
}
#endif // _PLATFORM_AGILE_H_
......@@ -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 <windows.h>
#include <guiddef.h>
#include <mfidl.h>
#include <Mfapi.h>
#include <mfplay.h>
#include <mfobjects.h>
#include <tchar.h>
#include <strsafe.h>
#include <Mfreadwrite.h>
#include <new>
......@@ -71,13 +80,11 @@
#pragma comment(lib, "Mfreadwrite")
#pragma comment(lib, "MinCore_Downlevel")
// for ComPtr usage
#include <wrl/client.h>
using namespace Microsoft::WRL;
#include <mferror.h>
#ifdef HAVE_WINRT
// for ComPtr usage
#include <wrl/client.h>
#ifdef __cplusplus_winrt
#include <agile.h>
#include <vccorlib.h>
......@@ -89,10 +96,169 @@ using namespace Microsoft::WRL;
#include <wrl\wrappers\corewrappers.h>
#include <windows.media.capture.h>
#include <windows.devices.enumeration.h>
#ifdef HAVE_CONCURRENCY
#include <concrt.h>
#include <ppltasks.h>
#ifndef __cplusplus_winrt
__declspec(noreturn) void __stdcall __abi_WinRTraiseException(long);
inline void __abi_ThrowIfFailed(long __hrArg)
{
if (__hrArg < 0)
{
__abi_WinRTraiseException(__hrArg);
}
}
using namespace Microsoft::WRL::Wrappers;
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<const __s_GUID&>(__guid).Data1),
__b(reinterpret_cast<const __s_GUID&>(__guid).Data2),
__c(reinterpret_cast<const __s_GUID&>(__guid).Data3),
__d(reinterpret_cast<const __s_GUID&>(__guid).Data4[0]),
__e(reinterpret_cast<const __s_GUID&>(__guid).Data4[1]),
__f(reinterpret_cast<const __s_GUID&>(__guid).Data4[2]),
__g(reinterpret_cast<const __s_GUID&>(__guid).Data4[3]),
__h(reinterpret_cast<const __s_GUID&>(__guid).Data4[4]),
__i(reinterpret_cast<const __s_GUID&>(__guid).Data4[5]),
__j(reinterpret_cast<const __s_GUID&>(__guid).Data4[6]),
__k(reinterpret_cast<const __s_GUID&>(__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<unsigned long*>(&__aArg);
auto __b = reinterpret_cast<unsigned long*>(&__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<unsigned long*>(&__aArg);
auto __b = reinterpret_cast<unsigned long*>(&__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 <atlbase.h>
#endif
struct IMFMediaType;
......@@ -114,18 +280,23 @@ template <class T> 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<UINT64, FrameRateMap> 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<HRESULT>* pTask, MAKE_WRL_REF(_IDeviceInformation)* ppDevice);
#ifdef HAVE_CONCURRENCY
long checkDevice(_DeviceClass devClass, DEFINE_TASK<void>* 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,6 +746,14 @@ void DebugPrintOut::printOut(const wchar_t *format, ...)
wchar_t *p = NULL;
va_list args;
va_start(args, format);
if( ::IsDebuggerPresent() )
{
WCHAR szMsg[512];
::StringCchVPrintfW(szMsg, sizeof(szMsg)/sizeof(szMsg[0]), format, args);
::OutputDebugStringW(szMsg);
}
else
{
if(wcscmp(format, L"%i"))
{
i = va_arg (args, int);
......@@ -567,14 +763,16 @@ void DebugPrintOut::printOut(const wchar_t *format, ...)
p = va_arg (args, wchar_t *);
}
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<IMFMediaType> pType = NULL;
_ComPtr<IMFMediaType> 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<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(pAction, context, this)
HRESULT hr;
DO_ACTION_SYNCHRONOUSLY(hr, pAction, context);
#ifdef HAVE_CONCURRENCY
DEFINE_TASK<void> _task = CREATE_TASK DEFINE_RET_TYPE(void)(pAction);
*action = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(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<IMFActivate> pSinkActivate = NULL;
ComPtr<IMFMediaType> pType = NULL;
ComPtr<IMFPresentationDescriptor> pPD = NULL;
ComPtr<IMFStreamDescriptor> pSD = NULL;
ComPtr<IMFMediaTypeHandler> pHandler = NULL;
ComPtr<IMFMediaType> pCurrentType = NULL;
HRESULT hr = S_OK;
_ComPtr<IMFActivate> pSinkActivate = NULL;
_ComPtr<IMFMediaType> pType = NULL;
_ComPtr<IMFPresentationDescriptor> pPD = NULL;
_ComPtr<IMFStreamDescriptor> pSD = NULL;
_ComPtr<IMFMediaTypeHandler> pHandler = NULL;
_ComPtr<IMFMediaType> 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<IMFMediaEvent> pEvent = NULL;
_ComPtr<IMFMediaEvent> 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<IMFPresentationDescriptor> pPD = NULL;
ComPtr<IMFStreamDescriptor> pSD = NULL;
ComPtr<IMFMediaTypeHandler> pHandler = NULL;
ComPtr<IMFTopologyNode> pNode1 = NULL;
ComPtr<IMFTopologyNode> pNode2 = NULL;
_ComPtr<IMFPresentationDescriptor> pPD = NULL;
_ComPtr<IMFStreamDescriptor> pSD = NULL;
_ComPtr<IMFMediaTypeHandler> pHandler = NULL;
_ComPtr<IMFTopologyNode> pNode1 = NULL;
_ComPtr<IMFTopologyNode> 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<IMFTopologyNode> pNode = NULL;
_ComPtr<IMFTopologyNode> 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<IMFTopologyNode> pNode = NULL;
_ComPtr<IMFTopologyNode> 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<IMFAttributes> pAttributes = NULL;
_ComPtr<IMFAttributes> 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<void> _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<MAKE_WRL_REF(_AsyncAction)>(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<MAKE_WRL_REF(_AsyncAction)>(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<HRESULT>* pTask, MAKE_WRL_REF(_IDeviceInformation)* ppDevice)
#ifdef HAVE_CONCURRENCY
long videoDevice::checkDevice(_DeviceClass devClass, DEFINE_TASK<void>* 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<HRESULT>* pTask
MAKE_WRL_REF(_AsyncOperation<MAKE_WRL_REF(_DeviceInformationCollection)>) pAction;
WRL_METHOD(pDevStat, _FindAllAsyncDeviceClass, pAction, hr, devClass)
if (SUCCEEDED(hr)) {
*pTask = CREATE_TASK([pAction, &ppDevice, this]() -> HRESULT {
HRESULT hr;
MAKE_WRL_OBJ(_VectorView<MAKE_WRL_REF(_DeviceInformation)>) 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<MAKE_WRL_REF(_DeviceInformation)>) pVector =
CREATE_TASK DEFINE_RET_TYPE(MAKE_WRL_REF(_VectorView<MAKE_WRL_REF(_DeviceInformation)>))(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<HRESULT>* 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<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(pOldAction, context, this)
vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(void, pOldAction, context, this)
HRESULT hr;
if (pOldAction) DO_ACTION_SYNCHRONOUSLY(hr, pOldAction, GET_CURRENT_CONTEXT);
DEFINE_TASK<HRESULT> pTask;
if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait();
DEFINE_TASK<void> 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<void> _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<ABI::Windows::Media::Capture::IMediaCapture*>(DEREF_AGILE_WRL_OBJ(vd_pMedCap))->add_Failed(Microsoft::WRL::Callback<ABI::Windows::Media::Capture::IMediaCaptureFailedEventHandler>([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<ABI::Windows::Media::Capture::IMediaCapture*>(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<IMFAttributes> pAttributes = NULL;
_ComPtr<IMFAttributes> 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<ABI::Windows::Media::Capture::IMediaCapture*>(DEREF_AGILE_WRL_OBJ(vd_pMedCap)));
SafeRelease(&vd_pMedCapFail);
vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(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<ABI::Windows::Media::Capture::IMediaCapture*>(DEREF_AGILE_WRL_OBJ(vd_pMedCap))->remove_Failed(vd_cookie);
vd_cookie.value = 0;
vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(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<UINT64, FrameRateMap>::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<UINT64, SUBTYPEMap>::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<UINT64, SUBTYPEMap>::iterator f = FRM.begin();
for(; f != FRM.end(); f++)
{
if((*f).first >= frameRateMax)
{
if(frameRate > (*f).first)
// 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<String, vectorNum>::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];
}
......@@ -2310,9 +2510,12 @@ void videoDevice::buildLibraryofTypes()
std::vector<MediaType>::iterator i = vd_CurrentFormats.begin();
int count = 0;
for(; i != vd_CurrentFormats.end(); i++)
{
// 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;
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);
......@@ -2321,6 +2524,7 @@ void videoDevice::buildLibraryofTypes()
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<IMFPresentationDescriptor> pPD = NULL;
ComPtr<IMFStreamDescriptor> pSD = NULL;
ComPtr<IMFMediaTypeHandler> pHandler = NULL;
ComPtr<IMFMediaType> pType = NULL;
_ComPtr<IMFPresentationDescriptor> pPD = NULL;
_ComPtr<IMFStreamDescriptor> pSD = NULL;
_ComPtr<IMFMediaTypeHandler> pHandler = NULL;
_ComPtr<IMFMediaType> 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<MAKE_WRL_REF(_AsyncAction)>(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<void> _task = CREATE_TASK DEFINE_RET_TYPE(void)(action);
vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(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<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(pOldAction, context, id, DPO, this)
vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(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)) {
DEFINE_TASK<void> _task;
BEGIN_CALL_IN_CONTEXT(hr, context, id, &_task, this)
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);
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<IMFMediaType> pType = NULL;
_ComPtr<IMFMediaType> 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<IMFPresentationDescriptor> pPD = NULL;
ComPtr<IMFStreamDescriptor> pSD = NULL;
ComPtr<IMFMediaTypeHandler> pHandler = NULL;
ComPtr<IMFMediaType> pType = NULL;
_ComPtr<IMFPresentationDescriptor> pPD = NULL;
_ComPtr<IMFStreamDescriptor> pSD = NULL;
_ComPtr<IMFMediaTypeHandler> pHandler = NULL;
_ComPtr<IMFMediaType> pType = NULL;
HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf());
if (FAILED(hr))
{
......@@ -2649,11 +2865,12 @@ long videoDevices::initDevices(_DeviceClass devClass)
MAKE_WRL_REF(_AsyncOperation<MAKE_WRL_REF(_DeviceInformationCollection)>) pAction;
WRL_METHOD(pDevStat, _FindAllAsyncDeviceClass, pAction, hr, devClass)
if (SUCCEEDED(hr)) {
#ifdef HAVE_CONCURRENCY
SAVE_CURRENT_CONTEXT(context);
vds_enumTask = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(pAction, context, this)
HRESULT hr;
MAKE_WRL_OBJ(_VectorView<MAKE_WRL_REF(_DeviceInformation)>) pVector;
DO_OPERATION_SYNCHRONOUSLY_VECTOR(hr, pAction, GET_CURRENT_CONTEXT, pVector, _VectorView, _DeviceInformation, _DeviceInformationCollection);
vds_enumTask = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(void, pAction, context, this)
HRESULT hr = S_OK;
MAKE_WRL_OBJ(_VectorView<MAKE_WRL_REF(_DeviceInformation)>) pVector =
CREATE_TASK DEFINE_RET_TYPE(MAKE_WRL_REF(_VectorView<MAKE_WRL_REF(_DeviceInformation)>))(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<bool> 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<IMFSourceResolver> pSourceResolver = NULL;
_ComPtr<IMFSourceResolver> 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<IMFPresentationDescriptor> pPD = NULL;
ComPtr<IMFStreamDescriptor> pSD = NULL;
ComPtr<IMFMediaTypeHandler> pHandler = NULL;
ComPtr<IMFMediaType> pType = NULL;
_ComPtr<IMFPresentationDescriptor> pPD = NULL;
_ComPtr<IMFStreamDescriptor> pSD = NULL;
_ComPtr<IMFMediaTypeHandler> pHandler = NULL;
_ComPtr<IMFMediaType> pType = NULL;
HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf());
if (FAILED(hr))
{
......@@ -3834,7 +4072,7 @@ private:
GUID inputFormat;
DWORD streamIndex;
ComPtr<IMFSinkWriter> sinkWriter;
_ComPtr<IMFSinkWriter> 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<IMFAttributes> spAttr;
ComPtr<IMFMediaType> mediaTypeOut;
ComPtr<IMFMediaType> mediaTypeIn;
ComPtr<IMFByteStream> spByteStream;
_ComPtr<IMFAttributes> spAttr;
_ComPtr<IMFMediaType> mediaTypeOut;
_ComPtr<IMFMediaType> mediaTypeIn;
_ComPtr<IMFByteStream> 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<IMFSample> sample;
ComPtr<IMFMediaBuffer> buffer;
_ComPtr<IMFSample> sample;
_ComPtr<IMFMediaBuffer> buffer;
const LONG cbWidth = 4 * videoWidth;
const DWORD cbBuffer = cbWidth * videoHeight;
......
#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<typename _Type, bool bUnknown = std::is_base_of<IUnknown, _Type>::value>
struct winrt_type
{
};
template<typename _Type>
struct winrt_type<_Type, true>
{
static IUnknown* create(_Type* _ObjInCtx) {
return reinterpret_cast<IUnknown*>(_ObjInCtx);
}
static IID getuuid() { return __uuidof(_Type); }
static const ABI::Windows::Foundation::PropertyType _PropType = ABI::Windows::Foundation::PropertyType::PropertyType_OtherType;
};
template <typename _Type>
struct winrt_type<_Type, false>
{
static IUnknown* create(_Type* _ObjInCtx) {
Microsoft::WRL::ComPtr<IInspectable> _PObj;
Microsoft::WRL::ComPtr<IActivationFactory> 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<ABI::Windows::Foundation::IPropertyValueStatics> 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<IUnknown*>(_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<void>
{
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<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<typename _Type>
struct winrt_array_type
{
static IUnknown* create(_Type* _ObjInCtx, size_t N) {
Microsoft::WRL::ComPtr<IInspectable> _PObj;
Microsoft::WRL::ComPtr<IActivationFactory> 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<ABI::Windows::Foundation::IPropertyValueStatics> 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<IUnknown*>(_PObj.Detach());
}
return nullptr;
}
static const ABI::Windows::Foundation::PropertyType _PropType = ABI::Windows::Foundation::PropertyType::PropertyType_OtherTypeArray;
};
template<int>
struct winrt_prop_type {};
template <>
struct winrt_prop_type<ABI::Windows::Foundation::PropertyType_Empty> {
typedef void _Type;
};
template <>
struct winrt_prop_type<ABI::Windows::Foundation::PropertyType_OtherType> {
typedef void _Type;
};
template <>
struct winrt_prop_type<ABI::Windows::Foundation::PropertyType_OtherTypeArray> {
typedef void _Type;
};
#define MAKE_PROP(Prop, Type) template <>\
struct winrt_prop_type<ABI::Windows::Foundation::PropertyType_##Prop> {\
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<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<Type> PropertyValueToVector(ABI::Windows::Foundation::IPropertyValue* propValue)\
{\
UINT32 uLen = 0;\
Type* pArray = nullptr;\
propValue->Get##Name##Array(&uLen, &pArray);\
return std::vector<Type>(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<T*>
{
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<Microsoft::WRL::Details::RuntimeClassBase, _Type>::value || \
std::is_base_of<IInspectable, typename DerefHelper<_Type>::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<Windows::Foundation::IAsyncAction^>(action), ctxt)
#define DO_OPERATION_SYNCHRONOUSLY_VECTOR(hr, action, ctxt, pResult, vectortype, elementtype, _type) hr = S_OK;\
pResult = CCompletionHandler::PerformSynchronously<_type^>(reinterpret_cast<Windows::Foundation::IAsyncOperation<_type^>^>(action), ctxt)
#define BEGIN_CREATE_ASYNC(...) reinterpret_cast<ABI::Windows::Foundation::IAsyncAction*>(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<rettype>()) ? 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<x^>
#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<objtype^>(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<type*>(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<ABI::Windows::Foundation::IAsyncActionCompletedHandler, ABI::Windows::Foundation::IAsyncAction>::PerformActionSynchronously(action, ctxt)
#define DO_OPERATION_SYNCHRONOUSLY_VECTOR(hr, action, ctxt, pResult, vectortype, elementtype, _type) hr = CCompletionHandler<ABI::Windows::Foundation::IAsyncOperationCompletedHandler<_type*>, ABI::Windows::Foundation::IAsyncOperation<_type*>>::PerformSynchronously<vectortype<elementtype*>*>(action, ctxt, pResult.GetAddressOf())
#define BEGIN_CREATE_ASYNC(...) Concurrency_winrt::create_async([__VA_ARGS__]() -> HRESULT {
#define BEGIN_CREATE_ASYNC(type, ...) Concurrency_winrt::create_async<type>([__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<rettype>()) ? 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<rettype>()) ? Concurrency_winrt::create_task<rettype>(func) : _task.then([func](rettype, rettype* retVal) -> HRESULT { return func(retVal); });
#define DEFINE_RET_VAL(x) x* retVal
#define DEFINE_RET_TYPE(x) <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<x>
#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<objtype> 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<objtype>()
#define ACTIVATE_LOCAL_OBJ(objtype, ...) Microsoft::WRL::Make<objtype>(__VA_ARGS__)
#define ACTIVATE_EVENT_HANDLER(objtype, ...) Microsoft::WRL::Callback<objtype>(__VA_ARGS__).Get()
#define ACTIVATE_OBJ(rtclass, objtype, obj, hr) MAKE_WRL_OBJ(objtype) obj;\
{\
Microsoft::WRL::ComPtr<IActivationFactory> 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 <typename TCompletionHandler, typename TAction>
class CCompletionHandler
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::ClassicCom>,
TCompletionHandler, IAgileObject, FtmBase>
#endif
template <class T>
class ComPtr : public ATL::CComPtr<T>
{
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 <typename TResult>
static TResult PerformSynchronously(Windows::Foundation::IAsyncOperation<TResult>^ asyncOp, _ContextCallback context)
{
TResult pResult;
context._CallInContext([asyncOp, &pResult]() { Concurrency::task<TResult> asyncTask = Concurrency::task<TResult>(asyncOp); pResult = asyncTask.get(); });
return pResult;
#else
template <typename TResult>
static HRESULT PerformSynchronously(TAction* asyncOp, _ContextCallback context, TResult* pResult)
ComPtr(int nNull) throw() :
CComPtr<T>((T*)nNull)
{
HRESULT hr;
ComPtr<CCompletionHandler<TCompletionHandler, TAction>> completeHandler = Microsoft::WRL::Make<CCompletionHandler<TCompletionHandler, TAction>>();
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(T* lp) throw() :
CComPtr<T>(lp)
#ifdef __cplusplus_winrt
static void PerformActionSynchronously(Windows::Foundation::IAsyncAction^ asyncOp, _ContextCallback context)
{
context._CallInContext([asyncOp](){ Concurrency::task<void>(asyncOp).get(); });
#else
static HRESULT PerformActionSynchronously(TAction* asyncOp, _ContextCallback context)
}
ComPtr(_In_ const CComPtr<T>& lp) throw() :
CComPtr<T>(lp.p)
{
HRESULT hr;
ComPtr<CCompletionHandler<TCompletionHandler, TAction>> completeHandler = Microsoft::WRL::Make<CCompletionHandler<TCompletionHandler, TAction>>();
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
}
#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<typename _Ty>
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<typename _Ty>
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<typename _Ty>
static auto _IsValidCreateAsync(_Ty _Param, int, int, ...) -> typename decltype(_Param(details::_ProgressReporterCtorArgType()), std::true_type());
virtual ~ComPtr() {}
// A parameter lambda taking a progress report and a cancellation_token argument is valid
template<typename _Ty>
static auto _IsValidCreateAsync(_Ty _Param, int, ...) -> typename decltype(_Param(details::_ProgressReporterCtorArgType(), cancellation_token::none()), std::true_type());
// All else is invalid
template<typename _Ty>
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<typename _Function>
class CAsyncAction
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::WinRt>,
Microsoft::WRL::Implements<ABI::Windows::Foundation::IAsyncAction>, Microsoft::WRL::AsyncBase<ABI::Windows::Foundation::IAsyncActionCompletedHandler >>
{
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)
{
if (!(std::is_same<Concurrency_winrt::details::_TaskTypeTraits<Concurrency_winrt::task<HRESULT>>::_AsyncKind, Concurrency_winrt::details::_TypeSelectorAsyncTask>::value))
T* const* GetAddressOf() const throw()
{
// 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);
}
return &p;
}
HRESULT STDMETHODCALLTYPE put_Completed(
/* [in] */ __RPC__in_opt ABI::Windows::Foundation::IAsyncActionCompletedHandler *handler)
T** GetAddressOf() throw()
{
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 &p;
}
return hr;
}
HRESULT OnStart() {
_M_task = Concurrency_winrt::task<HRESULT>(_M_func, _M_cts.get_token());
AddRef();
_M_task.then([this](Concurrency_winrt::task<HRESULT> _Antecedent) {
try {
HRESULT hr = _Antecedent.get();
if (FAILED(hr)) TryTransitionToError(hr);
T** ReleaseAndGetAddressOf() throw()
{
InternalRelease();
return &p;
}
catch (Concurrency::task_canceled&){
T* Get() const throw()
{
return p;
}
catch (...) {
TryTransitionToError(E_FAIL);
ComPtr& operator=(decltype(__nullptr)) throw()
{
InternalRelease();
return *this;
}
_FireCompletion();
Release();
});
return S_OK;
ComPtr& operator=(_In_ const int nNull) throw()
{
ASSERT(nNull == 0);
(void)nNull;
InternalRelease();
return *this;
}
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()
unsigned long Reset()
{
AddRef();
_M_completeDelegateContext._CallInContext([this]() -> HRESULT {
FireCompletion();
Release();
return S_OK;
});
return InternalRelease();
}
private:
_Function _M_func;
Concurrency_winrt::task<HRESULT> _M_task;
Concurrency::cancellation_token_source _M_cts;
_ContextCallback _M_completeDelegateContext;
};
template<typename _Function>
__declspec(noinline)
CAsyncAction<_Function>* create_async(const _Function& _Func)
{
static_assert(std::is_same<decltype(_IsValidCreateAsync(_Func, 0, 0, 0, 0)), std::true_type>::value,
"argument to create_async must be a callable object taking zero, one or two arguments");
CAsyncAction<_Function>* action = Microsoft::WRL::Make<CAsyncAction<_Function>>(_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<typename _Function>
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)
// query for U interface
template<typename U>
HRESULT As(_Inout_ U** lp) const throw()
{
return pMedCap->add_Failed(this, &m_cookie);
return p->QueryInterface(__uuidof(U), (void**)lp);
}
HRESULT RemoveHandler(ABI::Windows::Media::Capture::IMediaCapture* pMedCap)
// query for U interface
template<typename U>
HRESULT As(_Out_ ComPtr<U>* lp) const throw()
{
return pMedCap->remove_Failed(m_cookie);
return p->QueryInterface(__uuidof(U), reinterpret_cast<void**>(lp->ReleaseAndGetAddressOf()));
}
HRESULT STDMETHODCALLTYPE Invoke(
ABI::Windows::Media::Capture::IMediaCapture *sender,
ABI::Windows::Media::Capture::IMediaCaptureFailedEventArgs *errorEventArgs)
private:
unsigned long InternalRelease() throw()
{
(void)sender;
(void)errorEventArgs;
AddRef();
_M_func();
Release();
return S_OK;
unsigned long ref = 0;
T* temp = p;
if (temp != nullptr)
{
p = nullptr;
ref = temp->Release();
}
private:
_Function _M_func;
EventRegistrationToken m_cookie;
return ref;
}
};
template<typename _Function>
__declspec(noinline)
MediaCaptureFailedHandler<_Function>* create_medcapfailedhandler(const _Function& _Func)
{
return Microsoft::WRL::Make<MediaCaptureFailedHandler<_Function>>(_Func).Detach();
}
#define _ComPtr ComPtr
#endif
template <class TBase=IMFAttributes>
......@@ -946,7 +1024,7 @@ done:
}
protected:
ComPtr<IMFAttributes> _spAttributes;
_ComPtr<IMFAttributes> _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<IMFStreamSink*>(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<IMFMediaSink> pMedSink;
_ComPtr<IMFMediaSink> 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<IMFSampleGrabberSinkCallback> pSampleCallback;
_ComPtr<IMFSampleGrabberSinkCallback> 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<IMFMediaSink> pMedSink;
_ComPtr<IMFMediaSink> 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<IMFMediaBuffer> pInput;
ComPtr<IMFSampleGrabberSinkCallback> pSampleCallback;
_ComPtr<IMFMediaBuffer> pInput;
_ComPtr<IMFSampleGrabberSinkCallback> 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<IMFMediaEventQueue> pQueue;
_ComPtr<IMFMediaEventQueue> 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<IMFMediaType> pType;
_ComPtr<IMFMediaType> 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<IMFMediaType> pType;
_ComPtr<IMFMediaType> 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<IMFMediaType> pType;
_ComPtr<IMFMediaType> 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<IMFMediaType> m_spCurrentType;
ComPtr<IMFMediaEventQueue> m_spEventQueue; // Event queue
_ComPtr<IMFMediaType> m_spCurrentType;
_ComPtr<IMFMediaEventQueue> m_spEventQueue; // Event queue
ComPtr<IUnknown> m_spFTM;
_ComPtr<IUnknown> m_spFTM;
State m_state;
bool m_fGetStartTimeFromSample;
bool m_fWaitingForFirstSample;
......@@ -2296,7 +2359,7 @@ class MediaSink :
Microsoft::WRL::Implements<ABI::Windows::Media::IMediaExtension>,
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<IInspectable> spInsp;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> spSetting;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IPropertyValue> spPropVal;
ComPtr<ABI::Windows::Media::MediaProperties::IMediaEncodingProperties> pMedEncProps;
Microsoft::WRL::ComPtr<ABI::Windows::Media::MediaProperties::IMediaEncodingProperties> 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<IInspectable> value;
Microsoft::WRL::ComPtr<IInspectable> 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<IMFMediaType> spMT;
ComPtr<ABI::Windows::Foundation::Collections::IMap<GUID, IInspectable*>> spMap;
ComPtr<ABI::Windows::Foundation::Collections::IIterable<ABI::Windows::Foundation::Collections::IKeyValuePair<GUID, IInspectable*>*>> spIterable;
ComPtr<ABI::Windows::Foundation::Collections::IIterator<ABI::Windows::Foundation::Collections::IKeyValuePair<GUID, IInspectable*>*>> spIterator;
_ComPtr<IMFMediaType> spMT;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IMap<GUID, IInspectable*>> spMap;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IIterable<ABI::Windows::Foundation::Collections::IKeyValuePair<GUID, IInspectable*>*>> spIterable;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IIterator<ABI::Windows::Foundation::Collections::IKeyValuePair<GUID, IInspectable*>*>> 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<ABI::Windows::Foundation::Collections::IKeyValuePair<GUID, IInspectable*> > spKeyValuePair;
ComPtr<IInspectable> spValue;
ComPtr<ABI::Windows::Foundation::IPropertyValue> spPropValue;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IKeyValuePair<GUID, IInspectable*> > spKeyValuePair;
Microsoft::WRL::ComPtr<IInspectable> spValue;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IPropertyValue> spPropValue;
GUID guidKey;
hr = spIterator->get_Current(&spKeyValuePair);
......@@ -2609,8 +2669,8 @@ public:
if (SUCCEEDED(hr))
{
ComPtr<IInspectable> spValue;
ComPtr<ABI::Windows::Foundation::IPropertyValue> spPropValue;
Microsoft::WRL::ComPtr<IInspectable> spValue;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IPropertyValue> 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<IMFMediaType> spMediaType;
_ComPtr<IMFMediaType> 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<IMFStreamSink> spStreamSink;
_ComPtr<IMFStreamSink> 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<IMFStreamSink> spMFStream;
ComPtr<ICustomStreamSink> pStream;
_ComPtr<IMFStreamSink> spMFStream;
_ComPtr<ICustomStreamSink> pStream;
EnterCriticalSection(&m_critSec);
HRESULT hr = CheckShutdown();
......@@ -2729,7 +2789,7 @@ public:
}
// Initialize the stream.
ComPtr<IMFAttributes> pAttr;
_ComPtr<IMFAttributes> pAttr;
if (SUCCEEDED(hr)) {
hr = pStream.As(&pAttr);
}
......@@ -2752,7 +2812,7 @@ public:
for (; pos != posEnd; pos = m_streams.Next(pos))
{
DWORD dwCurrId;
ComPtr<IMFStreamSink> spCurr;
_ComPtr<IMFStreamSink> 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<IMFStreamSink>::POSITION pos = m_streams.FrontPosition();
ComPtrList<IMFStreamSink>::POSITION endPos = m_streams.EndPosition();
ComPtr<IMFStreamSink> spStream;
_ComPtr<IMFStreamSink> spStream;
if (SUCCEEDED(hr))
{
......@@ -2821,11 +2880,18 @@ public:
if (SUCCEEDED(hr))
{
hr = m_streams.Remove(pos, nullptr);
static_cast<StreamSink *>(spStream.Get())->Shutdown();
_ComPtr<ICustomStreamSink> spCustomSink;
#ifdef HAVE_WINRT
spCustomSink = static_cast<StreamSink*>(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<IMFStreamSink> spStream;
_ComPtr<IMFStreamSink> 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<IMFStreamSink> spResult;
_ComPtr<IMFStreamSink> spResult;
if (SUCCEEDED(hr))
{
......@@ -2917,7 +2981,7 @@ public:
for (; pos != endPos; pos = m_streams.Next(pos))
{
ComPtr<IMFStreamSink> spStream;
_ComPtr<IMFStreamSink> 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<IMFSampleGrabberSinkCallback> pSampleCallback;
_ComPtr<IMFSampleGrabberSinkCallback> 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<IMFMediaType> 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<StreamSink *>(pStream)->Shutdown();
return S_OK;
_ComPtr<ICustomStreamSink> spCustomSink;
HRESULT hr;
#ifdef HAVE_WINRT
spCustomSink = static_cast<StreamSink*>(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<StreamSink *>(pStream)->Start(_llStartTime);
_ComPtr<ICustomStreamSink> spCustomSink;
HRESULT hr;
#ifdef HAVE_WINRT
spCustomSink = static_cast<StreamSink*>(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<StreamSink *>(pStream)->Stop();
_ComPtr<ICustomStreamSink> spCustomSink;
HRESULT hr;
#ifdef HAVE_WINRT
spCustomSink = static_cast<StreamSink*>(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<T> spStream;
_ComPtr<T> spStream;
hr = col.GetItemPos(pos, &spStream);
if (FAILED(hr))
......@@ -3104,14 +3194,13 @@ public:
m_llStartTime = llClockStartOffset;
hr = ForEach(m_streams, StartFunc(llClockStartOffset));
}
ComPtr<IMFSampleGrabberSinkCallback> pSampleCallback;
_ComPtr<IMFSampleGrabberSinkCallback> 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<IMFSampleGrabberSinkCallback> pSampleCallback;
_ComPtr<IMFSampleGrabberSinkCallback> 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<IMFSampleGrabberSinkCallback> pSampleCallback;
_ComPtr<IMFSampleGrabberSinkCallback> 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<IMFSampleGrabberSinkCallback> pSampleCallback;
_ComPtr<IMFSampleGrabberSinkCallback> 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<IMFSampleGrabberSinkCallback> pSampleCallback;
_ComPtr<IMFSampleGrabberSinkCallback> 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<IMFStreamSink> m_streams;
ComPtr<IMFPresentationClock> m_spClock;
_ComPtr<IMFPresentationClock> m_spClock;
LONGLONG m_llStartTime;
};
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment