Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
d08cb6b3
Commit
d08cb6b3
authored
May 15, 2015
by
Maxim Kostin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added WinRT support for videoio.
Signed-off-by:
Maxim Kostin
<
v-maxkos@microsoft.com
>
parent
d40eefd5
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
2456 additions
and
3 deletions
+2456
-3
videoio.hpp
modules/videoio/include/opencv2/videoio.hpp
+4
-2
cap_winrt.hpp
modules/videoio/include/opencv2/videoio/cap_winrt.hpp
+131
-0
cap.cpp
modules/videoio/src/cap.cpp
+42
-1
CaptureFrameGrabber.cpp
modules/videoio/src/cap_winrt/CaptureFrameGrabber.cpp
+174
-0
CaptureFrameGrabber.hpp
modules/videoio/src/cap_winrt/CaptureFrameGrabber.hpp
+86
-0
MFIncludes.hpp
modules/videoio/src/cap_winrt/MFIncludes.hpp
+173
-0
MediaSink.hpp
modules/videoio/src/cap_winrt/MediaSink.hpp
+397
-0
MediaStreamSink.cpp
modules/videoio/src/cap_winrt/MediaStreamSink.cpp
+387
-0
MediaStreamSink.hpp
modules/videoio/src/cap_winrt/MediaStreamSink.hpp
+115
-0
cap_winrt_bridge.cpp
modules/videoio/src/cap_winrt_bridge.cpp
+90
-0
cap_winrt_bridge.hpp
modules/videoio/src/cap_winrt_bridge.hpp
+97
-0
cap_winrt_capture.cpp
modules/videoio/src/cap_winrt_capture.cpp
+280
-0
cap_winrt_capture.hpp
modules/videoio/src/cap_winrt_capture.hpp
+83
-0
cap_winrt_video.cpp
modules/videoio/src/cap_winrt_video.cpp
+323
-0
cap_winrt_video.hpp
modules/videoio/src/cap_winrt_video.hpp
+74
-0
No files found.
modules/videoio/include/opencv2/videoio.hpp
View file @
d08cb6b3
...
...
@@ -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)
};
...
...
modules/videoio/include/opencv2/videoio/cap_winrt.hpp
0 → 100644
View file @
d08cb6b3
// 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
\ No newline at end of file
modules/videoio/src/cap.cpp
View file @
d08cb6b3
...
...
@@ -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
;
}
...
...
@@ -760,4 +800,4 @@ int VideoWriter::fourcc(char c1, char c2, char c3, char c4)
return
(
c1
&
255
)
+
((
c2
&
255
)
<<
8
)
+
((
c3
&
255
)
<<
16
)
+
((
c4
&
255
)
<<
24
);
}
}
}
\ No newline at end of file
modules/videoio/src/cap_winrt/CaptureFrameGrabber.cpp
0 → 100644
View file @
d08cb6b3
// 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
));
}
\ No newline at end of file
modules/videoio/src/cap_winrt/CaptureFrameGrabber.hpp
0 → 100644
View file @
d08cb6b3
// 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
;
};
}
\ No newline at end of file
modules/videoio/src/cap_winrt/MFIncludes.hpp
0 → 100644
View file @
d08cb6b3
// 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
);
\ No newline at end of file
modules/videoio/src/cap_winrt/MediaSink.hpp
0 → 100644
View file @
d08cb6b3
// 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
;
};
}
\ No newline at end of file
modules/videoio/src/cap_winrt/MediaStreamSink.cpp
0 → 100644
View file @
d08cb6b3
// 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
()));
}
\ No newline at end of file
modules/videoio/src/cap_winrt/MediaStreamSink.hpp
0 → 100644
View file @
d08cb6b3
// 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
;
};
}
\ No newline at end of file
modules/videoio/src/cap_winrt_bridge.cpp
0 → 100644
View file @
d08cb6b3
// 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
\ No newline at end of file
modules/videoio/src/cap_winrt_bridge.hpp
0 → 100644
View file @
d08cb6b3
// 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
;
};
\ No newline at end of file
modules/videoio/src/cap_winrt_capture.cpp
0 → 100644
View file @
d08cb6b3
// 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
\ No newline at end of file
modules/videoio/src/cap_winrt_capture.hpp
0 → 100644
View file @
d08cb6b3
// 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
;
};
}
\ No newline at end of file
modules/videoio/src/cap_winrt_video.cpp
0 → 100644
View file @
d08cb6b3
// 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
\ No newline at end of file
modules/videoio/src/cap_winrt_video.hpp
0 → 100644
View file @
d08cb6b3
// 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
;
};
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment