Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/videoio/src/cap_winrt/CaptureFrameGrabber.cpp
16348 views
1
// Copyright (c) Microsoft. All rights reserved.
2
//
3
// The MIT License (MIT)
4
//
5
// Permission is hereby granted, free of charge, to any person obtaining a copy
6
// of this software and associated documentation files(the "Software"), to deal
7
// in the Software without restriction, including without limitation the rights
8
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the Software is
10
// furnished to do so, subject to the following conditions :
11
//
12
// The above copyright notice and this permission notice shall be included in
13
// all copies or substantial portions of the Software.
14
//
15
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
18
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
// THE SOFTWARE.
22
23
#include "MediaStreamSink.hpp"
24
#include "MediaSink.hpp"
25
#include "CaptureFrameGrabber.hpp"
26
27
using namespace Media;
28
using namespace Platform;
29
using namespace Windows::Foundation;
30
using namespace Windows::Media;
31
using namespace Windows::Media::Capture;
32
using namespace Windows::Media::MediaProperties;
33
using namespace concurrency;
34
using namespace Microsoft::WRL::Details;
35
using namespace Microsoft::WRL;
36
37
task<Media::CaptureFrameGrabber^> Media::CaptureFrameGrabber::CreateAsync(_In_ MediaCapture^ capture, _In_ VideoEncodingProperties^ props, CaptureStreamType streamType)
38
{
39
auto reader = ref new Media::CaptureFrameGrabber(capture, props, streamType);
40
41
auto profile = ref new MediaEncodingProfile();
42
profile->Video = props;
43
44
task<void> task;
45
if (reader->_streamType == CaptureStreamType::Preview)
46
{
47
task = create_task(capture->StartPreviewToCustomSinkAsync(profile, reader->_mediaExtension));
48
}
49
else
50
{
51
task = create_task(capture->StartRecordToCustomSinkAsync(profile, reader->_mediaExtension));
52
}
53
54
return task.then([reader]()
55
{
56
reader->_state = State::Started;
57
return reader;
58
});
59
}
60
61
Media::CaptureFrameGrabber::CaptureFrameGrabber(_In_ MediaCapture^ capture, _In_ VideoEncodingProperties^ props, CaptureStreamType streamType)
62
: _state(State::Created)
63
, _streamType(streamType)
64
, _capture(capture)
65
{
66
auto videoSampleHandler = ref new MediaSampleHandler(this, &Media::CaptureFrameGrabber::ProcessSample);
67
68
_mediaSink = Make<MediaSink>(nullptr, props, nullptr, videoSampleHandler);
69
_mediaExtension = reinterpret_cast<IMediaExtension^>(static_cast<AWM::IMediaExtension*>(_mediaSink.Get()));
70
}
71
72
Media::CaptureFrameGrabber::~CaptureFrameGrabber()
73
{
74
if (_state == State::Started)
75
{
76
if (_streamType == CaptureStreamType::Preview)
77
{
78
(void)_capture->StopPreviewAsync();
79
}
80
else
81
{
82
(void)_capture->StopRecordAsync();
83
}
84
}
85
86
if (_mediaSink != nullptr)
87
{
88
(void)_mediaSink->Shutdown();
89
_mediaSink = nullptr;
90
}
91
_mediaExtension = nullptr;
92
_capture = nullptr;
93
}
94
95
void Media::CaptureFrameGrabber::ShowCameraSettings()
96
{
97
#if WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP
98
if (_state == State::Started)
99
{
100
CameraOptionsUI::Show(_capture.Get());
101
}
102
#endif
103
}
104
105
task<void> Media::CaptureFrameGrabber::FinishAsync()
106
{
107
auto lock = _lock.LockExclusive();
108
109
if (_state != State::Started)
110
{
111
throw ref new COMException(E_UNEXPECTED, L"State");
112
}
113
_state = State::Closing;
114
115
if (_mediaSink != nullptr)
116
{
117
(void)_mediaSink->Shutdown();
118
_mediaSink = nullptr;
119
}
120
_mediaExtension = nullptr;
121
122
task<void> task;
123
if (_streamType == CaptureStreamType::Preview)
124
{
125
task = create_task(_capture->StopPreviewAsync());
126
}
127
else
128
{
129
task = create_task(_capture->StopRecordAsync());
130
}
131
132
return task.then([this]()
133
{
134
auto lock = _lock.LockExclusive();
135
_state = State::Closed;
136
_capture = nullptr;
137
});
138
}
139
140
task<ComPtr<IMF2DBuffer2>> Media::CaptureFrameGrabber::GetFrameAsync()
141
{
142
auto lock = _lock.LockExclusive();
143
144
if (_state != State::Started)
145
{
146
throw ref new COMException(E_UNEXPECTED, L"State");
147
}
148
149
_mediaSink->RequestVideoSample();
150
151
task_completion_event<ComPtr<IMF2DBuffer2>> taskEvent;
152
_videoSampleRequestQueue.push(taskEvent);
153
154
return create_task(taskEvent);
155
}
156
157
void Media::CaptureFrameGrabber::ProcessSample(_In_ MediaSample^ sample)
158
{
159
task_completion_event<ComPtr<IMF2DBuffer2>> t;
160
161
{
162
auto lock = _lock.LockExclusive();
163
164
t = _videoSampleRequestQueue.front();
165
_videoSampleRequestQueue.pop();
166
}
167
168
ComPtr<IMFMediaBuffer> buffer;
169
CHK(sample->Sample->ConvertToContiguousBuffer(&buffer));
170
171
// Dispatch without the lock taken to avoid deadlocks
172
t.set(As<IMF2DBuffer2>(buffer));
173
}
174