Path: blob/master/modules/videoio/src/cap_winrt/MediaSink.hpp
16348 views
// Copyright (c) Microsoft. All rights reserved.1//2// The MIT License (MIT)3//4// Permission is hereby granted, free of charge, to any person obtaining a copy5// of this software and associated documentation files(the "Software"), to deal6// in the Software without restriction, including without limitation the rights7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell8// copies of the Software, and to permit persons to whom the Software is9// furnished to do so, subject to the following conditions :10//11// The above copyright notice and this permission notice shall be included in12// all copies or substantial portions of the Software.13//14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN20// THE SOFTWARE.2122#pragma once2324#include "MediaStreamSink.hpp"25#include "MFIncludes.hpp"2627namespace Media {2829const unsigned int c_audioStreamSinkId = 0;30const unsigned int c_videoStreamSinkId = 1;3132class MediaSink WrlSealed33: public MW::RuntimeClass<34MW::RuntimeClassFlags<35MW::RuntimeClassType::WinRtClassicComMix>36, AWM::IMediaExtension37, IMFMediaSink38, IMFClockStateSink39, MW::FtmBase40>41{42InspectableClass(L"MediaSink", BaseTrust)4344public:4546MediaSink(47_In_opt_ WMMp::AudioEncodingProperties^ audioProps,48_In_opt_ WMMp::VideoEncodingProperties^ videoProps,49_In_opt_ MediaSampleHandler^ audioSampleHandler,50_In_opt_ MediaSampleHandler^ videoSampleHandler51)52: _shutdown(false)53{54MW::ComPtr<IMFMediaType> audioMT;55if (audioProps != nullptr)56{57CHK(MFCreateMediaTypeFromProperties(As<IUnknown>(audioProps).Get(), &audioMT));58_audioStreamSink = MW::Make<MediaStreamSink>(59this,60c_audioStreamSinkId,61audioMT,62audioSampleHandler63);64}6566MW::ComPtr<IMFMediaType> videoMT;67if (videoProps != nullptr)68{69CHK(MFCreateMediaTypeFromProperties(As<IUnknown>(videoProps).Get(), &videoMT));70_videoStreamSink = MW::Make<MediaStreamSink>(71this,72c_videoStreamSinkId,73videoMT,74videoSampleHandler75);76}77}7879void RequestAudioSample()80{81auto lock = _lock.LockExclusive();8283_VerifyNotShutdown();8485_audioStreamSink->RequestSample();86}8788void RequestVideoSample()89{90auto lock = _lock.LockExclusive();9192_VerifyNotShutdown();9394_videoStreamSink->RequestSample();95}9697void SetCurrentAudioMediaType(_In_ IMFMediaType* mt)98{99auto lock = _lock.LockExclusive();100101_VerifyNotShutdown();102103_audioStreamSink->InternalSetCurrentMediaType(mt);104}105106void SetCurrentVideoMediaType(_In_ IMFMediaType* mt)107{108auto lock = _lock.LockExclusive();109110_VerifyNotShutdown();111112_videoStreamSink->InternalSetCurrentMediaType(mt);113}114115//116// IMediaExtension117//118119IFACEMETHODIMP SetProperties(_In_ AWFC::IPropertySet * /*configuration*/)120{121return ExceptionBoundary([this]()122{123auto lock = _lock.LockExclusive();124125_VerifyNotShutdown();126});127}128129//130// IMFMediaSink131//132133IFACEMETHODIMP GetCharacteristics(_Out_ DWORD *characteristics)134{135return ExceptionBoundary([this, characteristics]()136{137_VerifyNotShutdown();138139CHKNULL(characteristics);140*characteristics = MEDIASINK_RATELESS | MEDIASINK_FIXED_STREAMS;141});142}143144IFACEMETHODIMP AddStreamSink(145DWORD /*streamSinkIdentifier*/,146_In_ IMFMediaType * /*mediaType*/,147_COM_Outptr_ IMFStreamSink **streamSink148)149{150return ExceptionBoundary([this, streamSink]()151{152_VerifyNotShutdown();153154CHKNULL(streamSink);155*streamSink = nullptr;156157CHK(MF_E_STREAMSINKS_FIXED);158});159}160161IFACEMETHODIMP RemoveStreamSink(DWORD /*streamSinkIdentifier*/)162{163return ExceptionBoundary([this]()164{165_VerifyNotShutdown();166167CHK(MF_E_STREAMSINKS_FIXED);168});169}170171IFACEMETHODIMP GetStreamSinkCount(_Out_ DWORD *streamSinkCount)172{173return ExceptionBoundary([this, streamSinkCount]()174{175CHKNULL(streamSinkCount);176177_VerifyNotShutdown();178179*streamSinkCount = (_audioStreamSink != nullptr) + (_videoStreamSink != nullptr);180});181}182183IFACEMETHODIMP GetStreamSinkByIndex(DWORD index, _COM_Outptr_ IMFStreamSink **streamSink)184{185return ExceptionBoundary([this, index, streamSink]()186{187auto lock = _lock.LockExclusive();188189CHKNULL(streamSink);190*streamSink = nullptr;191192_VerifyNotShutdown();193194switch (index)195{196case 0:197if (_audioStreamSink != nullptr)198{199CHK(_audioStreamSink.CopyTo(streamSink));200}201else202{203CHK(_videoStreamSink.CopyTo(streamSink));204}205break;206207case 1:208if ((_audioStreamSink != nullptr) && (_videoStreamSink != nullptr))209{210CHK(_videoStreamSink.CopyTo(streamSink));211}212else213{214CHK(E_INVALIDARG);215}216break;217218default:219CHK(E_INVALIDARG);220}221});222}223224IFACEMETHODIMP GetStreamSinkById(DWORD identifier, _COM_Outptr_ IMFStreamSink **streamSink)225{226return ExceptionBoundary([this, identifier, streamSink]()227{228auto lock = _lock.LockExclusive();229230CHKNULL(streamSink);231*streamSink = nullptr;232233_VerifyNotShutdown();234235if ((identifier == 0) && (_audioStreamSink != nullptr))236{237CHK(_audioStreamSink.CopyTo(streamSink));238}239else if ((identifier == 1) && (_videoStreamSink != nullptr))240{241CHK(_videoStreamSink.CopyTo(streamSink));242}243else244{245CHK(E_INVALIDARG);246}247});248}249250IFACEMETHODIMP SetPresentationClock(_In_ IMFPresentationClock *clock)251{252return ExceptionBoundary([this, clock]()253{254auto lock = _lock.LockExclusive();255256_VerifyNotShutdown();257258if (_clock != nullptr)259{260CHK(_clock->RemoveClockStateSink(this));261_clock = nullptr;262}263264if (clock != nullptr)265{266CHK(clock->AddClockStateSink(this));267_clock = clock;268}269});270}271272IFACEMETHODIMP GetPresentationClock(_COM_Outptr_ IMFPresentationClock **clock)273{274return ExceptionBoundary([this, clock]()275{276auto lock = _lock.LockExclusive();277278CHKNULL(clock);279*clock = nullptr;280281_VerifyNotShutdown();282283if (_clock != nullptr)284{285CHK(_clock.CopyTo(clock))286}287});288}289290IFACEMETHODIMP Shutdown()291{292return ExceptionBoundary([this]()293{294auto lock = _lock.LockExclusive();295296if (_shutdown)297{298return;299}300_shutdown = true;301302if (_audioStreamSink != nullptr)303{304_audioStreamSink->Shutdown();305_audioStreamSink = nullptr;306}307308if (_videoStreamSink != nullptr)309{310_videoStreamSink->Shutdown();311_videoStreamSink = nullptr;312}313314if (_clock != nullptr)315{316(void)_clock->RemoveClockStateSink(this);317_clock = nullptr;318}319});320}321322//323// IMFClockStateSink methods324//325326IFACEMETHODIMP OnClockStart(MFTIME /*hnsSystemTime*/, LONGLONG /*llClockStartOffset*/)327{328return ExceptionBoundary([this]()329{330auto lock = _lock.LockExclusive();331332_VerifyNotShutdown();333});334}335336IFACEMETHODIMP OnClockStop(MFTIME /*hnsSystemTime*/)337{338return ExceptionBoundary([this]()339{340auto lock = _lock.LockExclusive();341342_VerifyNotShutdown();343});344}345346IFACEMETHODIMP OnClockPause(MFTIME /*hnsSystemTime*/)347{348return ExceptionBoundary([this]()349{350auto lock = _lock.LockExclusive();351352_VerifyNotShutdown();353});354}355356IFACEMETHODIMP OnClockRestart(MFTIME /*hnsSystemTime*/)357{358return ExceptionBoundary([this]()359{360auto lock = _lock.LockExclusive();361362_VerifyNotShutdown();363});364}365366IFACEMETHODIMP OnClockSetRate(MFTIME /*hnsSystemTime*/, float /*flRate*/)367{368return ExceptionBoundary([this]()369{370auto lock = _lock.LockExclusive();371372_VerifyNotShutdown();373});374}375376private:377378bool _shutdown;379380void _VerifyNotShutdown()381{382if (_shutdown)383{384CHK(MF_E_SHUTDOWN);385}386}387388MW::ComPtr<MediaStreamSink> _audioStreamSink;389MW::ComPtr<MediaStreamSink> _videoStreamSink;390MW::ComPtr<IMFPresentationClock> _clock;391392MWW::SRWLock _lock;393};394395}396397