Commit 1578dd10 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

Merge pull request #2702 from GregoryMorse:patch-3

parents 06e55ddf b5a4159e
//
// 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_
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -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);
}
}
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];
}
using namespace Microsoft::WRL::Wrappers;
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,23 +746,33 @@ void DebugPrintOut::printOut(const wchar_t *format, ...)
wchar_t *p = NULL;
va_list args;
va_start(args, format);
if(wcscmp(format, L"%i"))
if( ::IsDebuggerPresent() )
{
i = va_arg (args, int);
WCHAR szMsg[512];
::StringCchVPrintfW(szMsg, sizeof(szMsg)/sizeof(szMsg[0]), format, args);
::OutputDebugStringW(szMsg);
}
if(wcscmp(format, L"%s"))
else
{
p = va_arg (args, wchar_t *);
if(wcscmp(format, L"%i"))
{
i = va_arg (args, int);
}
if(wcscmp(format, L"%s"))
{
p = va_arg (args, wchar_t *);
}
wprintf(format, i,p);
}
wprintf(format, i,p);
va_end (args);
}
}
void DebugPrintOut::setVerbose(bool state)
void DPO::setVerbose(bool state)
{
verbose = state;
}
#endif
LPCWSTR GetGUIDNameConstNew(const GUID& guid);
HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz);
......@@ -650,7 +848,7 @@ HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType
hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
if (SUCCEEDED(hr))
{
out.MF_MT_AM_FORMAT_TYPE = MF_MT_AM_FORMAT_TYPE;
out.MF_MT_AM_FORMAT_TYPE = *var.puuid;
out.pMF_MT_AM_FORMAT_TYPEName = pGuidValName;
pGuidValName = NULL;
}
......@@ -660,7 +858,7 @@ HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType
hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
if (SUCCEEDED(hr))
{
out.MF_MT_MAJOR_TYPE = MF_MT_MAJOR_TYPE;
out.MF_MT_MAJOR_TYPE = *var.puuid;
out.pMF_MT_MAJOR_TYPEName = pGuidValName;
pGuidValName = NULL;
}
......@@ -670,7 +868,7 @@ HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType
hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
if (SUCCEEDED(hr))
{
out.MF_MT_SUBTYPE = MF_MT_SUBTYPE;
out.MF_MT_SUBTYPE = *var.puuid;
out.pMF_MT_SUBTYPEName = pGuidValName;
pGuidValName = NULL;
}
......@@ -963,9 +1161,8 @@ FormatReader::FormatReader(void)
MediaType FormatReader::Read(IMFMediaType *pType)
{
UINT32 count = 0;
HRESULT hr = S_OK;
MediaType out;
hr = pType->LockStore();
HRESULT hr = pType->LockStore();
if (FAILED(hr))
{
return out;
......@@ -1032,9 +1229,8 @@ ImageGrabber::~ImageGrabber(void)
SafeRelease(&ig_pSession);
SafeRelease(&ig_pTopology);
DebugPrintOut *DPO = &DebugPrintOut::getInstance();
DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Destroying instance of the ImageGrabber class\n", ig_DeviceID);
DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Destroying instance of the ImageGrabber class\n", ig_DeviceID);
}
#ifdef HAVE_WINRT
......@@ -1063,9 +1259,7 @@ ImageGrabberWinRT::~ImageGrabberWinRT(void)
CloseHandle(ig_hFrameGrabbed);
}
DebugPrintOut *DPO = &DebugPrintOut::getInstance();
DPO->printOut(L"IMAGEGRABBER VIDEODEVICE: Destroying instance of the ImageGrabberWinRT class\n");
DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE: Destroying instance of the ImageGrabberWinRT class\n");
}
HRESULT ImageGrabberWinRT::initImageGrabber(MAKE_WRL_REF(_MediaCapture) pSource,
......@@ -1082,7 +1276,7 @@ HRESULT ImageGrabberWinRT::initImageGrabber(MAKE_WRL_REF(_MediaCapture) pSource,
if (FAILED(hr)) return hr;
GET_WRL_OBJ_FROM_OBJ(_VideoEncodingProperties, pVidProps, pMedEncProps, hr);
if (FAILED(hr)) return hr;
ComPtr<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)
{
frameRateMax = (*f).first;
STMMax = (*f).second;
}
}
// Looking for frame rate higher that recently found but not higher then demanded.
if( (*f).first >= frameRateMax && (*f).first <= frameRate )
{
frameRateMax = (*f).first;
STMMax = (*f).second;
}
}
}
if(STMMax.size() == 0)
return 0;
std::map<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];
}
......@@ -2311,16 +2511,20 @@ void videoDevice::buildLibraryofTypes()
int count = 0;
for(; i != vd_CurrentFormats.end(); i++)
{
size = (*i).MF_MT_FRAME_SIZE;
framerate = (*i).MF_MT_FRAME_RATE_NUMERATOR;
FrameRateMap FRM = vd_CaptureFormats[size];
SUBTYPEMap STM = FRM[framerate];
String subType((*i).pMF_MT_SUBTYPEName);
vectorNum VN = STM[subType];
VN.push_back(count);
STM[subType] = VN;
FRM[framerate] = STM;
vd_CaptureFormats[size] = FRM;
// Count only supported video formats.
if( (*i).MF_MT_SUBTYPE == MFVideoFormat_RGB24 )
{
size = (*i).MF_MT_FRAME_SIZE;
framerate = (*i).MF_MT_FRAME_RATE_NUMERATOR / (*i).MF_MT_FRAME_RATE_DENOMINATOR;
FrameRateMap FRM = vd_CaptureFormats[size];
SUBTYPEMap STM = FRM[framerate];
String subType((*i).pMF_MT_SUBTYPEName);
vectorNum VN = STM[subType];
VN.push_back(count);
STM[subType] = VN;
FRM[framerate] = STM;
vd_CaptureFormats[size] = FRM;
}
count++;
}
}
......@@ -2347,10 +2551,10 @@ long videoDevice::setDeviceFormat(MAKE_WRL_REF(_MediaCapture) pSource, unsigned
long videoDevice::setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex)
{
ComPtr<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)) {
MAKE_WRL_REF(_AsyncAction) pAction;
BEGIN_CALL_IN_CONTEXT(hr, context, id, &pAction, this)
END_CALL_IN_CONTEXT(setDeviceFormat(DEREF_AGILE_WRL_OBJ(vd_pMedCap), (DWORD) id, &pAction))
if (SUCCEEDED(hr)) DO_ACTION_SYNCHRONOUSLY(hr, pAction, context);
DEFINE_TASK<void> _task;
BEGIN_CALL_IN_CONTEXT(hr, context, id, &_task, this)
MAKE_WRL_REF(_AsyncAction) pAction;
HRESULT hr = setDeviceFormat(DEREF_AGILE_WRL_OBJ(vd_pMedCap), (DWORD) id, &pAction);
if (SUCCEEDED(hr)) _task = CREATE_TASK DEFINE_RET_TYPE(void)(pAction);
END_CALL_IN_CONTEXT(hr)
if (SUCCEEDED(hr)) _task.wait();
} else
#endif
#endif
hr = setDeviceFormat(vd_pSource, (DWORD) id);
vd_IsSetuped = (SUCCEEDED(hr));
if(vd_IsSetuped)
DPO->printOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber);
DebugPrintOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber);
vd_PrevParametrs = getParametrs();
#ifdef HAVE_WINRT
#ifdef HAVE_CONCURRENCY
END_CREATE_ASYNC(hr));
#endif
return true;
#else
return vd_IsSetuped;
......@@ -2502,13 +2715,13 @@ bool videoDevice::setupDevice(unsigned int id)
}
else
{
DPO->printOut(L"VIDEODEVICE %i: Interface IMFMediaSource cannot be got \n", vd_CurrentNumber);
DebugPrintOut(L"VIDEODEVICE %i: Interface IMFMediaSource cannot be got \n", vd_CurrentNumber);
return false;
}
}
else
{
DPO->printOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber);
DebugPrintOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber);
return false;
}
}
......@@ -2516,6 +2729,9 @@ bool videoDevice::setupDevice(unsigned int id)
bool videoDevice::setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate)
{
unsigned int id = findType(w * h, idealFramerate);
if( id < 0 )
return false;
return setupDevice(id);
}
......@@ -2554,7 +2770,7 @@ HRESULT videoDevice::enumerateCaptureFormats(MAKE_WRL_REF(_MediaCapture) pSource
MAKE_WRL_OBJ(_MediaEncodingProperties) pMedEncProps;
WRL_METHOD(pVector, GetAt, pMedEncProps, hr, i)
if (FAILED(hr)) return hr;
ComPtr<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());
// 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
virtual ~ComPtr() {}
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)
T* const* GetAddressOf() const throw()
{
if (!(std::is_same<Concurrency_winrt::details::_TaskTypeTraits<Concurrency_winrt::task<HRESULT>>::_AsyncKind, Concurrency_winrt::details::_TypeSelectorAsyncTask>::value))
{
// 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;
return &p;
}
HRESULT STDMETHODCALLTYPE get_Completed(
/* [out][retval] */ __RPC__deref_out_opt ABI::Windows::Foundation::IAsyncActionCompletedHandler **handler) {
if (!handler) return E_POINTER;
return GetOnComplete(handler);
T** ReleaseAndGetAddressOf() throw()
{
InternalRelease();
return &p;
}
HRESULT STDMETHODCALLTYPE GetResults(void) {
HRESULT hr = CheckValidStateForResultsCall();
if (SUCCEEDED(hr)) {
_M_task.get();
}
return hr;
T* Get() const throw()
{
return p;
}
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);
}
catch (Concurrency::task_canceled&){
}
catch (...) {
TryTransitionToError(E_FAIL);
}
_FireCompletion();
Release();
});
return S_OK;
ComPtr& operator=(decltype(__nullptr)) throw()
{
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()
{
AddRef();
_M_completeDelegateContext._CallInContext([this]() -> HRESULT {
FireCompletion();
Release();
return S_OK;
});
ComPtr& operator=(_In_ const int nNull) throw()
{
ASSERT(nNull == 0);
(void)nNull;
InternalRelease();
return *this;
}
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)
unsigned long Reset()
{
return pMedCap->add_Failed(this, &m_cookie);
return InternalRelease();
}
HRESULT RemoveHandler(ABI::Windows::Media::Capture::IMediaCapture* pMedCap)
// query for U interface
template<typename U>
HRESULT As(_Inout_ U** lp) const throw()
{
return pMedCap->remove_Failed(m_cookie);
return p->QueryInterface(__uuidof(U), (void**)lp);
}
HRESULT STDMETHODCALLTYPE Invoke(
ABI::Windows::Media::Capture::IMediaCapture *sender,
ABI::Windows::Media::Capture::IMediaCaptureFailedEventArgs *errorEventArgs)
// query for U interface
template<typename U>
HRESULT As(_Out_ ComPtr<U>* lp) const throw()
{
(void)sender;
(void)errorEventArgs;
AddRef();
_M_func();
Release();
return S_OK;
return p->QueryInterface(__uuidof(U), reinterpret_cast<void**>(lp->ReleaseAndGetAddressOf()));
}
private:
_Function _M_func;
EventRegistrationToken m_cookie;
};
unsigned long InternalRelease() throw()
{
unsigned long ref = 0;
T* temp = p;
template<typename _Function>
__declspec(noinline)
MediaCaptureFailedHandler<_Function>* create_medcapfailedhandler(const _Function& _Func)
{
return Microsoft::WRL::Make<MediaCaptureFailedHandler<_Function>>(_Func).Detach();
}
if (temp != nullptr)
{
p = nullptr;
ref = temp->Release();
}
return ref;
}
};
#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;
};
......
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