From aa3c36f545542b6c7f792a04426dd97ae7dba157 Mon Sep 17 00:00:00 2001 From: GregoryMorse Date: Sat, 14 Dec 2013 16:53:30 +0800 Subject: [PATCH] Update cap_msmf.cpp Add support for WinRT in the MF capture framework by removing the disallowed calls to enumerate devices and create a sample grabber sink and adding framework for the MediaCapture interface and a custom sink which interfaces with the sample grabber callback interface. The change requires discussion for making it completely functional as redundancy is required given that if the source is a video file, the old code pathways must be used. Otherwise all IMFMediaSession, IMFMediaSource, and IMFActivate code must use a MediaCapture code path and all sink code must use the CMediaSink custom sink. Support for the custom sink is extended to non-WinRT not for compatibility as Windows Vista client is a minimum regardless, but because it offers more flexibility, could be faster and is able to be used as an optionally different code path during sink creation based on a future configuration parameter. My discussion and proposal to finish this change: Devices are so easily enumerated through WinRT Windows.Devices namespace that wrapping the calls in a library is quite a chore for little benefit though to get the various modes and formats could still be a worthwhile project. For now conditional compilation to remove videodevices and any offending non-video file related activity in videodevice. In my opinion, this is a different , far less fundamental and important change which can possibly be done as a future project and also much more easily implemented in C++/CX. ImageGrabber has the IMFSampleGrabberSinkCallback replaced with a base class (SharedSampleGrabber) which also be is base class for ImageGrabberRT. This change is necessary as the custom sink does not require a thread to pump events which is done through MediaCapture already. IMFSampleGrabberSinkCallback is the common element between both models and that piece can be shared. Initializing the new ImageGrabberRT is as simple as passing an already initialized MediaCapture object and any video format/encoding parameters. The concurrency event is necessary to wait for completion and is the way the underlying, IAsyncAction wrappers in the task library work as well. Native WIN32 event objects would be an option if HAVE_CONCURRENCY is not defined. I could even imagine doing it with sleep/thread yield and InterlockedCompareExchange yet I am not enthusiastic about that approach either. Since there is a specific compiler HAVE_ for concurrency, I do not like pulling it in though I think for WinRT it is safe to say we will always have it available though should probably conditionally compile with the Interlocked option as WIN32 events would require HAVE_WIN32. It looks like C++/CX cannot be used for the IMediaExtension sink (which should not be a problem) as using COM objects requires WRL and though deriving from IMediaExtension can be done, there is little purpose without COM. Objects from C++/CX can be swapped to interact with objects from native C++ as Inspectable* can reinterpret_cast to the ref object IInspectable^ and vice-versa. A solution to the COM class with C++/CX would be great so we could have dual support. Also without #define for every WRL object in use, the code will get quite muddy given that the */^ would need to be ifdef'd everywhere. Update cap_msmf.cpp Fixed bugs and completed the change. I believe the new classes need to be moved to a header file as the file has become to large and more classes need to be added for handling all the asynchronous problems (one wrapping IAsyncAction in a task and another for making a task out of IAsyncAction). Unfortunately, blocking on the UI thread is not an option in WinRT so a synchronous architecture is considered "illegal" by Microsoft's standards even if implementable (C++/CX ppltasks library throws errors if you try it). Worse, either by design or a bug in the MF MediaCapture class with Custom Sinks causes a crash if stop/start previewing without reinitializing (spPreferredPreviewMediaType is fatally nulled). After decompiling Windows.Media.dll, I worked around this in my own projects by using an activate-able custom sink ID which strangely assigns 1 to this pointer allowing it to be reinitialized in what can only be described as a hack by Microsoft. This would add additional overhead to the project to implement especially for static libraries as it requires IDL/DLL exporting followed by manifest declaration. Better to document that it is not supported. Furthermore, an additional class for IMFAttributes should be implemented to make clean architecture for passing around attributes as opposed to directly calling non-COM interface calls on the objects and making use of SetProperties which would also be a set up for an object that uses the RuntimeClass activation ID. The remaining changes are not difficult and will be complete soon along with debug tracing messages. Update and rename cap_msmf.h to cap_msmf.hpp Update cap_msmf.cpp Successful test - samples are grabbed Update ppltasks_winrt.h Library updated and cleaned up with comments, marshaling, exceptions and linker settings Fixed trailing whitespace Support VS 2013 and consistency cleanup and C++/CX object creation fixed --- modules/highgui/src/cap_msmf.cpp | 50 ++++++++--------- modules/highgui/src/cap_msmf.hpp | 83 ++++++++++++++-------------- modules/highgui/src/ppltasks_winrt.h | 51 +++++++++-------- 3 files changed, 96 insertions(+), 88 deletions(-) diff --git a/modules/highgui/src/cap_msmf.cpp b/modules/highgui/src/cap_msmf.cpp index 80b17cafa..b1122efbe 100644 --- a/modules/highgui/src/cap_msmf.cpp +++ b/modules/highgui/src/cap_msmf.cpp @@ -1075,12 +1075,12 @@ HRESULT ImageGrabberWinRT::initImageGrabber(MAKE_WRL_REF(_MediaCapture) pSource, MAKE_WRL_OBJ(_VideoDeviceController) pDevCont; WRL_PROP_GET(pSource, VideoDeviceController, pDevCont, hr) if (FAILED(hr)) return hr; - GET_WRL_MEDIA_DEVICE_CONTROLLER(pDevCont, pMedDevCont, hr) + GET_WRL_OBJ_FROM_OBJ(_MediaDeviceController, pMedDevCont, pDevCont, hr) if (FAILED(hr)) return hr; MAKE_WRL_OBJ(_MediaEncodingProperties) pMedEncProps; - WRL_METHOD(pMedDevCont, GetMediaStreamProperties, pMedEncProps, hr, _VideoPreview) + WRL_METHOD(pMedDevCont, GetMediaStreamProperties, pMedEncProps, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) if (FAILED(hr)) return hr; - GET_WRL_VIDEO_ENCODING_PROPERTIES(pMedEncProps, pVidProps, hr); + GET_WRL_OBJ_FROM_OBJ(_VideoEncodingProperties, pVidProps, pMedEncProps, hr); if (FAILED(hr)) return hr; ComPtr pType = NULL; hr = MediaSink::ConvertPropertiesToMediaType(DEREF_AS_NATIVE_WRL_OBJ(ABI::Windows::Media::MediaProperties::IMediaEncodingProperties, pMedEncProps), &pType); @@ -1108,7 +1108,7 @@ HRESULT ImageGrabberWinRT::stopGrabbing(MAKE_WRL_REF(_AsyncAction)* action) { HRESULT hr = S_OK; if (ig_pMedCapSource != nullptr) { - GET_WRL_VIDEO_PREVIEW(DEREF_AGILE_WRL_OBJ(ig_pMedCapSource), imedPrevCap, hr); + GET_WRL_OBJ_FROM_REF(_MediaCaptureVideoPreview, imedPrevCap, DEREF_AGILE_WRL_OBJ(ig_pMedCapSource), hr) if (FAILED(hr)) return hr; MAKE_WRL_REF(_AsyncAction) pAction; WRL_METHOD_BASE(imedPrevCap, StopPreviewAsync, pAction, hr) @@ -1128,17 +1128,17 @@ HRESULT ImageGrabberWinRT::stopGrabbing(MAKE_WRL_REF(_AsyncAction)* action) HRESULT ImageGrabberWinRT::startGrabbing(MAKE_WRL_REF(_AsyncAction)* action) { HRESULT hr = S_OK; - GET_WRL_VIDEO_PREVIEW(DEREF_AGILE_WRL_OBJ(ig_pMedCapSource), imedPrevCap, hr); + GET_WRL_OBJ_FROM_REF(_MediaCaptureVideoPreview, imedPrevCap, DEREF_AGILE_WRL_OBJ(ig_pMedCapSource), hr) if (FAILED(hr)) return hr; - ACTIVATE_OBJ(RuntimeClass_Windows_Foundation_Collections_PropertySet, MAKE_WRL_OBJ(_PropertySet), pSet, hr) + ACTIVATE_OBJ(RuntimeClass_Windows_Foundation_Collections_PropertySet, _PropertySet, pSet, hr) if (FAILED(hr)) return hr; - GET_WRL_MAP(pSet, spSetting, hr) + GET_WRL_OBJ_FROM_OBJ(_Map, spSetting, pSet, hr) if (FAILED(hr)) return hr; ACTIVATE_STATIC_OBJ(RuntimeClass_Windows_Foundation_PropertyValue, MAKE_WRL_OBJ(_PropertyValueStatics), spPropVal, hr) if (FAILED(hr)) return hr; _ObjectObj pVal; boolean bReplaced; - WRL_METHOD(spPropVal, CreateUInt32, pVal, hr, (unsigned int)_VideoPreview) + WRL_METHOD(spPropVal, CreateUInt32, pVal, hr, (unsigned int)WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) if (FAILED(hr)) return hr; WRL_METHOD(spSetting, Insert, bReplaced, hr, DEREF_WRL_OBJ(_StringReference(MF_PROP_VIDTYPE)), DEREF_WRL_OBJ(pVal)) if (FAILED(hr)) return hr; @@ -1147,14 +1147,14 @@ HRESULT ImageGrabberWinRT::startGrabbing(MAKE_WRL_REF(_AsyncAction)* action) MAKE_WRL_OBJ(_VideoDeviceController) pDevCont; WRL_PROP_GET(ig_pMedCapSource, VideoDeviceController, pDevCont, hr) if (FAILED(hr)) return hr; - GET_WRL_MEDIA_DEVICE_CONTROLLER(pDevCont, pMedDevCont, hr) + GET_WRL_OBJ_FROM_OBJ(_MediaDeviceController, pMedDevCont, pDevCont, hr) if (FAILED(hr)) return hr; MAKE_WRL_OBJ(_MediaEncodingProperties) pMedEncProps; - WRL_METHOD(pMedDevCont, GetMediaStreamProperties, pMedEncProps, hr, _VideoPreview) + WRL_METHOD(pMedDevCont, GetMediaStreamProperties, pMedEncProps, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) if (FAILED(hr)) return hr; - GET_WRL_VIDEO_ENCODING_PROPERTIES(pMedEncProps, pVidProps, hr); + GET_WRL_OBJ_FROM_OBJ(_VideoEncodingProperties, pVidProps, pMedEncProps, hr); if (FAILED(hr)) return hr; - ACTIVATE_OBJ(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile, MAKE_WRL_OBJ(_MediaEncodingProfile), pEncProps, hr) + ACTIVATE_OBJ(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile, _MediaEncodingProfile, pEncProps, hr) if (FAILED(hr)) return hr; WRL_PROP_PUT(pEncProps, Video, DEREF_WRL_OBJ(pVidProps), hr) if (FAILED(hr)) return hr; @@ -1718,7 +1718,7 @@ bool Media_Foundation::buildListOfDevices() HRESULT hr = S_OK; #ifdef HAVE_WINRT videoDevices *vDs = &videoDevices::getInstance(); - hr = vDs->initDevices(_VideoCapture); + hr = vDs->initDevices(WRL_ENUM_GET(_DeviceClass, DeviceClass, VideoCapture)); #else ComPtr pAttributes = NULL; CoInitialize(NULL); @@ -1907,9 +1907,9 @@ long videoDevice::resetDevice(IMFActivate *pActivate) #ifdef HAVE_WINRT if (pDevice) { - ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCapture, MAKE_WRL_OBJ(_MediaCapture), pIMedCap, hr) + ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCapture, _MediaCapture, pIMedCap, hr) if (FAILED(hr)) return hr; - ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCaptureInitializationSettings, MAKE_WRL_OBJ(_MediaCaptureInitializationSettings), pCapInitSet, hr) + ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCaptureInitializationSettings, _MediaCaptureInitializationSettings, pCapInitSet, hr) if (FAILED(hr)) return hr; _StringObj str; WRL_PROP_GET(pDevice, Name, *REF_WRL_OBJ(str), hr) @@ -1922,7 +1922,7 @@ long videoDevice::resetDevice(IMFActivate *pActivate) if (FAILED(hr)) return hr; WRL_PROP_PUT(pCapInitSet, VideoDeviceId, DEREF_WRL_OBJ(str), hr) if (FAILED(hr)) return hr; - WRL_PROP_PUT(pCapInitSet, StreamingCaptureMode, _Video, hr) + WRL_PROP_PUT(pCapInitSet, StreamingCaptureMode, WRL_ENUM_GET(_StreamingCaptureMode, StreamingCaptureMode, Video), hr) if (FAILED(hr)) return hr; MAKE_WRL_REF(_AsyncAction) pAction; WRL_METHOD(DEREF_WRL_OBJ(pIMedCap), _InitializeWithSettingsAsync, pAction, hr, DEREF_WRL_OBJ(pCapInitSet)) @@ -2100,17 +2100,17 @@ long videoDevice::initDevice() if (pOldAction) DO_ACTION_SYNCHRONOUSLY(hr, pOldAction, GET_CURRENT_CONTEXT); DEFINE_TASK pTask; MAKE_WRL_OBJ(_IDeviceInformation) pDevInfo; - hr = checkDevice(_VideoCapture, &pTask, REF_WRL_OBJ(pDevInfo)); + hr = checkDevice(WRL_ENUM_GET(_DeviceClass, DeviceClass, VideoCapture), &pTask, REF_WRL_OBJ(pDevInfo)); if (SUCCEEDED(hr)) hr = pTask.get(); if (SUCCEEDED(hr)) { MAKE_WRL_REF(_AsyncAction) pAction; BEGIN_CALL_IN_CONTEXT(hr, context, pDevInfo, &pAction, context, this) HRESULT hr; - ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCapture, MAKE_WRL_OBJ(_MediaCapture), pIMedCap, hr) + ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCapture, _MediaCapture, pIMedCap, hr) if (SUCCEEDED(hr)) { RELEASE_WRL(vd_pMedCap); vd_pMedCap = PREPARE_TRANSFER_WRL_OBJ(pIMedCap); - ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCaptureInitializationSettings, MAKE_WRL_OBJ(_MediaCaptureInitializationSettings), pCapInitSet, hr) + ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCaptureInitializationSettings, _MediaCaptureInitializationSettings, pCapInitSet, hr) _StringObj str; if (SUCCEEDED(hr)) { WRL_PROP_GET(pDevInfo, Id, *REF_WRL_OBJ(str), hr) @@ -2119,7 +2119,7 @@ long videoDevice::initDevice() } } if (SUCCEEDED(hr)) - WRL_PROP_PUT(pCapInitSet, StreamingCaptureMode, _Video, hr) + WRL_PROP_PUT(pCapInitSet, StreamingCaptureMode, WRL_ENUM_GET(_StreamingCaptureMode, StreamingCaptureMode, Video), hr) if (SUCCEEDED(hr)) { vd_pMedCapFail = create_medcapfailedhandler([this, context](){ HRESULT hr; @@ -2332,15 +2332,15 @@ long videoDevice::setDeviceFormat(MAKE_WRL_REF(_MediaCapture) pSource, unsigned MAKE_WRL_OBJ(_VideoDeviceController) pDevCont; WRL_PROP_GET(pSource, VideoDeviceController, pDevCont, hr) if (FAILED(hr)) return hr; - GET_WRL_MEDIA_DEVICE_CONTROLLER(pDevCont, pMedDevCont, hr) + GET_WRL_OBJ_FROM_OBJ(_MediaDeviceController, pMedDevCont, pDevCont, hr) if (FAILED(hr)) return hr; MAKE_WRL_OBJ(_VectorView) pVector; - WRL_METHOD(pMedDevCont, GetAvailableMediaStreamProperties, pVector, hr, _VideoPreview) + WRL_METHOD(pMedDevCont, GetAvailableMediaStreamProperties, pVector, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) if (FAILED(hr)) return hr; MAKE_WRL_OBJ(_MediaEncodingProperties) pMedEncProps; WRL_METHOD(pVector, GetAt, pMedEncProps, hr, dwFormatIndex) if (FAILED(hr)) return hr; - WRL_METHOD(pMedDevCont, SetMediaStreamPropertiesAsync, *pAction, hr, _VideoPreview, DEREF_WRL_OBJ(pMedEncProps)) + WRL_METHOD(pMedDevCont, SetMediaStreamPropertiesAsync, *pAction, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview), DEREF_WRL_OBJ(pMedEncProps)) return hr; } #endif @@ -2542,10 +2542,10 @@ HRESULT videoDevice::enumerateCaptureFormats(MAKE_WRL_REF(_MediaCapture) pSource MAKE_WRL_OBJ(_VideoDeviceController) pDevCont; WRL_PROP_GET(pSource, VideoDeviceController, pDevCont, hr) if (FAILED(hr)) return hr; - GET_WRL_MEDIA_DEVICE_CONTROLLER(pDevCont, pMedDevCont, hr) + GET_WRL_OBJ_FROM_OBJ(_MediaDeviceController, pMedDevCont, pDevCont, hr) if (FAILED(hr)) return hr; MAKE_WRL_OBJ(_VectorView) pVector; - WRL_METHOD(pMedDevCont, GetAvailableMediaStreamProperties, pVector, hr, _VideoPreview) + WRL_METHOD(pMedDevCont, GetAvailableMediaStreamProperties, pVector, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) if (FAILED(hr)) return hr; UINT32 count; WRL_PROP_GET(pVector, Size, count, hr) diff --git a/modules/highgui/src/cap_msmf.hpp b/modules/highgui/src/cap_msmf.hpp index f755fd780..c212ca910 100644 --- a/modules/highgui/src/cap_msmf.hpp +++ b/modules/highgui/src/cap_msmf.hpp @@ -186,20 +186,23 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #define _StringReference ref new Platform::String #define _DeviceInformationCollection Windows::Devices::Enumeration::DeviceInformationCollection #define _MediaCapture Windows::Media::Capture::MediaCapture +#define _MediaCaptureVideoPreview Windows::Media::Capture::MediaCapture #define _MediaCaptureInitializationSettings Windows::Media::Capture::MediaCaptureInitializationSettings #define _VideoDeviceController Windows::Media::Devices::VideoDeviceController +#define _MediaDeviceController Windows::Media::Devices::VideoDeviceController #define _MediaEncodingProperties Windows::Media::MediaProperties::IMediaEncodingProperties -#define _VideoPreview Windows::Media::Capture::MediaStreamType::VideoPreview +#define _VideoEncodingProperties Windows::Media::MediaProperties::VideoEncodingProperties +#define _MediaStreamType Windows::Media::Capture::MediaStreamType #define _AsyncAction Windows::Foundation::IAsyncAction #define _AsyncOperation Windows::Foundation::IAsyncOperation #define _DeviceClass Windows::Devices::Enumeration::DeviceClass -#define _VideoCapture Windows::Devices::Enumeration::DeviceClass::VideoCapture #define _IDeviceInformation Windows::Devices::Enumeration::DeviceInformation #define _DeviceInformation Windows::Devices::Enumeration::DeviceInformation #define _DeviceInformationStatics Windows::Devices::Enumeration::DeviceInformation #define _MediaEncodingProfile Windows::Media::MediaProperties::MediaEncodingProfile -#define _Video Windows::Media::Capture::StreamingCaptureMode::Video +#define _StreamingCaptureMode Windows::Media::Capture::StreamingCaptureMode #define _PropertySet Windows::Foundation::Collections::PropertySet +#define _Map Windows::Foundation::Collections::PropertySet #define _PropertyValueStatics Windows::Foundation::PropertyValue #define _VectorView Windows::Foundation::Collections::IVectorView #define _StartPreviewToCustomSinkIdAsync StartPreviewToCustomSinkAsync @@ -208,16 +211,16 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #define _MediaExtension Windows::Media::IMediaExtension #define _ContextCallback Concurrency::details::_ContextCallback #define BEGIN_CALL_IN_CONTEXT(hr, var, ...) hr = S_OK;\ - var._CallInContext([__VA_ARGS__]() { +var._CallInContext([__VA_ARGS__]() { #define END_CALL_IN_CONTEXT(hr) if (FAILED(hr)) throw Platform::Exception::CreateException(hr);\ - }); +}); #define DO_ACTION_SYNCHRONOUSLY(hr, action, ctxt) hr = S_OK;\ - CCompletionHandler::PerformActionSynchronously(reinterpret_cast(action), ctxt) +CCompletionHandler::PerformActionSynchronously(reinterpret_cast(action), ctxt) #define DO_OPERATION_SYNCHRONOUSLY_VECTOR(hr, action, ctxt, pResult, vectortype, elementtype, _type) hr = S_OK;\ - pResult = CCompletionHandler::PerformSynchronously<_type^>(reinterpret_cast^>(action), ctxt) +pResult = CCompletionHandler::PerformSynchronously<_type^>(reinterpret_cast^>(action), ctxt) #define BEGIN_CREATE_ASYNC(...) reinterpret_cast(Concurrency::create_async([__VA_ARGS__]() { #define END_CREATE_ASYNC(hr) if (FAILED(hr)) throw Platform::Exception::CreateException(hr);\ - })) +})) #define DEFINE_TASK Concurrency::task #define CREATE_TASK Concurrency::create_task #define CREATE_OR_CONTINUE_TASK(_task, rettype, func) _task = (_task == Concurrency::task()) ? Concurrency::create_task(func) : _task.then([func](rettype) -> rettype { return func(); }); @@ -226,53 +229,53 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #define MAKE_WRL_AGILE_REF(x) Platform::Agile #define RELEASE_AGILE_WRL(x) x = nullptr; #define RELEASE_WRL(x) x = nullptr; -#define GET_WRL_VIDEO_PREVIEW(medCap, prevMedCap, hr) Windows::Media::Capture::MediaCapture^ prevMedCap = medCap;\ - hr = S_OK; -#define GET_WRL_MEDIA_DEVICE_CONTROLLER(devCont, medDevCont, hr) Windows::Media::Devices::VideoDeviceController^ medDevCont = devCont;\ - hr = S_OK; -#define GET_WRL_VIDEO_ENCODING_PROPERTIES(encProp, vidEncProp, hr) Windows::Media::MediaProperties::VideoEncodingProperties^ vidEncProp = safe_cast(encProp);\ - hr = S_OK; -#define GET_WRL_MAP(pSet, map, hr) Windows::Foundation::Collections::PropertySet^ map = pSet;\ - hr = S_OK; +#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;\ +hr = S_OK; +#define WRL_ENUM_GET(obj, prefix, prop) obj::##prop #define WRL_PROP_GET(obj, prop, arg, hr) arg = obj->##prop;\ - hr = S_OK; +hr = S_OK; #define WRL_PROP_PUT(obj, prop, arg, hr) obj->##prop = arg;\ - hr = S_OK; +hr = S_OK; #define WRL_METHOD_BASE(obj, method, ret, hr) ret = obj->##method();\ - hr = S_OK; +hr = S_OK; #define WRL_METHOD(obj, method, ret, hr, ...) ret = obj->##method(__VA_ARGS__);\ - hr = S_OK; +hr = S_OK; #define REF_WRL_OBJ(obj) &obj #define DEREF_WRL_OBJ(obj) obj #define DEREF_AGILE_WRL_OBJ(obj) obj.Get() #define DEREF_AS_NATIVE_WRL_OBJ(type, obj) reinterpret_cast(obj) #define PREPARE_TRANSFER_WRL_OBJ(obj) obj -#define ACTIVATE_OBJ(rtclass, objtype, obj, hr) objtype obj;\ - hr = S_OK; +#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;\ - hr = S_OK; +hr = S_OK; #else #define _Object IInspectable* #define _ObjectObj Microsoft::WRL::ComPtr #define _String HSTRING -#define _StringObj HString -#define _StringReference HStringReference +#define _StringObj Microsoft::WRL::Wrappers::HString +#define _StringReference 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 #define _MediaCaptureInitializationSettings ABI::Windows::Media::Capture::IMediaCaptureInitializationSettings #define _VideoDeviceController ABI::Windows::Media::Devices::IVideoDeviceController +#define _MediaDeviceController ABI::Windows::Media::Devices::IMediaDeviceController #define _MediaEncodingProperties ABI::Windows::Media::MediaProperties::IMediaEncodingProperties -#define _VideoPreview ABI::Windows::Media::Capture::MediaStreamType::MediaStreamType_VideoPreview +#define _VideoEncodingProperties ABI::Windows::Media::MediaProperties::IVideoEncodingProperties +#define _MediaStreamType ABI::Windows::Media::Capture::MediaStreamType #define _AsyncAction ABI::Windows::Foundation::IAsyncAction #define _AsyncOperation ABI::Windows::Foundation::IAsyncOperation #define _DeviceClass ABI::Windows::Devices::Enumeration::DeviceClass -#define _VideoCapture ABI::Windows::Devices::Enumeration::DeviceClass::DeviceClass_VideoCapture #define _IDeviceInformation ABI::Windows::Devices::Enumeration::IDeviceInformation #define _DeviceInformation ABI::Windows::Devices::Enumeration::DeviceInformation #define _DeviceInformationStatics ABI::Windows::Devices::Enumeration::IDeviceInformationStatics #define _MediaEncodingProfile ABI::Windows::Media::MediaProperties::IMediaEncodingProfile -#define _Video ABI::Windows::Media::Capture::StreamingCaptureMode::StreamingCaptureMode_Video +#define _StreamingCaptureMode ABI::Windows::Media::Capture::StreamingCaptureMode #define _PropertySet ABI::Windows::Foundation::Collections::IPropertySet +#define _Map ABI::Windows::Foundation::Collections::IMap #define _PropertyValueStatics ABI::Windows::Foundation::IPropertyValueStatics #define _VectorView ABI::Windows::Foundation::Collections::IVectorView #define _StartPreviewToCustomSinkIdAsync StartPreviewToCustomSinkIdAsync @@ -282,12 +285,12 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #define _ContextCallback Concurrency_winrt::details::_ContextCallback #define BEGIN_CALL_IN_CONTEXT(hr, var, ...) hr = var._CallInContext([__VA_ARGS__]() -> HRESULT { #define END_CALL_IN_CONTEXT(hr) return hr;\ - }); +}); #define DO_ACTION_SYNCHRONOUSLY(hr, action, ctxt) hr = CCompletionHandler::PerformActionSynchronously(action, ctxt) #define DO_OPERATION_SYNCHRONOUSLY_VECTOR(hr, action, ctxt, pResult, vectortype, elementtype, _type) hr = CCompletionHandler, ABI::Windows::Foundation::IAsyncOperation<_type*>>::PerformSynchronously*>(action, ctxt, pResult.GetAddressOf()) #define BEGIN_CREATE_ASYNC(...) Concurrency_winrt::create_async([__VA_ARGS__]() -> HRESULT { #define END_CREATE_ASYNC(hr) return hr;\ - }) +}) #define DEFINE_TASK Concurrency_winrt::task #define CREATE_TASK Concurrency_winrt::create_task #define CREATE_OR_CONTINUE_TASK(_task, rettype, func) _task = (_task == Concurrency_winrt::task()) ? Concurrency_winrt::create_task(func) : _task.then([func](rettype) -> rettype { return func(); }); @@ -296,14 +299,11 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #define MAKE_WRL_AGILE_REF(x) x* #define RELEASE_AGILE_WRL(x) if (x) { (x)->Release(); x = nullptr; } #define RELEASE_WRL(x) if (x) { (x)->Release(); x = nullptr; } -#define GET_WRL_VIDEO_PREVIEW(medCap, prevMedCap, hr) Microsoft::WRL::ComPtr prevMedCap;\ - hr = medCap->QueryInterface(__uuidof(ABI::Windows::Media::Capture::IMediaCaptureVideoPreview), &prevMedCap); -#define GET_WRL_MEDIA_DEVICE_CONTROLLER(devCont, medDevCont, hr) Microsoft::WRL::ComPtr medDevCont;\ - hr = devCont.As(&medDevCont); -#define GET_WRL_VIDEO_ENCODING_PROPERTIES(encProp, vidEncProp, hr) Microsoft::WRL::ComPtr vidEncProp;\ - hr = encProp.As(&vidEncProp); -#define GET_WRL_MAP(pSet, map, hr) Microsoft::WRL::ComPtr> map;\ - hr = pSet.As(&map); +#define GET_WRL_OBJ_FROM_REF(objtype, obj, orig, hr) Microsoft::WRL::ComPtr obj;\ +hr = orig->QueryInterface(__uuidof(objtype), &obj); +#define GET_WRL_OBJ_FROM_OBJ(objtype, obj, orig, hr) Microsoft::WRL::ComPtr obj;\ +hr = orig.As(&obj); +#define WRL_ENUM_GET(obj, prefix, prop) obj::prefix##_##prop #define WRL_PROP_GET(obj, prop, arg, hr) hr = obj->get_##prop(&arg); #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); @@ -313,10 +313,10 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #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_OBJ(rtclass, objtype, obj, hr) objtype obj;\ +#define ACTIVATE_OBJ(rtclass, objtype, obj, hr) MAKE_WRL_OBJ(objtype) obj;\ {\ Microsoft::WRL::ComPtr objFactory;\ - hr = Windows::Foundation::GetActivationFactory(HStringReference(rtclass).Get(), objFactory.ReleaseAndGetAddressOf());\ + hr = Windows::Foundation::GetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(rtclass).Get(), objFactory.ReleaseAndGetAddressOf());\ if (SUCCEEDED(hr)) {\ Microsoft::WRL::ComPtr pInsp;\ hr = objFactory->ActivateInstance(pInsp.GetAddressOf());\ @@ -326,7 +326,7 @@ MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypeP #define ACTIVATE_STATIC_OBJ(rtclass, objtype, obj, hr) objtype obj;\ {\ Microsoft::WRL::ComPtr objFactory;\ - hr = Windows::Foundation::GetActivationFactory(HStringReference(rtclass).Get(), objFactory.ReleaseAndGetAddressOf());\ + hr = Windows::Foundation::GetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(rtclass).Get(), objFactory.ReleaseAndGetAddressOf());\ if (SUCCEEDED(hr)) {\ if (SUCCEEDED(hr)) hr = objFactory.As(&obj);\ }\ @@ -346,6 +346,7 @@ class CCompletionHandler TCompletionHandler, IAgileObject, FtmBase> #endif { + MixInHelper() #ifndef __cplusplus_winrt public: CCompletionHandler() {} diff --git a/modules/highgui/src/ppltasks_winrt.h b/modules/highgui/src/ppltasks_winrt.h index 8cf91a3ed..29dccbd70 100644 --- a/modules/highgui/src/ppltasks_winrt.h +++ b/modules/highgui/src/ppltasks_winrt.h @@ -31,7 +31,6 @@ #include #include #include -#include #ifndef _UITHREADCTXT_SUPPORT @@ -1213,21 +1212,20 @@ namespace details { } - explicit _ExceptionHolder(const _com_error& _E, void* _SourceAddressHint) : - _M_exceptionObserved(0), _M_disassembleMe(_SourceAddressHint) + explicit _ExceptionHolder(IRestrictedErrorInfo*& _E, void* _SourceAddressHint) : + _M_exceptionObserved(0), _M_disassembleMe(_SourceAddressHint), _M_winRTException(_E) { - _M_winRTException = std::unique_ptr<_com_error>(new _com_error(_E)); } __declspec(noinline) ~_ExceptionHolder() { - if (_M_exceptionObserved == 0) - { - // Disassemble at this->_M_disassembleMe to get to the source location right after either the creation of the task (constructor - // or then method) that encountered this exception, or the set_exception call for a task_completion_event. - Concurrency::details::_ReportUnobservedException(); - } + if (_M_exceptionObserved == 0) + { + // Disassemble at this->_M_disassembleMe to get to the source location right after either the creation of the task (constructor + // or then method) that encountered this exception, or the set_exception call for a task_completion_event. + Concurrency::details::_ReportUnobservedException(); } + } void _RethrowUserException() { @@ -1238,7 +1236,7 @@ namespace details if (_M_winRTException != nullptr) { - throw _M_winRTException.get(); + throw _M_winRTException.Get(); } std::rethrow_exception(_M_stdException); } @@ -1249,7 +1247,7 @@ namespace details // Either _M_stdException or _M_winRTException is populated based on the type of exception encountered. std::exception_ptr _M_stdException; - std::unique_ptr<_com_error> _M_winRTException; + Microsoft::WRL::ComPtr _M_winRTException; // Disassembling this value will point to a source instruction right after a call instruction. If the call is to create_task, // a task constructor or the then method, the task created by that method is the one that encountered this exception. If the call @@ -1262,6 +1260,7 @@ namespace details struct _AsyncInfoCompletionHandler : public Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::ClassicCom>, _CompletionHandlerType> { + MixInHelper() public: _AsyncInfoCompletionHandler(_Function func) : _M_function(func) {} STDMETHODIMP Invoke(_AsyncOperationType *asyncInfo, ABI::Windows::Foundation::AsyncStatus status) @@ -1603,7 +1602,7 @@ namespace details _M_pTask->_Cancel(true); throw; } - catch(const _com_error& _E) + catch(IRestrictedErrorInfo*& _E) { _M_pTask->_CancelWithException(_E); throw; @@ -1742,7 +1741,7 @@ namespace details // the exception and canceled the task. Swallow the exception here. _CONCRT_ASSERT(_IsCanceled()); } - catch(const _com_error& _E) + catch(IRestrictedErrorInfo*& _E) { // Its possible the task body hasn't seen the exception, if so we need to cancel with exception here. if(!_HasUserException()) @@ -1818,7 +1817,7 @@ namespace details return _CancelAndRunContinuations(true, true, _PropagatedFromAncestor, _ExHolder); } - bool _CancelWithException(const _com_error& _Exception) + bool _CancelWithException(IRestrictedErrorInfo*& _Exception) { // This task was canceled because the task body encountered an exception. _CONCRT_ASSERT(!_HasUserException()); @@ -1879,7 +1878,7 @@ namespace details bool _HasUserException() { - return _M_exceptionHolder; + return _M_exceptionHolder != nullptr; } void _SetScheduledEvent() @@ -2042,7 +2041,7 @@ namespace details return S_OK; }); } - catch(const _com_error& _E) + catch(IRestrictedErrorInfo*& _E) { _TaskImplPtr->_CancelWithException(_E); } @@ -2489,7 +2488,7 @@ namespace details bool _HasUserException() { - return _M_exceptionHolder; + return _M_exceptionHolder != nullptr; } ~_Task_completion_event_impl() @@ -3524,7 +3523,7 @@ private: } // - // Overload 1: returns IAsyncOperation<_InternalReturnType>^ (only uder /ZW) + // Overload 1: returns IAsyncOperation<_InternalReturnType>^ (only under /ZW) // or // returns task<_InternalReturnType> // @@ -4485,7 +4484,7 @@ namespace details template _Ty _GetUnwrappedType(task<_Ty>); - // Unwrap all supportted types + // Unwrap all supported types template auto _GetUnwrappedReturnType(_Ty _Arg, int) -> decltype(_GetUnwrappedType(_Arg)); // fallback @@ -5627,7 +5626,11 @@ namespace details _M_CompleteDelegateAssigned(0), _M_CallbackMade(0) { +#if _MSC_VER < 1800 _M_id = Concurrency::details::_GetNextAsyncId(); +#else + _M_id = Concurrency::details::platform::GetNextAsyncId(); +#endif } virtual STDMETHODIMP GetResults(typename _Attributes::_ReturnType* results) @@ -6113,9 +6116,13 @@ namespace details { _TryTransitionToCancelled(); } - catch(const _com_error& _Ex) + catch(IRestrictedErrorInfo*& _Ex) { - _TryTransitionToError(_Ex->HResult); + HRESULT hr; + HRESULT _hr; + hr = _Ex->GetErrorDetails(NULL, &_hr, NULL, NULL); + if (SUCCEEDED(hr)) hr = _hr; + _TryTransitionToError(hr); } catch (...) {