Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/videoio/src/cap_winrt/MediaSink.hpp
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
#pragma once
24
25
#include "MediaStreamSink.hpp"
26
#include "MFIncludes.hpp"
27
28
namespace Media {
29
30
const unsigned int c_audioStreamSinkId = 0;
31
const unsigned int c_videoStreamSinkId = 1;
32
33
class MediaSink WrlSealed
34
: public MW::RuntimeClass<
35
MW::RuntimeClassFlags<
36
MW::RuntimeClassType::WinRtClassicComMix>
37
, AWM::IMediaExtension
38
, IMFMediaSink
39
, IMFClockStateSink
40
, MW::FtmBase
41
>
42
{
43
InspectableClass(L"MediaSink", BaseTrust)
44
45
public:
46
47
MediaSink(
48
_In_opt_ WMMp::AudioEncodingProperties^ audioProps,
49
_In_opt_ WMMp::VideoEncodingProperties^ videoProps,
50
_In_opt_ MediaSampleHandler^ audioSampleHandler,
51
_In_opt_ MediaSampleHandler^ videoSampleHandler
52
)
53
: _shutdown(false)
54
{
55
MW::ComPtr<IMFMediaType> audioMT;
56
if (audioProps != nullptr)
57
{
58
CHK(MFCreateMediaTypeFromProperties(As<IUnknown>(audioProps).Get(), &audioMT));
59
_audioStreamSink = MW::Make<MediaStreamSink>(
60
this,
61
c_audioStreamSinkId,
62
audioMT,
63
audioSampleHandler
64
);
65
}
66
67
MW::ComPtr<IMFMediaType> videoMT;
68
if (videoProps != nullptr)
69
{
70
CHK(MFCreateMediaTypeFromProperties(As<IUnknown>(videoProps).Get(), &videoMT));
71
_videoStreamSink = MW::Make<MediaStreamSink>(
72
this,
73
c_videoStreamSinkId,
74
videoMT,
75
videoSampleHandler
76
);
77
}
78
}
79
80
void RequestAudioSample()
81
{
82
auto lock = _lock.LockExclusive();
83
84
_VerifyNotShutdown();
85
86
_audioStreamSink->RequestSample();
87
}
88
89
void RequestVideoSample()
90
{
91
auto lock = _lock.LockExclusive();
92
93
_VerifyNotShutdown();
94
95
_videoStreamSink->RequestSample();
96
}
97
98
void SetCurrentAudioMediaType(_In_ IMFMediaType* mt)
99
{
100
auto lock = _lock.LockExclusive();
101
102
_VerifyNotShutdown();
103
104
_audioStreamSink->InternalSetCurrentMediaType(mt);
105
}
106
107
void SetCurrentVideoMediaType(_In_ IMFMediaType* mt)
108
{
109
auto lock = _lock.LockExclusive();
110
111
_VerifyNotShutdown();
112
113
_videoStreamSink->InternalSetCurrentMediaType(mt);
114
}
115
116
//
117
// IMediaExtension
118
//
119
120
IFACEMETHODIMP SetProperties(_In_ AWFC::IPropertySet * /*configuration*/)
121
{
122
return ExceptionBoundary([this]()
123
{
124
auto lock = _lock.LockExclusive();
125
126
_VerifyNotShutdown();
127
});
128
}
129
130
//
131
// IMFMediaSink
132
//
133
134
IFACEMETHODIMP GetCharacteristics(_Out_ DWORD *characteristics)
135
{
136
return ExceptionBoundary([this, characteristics]()
137
{
138
_VerifyNotShutdown();
139
140
CHKNULL(characteristics);
141
*characteristics = MEDIASINK_RATELESS | MEDIASINK_FIXED_STREAMS;
142
});
143
}
144
145
IFACEMETHODIMP AddStreamSink(
146
DWORD /*streamSinkIdentifier*/,
147
_In_ IMFMediaType * /*mediaType*/,
148
_COM_Outptr_ IMFStreamSink **streamSink
149
)
150
{
151
return ExceptionBoundary([this, streamSink]()
152
{
153
_VerifyNotShutdown();
154
155
CHKNULL(streamSink);
156
*streamSink = nullptr;
157
158
CHK(MF_E_STREAMSINKS_FIXED);
159
});
160
}
161
162
IFACEMETHODIMP RemoveStreamSink(DWORD /*streamSinkIdentifier*/)
163
{
164
return ExceptionBoundary([this]()
165
{
166
_VerifyNotShutdown();
167
168
CHK(MF_E_STREAMSINKS_FIXED);
169
});
170
}
171
172
IFACEMETHODIMP GetStreamSinkCount(_Out_ DWORD *streamSinkCount)
173
{
174
return ExceptionBoundary([this, streamSinkCount]()
175
{
176
CHKNULL(streamSinkCount);
177
178
_VerifyNotShutdown();
179
180
*streamSinkCount = (_audioStreamSink != nullptr) + (_videoStreamSink != nullptr);
181
});
182
}
183
184
IFACEMETHODIMP GetStreamSinkByIndex(DWORD index, _COM_Outptr_ IMFStreamSink **streamSink)
185
{
186
return ExceptionBoundary([this, index, streamSink]()
187
{
188
auto lock = _lock.LockExclusive();
189
190
CHKNULL(streamSink);
191
*streamSink = nullptr;
192
193
_VerifyNotShutdown();
194
195
switch (index)
196
{
197
case 0:
198
if (_audioStreamSink != nullptr)
199
{
200
CHK(_audioStreamSink.CopyTo(streamSink));
201
}
202
else
203
{
204
CHK(_videoStreamSink.CopyTo(streamSink));
205
}
206
break;
207
208
case 1:
209
if ((_audioStreamSink != nullptr) && (_videoStreamSink != nullptr))
210
{
211
CHK(_videoStreamSink.CopyTo(streamSink));
212
}
213
else
214
{
215
CHK(E_INVALIDARG);
216
}
217
break;
218
219
default:
220
CHK(E_INVALIDARG);
221
}
222
});
223
}
224
225
IFACEMETHODIMP GetStreamSinkById(DWORD identifier, _COM_Outptr_ IMFStreamSink **streamSink)
226
{
227
return ExceptionBoundary([this, identifier, streamSink]()
228
{
229
auto lock = _lock.LockExclusive();
230
231
CHKNULL(streamSink);
232
*streamSink = nullptr;
233
234
_VerifyNotShutdown();
235
236
if ((identifier == 0) && (_audioStreamSink != nullptr))
237
{
238
CHK(_audioStreamSink.CopyTo(streamSink));
239
}
240
else if ((identifier == 1) && (_videoStreamSink != nullptr))
241
{
242
CHK(_videoStreamSink.CopyTo(streamSink));
243
}
244
else
245
{
246
CHK(E_INVALIDARG);
247
}
248
});
249
}
250
251
IFACEMETHODIMP SetPresentationClock(_In_ IMFPresentationClock *clock)
252
{
253
return ExceptionBoundary([this, clock]()
254
{
255
auto lock = _lock.LockExclusive();
256
257
_VerifyNotShutdown();
258
259
if (_clock != nullptr)
260
{
261
CHK(_clock->RemoveClockStateSink(this));
262
_clock = nullptr;
263
}
264
265
if (clock != nullptr)
266
{
267
CHK(clock->AddClockStateSink(this));
268
_clock = clock;
269
}
270
});
271
}
272
273
IFACEMETHODIMP GetPresentationClock(_COM_Outptr_ IMFPresentationClock **clock)
274
{
275
return ExceptionBoundary([this, clock]()
276
{
277
auto lock = _lock.LockExclusive();
278
279
CHKNULL(clock);
280
*clock = nullptr;
281
282
_VerifyNotShutdown();
283
284
if (_clock != nullptr)
285
{
286
CHK(_clock.CopyTo(clock))
287
}
288
});
289
}
290
291
IFACEMETHODIMP Shutdown()
292
{
293
return ExceptionBoundary([this]()
294
{
295
auto lock = _lock.LockExclusive();
296
297
if (_shutdown)
298
{
299
return;
300
}
301
_shutdown = true;
302
303
if (_audioStreamSink != nullptr)
304
{
305
_audioStreamSink->Shutdown();
306
_audioStreamSink = nullptr;
307
}
308
309
if (_videoStreamSink != nullptr)
310
{
311
_videoStreamSink->Shutdown();
312
_videoStreamSink = nullptr;
313
}
314
315
if (_clock != nullptr)
316
{
317
(void)_clock->RemoveClockStateSink(this);
318
_clock = nullptr;
319
}
320
});
321
}
322
323
//
324
// IMFClockStateSink methods
325
//
326
327
IFACEMETHODIMP OnClockStart(MFTIME /*hnsSystemTime*/, LONGLONG /*llClockStartOffset*/)
328
{
329
return ExceptionBoundary([this]()
330
{
331
auto lock = _lock.LockExclusive();
332
333
_VerifyNotShutdown();
334
});
335
}
336
337
IFACEMETHODIMP OnClockStop(MFTIME /*hnsSystemTime*/)
338
{
339
return ExceptionBoundary([this]()
340
{
341
auto lock = _lock.LockExclusive();
342
343
_VerifyNotShutdown();
344
});
345
}
346
347
IFACEMETHODIMP OnClockPause(MFTIME /*hnsSystemTime*/)
348
{
349
return ExceptionBoundary([this]()
350
{
351
auto lock = _lock.LockExclusive();
352
353
_VerifyNotShutdown();
354
});
355
}
356
357
IFACEMETHODIMP OnClockRestart(MFTIME /*hnsSystemTime*/)
358
{
359
return ExceptionBoundary([this]()
360
{
361
auto lock = _lock.LockExclusive();
362
363
_VerifyNotShutdown();
364
});
365
}
366
367
IFACEMETHODIMP OnClockSetRate(MFTIME /*hnsSystemTime*/, float /*flRate*/)
368
{
369
return ExceptionBoundary([this]()
370
{
371
auto lock = _lock.LockExclusive();
372
373
_VerifyNotShutdown();
374
});
375
}
376
377
private:
378
379
bool _shutdown;
380
381
void _VerifyNotShutdown()
382
{
383
if (_shutdown)
384
{
385
CHK(MF_E_SHUTDOWN);
386
}
387
}
388
389
MW::ComPtr<MediaStreamSink> _audioStreamSink;
390
MW::ComPtr<MediaStreamSink> _videoStreamSink;
391
MW::ComPtr<IMFPresentationClock> _clock;
392
393
MWW::SRWLock _lock;
394
};
395
396
}
397