Merge pull request #4005 from MSOpenTech:videoio-contrib
@ -45,6 +45,24 @@ endif(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES Window
|
||||
|
||||
if(WINRT)
|
||||
add_definitions(-DWINRT -DNO_GETENV)
|
||||
|
||||
# Making definitions available to other configurations and
|
||||
# to filter dependency restrictions at compile time.
|
||||
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone)
|
||||
set(WINRT_PHONE TRUE)
|
||||
add_definitions(-DWINRT_PHONE)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES WindowsStore)
|
||||
set(WINRT_STORE TRUE)
|
||||
add_definitions(-DWINRT_STORE)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_VERSION MATCHES 8.1)
|
||||
set(WINRT_8_1 TRUE)
|
||||
add_definitions(-DWINRT_8_1)
|
||||
elseif(CMAKE_SYSTEM_VERSION MATCHES 8.0)
|
||||
set(WINRT_8_0 TRUE)
|
||||
add_definitions(-DWINRT_8_0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(POLICY CMP0022)
|
||||
|
@ -1,7 +1,3 @@
|
||||
if(WINRT)
|
||||
ocv_module_disable(videoio)
|
||||
endif()
|
||||
|
||||
set(the_description "Media I/O")
|
||||
ocv_add_module(videoio opencv_imgproc opencv_imgcodecs OPTIONAL opencv_androidcamera WRAP java python)
|
||||
|
||||
@ -11,7 +7,7 @@ ocv_add_module(videoio opencv_imgproc opencv_imgcodecs OPTIONAL opencv_androidca
|
||||
# Jose Luis Blanco, 2008
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if(HAVE_WINRT_CX AND NOT WINRT)
|
||||
if(WINRT_8_1)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /ZW")
|
||||
endif()
|
||||
|
||||
@ -36,6 +32,36 @@ file(GLOB videoio_ext_hdrs
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/*.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/*.h")
|
||||
|
||||
# Removing WinRT API headers by default
|
||||
status(" ${name}: Removing WinRT API headers by default")
|
||||
list(REMOVE_ITEM videoio_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/cap_winrt.hpp")
|
||||
|
||||
# Dependencies used by the implementation referenced
|
||||
# below are not available on WinRT 8.0.
|
||||
# Enabling it for WiRT 8.1+ only.
|
||||
if(DEFINED WINRT AND NOT DEFINED WINRT_8_0)
|
||||
|
||||
# WinRT detected. Adding WinRT API header
|
||||
status(" ${name}: WinRT detected. Adding WinRT API header")
|
||||
list(APPEND videoio_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/cap_winrt.hpp")
|
||||
|
||||
# Adding WinRT internal sources and headers
|
||||
list(APPEND videoio_srcs
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt_capture.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt_bridge.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt_video.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt/CaptureFrameGrabber.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt/MediaStreamSink.cpp)
|
||||
list(APPEND videoio_hdrs
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt_capture.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt_bridge.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt_video.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt/MFIncludes.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt/CaptureFrameGrabber.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt/MediaSink.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt/MediaStreamSink.hpp)
|
||||
endif()
|
||||
|
||||
if(WIN32 AND NOT ARM)
|
||||
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_cmu.cpp)
|
||||
endif()
|
||||
|
@ -50,6 +50,7 @@
|
||||
@{
|
||||
@defgroup videoio_c C API
|
||||
@defgroup videoio_ios iOS glue
|
||||
@defgroup videoio_winrt WinRT glue
|
||||
@}
|
||||
*/
|
||||
|
||||
@ -85,8 +86,9 @@ enum { CAP_ANY = 0, // autodetect
|
||||
CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API)
|
||||
CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK
|
||||
CAP_MSMF = 1400, // Microsoft Media Foundation (via videoInput)
|
||||
CAP_INTELPERC = 1500, // Intel Perceptual Computing SDK
|
||||
CAP_OPENNI2 = 1600, // OpenNI2 (for Kinect)
|
||||
CAP_WINRT = 1410, // Microsoft Windows Runtime using Media Foundation
|
||||
CAP_INTELPERC = 1500, // Intel Perceptual Computing SDK
|
||||
CAP_OPENNI2 = 1600, // OpenNI2 (for Kinect)
|
||||
CAP_OPENNI2_ASUS = 1610 // OpenNI2 (for Asus Xtion and Occipital Structure sensors)
|
||||
};
|
||||
|
||||
|
130
modules/videoio/include/opencv2/videoio/cap_winrt.hpp
Normal file
@ -0,0 +1,130 @@
|
||||
// Video support for Windows Runtime
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <ppl.h>
|
||||
#include <functional>
|
||||
#include <concrt.h>
|
||||
#include <agile.h>
|
||||
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
//! @addtogroup videoio_winrt
|
||||
//! @{
|
||||
|
||||
enum {
|
||||
OPEN_CAMERA = 300,
|
||||
CLOSE_CAMERA,
|
||||
UPDATE_IMAGE_ELEMENT,
|
||||
SHOW_TRACKBAR
|
||||
};
|
||||
|
||||
/********************************** WinRT API ************************************************/
|
||||
|
||||
template <typename ...Args>
|
||||
CV_EXPORTS void winrt_startMessageLoop(std::function<void(Args...)>&& callback, Args... args);
|
||||
|
||||
template <typename ...Args>
|
||||
CV_EXPORTS void winrt_startMessageLoop(void callback(Args...), Args... args);
|
||||
|
||||
/** @brief
|
||||
@note
|
||||
Sets the reporter method for the HighguiAssist singleton. Starts the main OpenCV as
|
||||
an async thread in WinRT. See VideoCapture for the example of callback implementation.
|
||||
Here is how the class can be used:
|
||||
@code
|
||||
void cvMain()
|
||||
{
|
||||
Mat frame;
|
||||
VideoCapture cam;
|
||||
cam.open(0);
|
||||
|
||||
while (1)
|
||||
{
|
||||
cam >> frame;
|
||||
|
||||
// don't reprocess the same frame again
|
||||
if (!cam.grab()) continue;
|
||||
|
||||
// your processing logic goes here
|
||||
|
||||
// obligatory step to get XAML image component updated
|
||||
winrt_imshow();
|
||||
}
|
||||
}
|
||||
|
||||
MainPage::MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
cv::winrt_setFrameContainer(cvImage);
|
||||
cv::winrt_startMessageLoop(cvMain);
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
template
|
||||
CV_EXPORTS void winrt_startMessageLoop(void callback(void));
|
||||
|
||||
/** @brief
|
||||
@note
|
||||
Must be called from WinRT specific callback to handle image grabber state.
|
||||
Here is how the class can be used:
|
||||
@code
|
||||
MainPage::MainPage()
|
||||
{
|
||||
// ...
|
||||
Window::Current->VisibilityChanged += ref new Windows::UI::Xaml::WindowVisibilityChangedEventHandler(this, &Application::MainPage::OnVisibilityChanged);
|
||||
// ...
|
||||
}
|
||||
|
||||
void Application::MainPage::OnVisibilityChanged(Platform::Object ^sender,
|
||||
Windows::UI::Core::VisibilityChangedEventArgs ^e)
|
||||
{
|
||||
cv::winrt_onVisibilityChanged(e->Visible);
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
CV_EXPORTS void winrt_onVisibilityChanged(bool visible);
|
||||
|
||||
/** @brief
|
||||
@note
|
||||
Must be called to assign WinRT control holding image you're working with.
|
||||
Code sample is available for winrt_startMessageLoop().
|
||||
*/
|
||||
CV_EXPORTS void winrt_setFrameContainer(::Windows::UI::Xaml::Controls::Image^ image);
|
||||
|
||||
/** @brief
|
||||
@note
|
||||
Must be called to update attached image source.
|
||||
Code sample is available for winrt_startMessageLoop().
|
||||
*/
|
||||
CV_EXPORTS void winrt_imshow();
|
||||
|
||||
//! @} videoio_winrt
|
||||
|
||||
} // cv
|
568
modules/videoio/src/agile_wrl.hpp
Normal file
@ -0,0 +1,568 @@
|
||||
//
|
||||
// Copyright (C) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
// Modified for native C++ WRL support by Gregory Morse
|
||||
//
|
||||
// Code in Details namespace is for internal usage within the library code
|
||||
//
|
||||
|
||||
#ifndef _PLATFORM_AGILE_H_
|
||||
#define _PLATFORM_AGILE_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <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(¤tContextToken));
|
||||
if (currentContextToken == _contextToken)
|
||||
{
|
||||
return _object;
|
||||
}
|
||||
|
||||
#if _MSC_VER >= 1800
|
||||
// Different context and holding on to a non agile object
|
||||
// Do the costly work of getting a proxy
|
||||
TypeT localObject;
|
||||
__abi_ThrowIfFailed(Details::GetProxy(_object, _contextCallback.Get(), &localObject));
|
||||
|
||||
if (_agileState == AgileState::Unknown)
|
||||
#else
|
||||
// Object is agile if it implements IAgileObject
|
||||
// GetAddressOf captures the context with out knowing the type of object that it will hold
|
||||
if (_object != nullptr)
|
||||
#endif
|
||||
{
|
||||
#if _MSC_VER >= 1800
|
||||
// Object is agile if it implements IAgileObject
|
||||
// GetAddressOf captures the context with out knowing the type of object that it will hold
|
||||
::Microsoft::WRL::ComPtr<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(¤tContextToken));
|
||||
if (_contextToken == 0 || _contextCallback == nullptr || _contextToken == currentContextToken)
|
||||
{
|
||||
pObject->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
Details::ReleaseInContext(pObject, _contextCallback.Get());
|
||||
}
|
||||
_contextCallback = nullptr;
|
||||
_contextToken = 0;
|
||||
#if _MSC_VER >= 1800
|
||||
_agileState = AgileState::Unknown;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(nullptr_t) const throw()
|
||||
{
|
||||
return _object == nullptr;
|
||||
}
|
||||
|
||||
bool operator==(const Agile& other) const throw()
|
||||
{
|
||||
return _object == other._object && _contextToken == other._contextToken;
|
||||
}
|
||||
|
||||
bool operator<(const Agile& other) const throw()
|
||||
{
|
||||
if (reinterpret_cast<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_
|
@ -43,6 +43,13 @@
|
||||
#include "cap_intelperc.hpp"
|
||||
#include "cap_dshow.hpp"
|
||||
|
||||
// All WinRT versions older than 8.0 should provide classes used for video support
|
||||
#if defined(WINRT) && !defined(WINRT_8_0)
|
||||
# include "cap_winrt_capture.hpp"
|
||||
# include "cap_winrt_bridge.hpp"
|
||||
# define WINRT_VIDEO
|
||||
#endif
|
||||
|
||||
#if defined _M_X64 && defined _MSC_VER && !defined CV_ICC
|
||||
#pragma optimize("",off)
|
||||
#pragma warning(disable: 4748)
|
||||
@ -508,6 +515,9 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
|
||||
#endif
|
||||
#ifdef HAVE_INTELPERC
|
||||
CV_CAP_INTELPERC,
|
||||
#endif
|
||||
#ifdef WINRT_VIDEO
|
||||
CAP_WINRT,
|
||||
#endif
|
||||
-1, -1
|
||||
};
|
||||
@ -526,6 +536,7 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
|
||||
{
|
||||
#if defined(HAVE_DSHOW) || \
|
||||
defined(HAVE_INTELPERC) || \
|
||||
defined(WINRT_VIDEO) || \
|
||||
(0)
|
||||
Ptr<IVideoCapture> capture;
|
||||
|
||||
@ -540,6 +551,13 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
|
||||
case CV_CAP_INTELPERC:
|
||||
capture = makePtr<VideoCapture_IntelPerC>();
|
||||
break; // CV_CAP_INTEL_PERC
|
||||
#endif
|
||||
#ifdef WINRT_VIDEO
|
||||
case CAP_WINRT:
|
||||
capture = Ptr<IVideoCapture>(new cv::VideoCapture_WinRT(index));
|
||||
if (capture)
|
||||
return capture;
|
||||
break; // CAP_WINRT
|
||||
#endif
|
||||
}
|
||||
if (capture && capture->isOpened())
|
||||
@ -664,7 +682,29 @@ bool VideoCapture::read(OutputArray image)
|
||||
|
||||
VideoCapture& VideoCapture::operator >> (Mat& image)
|
||||
{
|
||||
#ifdef WINRT_VIDEO
|
||||
if (grab())
|
||||
{
|
||||
if (retrieve(image))
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(VideoioBridge::getInstance().inputBufferMutex);
|
||||
VideoioBridge& bridge = VideoioBridge::getInstance();
|
||||
|
||||
// double buffering
|
||||
bridge.swapInputBuffers();
|
||||
auto p = bridge.frontInputPtr;
|
||||
|
||||
bridge.bIsFrameNew = false;
|
||||
|
||||
// needed here because setting Mat 'image' is not allowed by OutputArray in read()
|
||||
Mat m(bridge.height, bridge.width, CV_8UC3, p);
|
||||
image = m;
|
||||
}
|
||||
}
|
||||
#else
|
||||
read(image);
|
||||
#endif
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
173
modules/videoio/src/cap_winrt/CaptureFrameGrabber.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "MediaStreamSink.hpp"
|
||||
#include "MediaSink.hpp"
|
||||
#include "CaptureFrameGrabber.hpp"
|
||||
|
||||
using namespace Media;
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Media;
|
||||
using namespace Windows::Media::Capture;
|
||||
using namespace Windows::Media::MediaProperties;
|
||||
using namespace concurrency;
|
||||
using namespace Microsoft::WRL::Details;
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
task<Media::CaptureFrameGrabber^> Media::CaptureFrameGrabber::CreateAsync(_In_ MediaCapture^ capture, _In_ VideoEncodingProperties^ props, CaptureStreamType streamType)
|
||||
{
|
||||
auto reader = ref new Media::CaptureFrameGrabber(capture, props, streamType);
|
||||
|
||||
auto profile = ref new MediaEncodingProfile();
|
||||
profile->Video = props;
|
||||
|
||||
task<void> task;
|
||||
if (reader->_streamType == CaptureStreamType::Preview)
|
||||
{
|
||||
task = create_task(capture->StartPreviewToCustomSinkAsync(profile, reader->_mediaExtension));
|
||||
}
|
||||
else
|
||||
{
|
||||
task = create_task(capture->StartRecordToCustomSinkAsync(profile, reader->_mediaExtension));
|
||||
}
|
||||
|
||||
return task.then([reader]()
|
||||
{
|
||||
reader->_state = State::Started;
|
||||
return reader;
|
||||
});
|
||||
}
|
||||
|
||||
Media::CaptureFrameGrabber::CaptureFrameGrabber(_In_ MediaCapture^ capture, _In_ VideoEncodingProperties^ props, CaptureStreamType streamType)
|
||||
: _state(State::Created)
|
||||
, _streamType(streamType)
|
||||
, _capture(capture)
|
||||
{
|
||||
auto videoSampleHandler = ref new MediaSampleHandler(this, &Media::CaptureFrameGrabber::ProcessSample);
|
||||
|
||||
_mediaSink = Make<MediaSink>(nullptr, props, nullptr, videoSampleHandler);
|
||||
_mediaExtension = reinterpret_cast<IMediaExtension^>(static_cast<AWM::IMediaExtension*>(_mediaSink.Get()));
|
||||
}
|
||||
|
||||
Media::CaptureFrameGrabber::~CaptureFrameGrabber()
|
||||
{
|
||||
if (_state == State::Started)
|
||||
{
|
||||
if (_streamType == CaptureStreamType::Preview)
|
||||
{
|
||||
(void)_capture->StopPreviewAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)_capture->StopRecordAsync();
|
||||
}
|
||||
}
|
||||
|
||||
if (_mediaSink != nullptr)
|
||||
{
|
||||
(void)_mediaSink->Shutdown();
|
||||
_mediaSink = nullptr;
|
||||
}
|
||||
_mediaExtension = nullptr;
|
||||
_capture = nullptr;
|
||||
}
|
||||
|
||||
void Media::CaptureFrameGrabber::ShowCameraSettings()
|
||||
{
|
||||
#if WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP
|
||||
if (_state == State::Started)
|
||||
{
|
||||
CameraOptionsUI::Show(_capture.Get());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
task<void> Media::CaptureFrameGrabber::FinishAsync()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
if (_state != State::Started)
|
||||
{
|
||||
throw ref new COMException(E_UNEXPECTED, L"State");
|
||||
}
|
||||
_state = State::Closing;
|
||||
|
||||
if (_mediaSink != nullptr)
|
||||
{
|
||||
(void)_mediaSink->Shutdown();
|
||||
_mediaSink = nullptr;
|
||||
}
|
||||
_mediaExtension = nullptr;
|
||||
|
||||
task<void> task;
|
||||
if (_streamType == CaptureStreamType::Preview)
|
||||
{
|
||||
task = create_task(_capture->StopPreviewAsync());
|
||||
}
|
||||
else
|
||||
{
|
||||
task = create_task(_capture->StopRecordAsync());
|
||||
}
|
||||
|
||||
return task.then([this]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
_state = State::Closed;
|
||||
_capture = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
task<ComPtr<IMF2DBuffer2>> Media::CaptureFrameGrabber::GetFrameAsync()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
if (_state != State::Started)
|
||||
{
|
||||
throw ref new COMException(E_UNEXPECTED, L"State");
|
||||
}
|
||||
|
||||
_mediaSink->RequestVideoSample();
|
||||
|
||||
task_completion_event<ComPtr<IMF2DBuffer2>> taskEvent;
|
||||
_videoSampleRequestQueue.push(taskEvent);
|
||||
|
||||
return create_task(taskEvent);
|
||||
}
|
||||
|
||||
void Media::CaptureFrameGrabber::ProcessSample(_In_ MediaSample^ sample)
|
||||
{
|
||||
task_completion_event<ComPtr<IMF2DBuffer2>> t;
|
||||
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
t = _videoSampleRequestQueue.front();
|
||||
_videoSampleRequestQueue.pop();
|
||||
}
|
||||
|
||||
ComPtr<IMFMediaBuffer> buffer;
|
||||
CHK(sample->Sample->ConvertToContiguousBuffer(&buffer));
|
||||
|
||||
// Dispatch without the lock taken to avoid deadlocks
|
||||
t.set(As<IMF2DBuffer2>(buffer));
|
||||
}
|
85
modules/videoio/src/cap_winrt/CaptureFrameGrabber.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MFIncludes.hpp"
|
||||
|
||||
|
||||
namespace Media {
|
||||
|
||||
class MediaSink;
|
||||
|
||||
enum class CaptureStreamType
|
||||
{
|
||||
Preview = 0,
|
||||
Record
|
||||
};
|
||||
|
||||
ref class CaptureFrameGrabber sealed
|
||||
{
|
||||
public:
|
||||
|
||||
// IClosable
|
||||
virtual ~CaptureFrameGrabber();
|
||||
|
||||
virtual void ShowCameraSettings();
|
||||
|
||||
internal:
|
||||
|
||||
static concurrency::task<CaptureFrameGrabber^> CreateAsync(_In_ WMC::MediaCapture^ capture, _In_ WMMp::VideoEncodingProperties^ props)
|
||||
{
|
||||
return CreateAsync(capture, props, CaptureStreamType::Preview);
|
||||
}
|
||||
|
||||
static concurrency::task<CaptureFrameGrabber^> CreateAsync(_In_ WMC::MediaCapture^ capture, _In_ WMMp::VideoEncodingProperties^ props, CaptureStreamType streamType);
|
||||
|
||||
concurrency::task<MW::ComPtr<IMF2DBuffer2>> GetFrameAsync();
|
||||
concurrency::task<void> FinishAsync();
|
||||
|
||||
private:
|
||||
|
||||
CaptureFrameGrabber(_In_ WMC::MediaCapture^ capture, _In_ WMMp::VideoEncodingProperties^ props, CaptureStreamType streamType);
|
||||
|
||||
void ProcessSample(_In_ MediaSample^ sample);
|
||||
|
||||
Platform::Agile<WMC::MediaCapture> _capture;
|
||||
::Windows::Media::IMediaExtension^ _mediaExtension;
|
||||
|
||||
MW::ComPtr<MediaSink> _mediaSink;
|
||||
|
||||
CaptureStreamType _streamType;
|
||||
|
||||
enum class State
|
||||
{
|
||||
Created,
|
||||
Started,
|
||||
Closing,
|
||||
Closed
|
||||
} _state;
|
||||
|
||||
std::queue<concurrency::task_completion_event<MW::ComPtr<IMF2DBuffer2>>> _videoSampleRequestQueue;
|
||||
AutoMF _mf;
|
||||
MWW::SRWLock _lock;
|
||||
};
|
||||
|
||||
}
|
172
modules/videoio/src/cap_winrt/MFIncludes.hpp
Normal file
@ -0,0 +1,172 @@
|
||||
// Header for standard system include files.
|
||||
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <collection.h>
|
||||
#include <ppltasks.h>
|
||||
|
||||
#include <wrl\implements.h>
|
||||
#include <wrl\wrappers\corewrappers.h>
|
||||
#include <Roerrorapi.h>
|
||||
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
|
||||
#include <robuffer.h>
|
||||
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
#include <Mferror.h>
|
||||
|
||||
#include <windows.media.h>
|
||||
#include <windows.media.mediaproperties.h>
|
||||
|
||||
namespace AWM = ::ABI::Windows::Media;
|
||||
namespace AWMMp = ::ABI::Windows::Media::MediaProperties;
|
||||
namespace AWFC = ::ABI::Windows::Foundation::Collections;
|
||||
namespace MW = ::Microsoft::WRL;
|
||||
namespace MWD = ::Microsoft::WRL::Details;
|
||||
namespace MWW = ::Microsoft::WRL::Wrappers;
|
||||
namespace WMC = ::Windows::Media::Capture;
|
||||
namespace WF = ::Windows::Foundation;
|
||||
namespace WMMp = ::Windows::Media::MediaProperties;
|
||||
namespace WSS = ::Windows::Storage::Streams;
|
||||
|
||||
// Exception-based error handling
|
||||
#define CHK(statement) {HRESULT _hr = (statement); if (FAILED(_hr)) { throw ref new Platform::COMException(_hr); };}
|
||||
#define CHKNULL(p) {if ((p) == nullptr) { throw ref new Platform::NullReferenceException(L#p); };}
|
||||
|
||||
// Exception-free error handling
|
||||
#define CHK_RETURN(statement) {hr = (statement); if (FAILED(hr)) { return hr; };}
|
||||
|
||||
// Cast a C++/CX msartpointer to an ABI smartpointer
|
||||
template<typename T, typename U>
|
||||
MW::ComPtr<T> As(U^ in)
|
||||
{
|
||||
MW::ComPtr<T> out;
|
||||
CHK(reinterpret_cast<IInspectable*>(in)->QueryInterface(IID_PPV_ARGS(&out)));
|
||||
return out;
|
||||
}
|
||||
|
||||
// Cast an ABI smartpointer
|
||||
template<typename T, typename U>
|
||||
Microsoft::WRL::ComPtr<T> As(const Microsoft::WRL::ComPtr<U>& in)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<T> out;
|
||||
CHK(in.As(&out));
|
||||
return out;
|
||||
}
|
||||
|
||||
// Cast an ABI smartpointer
|
||||
template<typename T, typename U>
|
||||
Microsoft::WRL::ComPtr<T> As(U* in)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<T> out;
|
||||
CHK(in->QueryInterface(IID_PPV_ARGS(&out)));
|
||||
return out;
|
||||
}
|
||||
|
||||
// Get access to bytes in IBuffer
|
||||
inline unsigned char* GetData(_In_ WSS::IBuffer^ buffer)
|
||||
{
|
||||
unsigned char* bytes = nullptr;
|
||||
CHK(As<WSS::IBufferByteAccess>(buffer)->Buffer(&bytes));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// Class to start and shutdown Media Foundation
|
||||
class AutoMF
|
||||
{
|
||||
public:
|
||||
AutoMF()
|
||||
: _bInitialized(false)
|
||||
{
|
||||
CHK(MFStartup(MF_VERSION));
|
||||
}
|
||||
|
||||
~AutoMF()
|
||||
{
|
||||
if (_bInitialized)
|
||||
{
|
||||
(void)MFShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool _bInitialized;
|
||||
};
|
||||
|
||||
// Class to track error origin
|
||||
template <size_t N>
|
||||
HRESULT OriginateError(__in HRESULT hr, __in wchar_t const (&str)[N])
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
::RoOriginateErrorW(hr, N - 1, str);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Class to track error origin
|
||||
inline HRESULT OriginateError(__in HRESULT hr)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
::RoOriginateErrorW(hr, 0, nullptr);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Converts exceptions into HRESULTs
|
||||
template <typename Lambda>
|
||||
HRESULT ExceptionBoundary(Lambda&& lambda)
|
||||
{
|
||||
try
|
||||
{
|
||||
lambda();
|
||||
return S_OK;
|
||||
}
|
||||
catch (Platform::Exception^ e)
|
||||
{
|
||||
return e->HResult;
|
||||
}
|
||||
catch (const std::bad_alloc&)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Wraps an IMFSample in a C++/CX class to be able to define a callback delegate
|
||||
ref class MediaSample sealed
|
||||
{
|
||||
internal:
|
||||
MW::ComPtr<IMFSample> Sample;
|
||||
};
|
||||
|
||||
delegate void MediaSampleHandler(MediaSample^ sample);
|
396
modules/videoio/src/cap_winrt/MediaSink.hpp
Normal file
@ -0,0 +1,396 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MediaStreamSink.hpp"
|
||||
#include "MFIncludes.hpp"
|
||||
|
||||
namespace Media {
|
||||
|
||||
const unsigned int c_audioStreamSinkId = 0;
|
||||
const unsigned int c_videoStreamSinkId = 1;
|
||||
|
||||
class MediaSink WrlSealed
|
||||
: public MW::RuntimeClass<
|
||||
MW::RuntimeClassFlags<
|
||||
MW::RuntimeClassType::WinRtClassicComMix>
|
||||
, AWM::IMediaExtension
|
||||
, IMFMediaSink
|
||||
, IMFClockStateSink
|
||||
, MW::FtmBase
|
||||
>
|
||||
{
|
||||
InspectableClass(L"MediaSink", BaseTrust)
|
||||
|
||||
public:
|
||||
|
||||
MediaSink(
|
||||
_In_opt_ WMMp::AudioEncodingProperties^ audioProps,
|
||||
_In_opt_ WMMp::VideoEncodingProperties^ videoProps,
|
||||
_In_opt_ MediaSampleHandler^ audioSampleHandler,
|
||||
_In_opt_ MediaSampleHandler^ videoSampleHandler
|
||||
)
|
||||
: _shutdown(false)
|
||||
{
|
||||
MW::ComPtr<IMFMediaType> audioMT;
|
||||
if (audioProps != nullptr)
|
||||
{
|
||||
CHK(MFCreateMediaTypeFromProperties(As<IUnknown>(audioProps).Get(), &audioMT));
|
||||
_audioStreamSink = MW::Make<MediaStreamSink>(
|
||||
this,
|
||||
c_audioStreamSinkId,
|
||||
audioMT,
|
||||
audioSampleHandler
|
||||
);
|
||||
}
|
||||
|
||||
MW::ComPtr<IMFMediaType> videoMT;
|
||||
if (videoProps != nullptr)
|
||||
{
|
||||
CHK(MFCreateMediaTypeFromProperties(As<IUnknown>(videoProps).Get(), &videoMT));
|
||||
_videoStreamSink = MW::Make<MediaStreamSink>(
|
||||
this,
|
||||
c_videoStreamSinkId,
|
||||
videoMT,
|
||||
videoSampleHandler
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void RequestAudioSample()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
_audioStreamSink->RequestSample();
|
||||
}
|
||||
|
||||
void RequestVideoSample()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
_videoStreamSink->RequestSample();
|
||||
}
|
||||
|
||||
void SetCurrentAudioMediaType(_In_ IMFMediaType* mt)
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
_audioStreamSink->InternalSetCurrentMediaType(mt);
|
||||
}
|
||||
|
||||
void SetCurrentVideoMediaType(_In_ IMFMediaType* mt)
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
_videoStreamSink->InternalSetCurrentMediaType(mt);
|
||||
}
|
||||
|
||||
//
|
||||
// IMediaExtension
|
||||
//
|
||||
|
||||
IFACEMETHODIMP SetProperties(_In_ AWFC::IPropertySet * /*configuration*/)
|
||||
{
|
||||
return ExceptionBoundary([this]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// IMFMediaSink
|
||||
//
|
||||
|
||||
IFACEMETHODIMP GetCharacteristics(_Out_ DWORD *characteristics)
|
||||
{
|
||||
return ExceptionBoundary([this, characteristics]()
|
||||
{
|
||||
_VerifyNotShutdown();
|
||||
|
||||
CHKNULL(characteristics);
|
||||
*characteristics = MEDIASINK_RATELESS | MEDIASINK_FIXED_STREAMS;
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AddStreamSink(
|
||||
DWORD /*streamSinkIdentifier*/,
|
||||
_In_ IMFMediaType * /*mediaType*/,
|
||||
_COM_Outptr_ IMFStreamSink **streamSink
|
||||
)
|
||||
{
|
||||
return ExceptionBoundary([this, streamSink]()
|
||||
{
|
||||
_VerifyNotShutdown();
|
||||
|
||||
CHKNULL(streamSink);
|
||||
*streamSink = nullptr;
|
||||
|
||||
CHK(MF_E_STREAMSINKS_FIXED);
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP RemoveStreamSink(DWORD /*streamSinkIdentifier*/)
|
||||
{
|
||||
return ExceptionBoundary([this]()
|
||||
{
|
||||
_VerifyNotShutdown();
|
||||
|
||||
CHK(MF_E_STREAMSINKS_FIXED);
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP GetStreamSinkCount(_Out_ DWORD *streamSinkCount)
|
||||
{
|
||||
return ExceptionBoundary([this, streamSinkCount]()
|
||||
{
|
||||
CHKNULL(streamSinkCount);
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
*streamSinkCount = (_audioStreamSink != nullptr) + (_videoStreamSink != nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP GetStreamSinkByIndex(DWORD index, _COM_Outptr_ IMFStreamSink **streamSink)
|
||||
{
|
||||
return ExceptionBoundary([this, index, streamSink]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(streamSink);
|
||||
*streamSink = nullptr;
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
if (_audioStreamSink != nullptr)
|
||||
{
|
||||
CHK(_audioStreamSink.CopyTo(streamSink));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHK(_videoStreamSink.CopyTo(streamSink));
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if ((_audioStreamSink != nullptr) && (_videoStreamSink != nullptr))
|
||||
{
|
||||
CHK(_videoStreamSink.CopyTo(streamSink));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHK(E_INVALIDARG);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CHK(E_INVALIDARG);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP GetStreamSinkById(DWORD identifier, _COM_Outptr_ IMFStreamSink **streamSink)
|
||||
{
|
||||
return ExceptionBoundary([this, identifier, streamSink]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(streamSink);
|
||||
*streamSink = nullptr;
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
if ((identifier == 0) && (_audioStreamSink != nullptr))
|
||||
{
|
||||
CHK(_audioStreamSink.CopyTo(streamSink));
|
||||
}
|
||||
else if ((identifier == 1) && (_videoStreamSink != nullptr))
|
||||
{
|
||||
CHK(_videoStreamSink.CopyTo(streamSink));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHK(E_INVALIDARG);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP SetPresentationClock(_In_ IMFPresentationClock *clock)
|
||||
{
|
||||
return ExceptionBoundary([this, clock]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
if (_clock != nullptr)
|
||||
{
|
||||
CHK(_clock->RemoveClockStateSink(this));
|
||||
_clock = nullptr;
|
||||
}
|
||||
|
||||
if (clock != nullptr)
|
||||
{
|
||||
CHK(clock->AddClockStateSink(this));
|
||||
_clock = clock;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP GetPresentationClock(_COM_Outptr_ IMFPresentationClock **clock)
|
||||
{
|
||||
return ExceptionBoundary([this, clock]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(clock);
|
||||
*clock = nullptr;
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
if (_clock != nullptr)
|
||||
{
|
||||
CHK(_clock.CopyTo(clock))
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP Shutdown()
|
||||
{
|
||||
return ExceptionBoundary([this]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
if (_shutdown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_shutdown = true;
|
||||
|
||||
if (_audioStreamSink != nullptr)
|
||||
{
|
||||
_audioStreamSink->Shutdown();
|
||||
_audioStreamSink = nullptr;
|
||||
}
|
||||
|
||||
if (_videoStreamSink != nullptr)
|
||||
{
|
||||
_videoStreamSink->Shutdown();
|
||||
_videoStreamSink = nullptr;
|
||||
}
|
||||
|
||||
if (_clock != nullptr)
|
||||
{
|
||||
(void)_clock->RemoveClockStateSink(this);
|
||||
_clock = nullptr;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// IMFClockStateSink methods
|
||||
//
|
||||
|
||||
IFACEMETHODIMP OnClockStart(MFTIME /*hnsSystemTime*/, LONGLONG /*llClockStartOffset*/)
|
||||
{
|
||||
return ExceptionBoundary([this]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP OnClockStop(MFTIME /*hnsSystemTime*/)
|
||||
{
|
||||
return ExceptionBoundary([this]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP OnClockPause(MFTIME /*hnsSystemTime*/)
|
||||
{
|
||||
return ExceptionBoundary([this]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP OnClockRestart(MFTIME /*hnsSystemTime*/)
|
||||
{
|
||||
return ExceptionBoundary([this]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
});
|
||||
}
|
||||
|
||||
IFACEMETHODIMP OnClockSetRate(MFTIME /*hnsSystemTime*/, float /*flRate*/)
|
||||
{
|
||||
return ExceptionBoundary([this]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool _shutdown;
|
||||
|
||||
void _VerifyNotShutdown()
|
||||
{
|
||||
if (_shutdown)
|
||||
{
|
||||
CHK(MF_E_SHUTDOWN);
|
||||
}
|
||||
}
|
||||
|
||||
MW::ComPtr<MediaStreamSink> _audioStreamSink;
|
||||
MW::ComPtr<MediaStreamSink> _videoStreamSink;
|
||||
MW::ComPtr<IMFPresentationClock> _clock;
|
||||
|
||||
MWW::SRWLock _lock;
|
||||
};
|
||||
|
||||
}
|
386
modules/videoio/src/cap_winrt/MediaStreamSink.cpp
Normal file
@ -0,0 +1,386 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "MediaStreamSink.hpp"
|
||||
#include "MFIncludes.hpp"
|
||||
|
||||
using namespace Media;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
MediaStreamSink::MediaStreamSink(
|
||||
__in const MW::ComPtr<IMFMediaSink>& sink,
|
||||
__in DWORD id,
|
||||
__in const MW::ComPtr<IMFMediaType>& mt,
|
||||
__in MediaSampleHandler^ sampleHandler
|
||||
)
|
||||
: _shutdown(false)
|
||||
, _id(-1)
|
||||
, _width(0)
|
||||
, _height(0)
|
||||
{
|
||||
CHK(MFCreateEventQueue(&_eventQueue));
|
||||
CHK(MFCreateMediaType(&_curMT));
|
||||
|
||||
_UpdateMediaType(mt);
|
||||
|
||||
_sink = sink;
|
||||
_id = id;
|
||||
_sampleHandler = sampleHandler;
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::GetMediaSink(__deref_out IMFMediaSink **sink)
|
||||
{
|
||||
return ExceptionBoundary([this, sink]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(sink);
|
||||
*sink = nullptr;
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
CHK(_sink.CopyTo(sink));
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::GetIdentifier(__out DWORD *identifier)
|
||||
{
|
||||
return ExceptionBoundary([this, identifier]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(identifier);
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
*identifier = _id;
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::GetMediaTypeHandler(__deref_out IMFMediaTypeHandler **handler)
|
||||
{
|
||||
return ExceptionBoundary([this, handler]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(handler);
|
||||
*handler = nullptr;
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
*handler = this;
|
||||
this->AddRef();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void MediaStreamSink::RequestSample()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
CHK(_eventQueue->QueueEventParamVar(MEStreamSinkRequestSample, GUID_NULL, S_OK, nullptr));
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::ProcessSample(__in_opt IMFSample *sample)
|
||||
{
|
||||
return ExceptionBoundary([this, sample]()
|
||||
{
|
||||
MediaSampleHandler^ sampleHandler;
|
||||
auto mediaSample = ref new MediaSample();
|
||||
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
if (sample == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mediaSample->Sample = sample;
|
||||
sampleHandler = _sampleHandler;
|
||||
}
|
||||
|
||||
// Call back without the lock taken to avoid deadlocks
|
||||
sampleHandler(mediaSample);
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::PlaceMarker(__in MFSTREAMSINK_MARKER_TYPE /*markerType*/, __in const PROPVARIANT * /*markerValue*/, __in const PROPVARIANT * contextValue)
|
||||
{
|
||||
return ExceptionBoundary([this, contextValue]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
CHKNULL(contextValue);
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
CHK(_eventQueue->QueueEventParamVar(MEStreamSinkMarker, GUID_NULL, S_OK, contextValue));
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::Flush()
|
||||
{
|
||||
return ExceptionBoundary([this]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::GetEvent(__in DWORD flags, __deref_out IMFMediaEvent **event)
|
||||
{
|
||||
return ExceptionBoundary([this, flags, event]()
|
||||
{
|
||||
CHKNULL(event);
|
||||
*event = nullptr;
|
||||
|
||||
ComPtr<IMFMediaEventQueue> eventQueue;
|
||||
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
eventQueue = _eventQueue;
|
||||
}
|
||||
|
||||
// May block for a while
|
||||
CHK(eventQueue->GetEvent(flags, event));
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::BeginGetEvent(__in IMFAsyncCallback *callback, __in_opt IUnknown *state)
|
||||
{
|
||||
return ExceptionBoundary([this, callback, state]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
CHK(_eventQueue->BeginGetEvent(callback, state));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
HRESULT MediaStreamSink::EndGetEvent(__in IMFAsyncResult *result, __deref_out IMFMediaEvent **event)
|
||||
{
|
||||
return ExceptionBoundary([this, result, event]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(event);
|
||||
*event = nullptr;
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
CHK(_eventQueue->EndGetEvent(result, event));
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::QueueEvent(
|
||||
__in MediaEventType met,
|
||||
__in REFGUID extendedType,
|
||||
__in HRESULT status,
|
||||
__in_opt const PROPVARIANT *value
|
||||
)
|
||||
{
|
||||
return ExceptionBoundary([this, met, extendedType, status, value]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
CHK(_eventQueue->QueueEventParamVar(met, extendedType, status, value));
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::IsMediaTypeSupported(__in IMFMediaType *mediaType, __deref_out_opt IMFMediaType **closestMediaType)
|
||||
{
|
||||
bool supported = false;
|
||||
|
||||
HRESULT hr = ExceptionBoundary([this, mediaType, closestMediaType, &supported]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (closestMediaType != nullptr)
|
||||
{
|
||||
*closestMediaType = nullptr;
|
||||
}
|
||||
|
||||
CHKNULL(mediaType);
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
supported = _IsMediaTypeSupported(mediaType);
|
||||
});
|
||||
|
||||
// Avoid throwing an exception to return MF_E_INVALIDMEDIATYPE as this is not a exceptional case
|
||||
return FAILED(hr) ? hr : supported ? S_OK : MF_E_INVALIDMEDIATYPE;
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::GetMediaTypeCount(__out DWORD *typeCount)
|
||||
{
|
||||
return ExceptionBoundary([this, typeCount]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(typeCount);
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
// No media type provided by default (app needs to specify it)
|
||||
*typeCount = 0;
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::GetMediaTypeByIndex(__in DWORD /*index*/, __deref_out IMFMediaType **mediaType)
|
||||
{
|
||||
HRESULT hr = ExceptionBoundary([this, mediaType]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(mediaType);
|
||||
*mediaType = nullptr;
|
||||
|
||||
_VerifyNotShutdown();
|
||||
});
|
||||
|
||||
// Avoid throwing an exception to return MF_E_NO_MORE_TYPES as this is not a exceptional case
|
||||
return FAILED(hr) ? hr : MF_E_NO_MORE_TYPES;
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::SetCurrentMediaType(__in IMFMediaType *mediaType)
|
||||
{
|
||||
return ExceptionBoundary([this, mediaType]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
CHKNULL(mediaType);
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
if (!_IsMediaTypeSupported(mediaType))
|
||||
{
|
||||
CHK(MF_E_INVALIDMEDIATYPE);
|
||||
}
|
||||
|
||||
_UpdateMediaType(mediaType);
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::GetCurrentMediaType(__deref_out_opt IMFMediaType **mediaType)
|
||||
{
|
||||
return ExceptionBoundary([this, mediaType]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(mediaType);
|
||||
*mediaType = nullptr;
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
ComPtr<IMFMediaType> mt;
|
||||
CHK(MFCreateMediaType(&mt));
|
||||
CHK(_curMT->CopyAllItems(mt.Get()));
|
||||
*mediaType = mt.Detach();
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT MediaStreamSink::GetMajorType(__out GUID *majorType)
|
||||
{
|
||||
return ExceptionBoundary([this, majorType]()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(majorType);
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
*majorType = _majorType;
|
||||
});
|
||||
}
|
||||
|
||||
void MediaStreamSink::InternalSetCurrentMediaType(__in const ComPtr<IMFMediaType>& mediaType)
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
CHKNULL(mediaType);
|
||||
|
||||
_VerifyNotShutdown();
|
||||
|
||||
_UpdateMediaType(mediaType);
|
||||
}
|
||||
|
||||
void MediaStreamSink::Shutdown()
|
||||
{
|
||||
auto lock = _lock.LockExclusive();
|
||||
|
||||
if (_shutdown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_shutdown = true;
|
||||
|
||||
(void)_eventQueue->Shutdown();
|
||||
_eventQueue = nullptr;
|
||||
|
||||
_curMT = nullptr;
|
||||
_sink = nullptr;
|
||||
_sampleHandler = nullptr;
|
||||
}
|
||||
|
||||
bool MediaStreamSink::_IsMediaTypeSupported(__in const ComPtr<IMFMediaType>& mt) const
|
||||
{
|
||||
GUID majorType;
|
||||
GUID subType;
|
||||
if (SUCCEEDED(mt->GetGUID(MF_MT_MAJOR_TYPE, &majorType)) &&
|
||||
SUCCEEDED(mt->GetGUID(MF_MT_SUBTYPE, &subType)) &&
|
||||
(majorType == _majorType) &&
|
||||
(subType == _subType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MediaStreamSink::_UpdateMediaType(__in const ComPtr<IMFMediaType>& mt)
|
||||
{
|
||||
CHK(mt->GetGUID(MF_MT_MAJOR_TYPE, &_majorType));
|
||||
CHK(mt->GetGUID(MF_MT_SUBTYPE, &_subType));
|
||||
|
||||
if (_majorType == MFMediaType_Video)
|
||||
{
|
||||
CHK(MFGetAttributeSize(mt.Get(), MF_MT_FRAME_SIZE, &_width, &_height));
|
||||
}
|
||||
|
||||
CHK(mt->CopyAllItems(_curMT.Get()));
|
||||
}
|
114
modules/videoio/src/cap_winrt/MediaStreamSink.hpp
Normal file
@ -0,0 +1,114 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MFIncludes.hpp"
|
||||
|
||||
namespace Media {
|
||||
|
||||
class MediaStreamSink WrlSealed :
|
||||
public Microsoft::WRL::RuntimeClass<
|
||||
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
|
||||
IMFStreamSink,
|
||||
IMFMediaEventGenerator,
|
||||
IMFMediaTypeHandler
|
||||
>
|
||||
{
|
||||
public:
|
||||
|
||||
MediaStreamSink(
|
||||
__in const MW::ComPtr<IMFMediaSink>& sink,
|
||||
__in DWORD id,
|
||||
__in const MW::ComPtr<IMFMediaType>& mt,
|
||||
__in MediaSampleHandler^ sampleHandler
|
||||
);
|
||||
|
||||
//
|
||||
// IMFStreamSink
|
||||
//
|
||||
|
||||
IFACEMETHODIMP GetMediaSink(__deref_out IMFMediaSink **sink);
|
||||
IFACEMETHODIMP GetIdentifier(__out DWORD *identifier);
|
||||
IFACEMETHODIMP GetMediaTypeHandler(__deref_out IMFMediaTypeHandler **handler);
|
||||
IFACEMETHODIMP ProcessSample(__in_opt IMFSample *sample);
|
||||
IFACEMETHODIMP PlaceMarker(__in MFSTREAMSINK_MARKER_TYPE markerType, __in const PROPVARIANT * markerValue, __in const PROPVARIANT * contextValue);
|
||||
IFACEMETHODIMP Flush();
|
||||
|
||||
//
|
||||
// IMFMediaEventGenerator
|
||||
//
|
||||
|
||||
IFACEMETHODIMP GetEvent(__in DWORD flags, __deref_out IMFMediaEvent **event);
|
||||
IFACEMETHODIMP BeginGetEvent(__in IMFAsyncCallback *callback, __in_opt IUnknown *state);
|
||||
IFACEMETHODIMP EndGetEvent(__in IMFAsyncResult *result, __deref_out IMFMediaEvent **event);
|
||||
IFACEMETHODIMP QueueEvent(__in MediaEventType met, __in REFGUID extendedType, __in HRESULT status, __in_opt const PROPVARIANT *value);
|
||||
|
||||
//
|
||||
// IMFMediaTypeHandler
|
||||
//
|
||||
|
||||
IFACEMETHODIMP IsMediaTypeSupported(__in IMFMediaType *mediaType, __deref_out_opt IMFMediaType **closestMediaType);
|
||||
IFACEMETHODIMP GetMediaTypeCount(__out DWORD *typeCount);
|
||||
IFACEMETHODIMP GetMediaTypeByIndex(__in DWORD index, __deref_out IMFMediaType **mediaType);
|
||||
IFACEMETHODIMP SetCurrentMediaType(__in IMFMediaType *mediaType);
|
||||
IFACEMETHODIMP GetCurrentMediaType(__deref_out_opt IMFMediaType **mediaType);
|
||||
IFACEMETHODIMP GetMajorType(__out GUID *majorType);
|
||||
|
||||
//
|
||||
// Misc
|
||||
//
|
||||
|
||||
void InternalSetCurrentMediaType(__in const MW::ComPtr<IMFMediaType>& mediaType);
|
||||
void RequestSample();
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
|
||||
bool _IsMediaTypeSupported(__in const MW::ComPtr<IMFMediaType>& mt) const;
|
||||
void _UpdateMediaType(__in const MW::ComPtr<IMFMediaType>& mt);
|
||||
|
||||
void _VerifyNotShutdown()
|
||||
{
|
||||
if (_shutdown)
|
||||
{
|
||||
CHK(MF_E_SHUTDOWN);
|
||||
}
|
||||
}
|
||||
|
||||
MW::ComPtr<IMFMediaSink> _sink;
|
||||
MW::ComPtr<IMFMediaEventQueue> _eventQueue;
|
||||
MW::ComPtr<IMFMediaType> _curMT;
|
||||
|
||||
MediaSampleHandler^ _sampleHandler;
|
||||
|
||||
GUID _majorType;
|
||||
GUID _subType;
|
||||
unsigned int _width;
|
||||
unsigned int _height;
|
||||
DWORD _id;
|
||||
bool _shutdown;
|
||||
|
||||
MWW::SRWLock _lock;
|
||||
};
|
||||
|
||||
}
|
89
modules/videoio/src/cap_winrt_bridge.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
// videoio to XAML bridge for OpenCV
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "opencv2\videoio\cap_winrt.hpp"
|
||||
#include "cap_winrt_capture.hpp"
|
||||
#include "cap_winrt_bridge.hpp"
|
||||
#include "cap_winrt_video.hpp"
|
||||
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Media::Capture;
|
||||
using namespace Windows::Media::MediaProperties;
|
||||
using namespace Windows::Devices::Enumeration;
|
||||
|
||||
using namespace Windows::UI::Xaml::Media::Imaging;
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace ::Concurrency;
|
||||
|
||||
using namespace ::std;
|
||||
|
||||
/***************************** VideoioBridge class ******************************/
|
||||
|
||||
// non-blocking
|
||||
void VideoioBridge::requestForUIthreadAsync(int action, int widthp, int heightp)
|
||||
{
|
||||
reporter.report(action);
|
||||
}
|
||||
|
||||
VideoioBridge& VideoioBridge::getInstance()
|
||||
{
|
||||
static VideoioBridge instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void VideoioBridge::swapInputBuffers()
|
||||
{
|
||||
// TODO: already locked, check validity
|
||||
// lock_guard<mutex> lock(inputBufferMutex);
|
||||
swap(backInputPtr, frontInputPtr);
|
||||
//if (currentFrame != frameCounter)
|
||||
//{
|
||||
// currentFrame = frameCounter;
|
||||
// swap(backInputPtr, frontInputPtr);
|
||||
//}
|
||||
}
|
||||
|
||||
void VideoioBridge::swapOutputBuffers()
|
||||
{
|
||||
lock_guard<mutex> lock(outputBufferMutex);
|
||||
swap(frontOutputBuffer, backOutputBuffer);
|
||||
}
|
||||
|
||||
void VideoioBridge::allocateOutputBuffers()
|
||||
{
|
||||
frontOutputBuffer = ref new WriteableBitmap(width, height);
|
||||
backOutputBuffer = ref new WriteableBitmap(width, height);
|
||||
}
|
||||
|
||||
void VideoioBridge::imshow()
|
||||
{
|
||||
VideoioBridge::getInstance().swapOutputBuffers();
|
||||
VideoioBridge::getInstance().requestForUIthreadAsync(cv::UPDATE_IMAGE_ELEMENT);
|
||||
}
|
||||
|
||||
// end
|
96
modules/videoio/src/cap_winrt_bridge.hpp
Normal file
@ -0,0 +1,96 @@
|
||||
// videoio to XAML bridge for OpenCV
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
// this header is included in the XAML App, so it cannot include any
|
||||
// OpenCV headers, or a static assert will be raised
|
||||
|
||||
#include <ppl.h>
|
||||
#include <ppltasks.h>
|
||||
#include <concrt.h>
|
||||
#include <agile.h>
|
||||
#include <opencv2\core.hpp>
|
||||
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
|
||||
|
||||
// Class VideoioBridge (singleton) is needed because the interface for
|
||||
// VideoCapture_WinRT in cap_winrt_capture.hpp is fixed by OpenCV.
|
||||
class VideoioBridge
|
||||
{
|
||||
public:
|
||||
|
||||
static VideoioBridge& getInstance();
|
||||
|
||||
// call after initialization
|
||||
void setReporter(Concurrency::progress_reporter<int> pr) { reporter = pr; }
|
||||
|
||||
// to be called from cvMain via cap_winrt on bg thread - non-blocking (async)
|
||||
void requestForUIthreadAsync( int action, int width=0, int height=0 );
|
||||
|
||||
// TODO: modify in window.cpp: void cv::imshow( const String& winname, InputArray _img )
|
||||
void imshow(/*cv::InputArray matToShow*/); // shows Mat in the cvImage element
|
||||
void swapInputBuffers();
|
||||
void allocateOutputBuffers();
|
||||
void swapOutputBuffers();
|
||||
|
||||
|
||||
int deviceIndex, width, height;
|
||||
std::atomic<bool> bIsFrameNew;
|
||||
std::mutex inputBufferMutex; // input is double buffered
|
||||
unsigned char * frontInputPtr; // OpenCV reads this
|
||||
unsigned char * backInputPtr; // Video grabber writes this
|
||||
std::atomic<unsigned long> frameCounter;
|
||||
unsigned long currentFrame;
|
||||
|
||||
std::mutex outputBufferMutex; // output is double buffered
|
||||
Windows::UI::Xaml::Media::Imaging::WriteableBitmap^ frontOutputBuffer; // OpenCV write this
|
||||
Windows::UI::Xaml::Media::Imaging::WriteableBitmap^ backOutputBuffer; // XAML reads this
|
||||
Windows::UI::Xaml::Controls::Image ^cvImage;
|
||||
|
||||
private:
|
||||
|
||||
VideoioBridge() {
|
||||
deviceIndex = 0;
|
||||
width = 640;
|
||||
height = 480;
|
||||
deviceReady = false;
|
||||
bIsFrameNew = false;
|
||||
currentFrame = 0;
|
||||
frameCounter = 0;
|
||||
};
|
||||
|
||||
// singleton
|
||||
VideoioBridge(VideoioBridge const &);
|
||||
void operator=(const VideoioBridge &);
|
||||
|
||||
std::atomic<bool> deviceReady;
|
||||
Concurrency::progress_reporter<int> reporter;
|
||||
};
|
279
modules/videoio/src/cap_winrt_capture.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
// Capture support for WinRT
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "cap_winrt_capture.hpp"
|
||||
#include "cap_winrt_bridge.hpp"
|
||||
#include "cap_winrt_video.hpp"
|
||||
#include <opencv2\videoio\cap_winrt.hpp>
|
||||
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Media::Capture;
|
||||
using namespace Windows::Media::MediaProperties;
|
||||
using namespace Windows::Devices::Enumeration;
|
||||
|
||||
using namespace Platform;
|
||||
|
||||
using namespace Windows::UI::Xaml::Media::Imaging;
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
using namespace ::std;
|
||||
|
||||
|
||||
// nb. VideoCapture_WinRT is not a singleton, so the Mats are made file statics
|
||||
// we do not support more than one capture device simultaneously with the
|
||||
// design at this time
|
||||
|
||||
// nb. inputBufferMutex was not able to guarantee that OpenCV Mats were
|
||||
// ready to accept data in the UI thread (memory access exceptions were thrown
|
||||
// even though buffer address was good).
|
||||
// Therefore allocation of Mats is also done on the UI thread before the video
|
||||
// device is initialized.
|
||||
|
||||
static cv::Mat frontInputMat;
|
||||
static cv::Mat backInputMat;
|
||||
|
||||
namespace cv {
|
||||
|
||||
/***************************** exported control functions ******************************/
|
||||
|
||||
template <typename ...Args>
|
||||
void winrt_startMessageLoop(std::function<void(Args...)>&& callback, Args... args)
|
||||
{
|
||||
auto asyncTask = ::concurrency::create_async([=](::concurrency::progress_reporter<int> reporter)
|
||||
{
|
||||
VideoioBridge::getInstance().setReporter(reporter);
|
||||
|
||||
// frame reading loop
|
||||
callback(args...);
|
||||
});
|
||||
|
||||
asyncTask->Progress = ref new AsyncActionProgressHandler<int>([=](IAsyncActionWithProgress<int>^ act, int progress)
|
||||
{
|
||||
int action = progress;
|
||||
|
||||
// these actions will be processed on the UI thread asynchronously
|
||||
switch (action)
|
||||
{
|
||||
case OPEN_CAMERA:
|
||||
winrt_openCamera();
|
||||
break;
|
||||
case CLOSE_CAMERA:
|
||||
winrt_closeGrabber();
|
||||
break;
|
||||
case UPDATE_IMAGE_ELEMENT:
|
||||
winrt_updateFrameContainer();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
void winrt_startMessageLoop(void callback(Args...), Args... args)
|
||||
{
|
||||
winrt_startMessageLoop(std::function<void(Args...)>(callback), args...);
|
||||
}
|
||||
|
||||
void winrt_onVisibilityChanged(bool visible) {
|
||||
if (visible)
|
||||
{
|
||||
VideoioBridge& bridge = VideoioBridge::getInstance();
|
||||
|
||||
// only start the grabber if the camera was opened in OpenCV
|
||||
if (bridge.backInputPtr != nullptr)
|
||||
{
|
||||
if (Video::getInstance().isStarted()) return;
|
||||
|
||||
int device = bridge.deviceIndex;
|
||||
int width = bridge.width;
|
||||
int height = bridge.height;
|
||||
|
||||
winrt_initGrabber(device, width, height);
|
||||
}
|
||||
} else
|
||||
{
|
||||
//grabberStarted = false;
|
||||
winrt_closeGrabber();
|
||||
}
|
||||
}
|
||||
|
||||
void winrt_imshow() {
|
||||
VideoioBridge::getInstance().imshow();
|
||||
}
|
||||
|
||||
void winrt_setFrameContainer(::Windows::UI::Xaml::Controls::Image^ image) {
|
||||
VideoioBridge::getInstance().cvImage = image;
|
||||
}
|
||||
|
||||
|
||||
/********************************* Internal helpers ************************************/
|
||||
|
||||
void winrt_updateFrameContainer()
|
||||
{
|
||||
// copy output Mat to WBM
|
||||
winrt_copyOutput();
|
||||
|
||||
// set XAML image element with image WBM
|
||||
VideoioBridge::getInstance().cvImage->Source = VideoioBridge::getInstance().backOutputBuffer;
|
||||
}
|
||||
|
||||
// performed on UI thread
|
||||
bool winrt_openCamera()
|
||||
{
|
||||
VideoioBridge& bridge = VideoioBridge::getInstance();
|
||||
|
||||
int device = bridge.deviceIndex;
|
||||
int width = bridge.width;
|
||||
int height = bridge.height;
|
||||
|
||||
// buffers must alloc'd on UI thread
|
||||
winrt_allocateBuffers(width, height);
|
||||
|
||||
// nb. video capture device init must be done on UI thread;
|
||||
if (!Video::getInstance().isStarted())
|
||||
{
|
||||
winrt_initGrabber(device, width, height);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// performed on UI thread
|
||||
void winrt_allocateBuffers(int width, int height)
|
||||
{
|
||||
VideoioBridge& bridge = VideoioBridge::getInstance();
|
||||
|
||||
// allocate input Mats (bgra8 = CV_8UC4, RGB24 = CV_8UC3)
|
||||
frontInputMat.create(height, width, CV_8UC3);
|
||||
backInputMat.create(height, width, CV_8UC3);
|
||||
|
||||
bridge.frontInputPtr = frontInputMat.ptr(0);
|
||||
bridge.backInputPtr = backInputMat.ptr(0);
|
||||
|
||||
bridge.allocateOutputBuffers();
|
||||
}
|
||||
|
||||
// non-blocking
|
||||
bool winrt_initGrabber(int device, int w, int h) {
|
||||
// nb. Video class is not exported outside of this DLL
|
||||
// due to complexities in the CaptureFrameGrabber ref class
|
||||
// as written in the header not mixing well with pure C++ classes
|
||||
return Video::getInstance().initGrabber(device, w, h);
|
||||
}
|
||||
|
||||
void winrt_closeGrabber() {
|
||||
Video::getInstance().closeGrabber();
|
||||
}
|
||||
|
||||
// nb on UI thread
|
||||
void winrt_copyOutput() {
|
||||
Video::getInstance().CopyOutput();
|
||||
}
|
||||
|
||||
|
||||
/********************************* VideoCapture_WinRT class ****************************/
|
||||
|
||||
VideoCapture_WinRT::VideoCapture_WinRT(int device) : started(false)
|
||||
{
|
||||
VideoioBridge::getInstance().deviceIndex = device;
|
||||
}
|
||||
|
||||
bool VideoCapture_WinRT::isOpened() const
|
||||
{
|
||||
return true; // started;
|
||||
}
|
||||
|
||||
// grab a frame:
|
||||
// this will NOT block per spec
|
||||
// should be called on the image processing thread, not the UI thread
|
||||
bool VideoCapture_WinRT::grabFrame()
|
||||
{
|
||||
// if device is not started we must return true so retrieveFrame() is called to start device
|
||||
// nb. we cannot start the device here because we do not know the size of the input Mat
|
||||
if (!started) return true;
|
||||
|
||||
if (VideoioBridge::getInstance().bIsFrameNew)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// nb. if blocking is to be added:
|
||||
// unique_lock<mutex> lock(VideoioBridge::getInstance().frameReadyMutex);
|
||||
// VideoioBridge::getInstance().frameReadyEvent.wait(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
// should be called on the image processing thread after grabFrame
|
||||
// see VideoCapture::read
|
||||
bool VideoCapture_WinRT::retrieveFrame(int channel, cv::OutputArray outArray)
|
||||
{
|
||||
if (!started) {
|
||||
|
||||
int width, height;
|
||||
width = outArray.size().width;
|
||||
height = outArray.size().height;
|
||||
if (width == 0) width = 640;
|
||||
if (height == 0) height = 480;
|
||||
|
||||
VideoioBridge::getInstance().width = width;
|
||||
VideoioBridge::getInstance().height = height;
|
||||
|
||||
// nb. Mats will be alloc'd on UI thread
|
||||
|
||||
// request device init on UI thread - this does not block, and is async
|
||||
VideoioBridge::getInstance().requestForUIthreadAsync(OPEN_CAMERA,
|
||||
outArray.size().width, outArray.size().height);
|
||||
|
||||
started = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!started) return false;
|
||||
|
||||
return VideoioBridge::getInstance().bIsFrameNew;
|
||||
}
|
||||
|
||||
|
||||
bool VideoCapture_WinRT::setProperty(int property_id, double value)
|
||||
{
|
||||
switch (property_id)
|
||||
{
|
||||
case CAP_PROP_FRAME_WIDTH:
|
||||
size.width = (int)value;
|
||||
break;
|
||||
case CAP_PROP_FRAME_HEIGHT:
|
||||
size.height = (int)value;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// end
|
82
modules/videoio/src/cap_winrt_capture.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
// Capture support for WinRT
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
|
||||
#include <agile.h>
|
||||
|
||||
|
||||
// nb. implemented the newer IVideoCapture C++ interface so that we can work
|
||||
// directly with Mat, not the older C cv interface
|
||||
// (which may have added overhead for IPL file conversion)
|
||||
|
||||
namespace cv {
|
||||
|
||||
/******************* Internal helpers **************************************/
|
||||
|
||||
void winrt_updateFrameContainer();
|
||||
bool winrt_openCamera();
|
||||
bool winrt_initGrabber(int device, int w, int h);
|
||||
void winrt_closeGrabber();
|
||||
void winrt_copyOutput();
|
||||
void winrt_allocateBuffers(int width, int height);
|
||||
|
||||
/******************* VideoCapture_WinRT class ******************************/
|
||||
|
||||
class VideoCapture_WinRT : public IVideoCapture
|
||||
{
|
||||
public:
|
||||
VideoCapture_WinRT() : started(false) {}
|
||||
VideoCapture_WinRT(int device);
|
||||
virtual ~VideoCapture_WinRT() {}
|
||||
|
||||
// from base class IVideoCapture
|
||||
virtual double getProperty(int) { return 0; }
|
||||
virtual bool setProperty(int, double);
|
||||
virtual bool grabFrame();
|
||||
virtual bool retrieveFrame(int channel, cv::OutputArray outArray);
|
||||
|
||||
// Return the type of the capture object
|
||||
virtual int getCaptureDomain() { return CAP_WINRT; }
|
||||
|
||||
virtual bool isOpened() const;
|
||||
|
||||
protected:
|
||||
|
||||
bool started;
|
||||
CvSize size;
|
||||
int bytesPerPixel;
|
||||
unsigned long frameCurrent;
|
||||
std::atomic<bool> isFrameNew;
|
||||
};
|
||||
}
|
322
modules/videoio/src/cap_winrt_video.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
// Video support with XAML
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cap_winrt_video.hpp"
|
||||
|
||||
#include <ppl.h>
|
||||
#include <ppltasks.h>
|
||||
#include <concrt.h>
|
||||
#include <agile.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <future>
|
||||
#include <vector>
|
||||
|
||||
|
||||
using namespace ::concurrency;
|
||||
using namespace ::Windows::Foundation;
|
||||
using namespace ::std;
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Windows::Media::Devices;
|
||||
using namespace Windows::Media::MediaProperties;
|
||||
using namespace Windows::Media::Capture;
|
||||
using namespace Windows::UI::Xaml::Media::Imaging;
|
||||
using namespace Windows::Devices::Enumeration;
|
||||
|
||||
#include "cap_winrt/CaptureFrameGrabber.hpp"
|
||||
|
||||
// pull in Media Foundation libs
|
||||
#pragma comment(lib, "mfplat")
|
||||
#pragma comment(lib, "mf")
|
||||
#pragma comment(lib, "mfuuid")
|
||||
|
||||
#if (WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP) && !defined(_M_ARM)
|
||||
#pragma comment(lib, "Shlwapi")
|
||||
#endif
|
||||
|
||||
#include "cap_winrt_bridge.hpp"
|
||||
|
||||
Video::Video() {}
|
||||
|
||||
Video &Video::getInstance() {
|
||||
static Video v;
|
||||
return v;
|
||||
}
|
||||
|
||||
bool Video::isStarted() {
|
||||
return bGrabberInited.load();
|
||||
}
|
||||
|
||||
void Video::closeGrabber() {
|
||||
// assigning nullptr causes deref of grabber and thus closes the device
|
||||
m_frameGrabber = nullptr;
|
||||
bGrabberInited = false;
|
||||
bGrabberInitInProgress = false;
|
||||
}
|
||||
|
||||
|
||||
bool Video::initGrabber(int device, int w, int h) {
|
||||
// already started?
|
||||
if (bGrabberInited || bGrabberInitInProgress) return false;
|
||||
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
bGrabberInited = false;
|
||||
bGrabberInitInProgress = true;
|
||||
|
||||
m_deviceID = device;
|
||||
|
||||
create_task(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture))
|
||||
.then([this](task<DeviceInformationCollection^> findTask)
|
||||
{
|
||||
m_devices = findTask.get();
|
||||
|
||||
// got selected device?
|
||||
if ((unsigned)m_deviceID >= m_devices.Get()->Size)
|
||||
{
|
||||
OutputDebugStringA("Video::initGrabber - no video device found\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto devInfo = m_devices.Get()->GetAt(m_deviceID);
|
||||
|
||||
auto settings = ref new MediaCaptureInitializationSettings();
|
||||
settings->StreamingCaptureMode = StreamingCaptureMode::Video; // Video-only capture
|
||||
settings->VideoDeviceId = devInfo->Id;
|
||||
|
||||
auto location = devInfo->EnclosureLocation;
|
||||
bFlipImageX = true;
|
||||
if (location != nullptr && location->Panel == Windows::Devices::Enumeration::Panel::Back)
|
||||
{
|
||||
bFlipImageX = false;
|
||||
}
|
||||
|
||||
m_capture = ref new MediaCapture();
|
||||
create_task(m_capture->InitializeAsync(settings)).then([this](){
|
||||
|
||||
auto props = safe_cast<VideoEncodingProperties^>(m_capture->VideoDeviceController->GetMediaStreamProperties(MediaStreamType::VideoPreview));
|
||||
|
||||
// for 24 bpp
|
||||
props->Subtype = MediaEncodingSubtypes::Rgb24; bytesPerPixel = 3;
|
||||
|
||||
// format used by XAML & WBM (for testing)
|
||||
// props->Subtype = MediaEncodingSubtypes::Bgra8; bytesPerPixel = 4;
|
||||
|
||||
props->Width = width;
|
||||
props->Height = height;
|
||||
|
||||
return ::Media::CaptureFrameGrabber::CreateAsync(m_capture.Get(), props);
|
||||
|
||||
}).then([this](::Media::CaptureFrameGrabber^ frameGrabber)
|
||||
{
|
||||
m_frameGrabber = frameGrabber;
|
||||
bGrabberInited = true;
|
||||
bGrabberInitInProgress = false;
|
||||
//ready = true;
|
||||
_GrabFrameAsync(frameGrabber);
|
||||
});
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// nb. cannot block here - this will lock the UI thread:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Video::_GrabFrameAsync(::Media::CaptureFrameGrabber^ frameGrabber) {
|
||||
// use rgb24 layout
|
||||
create_task(frameGrabber->GetFrameAsync()).then([this, frameGrabber](const ComPtr<IMF2DBuffer2>& buffer)
|
||||
{
|
||||
// do the RGB swizzle while copying the pixels from the IMF2DBuffer2
|
||||
BYTE *pbScanline;
|
||||
LONG plPitch;
|
||||
unsigned int colBytes = width * bytesPerPixel;
|
||||
CHK(buffer->Lock2D(&pbScanline, &plPitch));
|
||||
|
||||
// flip
|
||||
if (bFlipImageX)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(VideoioBridge::getInstance().inputBufferMutex);
|
||||
|
||||
// ptr to input Mat data array
|
||||
auto buf = VideoioBridge::getInstance().backInputPtr;
|
||||
|
||||
for (unsigned int row = 0; row < height; row++)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
unsigned int j = colBytes - 1;
|
||||
|
||||
while (i < colBytes)
|
||||
{
|
||||
// reverse the scan line
|
||||
// as a side effect this also swizzles R and B channels
|
||||
buf[j--] = pbScanline[i++];
|
||||
buf[j--] = pbScanline[i++];
|
||||
buf[j--] = pbScanline[i++];
|
||||
}
|
||||
pbScanline += plPitch;
|
||||
buf += colBytes;
|
||||
}
|
||||
VideoioBridge::getInstance().bIsFrameNew = true;
|
||||
} else
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(VideoioBridge::getInstance().inputBufferMutex);
|
||||
|
||||
// ptr to input Mat data array
|
||||
auto buf = VideoioBridge::getInstance().backInputPtr;
|
||||
|
||||
for (unsigned int row = 0; row < height; row++)
|
||||
{
|
||||
// used for Bgr8:
|
||||
//for (unsigned int i = 0; i < colBytes; i++ )
|
||||
// buf[i] = pbScanline[i];
|
||||
|
||||
// used for RGB24:
|
||||
for (unsigned int i = 0; i < colBytes; i += bytesPerPixel)
|
||||
{
|
||||
// swizzle the R and B values (BGR to RGB)
|
||||
buf[i] = pbScanline[i + 2];
|
||||
buf[i + 1] = pbScanline[i + 1];
|
||||
buf[i + 2] = pbScanline[i];
|
||||
|
||||
// no swizzle
|
||||
//buf[i] = pbScanline[i];
|
||||
//buf[i + 1] = pbScanline[i + 1];
|
||||
//buf[i + 2] = pbScanline[i + 2];
|
||||
}
|
||||
|
||||
pbScanline += plPitch;
|
||||
buf += colBytes;
|
||||
}
|
||||
VideoioBridge::getInstance().bIsFrameNew = true;
|
||||
}
|
||||
CHK(buffer->Unlock2D());
|
||||
|
||||
VideoioBridge::getInstance().frameCounter++;
|
||||
|
||||
if (bGrabberInited)
|
||||
{
|
||||
_GrabFrameAsync(frameGrabber);
|
||||
}
|
||||
}, task_continuation_context::use_current());
|
||||
}
|
||||
|
||||
|
||||
// copy from input Mat to output WBM
|
||||
// must be on UI thread
|
||||
void Video::CopyOutput() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(VideoioBridge::getInstance().outputBufferMutex);
|
||||
|
||||
auto inAr = VideoioBridge::getInstance().frontInputPtr;
|
||||
auto outAr = GetData(VideoioBridge::getInstance().frontOutputBuffer->PixelBuffer);
|
||||
|
||||
const unsigned int bytesPerPixel = 3;
|
||||
auto pbScanline = inAr;
|
||||
auto plPitch = width * bytesPerPixel;
|
||||
|
||||
auto buf = outAr;
|
||||
unsigned int colBytes = width * 4;
|
||||
|
||||
// copy RGB24 to bgra8
|
||||
for (unsigned int row = 0; row < height; row++)
|
||||
{
|
||||
// used for Bgr8:
|
||||
// nb. no alpha
|
||||
// for (unsigned int i = 0; i < colBytes; i++ ) buf[i] = pbScanline[i];
|
||||
|
||||
// used for RGB24:
|
||||
// nb. alpha is set to full opaque
|
||||
for (unsigned int i = 0, j = 0; i < plPitch; i += bytesPerPixel, j += 4)
|
||||
{
|
||||
// swizzle the R and B values (RGB24 to Bgr8)
|
||||
buf[j] = pbScanline[i + 2];
|
||||
buf[j + 1] = pbScanline[i + 1];
|
||||
buf[j + 2] = pbScanline[i];
|
||||
buf[j + 3] = 0xff;
|
||||
|
||||
// if no swizzle is desired:
|
||||
//buf[i] = pbScanline[i];
|
||||
//buf[i + 1] = pbScanline[i + 1];
|
||||
//buf[i + 2] = pbScanline[i + 2];
|
||||
//buf[i + 3] = 0xff;
|
||||
}
|
||||
|
||||
pbScanline += plPitch;
|
||||
buf += colBytes;
|
||||
}
|
||||
VideoioBridge::getInstance().frontOutputBuffer->PixelBuffer->Length = width * height * 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Video::listDevicesTask() {
|
||||
std::atomic<bool> ready(false);
|
||||
|
||||
auto settings = ref new MediaCaptureInitializationSettings();
|
||||
|
||||
//vector <int> devices;
|
||||
|
||||
create_task(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture))
|
||||
.then([this, &ready](task<DeviceInformationCollection^> findTask)
|
||||
{
|
||||
m_devices = findTask.get();
|
||||
|
||||
for (size_t i = 0; i < m_devices->Size; i++)
|
||||
{
|
||||
// ofVideoDevice deviceInfo;
|
||||
auto d = m_devices->GetAt(i);
|
||||
//deviceInfo.bAvailable = true;
|
||||
//deviceInfo.deviceName = PlatformStringToString(d->Name);
|
||||
//deviceInfo.hardwareName = deviceInfo.deviceName;
|
||||
// devices.push_back(deviceInfo);
|
||||
}
|
||||
|
||||
ready = true;
|
||||
});
|
||||
|
||||
// wait for async task to complete
|
||||
int count = 0;
|
||||
while (!ready)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Video::listDevices() {
|
||||
// synchronous version of listing video devices on WinRT
|
||||
std::future<bool> result = std::async(std::launch::async, &Video::listDevicesTask, this);
|
||||
return result.get();
|
||||
}
|
||||
|
||||
// end
|
73
modules/videoio/src/cap_winrt_video.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
// Video support with XAML
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cap_winrt/CaptureFrameGrabber.hpp"
|
||||
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
|
||||
class Video {
|
||||
public:
|
||||
|
||||
bool initGrabber(int device, int w, int h);
|
||||
void closeGrabber();
|
||||
bool isStarted();
|
||||
|
||||
// singleton
|
||||
static Video &getInstance();
|
||||
|
||||
void CopyOutput();
|
||||
|
||||
private:
|
||||
// singleton
|
||||
Video();
|
||||
|
||||
void _GrabFrameAsync(::Media::CaptureFrameGrabber^ frameGrabber);
|
||||
|
||||
bool listDevices();
|
||||
|
||||
Platform::Agile<Windows::Media::Capture::MediaCapture> m_capture;
|
||||
Platform::Agile<Windows::Devices::Enumeration::DeviceInformationCollection> m_devices;
|
||||
|
||||
::Media::CaptureFrameGrabber^ m_frameGrabber;
|
||||
|
||||
bool listDevicesTask();
|
||||
|
||||
bool bChooseDevice;
|
||||
bool bVerbose;
|
||||
bool bFlipImageX;
|
||||
//std::atomic<bool> bGrabberInited;
|
||||
int m_deviceID;
|
||||
int attemptFramerate;
|
||||
std::atomic<bool> bIsFrameNew;
|
||||
std::atomic<bool> bGrabberInited;
|
||||
std::atomic<bool> bGrabberInitInProgress;
|
||||
unsigned int width, height;
|
||||
int bytesPerPixel;
|
||||
|
||||
};
|
9466
modules/videoio/src/ppltasks_winrt.hpp
Normal file
@ -4,5 +4,9 @@ if(HAVE_CUDA)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wmissing-declarations -Wshadow -Wunused-parameter)
|
||||
endif()
|
||||
|
||||
if(WINRT_8_1)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /ZW")
|
||||
endif()
|
||||
|
||||
ocv_define_module(videostab opencv_imgproc opencv_features2d opencv_video opencv_photo opencv_calib3d
|
||||
OPTIONAL opencv_cudawarping opencv_cudaoptflow opencv_videoio WRAP python)
|
||||
|
@ -0,0 +1,84 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "video_capture_xaml", "video_capture_xaml", "{D7F9BEB3-65C8-443A-82C6-9D6A5B2B00FC}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video_capture_xaml.Shared", "video_capture_xaml\video_capture_xaml.Shared\video_capture_xaml.Shared.vcxitems", "{6A274B7F-3982-499E-B55A-1F12EF2E3EC0}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video_capture_xaml.Windows", "video_capture_xaml\video_capture_xaml.Windows\video_capture_xaml.Windows.vcxproj", "{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video_capture_xaml.WindowsPhone", "video_capture_xaml\video_capture_xaml.WindowsPhone\video_capture_xaml.WindowsPhone.vcxproj", "{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
video_capture_xaml\video_capture_xaml.Shared\video_capture_xaml.Shared.vcxitems*{d7a82e7f-1535-4eec-aba9-2c8447669d33}*SharedItemsImports = 4
|
||||
video_capture_xaml\video_capture_xaml.Shared\video_capture_xaml.Shared.vcxitems*{6a274b7f-3982-499e-b55a-1f12ef2e3ec0}*SharedItemsImports = 9
|
||||
video_capture_xaml\video_capture_xaml.Shared\video_capture_xaml.Shared.vcxitems*{32fdab94-f87e-4f0a-89a4-9ec10a3b1d3d}*SharedItemsImports = 4
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|ARM = Release|ARM
|
||||
Release|Mixed Platforms = Release|Mixed Platforms
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|Mixed Platforms.Deploy.0 = Debug|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|Win32.Deploy.0 = Debug|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|x64.Build.0 = Debug|x64
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|ARM.Build.0 = Release|ARM
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|Mixed Platforms.Deploy.0 = Release|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|Win32.Build.0 = Release|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|Win32.Deploy.0 = Release|Win32
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|x64.ActiveCfg = Release|x64
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|x64.Build.0 = Release|x64
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D}.Release|x64.Deploy.0 = Release|x64
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|Mixed Platforms.Deploy.0 = Debug|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|Win32.Deploy.0 = Debug|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|ARM.Build.0 = Release|ARM
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|Mixed Platforms.Deploy.0 = Release|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|Win32.Build.0 = Release|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|Win32.Deploy.0 = Release|Win32
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33}.Release|x64.ActiveCfg = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{6A274B7F-3982-499E-B55A-1F12EF2E3EC0} = {D7F9BEB3-65C8-443A-82C6-9D6A5B2B00FC}
|
||||
{32FDAB94-F87E-4F0A-89A4-9EC10A3B1D3D} = {D7F9BEB3-65C8-443A-82C6-9D6A5B2B00FC}
|
||||
{D7A82E7F-1535-4EEC-ABA9-2C8447669D33} = {D7F9BEB3-65C8-443A-82C6-9D6A5B2B00FC}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<Runtime Condition="'$(ApplicationType)'=='Windows Phone'">WP</Runtime>
|
||||
<Runtime Condition="'$(ApplicationType)'=='Windows Store'">WS</Runtime>
|
||||
<OpenCV_Bin>$(OPENCV_WINRT_INSTALL_DIR)$(Runtime)\8.1\$(PlatformTarget)\$(PlatformTarget)\vc12\bin\</OpenCV_Bin>
|
||||
<OpenCV_Lib>$(OPENCV_WINRT_INSTALL_DIR)$(Runtime)\8.1\$(PlatformTarget)\$(PlatformTarget)\vc12\lib\</OpenCV_Lib>
|
||||
<OpenCV_Include>$(OPENCV_WINRT_INSTALL_DIR)$(Runtime)\8.1\$(PlatformTarget)\include\</OpenCV_Include>
|
||||
<!--debug suffix for OpenCV dlls and libs -->
|
||||
<DebugSuffix Condition="'$(Configuration)'=='Debug'">d</DebugSuffix>
|
||||
<DebugSuffix Condition="'$(Configuration)'!='Debug'"></DebugSuffix>
|
||||
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- Add required OpenCV dlls here-->
|
||||
|
||||
<!-- General-->
|
||||
<None Include="$(OpenCV_Bin)opencv_core300$(DebugSuffix).dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
<None Include="$(OpenCV_Bin)opencv_imgproc300$(DebugSuffix).dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
<None Include="$(OpenCV_Bin)opencv_flann300$(DebugSuffix).dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
<None Include="$(OpenCV_Bin)opencv_features2d300$(DebugSuffix).dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
<None Include="$(OpenCV_Bin)opencv_imgcodecs300$(DebugSuffix).dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
|
||||
<!-- Video processing -->
|
||||
<None Include="$(OpenCV_Bin)opencv_videoio300$(DebugSuffix).dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
|
||||
<!-- Face detection-->
|
||||
<None Include="$(OpenCV_Bin)opencv_objdetect300$(DebugSuffix).dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
<None Include="$(OpenCV_Bin)opencv_ml300$(DebugSuffix).dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(OpenCV_Include);%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<!--Add required OpenCV libs here-->
|
||||
<AdditionalDependencies>opencv_core300$(DebugSuffix).lib;opencv_imgproc300$(DebugSuffix).lib;opencv_flann300$(DebugSuffix).lib;opencv_videoio300$(DebugSuffix).lib;opencv_features2d300$(DebugSuffix).lib;opencv_objdetect300$(DebugSuffix).lib;opencv_ml300$(DebugSuffix).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OpenCV_Lib);%(AdditionalLibraryDirectories);</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
@ -0,0 +1,4 @@
|
||||
<Application x:Class="video_capture_xaml.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:video_capture_xaml" />
|
@ -0,0 +1,173 @@
|
||||
//
|
||||
// App.xaml.cpp
|
||||
// Implementation of the App class.
|
||||
//
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "pch.h"
|
||||
#include "MainPage.xaml.h"
|
||||
#include "App.xaml.h"
|
||||
|
||||
using namespace video_capture_xaml;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::ApplicationModel;
|
||||
using namespace Windows::ApplicationModel::Activation;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::UI::Xaml::Media::Animation;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Interop;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace Windows::UI::Xaml::Navigation;
|
||||
|
||||
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
App::App()
|
||||
{
|
||||
InitializeComponent();
|
||||
Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
|
||||
Resuming += ref new Windows::Foundation::EventHandler<Platform::Object ^>(this, &video_capture_xaml::App::OnResuming);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the application is launched normally by the end user. Other entry points
|
||||
/// will be used when the application is launched to open a specific file, to display
|
||||
/// search results, and so forth.
|
||||
/// </summary>
|
||||
/// <param name="e">Details about the launch request and process.</param>
|
||||
void App::OnLaunched(LaunchActivatedEventArgs^ e)
|
||||
{
|
||||
#if _DEBUG
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
DebugSettings->EnableFrameRateCounter = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto rootFrame = dynamic_cast<Frame^>(Window::Current->Content);
|
||||
|
||||
// Do not repeat app initialization when the Window already has content,
|
||||
// just ensure that the window is active.
|
||||
if (rootFrame == nullptr)
|
||||
{
|
||||
// Create a Frame to act as the navigation context and associate it with
|
||||
// a SuspensionManager key
|
||||
rootFrame = ref new Frame();
|
||||
|
||||
// TODO: Change this value to a cache size that is appropriate for your application.
|
||||
rootFrame->CacheSize = 1;
|
||||
|
||||
if (e->PreviousExecutionState == ApplicationExecutionState::Terminated)
|
||||
{
|
||||
// TODO: Restore the saved session state only when appropriate, scheduling the
|
||||
// final launch steps after the restore is complete.
|
||||
}
|
||||
|
||||
// Place the frame in the current Window
|
||||
Window::Current->Content = rootFrame;
|
||||
}
|
||||
|
||||
if (rootFrame->Content == nullptr)
|
||||
{
|
||||
#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
|
||||
// Removes the turnstile navigation for startup.
|
||||
if (rootFrame->ContentTransitions != nullptr)
|
||||
{
|
||||
_transitions = ref new TransitionCollection();
|
||||
for (auto transition : rootFrame->ContentTransitions)
|
||||
{
|
||||
_transitions->Append(transition);
|
||||
}
|
||||
}
|
||||
|
||||
rootFrame->ContentTransitions = nullptr;
|
||||
_firstNavigatedToken = rootFrame->Navigated += ref new NavigatedEventHandler(this, &App::RootFrame_FirstNavigated);
|
||||
#endif
|
||||
|
||||
// When the navigation stack isn't restored navigate to the first page,
|
||||
// configuring the new page by passing required information as a navigation
|
||||
// parameter.
|
||||
if (!rootFrame->Navigate(MainPage::typeid, e->Arguments))
|
||||
{
|
||||
throw ref new FailureException("Failed to create initial page");
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the current window is active
|
||||
Window::Current->Activate();
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
|
||||
/// <summary>
|
||||
/// Restores the content transitions after the app has launched.
|
||||
/// </summary>
|
||||
void App::RootFrame_FirstNavigated(Object^ sender, NavigationEventArgs^ e)
|
||||
{
|
||||
auto rootFrame = safe_cast<Frame^>(sender);
|
||||
|
||||
TransitionCollection^ newTransitions;
|
||||
if (_transitions == nullptr)
|
||||
{
|
||||
newTransitions = ref new TransitionCollection();
|
||||
newTransitions->Append(ref new NavigationThemeTransition());
|
||||
}
|
||||
else
|
||||
{
|
||||
newTransitions = _transitions;
|
||||
}
|
||||
|
||||
rootFrame->ContentTransitions = newTransitions;
|
||||
|
||||
rootFrame->Navigated -= _firstNavigatedToken;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when application execution is being suspended. Application state is saved
|
||||
/// without knowing whether the application will be terminated or resumed with the contents
|
||||
/// of memory still intact.
|
||||
/// </summary>
|
||||
void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e)
|
||||
{
|
||||
(void) sender; // Unused parameter
|
||||
(void) e; // Unused parameter
|
||||
|
||||
// TODO: Save application state and stop any background activity
|
||||
}
|
||||
|
||||
void video_capture_xaml::App::OnResuming(Platform::Object ^sender, Platform::Object ^args)
|
||||
{
|
||||
// throw ref new Platform::NotImplementedException();
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
//
|
||||
// App.xaml.h
|
||||
// Declaration of the App class.
|
||||
//
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "App.g.h"
|
||||
|
||||
namespace video_capture_xaml
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
ref class App sealed
|
||||
{
|
||||
public:
|
||||
App();
|
||||
|
||||
virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override;
|
||||
|
||||
private:
|
||||
#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
|
||||
Windows::UI::Xaml::Media::Animation::TransitionCollection^ _transitions;
|
||||
Windows::Foundation::EventRegistrationToken _firstNavigatedToken;
|
||||
|
||||
void RootFrame_FirstNavigated(Platform::Object^ sender, Windows::UI::Xaml::Navigation::NavigationEventArgs^ e);
|
||||
#endif
|
||||
|
||||
void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e);
|
||||
void OnResuming(Platform::Object ^sender, Platform::Object ^args);
|
||||
};
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
// main.cpp
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// (3 - clause BSD License)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||
// the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
||||
// following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
|
||||
// promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/features2d.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/videoio/cap_winrt.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
namespace video_capture_xaml {
|
||||
|
||||
void cvMain()
|
||||
{
|
||||
VideoCapture cam;
|
||||
|
||||
// open the default camera
|
||||
cam.open(0);
|
||||
|
||||
Mat edges;
|
||||
Mat frame;
|
||||
|
||||
// process frames
|
||||
while (1)
|
||||
{
|
||||
// get a new frame from camera - this is non-blocking per spec
|
||||
cam >> frame;
|
||||
|
||||
// don't reprocess the same frame again
|
||||
// nb if commented then flashing may occur
|
||||
if (!cam.grab()) continue;
|
||||
|
||||
// image processing calculations here
|
||||
// nb Mat frame is in RGB24 format (8UC3)
|
||||
|
||||
// select processing type 1 or 2
|
||||
#if 0
|
||||
// image manipulation example #1
|
||||
// write color bar at row 100 for 200 rows
|
||||
auto ar = frame.ptr(100);
|
||||
int bytesPerPixel = 3;
|
||||
int adjust = (int)(((float)30 / 100.0f) * 255.0);
|
||||
for (int i = 0; i < 640 * 100 * bytesPerPixel;)
|
||||
{
|
||||
ar[i++] = adjust; // R
|
||||
i++; // G
|
||||
ar[i++] = 255 - adjust; // B
|
||||
}
|
||||
#else
|
||||
// image processing example #2
|
||||
// apply 'canny' filter
|
||||
cvtColor(frame, edges, COLOR_RGB2GRAY);
|
||||
GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);
|
||||
Canny(edges, edges, 0, 30, 3);
|
||||
cvtColor(edges, frame, COLOR_GRAY2RGB);
|
||||
#endif
|
||||
// important step to get XAML image component updated
|
||||
winrt_imshow();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
//
|
||||
// pch.cpp
|
||||
// Include the standard header and generate the precompiled header.
|
||||
//
|
||||
|
||||
#include "pch.h"
|
@ -0,0 +1,11 @@
|
||||
//
|
||||
// pch.h
|
||||
// Header for standard system include files.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <collection.h>
|
||||
#include <ppltasks.h>
|
||||
|
||||
#include "App.xaml.h"
|
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<SharedGUID>98633655-f156-43bb-b452-37cd6a71e3f0</SharedGUID>
|
||||
<ItemsProjectGuid>{6a274b7f-3982-499e-b55a-1f12ef2e3ec0}</ItemsProjectGuid>
|
||||
<ItemsRootNamespace>highgui_xaml</ItemsRootNamespace>
|
||||
<ItemsProjectName>video_capture_xaml.Shared</ItemsProjectName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="$(MSBuildThisFileDirectory)App.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)App.xaml.cpp">
|
||||
<DependentUpon>$(MSBuildThisFileDirectory)App.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)main.cpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)App.xaml.h">
|
||||
<DependentUpon>$(MSBuildThisFileDirectory)App.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectCapability Include="SourceItemsFromImports" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<CLCompile Include="$(MSBuildThisFileDirectory)App.xaml.cpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)App.xaml.h" />
|
||||
<CLCompile Include="$(MSBuildThisFileDirectory)pch.cpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)pch.h" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="$(MSBuildThisFileDirectory)App.xaml" />
|
||||
</ItemGroup>
|
||||
</Project>
|
After Width: | Height: | Size: 801 B |
After Width: | Height: | Size: 329 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 429 B |
@ -0,0 +1,25 @@
|
||||
<Page x:Class="video_capture_xaml.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:video_capture_xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<TextBlock Margin="20,35,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="24"
|
||||
TextWrapping="Wrap">
|
||||
<Run Text="OpenCV: videoio implementation using XAML and Universal App Framework" />
|
||||
<Run />
|
||||
</TextBlock>
|
||||
<Image Name="cvImage"
|
||||
Width="640"
|
||||
Height="480"
|
||||
Margin="20,100,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top" />
|
||||
</Grid>
|
||||
</Page>
|
@ -0,0 +1,61 @@
|
||||
//
|
||||
// MainPage.xaml.cpp
|
||||
// Implementation of the MainPage class.
|
||||
//
|
||||
|
||||
#include "pch.h"
|
||||
#include "MainPage.xaml.h"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/features2d.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/videoio/cap_winrt.hpp>
|
||||
|
||||
using namespace video_capture_xaml;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace Windows::UI::Xaml::Navigation;
|
||||
|
||||
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
using namespace ::Windows::Foundation;
|
||||
using namespace Windows::UI::Xaml::Media::Imaging;
|
||||
|
||||
namespace video_capture_xaml
|
||||
{
|
||||
// nb. implemented in main.cpp
|
||||
void cvMain();
|
||||
|
||||
MainPage::MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Window::Current->VisibilityChanged += ref new Windows::UI::Xaml::WindowVisibilityChangedEventHandler(this, &video_capture_xaml::MainPage::OnVisibilityChanged);
|
||||
|
||||
// attach XAML elements
|
||||
cv::winrt_setFrameContainer(cvImage);
|
||||
|
||||
// start (1) frame-grabbing loop and (2) message loop
|
||||
//
|
||||
// 1. Function passed as an argument must implement common OCV reading frames
|
||||
// pattern (see cv::VideoCapture documentation) AND call cv::winrt_imgshow().
|
||||
// 2. Message processing loop required to overcome WinRT container and type
|
||||
// conversion restrictions. OCV provides default implementation
|
||||
cv::winrt_startMessageLoop(cvMain);
|
||||
}
|
||||
}
|
||||
|
||||
void video_capture_xaml::MainPage::OnVisibilityChanged(Platform::Object ^sender,
|
||||
Windows::UI::Core::VisibilityChangedEventArgs ^e)
|
||||
{
|
||||
cv::winrt_onVisibilityChanged(e->Visible);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
//
|
||||
// MainPage.xaml.h
|
||||
// Declaration of the MainPage class.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MainPage.g.h"
|
||||
|
||||
namespace video_capture_xaml
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public ref class MainPage sealed
|
||||
{
|
||||
public:
|
||||
MainPage();
|
||||
|
||||
private:
|
||||
void OnVisibilityChanged(Platform::Object ^sender, Windows::UI::Core::VisibilityChangedEventArgs ^e);
|
||||
|
||||
};
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
|
||||
<Identity Name="dd4947e8-f250-49d1-be17-4442dfea2737" Publisher="CN=daver_000" Version="1.0.0.0" />
|
||||
<Properties>
|
||||
<DisplayName>video_capture_xaml.Windows</DisplayName>
|
||||
<PublisherDisplayName>daver_000</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Prerequisites>
|
||||
<OSMinVersion>6.3.0</OSMinVersion>
|
||||
<OSMaxVersionTested>6.3.0</OSMaxVersionTested>
|
||||
</Prerequisites>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="video_capture_xaml_Windows.App">
|
||||
<m2:VisualElements DisplayName="video_capture_xaml.Windows" Square150x150Logo="Assets\Logo.png" Square30x30Logo="Assets\SmallLogo.png" Description="video_capture_xaml.Windows" ForegroundText="light" BackgroundColor="#464646">
|
||||
<m2:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
</m2:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<DeviceCapability Name="webcam" />
|
||||
</Capabilities>
|
||||
</Package>
|
@ -0,0 +1,30 @@
|
||||
notes for OpenCV WinRT implementation:
|
||||
|
||||
cvMain() in main.cpp
|
||||
implements the image processing and OpenCV app control
|
||||
it is running on a background thread, started by XAML
|
||||
see file main.cpp
|
||||
in the Application project
|
||||
|
||||
class VideoCapture_WinRT:
|
||||
implements the IVideoCapture interface from OpenCV
|
||||
video is initialized and frames are grabbed on the UI thread
|
||||
see files cap_winrt.hpp/cpp
|
||||
|
||||
class HighguiBridge, a singleton
|
||||
implements the OpenCV Highgui functions for XAML (limited at this time),
|
||||
and also bridges to the UI thread functions for XAML and video operations.
|
||||
see files cap_winrt_highgui.hpp/cpp
|
||||
|
||||
class Video, a singleton
|
||||
encapsulates the Media Foundation interface needed for video initialization and grabbing.
|
||||
called through Highgui and XAML, only on the UI thread
|
||||
see files cap_winrt_video.hpp/cpp
|
||||
|
||||
threading:
|
||||
requests from the OpenCV bg thread to the Video/XAML UI thread
|
||||
are made through HighguiBridge::requestForUIthreadAsync(), which uses
|
||||
the "progress reporter" method provided by the WinRT class
|
||||
IAsyncActionWithProgress. Also the bg thread is started by create_async().
|
||||
see file MainPage.xaml.cpp
|
||||
in the Application project
|
@ -0,0 +1,200 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{32fdab94-f87e-4f0a-89a4-9ec10a3b1d3d}</ProjectGuid>
|
||||
<RootNamespace>video_capture_xaml</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<ApplicationTypeRevision>8.1</ApplicationTypeRevision>
|
||||
<ProjectName>video_capture_xaml.Windows</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="..\video_capture_xaml.Shared\video_capture_xaml.Shared.vcxitems" Label="Shared" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<PackageCertificateKeyFile>video_capture_xaml.Windows_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<LibraryPath>$(OPENCV_WINRT_INSTALL_DIR)WS\8.1\x86\x86\vc12\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<ProjectReference>
|
||||
<UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>
|
||||
</ProjectReference>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ProjectReference>
|
||||
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
|
||||
</ProjectReference>
|
||||
<Link>
|
||||
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MainPage.xaml.h">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="MainPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
<None Include="video_capture_xaml.Windows_TemporaryKey.pfx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\Logo.scale-100.png" />
|
||||
<Image Include="Assets\SmallLogo.scale-100.png" />
|
||||
<Image Include="Assets\StoreLogo.scale-100.png" />
|
||||
<Image Include="Assets\SplashScreen.scale-100.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="MainPage.xaml.cpp">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="readme.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Xml Include="Assets\haarcascade_frontalface_alt.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Assets">
|
||||
<UniqueIdentifier>{ef9b8c45-f2b7-4eec-a8b4-a9b340be770b}</UniqueIdentifier>
|
||||
<Extensions>bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="MainPage.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="MainPage.xaml.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MainPage.xaml.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="video_capture_xaml.Windows_TemporaryKey.pfx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\Logo.scale-100.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\SmallLogo.scale-100.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\StoreLogo.scale-100.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\SplashScreen.scale-100.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="readme.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Xml Include="Assets\haarcascade_frontalface_alt.xml">
|
||||
<Filter>Assets</Filter>
|
||||
</Xml>
|
||||
</ItemGroup>
|
||||
</Project>
|
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 753 B |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.4 KiB |
@ -0,0 +1,26 @@
|
||||
<Page x:Class="video_capture_xaml.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:video_capture_xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<TextBlock Margin="20,35,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="24"
|
||||
TextWrapping="Wrap">
|
||||
<Run Text="OpenCV: videoio" />
|
||||
<Run />
|
||||
</TextBlock>
|
||||
<Image Name="cvImage"
|
||||
Width="640"
|
||||
Height="480"
|
||||
Margin="20,100,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top" />
|
||||
</Grid>
|
||||
</Page>
|
@ -0,0 +1,79 @@
|
||||
//
|
||||
// MainPage.xaml.cpp
|
||||
// Implementation of the MainPage class.
|
||||
//
|
||||
|
||||
#include "pch.h"
|
||||
#include "MainPage.xaml.h"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/features2d.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/videoio/cap_winrt.hpp>
|
||||
|
||||
using namespace video_capture_xaml;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace Windows::UI::Xaml::Navigation;
|
||||
|
||||
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
using namespace ::Windows::Foundation;
|
||||
using namespace Windows::UI::Xaml::Media::Imaging;
|
||||
|
||||
namespace video_capture_xaml {
|
||||
|
||||
// nb. implemented in main.cpp
|
||||
void cvMain();
|
||||
|
||||
MainPage::MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Window::Current->VisibilityChanged += ref new Windows::UI::Xaml::WindowVisibilityChangedEventHandler(this, &video_capture_xaml::MainPage::OnVisibilityChanged);
|
||||
|
||||
// attach XAML elements
|
||||
cv::winrt_setFrameContainer(cvImage);
|
||||
|
||||
// start (1) frame-grabbing loop and (2) message loop
|
||||
//
|
||||
// 1. Function passed as an argument must implement common OCV reading frames
|
||||
// pattern (see cv::VideoCapture documentation) AND call cv::winrt_imgshow().
|
||||
// 2. Message processing loop required to overcome WinRT container and type
|
||||
// conversion restrictions. OCV provides default implementation
|
||||
cv::winrt_startMessageLoop(cvMain);
|
||||
}
|
||||
|
||||
void video_capture_xaml::MainPage::OnVisibilityChanged(Platform::Object ^sender,
|
||||
Windows::UI::Core::VisibilityChangedEventArgs ^e)
|
||||
{
|
||||
cv::winrt_onVisibilityChanged(e->Visible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when this page is about to be displayed in a Frame.
|
||||
/// </summary>
|
||||
/// <param name="e">Event data that describes how this page was reached. The Parameter
|
||||
/// property is typically used to configure the page.</param>
|
||||
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
|
||||
{
|
||||
(void)e; // Unused parameter
|
||||
|
||||
// TODO: Prepare page for display here.
|
||||
|
||||
// TODO: If your application contains multiple pages, ensure that you are
|
||||
// handling the hardware Back button by registering for the
|
||||
// Windows::Phone::UI::Input::HardwareButtons.BackPressed event.
|
||||
// If you are using the NavigationHelper provided by some templates,
|
||||
// this event is handled for you.
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
//
|
||||
// MainPage.xaml.h
|
||||
// Declaration of the MainPage class.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MainPage.g.h"
|
||||
|
||||
namespace video_capture_xaml
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public ref class MainPage sealed
|
||||
{
|
||||
public:
|
||||
MainPage();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
|
||||
|
||||
private:
|
||||
|
||||
void OnVisibilityChanged(Platform::Object ^sender, Windows::UI::Core::VisibilityChangedEventArgs ^e);
|
||||
};
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest" xmlns:m3="http://schemas.microsoft.com/appx/2014/manifest" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
|
||||
|
||||
<Identity Name="dfafcbf2-a525-4ed0-9b6c-4e8bd5a9c0ba"
|
||||
Publisher="CN=daver_000"
|
||||
Version="1.0.0.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="dfafcbf2-a525-4ed0-9b6c-4e8bd5a9c0ba" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>video_capture_xaml.WindowsPhone</DisplayName>
|
||||
<PublisherDisplayName>daver_000</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Prerequisites>
|
||||
<OSMinVersion>6.3.1</OSMinVersion>
|
||||
<OSMaxVersionTested>6.3.1</OSMaxVersionTested>
|
||||
</Prerequisites>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate"/>
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App"
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="video_capture_xaml_WindowsPhone.App">
|
||||
<m3:VisualElements
|
||||
DisplayName="video_capture_xaml.WindowsPhone"
|
||||
Square150x150Logo="Assets\Logo.png"
|
||||
Square44x44Logo="Assets\SmallLogo.png"
|
||||
Description="video_capture_xaml.WindowsPhone"
|
||||
ForegroundText="light"
|
||||
BackgroundColor="transparent">
|
||||
<m3:DefaultTile Wide310x150Logo="Assets\WideLogo.png" Square71x71Logo="Assets\Square71x71Logo.png"/>
|
||||
<m3:SplashScreen Image="Assets\SplashScreen.png"/>
|
||||
<m3:ApplicationView MinWidth="width320"/> <!--Used in XAML Designer. DO NOT REMOVE-->
|
||||
</m3:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="internetClientServer" />
|
||||
<DeviceCapability Name="webcam" />
|
||||
</Capabilities>
|
||||
</Package>
|
@ -0,0 +1,147 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{d7a82e7f-1535-4eec-aba9-2c8447669d33}</ProjectGuid>
|
||||
<RootNamespace>video_capture_xaml</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Phone</ApplicationType>
|
||||
<ApplicationTypeRevision>8.1</ApplicationTypeRevision>
|
||||
<ProjectName>video_capture_xaml.WindowsPhone</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120_wp81</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120_wp81</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v120_wp81</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v120_wp81</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="..\video_capture_xaml.Shared\video_capture_xaml.Shared.vcxitems" Label="Shared" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\opencv.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LibraryPath>$(OPENCV_WINRT_INSTALL_DIR)WP\8.1\x86\x86\vc12\lib;$(VC_LibraryPath_x86);$(WindowsPhoneSDK_LibraryPath_x86);</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<LibraryPath>$(OPENCV_WINRT_INSTALL_DIR)WP\8.1\ARM\ARM\vc12\lib;$(VC_LibraryPath_ARM);$(WindowsPhoneSDK_LibraryPath_arm);</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>../../../../../modules/core/include;../../../../../modules/flann/include;../../../../../modules/videoio/include;../../../../../modules/hal/include;../../../../../modules/imgproc/include;../../../../../modules/features2d/include;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>opencv_core300d.lib;opencv_imgproc300d.lib;opencv_videoio300d.lib;WindowsPhoneCore.lib;RuntimeObject.lib;PhoneAppModelHost.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>../../../../../modules/core/include;../../../../../modules/flann/include;../../../../../modules/videoio/include;../../../../../modules/hal/include;../../../../../modules/imgproc/include;../../../../../modules/features2d/include;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>opencv_core300d.lib;opencv_imgproc300d.lib;opencv_videoio300d.lib;WindowsPhoneCore.lib;RuntimeObject.lib;PhoneAppModelHost.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MainPage.xaml.h">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="MainPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\Logo.scale-240.png" />
|
||||
<Image Include="Assets\SmallLogo.scale-240.png" />
|
||||
<Image Include="Assets\Square71x71Logo.scale-240.png" />
|
||||
<Image Include="Assets\StoreLogo.scale-240.png" />
|
||||
<Image Include="Assets\SplashScreen.scale-240.png" />
|
||||
<Image Include="Assets\WideLogo.scale-240.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="MainPage.xaml.cpp">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="video_capture_xaml.WindowsPhone_TemporaryKey.pfx" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Assets">
|
||||
<UniqueIdentifier>{$guid3$}</UniqueIdentifier>
|
||||
<Extensions>bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png</Extensions>
|
||||
</Filter>
|
||||
<Image Include="Assets\Logo.scale-240.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\SmallLogo.scale-240.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\Square71x71Logo.scale-240.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\StoreLogo.scale-240.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\SplashScreen.scale-240.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\WideLogo.scale-240.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="MainPage.xaml.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MainPage.xaml.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="MainPage.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="video_capture_xaml.WindowsPhone_TemporaryKey.pfx" />
|
||||
</ItemGroup>
|
||||
</Project>
|