This source file includes following definitions.
- InspectableClass
- RequestAudioSample
- RequestVideoSample
- SetCurrentAudioMediaType
- SetCurrentVideoMediaType
- SetProperties
- GetCharacteristics
- AddStreamSink
- RemoveStreamSink
- GetStreamSinkCount
- GetStreamSinkByIndex
- GetStreamSinkById
- SetPresentationClock
- GetPresentationClock
- Shutdown
- OnClockStart
- OnClockStop
- OnClockPause
- OnClockRestart
- OnClockSetRate
- _VerifyNotShutdown
#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);
}
IFACEMETHODIMP SetProperties(_In_ AWFC::IPropertySet * )
{
return ExceptionBoundary([this]()
{
auto lock = _lock.LockExclusive();
_VerifyNotShutdown();
});
}
IFACEMETHODIMP GetCharacteristics(_Out_ DWORD *characteristics)
{
return ExceptionBoundary([this, characteristics]()
{
_VerifyNotShutdown();
CHKNULL(characteristics);
*characteristics = MEDIASINK_RATELESS | MEDIASINK_FIXED_STREAMS;
});
}
IFACEMETHODIMP AddStreamSink(
DWORD ,
_In_ IMFMediaType * ,
_COM_Outptr_ IMFStreamSink **streamSink
)
{
return ExceptionBoundary([this, streamSink]()
{
_VerifyNotShutdown();
CHKNULL(streamSink);
*streamSink = nullptr;
CHK(MF_E_STREAMSINKS_FIXED);
});
}
IFACEMETHODIMP RemoveStreamSink(DWORD )
{
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;
}
});
}
IFACEMETHODIMP OnClockStart(MFTIME , LONGLONG )
{
return ExceptionBoundary([this]()
{
auto lock = _lock.LockExclusive();
_VerifyNotShutdown();
});
}
IFACEMETHODIMP OnClockStop(MFTIME )
{
return ExceptionBoundary([this]()
{
auto lock = _lock.LockExclusive();
_VerifyNotShutdown();
});
}
IFACEMETHODIMP OnClockPause(MFTIME )
{
return ExceptionBoundary([this]()
{
auto lock = _lock.LockExclusive();
_VerifyNotShutdown();
});
}
IFACEMETHODIMP OnClockRestart(MFTIME )
{
return ExceptionBoundary([this]()
{
auto lock = _lock.LockExclusive();
_VerifyNotShutdown();
});
}
IFACEMETHODIMP OnClockSetRate(MFTIME , float )
{
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;
};