Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/videoio/src/cap_winrt/MediaStreamSink.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 "MFIncludes.hpp"
25
26
using namespace Media;
27
using namespace Microsoft::WRL;
28
using namespace Platform;
29
using namespace Windows::Foundation;
30
31
MediaStreamSink::MediaStreamSink(
32
__in const MW::ComPtr<IMFMediaSink>& sink,
33
__in DWORD id,
34
__in const MW::ComPtr<IMFMediaType>& mt,
35
__in MediaSampleHandler^ sampleHandler
36
)
37
: _shutdown(false)
38
, _id(-1)
39
, _width(0)
40
, _height(0)
41
{
42
CHK(MFCreateEventQueue(&_eventQueue));
43
CHK(MFCreateMediaType(&_curMT));
44
45
_UpdateMediaType(mt);
46
47
_sink = sink;
48
_id = id;
49
_sampleHandler = sampleHandler;
50
}
51
52
HRESULT MediaStreamSink::GetMediaSink(__deref_out IMFMediaSink **sink)
53
{
54
return ExceptionBoundary([this, sink]()
55
{
56
auto lock = _lock.LockExclusive();
57
58
CHKNULL(sink);
59
*sink = nullptr;
60
61
_VerifyNotShutdown();
62
63
CHK(_sink.CopyTo(sink));
64
});
65
}
66
67
HRESULT MediaStreamSink::GetIdentifier(__out DWORD *identifier)
68
{
69
return ExceptionBoundary([this, identifier]()
70
{
71
auto lock = _lock.LockExclusive();
72
73
CHKNULL(identifier);
74
75
_VerifyNotShutdown();
76
77
*identifier = _id;
78
});
79
}
80
81
HRESULT MediaStreamSink::GetMediaTypeHandler(__deref_out IMFMediaTypeHandler **handler)
82
{
83
return ExceptionBoundary([this, handler]()
84
{
85
auto lock = _lock.LockExclusive();
86
87
CHKNULL(handler);
88
*handler = nullptr;
89
90
_VerifyNotShutdown();
91
92
*handler = this;
93
this->AddRef();
94
95
});
96
}
97
98
void MediaStreamSink::RequestSample()
99
{
100
auto lock = _lock.LockExclusive();
101
102
_VerifyNotShutdown();
103
104
CHK(_eventQueue->QueueEventParamVar(MEStreamSinkRequestSample, GUID_NULL, S_OK, nullptr));
105
}
106
107
HRESULT MediaStreamSink::ProcessSample(__in_opt IMFSample *sample)
108
{
109
return ExceptionBoundary([this, sample]()
110
{
111
MediaSampleHandler^ sampleHandler;
112
auto mediaSample = ref new MediaSample();
113
114
{
115
auto lock = _lock.LockExclusive();
116
117
_VerifyNotShutdown();
118
119
if (sample == nullptr)
120
{
121
return;
122
}
123
124
mediaSample->Sample = sample;
125
sampleHandler = _sampleHandler;
126
}
127
128
// Call back without the lock taken to avoid deadlocks
129
sampleHandler(mediaSample);
130
});
131
}
132
133
HRESULT MediaStreamSink::PlaceMarker(__in MFSTREAMSINK_MARKER_TYPE /*markerType*/, __in const PROPVARIANT * /*markerValue*/, __in const PROPVARIANT * contextValue)
134
{
135
return ExceptionBoundary([this, contextValue]()
136
{
137
auto lock = _lock.LockExclusive();
138
CHKNULL(contextValue);
139
140
_VerifyNotShutdown();
141
142
CHK(_eventQueue->QueueEventParamVar(MEStreamSinkMarker, GUID_NULL, S_OK, contextValue));
143
});
144
}
145
146
HRESULT MediaStreamSink::Flush()
147
{
148
return ExceptionBoundary([this]()
149
{
150
auto lock = _lock.LockExclusive();
151
152
_VerifyNotShutdown();
153
});
154
}
155
156
HRESULT MediaStreamSink::GetEvent(__in DWORD flags, __deref_out IMFMediaEvent **event)
157
{
158
return ExceptionBoundary([this, flags, event]()
159
{
160
CHKNULL(event);
161
*event = nullptr;
162
163
ComPtr<IMFMediaEventQueue> eventQueue;
164
165
{
166
auto lock = _lock.LockExclusive();
167
168
_VerifyNotShutdown();
169
170
eventQueue = _eventQueue;
171
}
172
173
// May block for a while
174
CHK(eventQueue->GetEvent(flags, event));
175
});
176
}
177
178
HRESULT MediaStreamSink::BeginGetEvent(__in IMFAsyncCallback *callback, __in_opt IUnknown *state)
179
{
180
return ExceptionBoundary([this, callback, state]()
181
{
182
auto lock = _lock.LockExclusive();
183
184
_VerifyNotShutdown();
185
186
CHK(_eventQueue->BeginGetEvent(callback, state));
187
});
188
}
189
190
191
HRESULT MediaStreamSink::EndGetEvent(__in IMFAsyncResult *result, __deref_out IMFMediaEvent **event)
192
{
193
return ExceptionBoundary([this, result, event]()
194
{
195
auto lock = _lock.LockExclusive();
196
197
CHKNULL(event);
198
*event = nullptr;
199
200
_VerifyNotShutdown();
201
202
CHK(_eventQueue->EndGetEvent(result, event));
203
});
204
}
205
206
HRESULT MediaStreamSink::QueueEvent(
207
__in MediaEventType met,
208
__in REFGUID extendedType,
209
__in HRESULT status,
210
__in_opt const PROPVARIANT *value
211
)
212
{
213
return ExceptionBoundary([this, met, extendedType, status, value]()
214
{
215
auto lock = _lock.LockExclusive();
216
217
_VerifyNotShutdown();
218
219
CHK(_eventQueue->QueueEventParamVar(met, extendedType, status, value));
220
});
221
}
222
223
HRESULT MediaStreamSink::IsMediaTypeSupported(__in IMFMediaType *mediaType, __deref_out_opt IMFMediaType **closestMediaType)
224
{
225
bool supported = false;
226
227
HRESULT hr = ExceptionBoundary([this, mediaType, closestMediaType, &supported]()
228
{
229
auto lock = _lock.LockExclusive();
230
231
if (closestMediaType != nullptr)
232
{
233
*closestMediaType = nullptr;
234
}
235
236
CHKNULL(mediaType);
237
238
_VerifyNotShutdown();
239
240
supported = _IsMediaTypeSupported(mediaType);
241
});
242
243
// Avoid throwing an exception to return MF_E_INVALIDMEDIATYPE as this is not a exceptional case
244
return FAILED(hr) ? hr : supported ? S_OK : MF_E_INVALIDMEDIATYPE;
245
}
246
247
HRESULT MediaStreamSink::GetMediaTypeCount(__out DWORD *typeCount)
248
{
249
return ExceptionBoundary([this, typeCount]()
250
{
251
auto lock = _lock.LockExclusive();
252
253
CHKNULL(typeCount);
254
255
_VerifyNotShutdown();
256
257
// No media type provided by default (app needs to specify it)
258
*typeCount = 0;
259
});
260
}
261
262
HRESULT MediaStreamSink::GetMediaTypeByIndex(__in DWORD /*index*/, __deref_out IMFMediaType **mediaType)
263
{
264
HRESULT hr = ExceptionBoundary([this, mediaType]()
265
{
266
auto lock = _lock.LockExclusive();
267
268
CHKNULL(mediaType);
269
*mediaType = nullptr;
270
271
_VerifyNotShutdown();
272
});
273
274
// Avoid throwing an exception to return MF_E_NO_MORE_TYPES as this is not a exceptional case
275
return FAILED(hr) ? hr : MF_E_NO_MORE_TYPES;
276
}
277
278
HRESULT MediaStreamSink::SetCurrentMediaType(__in IMFMediaType *mediaType)
279
{
280
return ExceptionBoundary([this, mediaType]()
281
{
282
auto lock = _lock.LockExclusive();
283
284
CHKNULL(mediaType);
285
286
_VerifyNotShutdown();
287
288
if (!_IsMediaTypeSupported(mediaType))
289
{
290
CHK(MF_E_INVALIDMEDIATYPE);
291
}
292
293
_UpdateMediaType(mediaType);
294
});
295
}
296
297
HRESULT MediaStreamSink::GetCurrentMediaType(__deref_out_opt IMFMediaType **mediaType)
298
{
299
return ExceptionBoundary([this, mediaType]()
300
{
301
auto lock = _lock.LockExclusive();
302
303
CHKNULL(mediaType);
304
*mediaType = nullptr;
305
306
_VerifyNotShutdown();
307
308
ComPtr<IMFMediaType> mt;
309
CHK(MFCreateMediaType(&mt));
310
CHK(_curMT->CopyAllItems(mt.Get()));
311
*mediaType = mt.Detach();
312
});
313
}
314
315
HRESULT MediaStreamSink::GetMajorType(__out GUID *majorType)
316
{
317
return ExceptionBoundary([this, majorType]()
318
{
319
auto lock = _lock.LockExclusive();
320
321
CHKNULL(majorType);
322
323
_VerifyNotShutdown();
324
325
*majorType = _majorType;
326
});
327
}
328
329
void MediaStreamSink::InternalSetCurrentMediaType(__in const ComPtr<IMFMediaType>& mediaType)
330
{
331
auto lock = _lock.LockExclusive();
332
333
CHKNULL(mediaType);
334
335
_VerifyNotShutdown();
336
337
_UpdateMediaType(mediaType);
338
}
339
340
void MediaStreamSink::Shutdown()
341
{
342
auto lock = _lock.LockExclusive();
343
344
if (_shutdown)
345
{
346
return;
347
}
348
_shutdown = true;
349
350
(void)_eventQueue->Shutdown();
351
_eventQueue = nullptr;
352
353
_curMT = nullptr;
354
_sink = nullptr;
355
_sampleHandler = nullptr;
356
}
357
358
bool MediaStreamSink::_IsMediaTypeSupported(__in const ComPtr<IMFMediaType>& mt) const
359
{
360
GUID majorType;
361
GUID subType;
362
if (SUCCEEDED(mt->GetGUID(MF_MT_MAJOR_TYPE, &majorType)) &&
363
SUCCEEDED(mt->GetGUID(MF_MT_SUBTYPE, &subType)) &&
364
(majorType == _majorType) &&
365
(subType == _subType))
366
{
367
return true;
368
}
369
370
return false;
371
}
372
373
void MediaStreamSink::_UpdateMediaType(__in const ComPtr<IMFMediaType>& mt)
374
{
375
CHK(mt->GetGUID(MF_MT_MAJOR_TYPE, &_majorType));
376
CHK(mt->GetGUID(MF_MT_SUBTYPE, &_subType));
377
378
if (_majorType == MFMediaType_Video)
379
{
380
CHK(MFGetAttributeSize(mt.Get(), MF_MT_FRAME_SIZE, &_width, &_height));
381
}
382
383
CHK(mt->CopyAllItems(_curMT.Get()));
384
}
385